FFMPEG编译安装、简单使用

目录

  • 源码下载
  • 编译和安装
  • API简单使用
    • 源代码
    • 编译
    • 运行
  • 工具的简单使用
  • 学习论坛

源码下载

地址: https://github.com/FFmpeg/FFmpeg

git clone https://github.com/FFmpeg/FFmpeg.git

编译和安装

  • 因为使用在板端编译,因此没有使用交叉编译链的部分。
  • 将如下内容复制到build.sh, 执行sh build.sh
./configure \
        --prefix="$PWD/install" \
        --enable-shared \
        --target-os=linux \
        --arch=aarch64 \
        --enable-gpl \
        --extra-libs=-ldl \
        --extra-cflags="-fPIC" \
        --extra-ldflags=-Wl,-Bsymbolic \
        --extra-libs="-lpthread -lm"

  • 如果没有报错,执行make -j4;make install
    • 以上版本工具有ffmpegffprobe
    • 接口在install目录下的include和lib

API简单使用

源代码

xxxxxxxxxxxxxxxxxxxx.hpp

#ifndef FILE_2_FRAME_H__
#define FILE_2_FRAME_H__

#include 
#include 
extern "C" {
	#include 
}



class CFile2Frame {
public:
	
	static constexpr char *RED_START = (char*)"\033[1;31m";
	static constexpr char *GREEN_START = (char*)"\033[1;32m";
	static constexpr char *COLOR_END = (char*)"\033[0m";

	typedef void (*func_data)(char*, int, void*pUser);
	
public:
	CFile2Frame(const std::string &filePath);
	~CFile2Frame();

	int start();

	int videoFormatConversion();
	void file2FrameExecLoop(void);
	
	void loop();
	static unsigned frameNo_;
private:
	bool isExit_;
	std::thread *pff_;
	func_data frameCb_;

	std::string strfileNamePath_;
	//ffmpeg
	AVFormatContext *ic_{nullptr};
	AVDictionary *opts_{nullptr};
	AVPacket *pkt;

	bool initSucc  ;		/*初始化成功完成标志, 读帧准备前的初始化*/
	int VideoStreamIndex_;

		
	

};

#endif 

xxxxxxxxxxxxxxxxxxxxx.cpp

#include 
#include 
#include 
#include 


#include 

unsigned CFile2Frame::frameNo_=0U;


static void frameCallback(char *pdata, int size, void *pUser)
{
	if(pUser){
		// *this
	}

	printf("fn:%06d - frame_size:%d\n", ++CFile2Frame::frameNo_, size);
	
}

static double r2d(AVRational r)
{
	return r.den == 0 ? 0 : r.num / r.den;
}


CFile2Frame::CFile2Frame(const std::string &filePath):frameCb_(frameCallback),pff_(nullptr), isExit_(false),strfileNamePath_(filePath),
		initSucc(false), VideoStreamIndex_(0)
	
{
	pff_ = new std::thread(&CFile2Frame::file2FrameExecLoop,this);
	if(!pff_){
		printf( "create file2FrameExecLoop failure!!!"  "\n");
	}

	
	
	

}


CFile2Frame::~CFile2Frame()
{
	isExit_ = true;
	if(pkt){
		av_packet_free(&pkt);

		if(nullptr != ic_){
			avformat_close_input(&ic_); ic_ = nullptr;
		}
	}
}


void CFile2Frame::file2FrameExecLoop(void){
	int ret = 0;
	
	frameCb_  = frameCallback;
	

	pkt = av_packet_alloc();
	printf(  "开始从%s文件中分离帧数据****"  "\n", strfileNamePath_.c_str());
	while(!isExit_){
		if(!ic_ || !initSucc){
			goto C;
		}
		ret = av_read_frame(ic_, pkt);
		if(0 != ret){
			std::cout << RED_START << "Read Frame End!" << COLOR_END << std::endl;;
			frameNo_ = 0;
			getchar();

			int ms = 3000;
			long long pos = ms / 1000.0 * r2d(ic_->streams[pkt->stream_index]->time_base);
			av_seek_frame(ic_, VideoStreamIndex_, pos, AVSEEK_FLAG_BACKWARD |AVSEEK_FLAG_FRAME);
			continue;
			
		}
		static int frameNo = 0;
		
	//	if(pkt->stream_index == VideoStreamIndex_ ){printf("[No.%06d]size:%d\n", ++frameNo, pkt->size);};

		if(pkt->size){

			frameCb_( (char *)pkt->data, pkt->size, nullptr);
		}
		
C:
		usleep(50*1000);
		av_packet_unref(pkt);		//引用计数减1,, 为0时释放空间

	}

	
}



