FFMpeg数据流处理 抽取音视频流

FFMpeg数据流处理

1.基本概念

(1)多媒体文件里面其实是流的容器
(2)流有很多种比如,stream/track…但是各路流互不影响
(3)每种流是由不同的编码器编码的
(4)从流中解码出的数据称为包
(5)在一个包中包含着一个或者多个帧

2.重要结构体

(1)AVFormatContext 上下文,连接多个api的桥梁
(2)AVStream 通过AVStream可以获取各种包
(3)AVPacket 包中包含的就是数据帧

3.操作流的基本步骤

(1)【解复用】-【获取流】-【读取数据包】-【释放资源】

4.(实战)FFMpeg打印音频的Meta信息

(1)API

av_register_all();
 AVFormatContext avformat_open_input();
 avformat_close_input(AVFormatContext  *);
 av_dump_format(); 
 av_err2str(ret);

(2)代码

void handleMedia(){
	AVFormatContext* fmt_ctx = NULL; 
	int ret;
	av_register_all();
	//打开多媒体文件
	ret = avformat_open_input(&fmt_ctx,
	"./test.mp4",
	/*输入文件格式,比如mp4*/NULL,
	/*通过命令行传入的参数,一般不用*/NULL);
	if(ret < 0){
		av_log(NULL,AV_LOG_ERROR,"Can't open file,%s\n",av_err2str(ret));
	}else{
		av_dump_format(fmt_ctx
			,/*s索引值,一般是0*/0
			,/*文件路径*/"./test.mp4"
			,/*输入刘0还是输出流1*/0);
		avformat_close_input(&fmt_ctx);
	}


}

( 3)编译

gcc ffmpeg_media_test.c -o media_test `pkg-config --libs --cflags libavutil libavformat`

5.抽取音频数据

(1)API

av_init_packet();
av_find_best_stream();//找到最好的一路流
av_read_frame();//读取流中的包,注意不是帧
av_packet_unref();//与上一个api联合使用

(3)代码

/*
gcc ffmpeg_media_test.c -o media_test `pkg-config --libs --cflags libavutil libavformat`
*/

#include 
#include 
#include 

void handleMedia(char* src_path,char* dst_path);
int extractAudio(AVFormatContext* fmt_ctx,char* dst_path);

int main(int argc,char* argv[])
{
	if(argc < 3){
		av_log(NULL,AV_LOG_ERROR,"less params\n");
		return -1;
	}

	//arg[0]表示当前函数名
    char* src_path = argv[1];
    char* dst_path = argv[2];
    if(!src_path || !dst_path){
    	av_log(NULL,AV_LOG_ERROR,"path is invalid\n");
    	return -1;
    }

	handleMedia(src_path,dst_path);
	return 0;
}


void handleMedia(char* src_path,char* dst_path){
	AVFormatContext* fmt_ctx = NULL; 
	int ret;
	av_register_all();
	//打开多媒体文件
	//1.读两个参数从控制台 
	ret = avformat_open_input(&fmt_ctx,
	src_path,
	/*输入文件格式,比如mp4*/NULL,
	/*通过命令行传入的参数,一般不用*/NULL);


	if(ret < 0){
		av_log(NULL,AV_LOG_ERROR,"Can't open file,%s\n",av_err2str(ret));
	}else{
		av_dump_format(fmt_ctx
			,/*s索引值,一般是0*/0
			,/*文件路径*/src_path
			,/*输入刘0还是输出流1*/0);



		//2.获取流
	    //3.抽取音频数据到一个新的文件
		extractAudio(fmt_ctx,dst_path);

		avformat_close_input(&fmt_ctx);

			

	}
}


/*提取音频到一个文件中*/
int extractAudio(AVFormatContext* fmt_ctx,char* dst_path){
	FILE* dst_file = fopen(dst_path,"wb");
	if(!dst_file){
	 	av_log(NULL,AV_LOG_ERROR,"output file create failed\n");
	 	return -1;
	}

	
	//正确返回索引值
	int	ret = av_find_best_stream(fmt_ctx,
			/*流的类型*/AVMEDIA_TYPE_AUDIO,
			/*流的索引号*/-1,
			/*流的索引号*/-1,
			/*编解码器*/NULL,
			/*FLAG*/0);

	if(ret < 0){
		av_log(NULL,AV_LOG_ERROR,"get av_find_best_stream failed,%s\n",av_err2str(ret));
	}else{
		int audio_index = ret;
		AVPacket pkt;
		av_init_packet(&pkt);
		int length ;
		while(av_read_frame(fmt_ctx,&pkt) >= 0){
			if(pkt.stream_index == audio_index){
				fwrite(pkt.data,1,pkt.size,dst_file);
				if(length!=pkt.size){
					av_log(NULL,AV_LOG_WARNING,"size not equal pkt.size\n");
				}
			}
			av_packet_unref(&pkt);
		}

		if(dst_file){
			fclose(dst_file);
		}
		return 0;
	}


	return -1;
}

编译

gcc ffmpeg_media_test.c -o media_test `pkg-config --libs --cflags libavutil libavformat libavcodec`

你可能感兴趣的:(ffmpeg)