(1)多媒体文件里面其实是流的容器
(2)流有很多种比如,stream/track…但是各路流互不影响
(3)每种流是由不同的编码器编码的
(4)从流中解码出的数据称为包
(5)在一个包中包含着一个或者多个帧
(1)AVFormatContext 上下文,连接多个api的桥梁
(2)AVStream 通过AVStream可以获取各种包
(3)AVPacket 包中包含的就是数据帧
(1)【解复用】-【获取流】-【读取数据包】-【释放资源】
(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`
(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`