//build {g++ file2Frame.cpp  -I include -I . -L ./lib -lavcodec -lavdevice -lavfilter -lavutil -lpostproc -lswscale -lavformat  -lswresample -lpthread}
int CFile2Frame::start()
{
	av_dict_set(&opts_, "rtsp_transport", "tcp", 0);
	av_dict_set(&opts_, "max_delay", "500", 0);
	
	int ret  = avformat_open_input(&ic_, strfileNamePath_.c_str(), nullptr, &opts_);
	if(0 != ret){
		char buf[1024]{0};
		av_strerror(ret, buf, sizeof(buf)-1);
		std::cout << "file open failed: " << buf << std::endl;
		return -1;
	}

	avformat_find_stream_info(ic_, nullptr);

	int nTime = ic_->duration / AV_TIME_BASE;
	std::cout << "total time : " << nTime << std::endl;

	av_dump_format(ic_, 0, nullptr, 0);

	
	for(unsigned int i = 0; i < ic_->nb_streams;++i){
		AVStream *stream = ic_->streams[i];
		//video
		if(stream->codecpar->codec_type == AVMediaType::AVMEDIA_TYPE_VIDEO){
			VideoStreamIndex_ = i;

			printf("[No.%d] {codecid:%d, w:%d,h:%d, format:%d}\n", i, stream->codecpar->codec_id,
							stream->codecpar->width, stream->codecpar->height, stream->codecpar->format);

			printf("fps:%d, size:%d\n", stream->avg_frame_rate, stream->codecpar->frame_size);

			printf("\n");
		}
		

	}

	VideoStreamIndex_ = av_find_best_stream(ic_, AVMediaType::AVMEDIA_TYPE_VIDEO, -1, -1, 0, 0); 
	initSucc = true;
}


void CFile2Frame::loop()
{
	while(!isExit_){
		usleep(100*1000);
	}
}
int main(int argc, char *argv[])
{
	auto pInv = std::make_shared("./blue.mp4");
	if(pInv){
		pInv->start();
	}

	pInv->loop();

	return 0;
}


编译

g++ file2Frame.cpp -I. -I include -L lib -lavcodec -lavdevice -lavfilter -lavformat -lavutil -lpostproc -lswresample -lswscale -lpthread

运行

开始从./blue.mp4文件中分离帧数据****
total time : 136
Input #0, mpeg, from '(null)':
  Duration: 00:02:16.76, start: 575.453000, bitrate: 3726 kb/s
    Stream #0:0[0x1e0]: Video: h264 (Main), yuv420p(progressive), 1920x1080, 90k tbr, 90k tbn
[No.0] {codecid:27, w:1920,h:1080, format:0}
fps:0, size:0

fn:000001 - frame_size:82093
fn:000002 - frame_size:22834
fn:000003 - frame_size:20793
fn:000004 - frame_size:19749
fn:000005 - frame_size:22469
fn:000006 - frame_size:18618
fn:000007 - frame_size:14481
fn:000008 - frame_size:18327
fn:000009 - frame_size:17599
fn:000010 - frame_size:17848
fn:000011 - frame_size:17835
fn:000012 - frame_size:18050
fn:000013 - frame_size:17740
fn:000014 - frame_size:17351
fn:000015 - frame_size:17392
fn:000016 - frame_size:17268
fn:000017 - frame_size:16904
fn:000018 - frame_size:16813
fn:000019 - frame_size:20473
fn:000020 - frame_size:17199
fn:000021 - frame_size:17412
fn:000022 - frame_size:17161
fn:000023 - frame_size:16997
fn:000024 - frame_size:16883
fn:000025 - frame_size:16717
fn:000026 - frame_size:16930
fn:000027 - frame_size:16866
fn:000028 - frame_size:16792
fn:000029 - frame_size:17012
fn:000030 - frame_size:20293
fn:000031 - frame_size:82470
fn:000032 - frame_size:22369
fn:000033 - frame_size:19886
fn:000034 - frame_size:19078
fn:000035 - frame_size:18911
fn:000036 - frame_size:18635

工具的简单使用

参数 说明
-h help
-t duration 设置处理时间,格式为hh:mm:ss
-ss position 设置起始时间,格式为hh:mm:ss
-b:v bitrate 设置视频码率
-b:a bitrate 设置音频码率
-r fps 设置帧率
-s wxh 设置帧大小,格式为WXH
-c:v codec 设置视频编码器
-c:a codec 设置音频编码器
-ar freq 设置音频采样率
  • MP4转MJPEG ./ffmpeg -i [你的mp4文件路径] -vf "fps=30" -q:v 9 out.mjpeg
  • 截取一段视频
ffmpeg -i blue.mp4 -ss 8 -t 3 -s 1280x720 -codec copy -f flv out.flv
-ss 开始时间:set the start time offset,单位秒,-t 持续时间 -s 分辨率。截取原视频中从第8秒开始,持续时间3秒的视频。输出分辨率1280x720
  • 解封装

ffmpeg -i blue.mp4 -codec copy -bsf: h264_mp4toannexb -f h264  out.264
-i blue.mp4:  是输入的MP4文件

-codec copy: 从mp4中拷贝

-bsf: h264_mp4toannexb: 从mp4拷贝到annexB封装

-f h264: 采用h264格式

out.264: 输出的文件

学习论坛

传送:https://superuser.com/questions/tagged/ffmpeg

你可能感兴趣的:(c/c++,ARM,ffmpeg)