使用 ffmpeg 库时,最好先理解好ffmpeg的代码结构图。
下面这张图表明了FFmpeg在解码一个视频的时候的函数调用流程,为了保证结构清晰,其中仅列出了最关键的函数,剔除了其它不是特别重要的函数。
FFMpeg 的 output_example.c 例子分析
该例子讲了如何输出一个 libavformat 库所支持格式的媒体文件。
(1)av_regis ter_all(),初始化 libavcodec 库,并注册所有的编解码器和格式。
(2)guess_form at(),根据文件名来获取输出文件格式,默认为 mpeg。
(3)av_alloc_form at_context()分配输出媒体内容。 ov->oform at = fm t; s nprintf( oc->filename, sizeof(oc->filename), “%s ”, filenam e );
(4)add_video_s tream ()使用默认格式的编解码器来增加一个视频流,并初始化编解码器。 (4.1)av_new_s tream ()增加一个新的流到一个媒体文件。
(4.2)初始化编解码器: c = s t->codec; c->codec_id = codec_id; c->codec_type = CODEC_TYPE_ VIDEO; c->bit_rate = 400000; c->width = 352; c->height = 288; c->tim e_base.den = STREAM_FR AME_RATE ; //每秒 25 副图像 c->tim e_base.num = 1; c->gop_size = 12; c->pix_fm t = STREAM_PIX_FMT; //默认格式为 P IX_FMT_ YUV420P …… ……
(5)av_s et_parameters ()设置输出参数,即使没有参数,该函数也必须被调用。
(6)dum p_form at()输出格式信息,用于调试。
(7)open_video()打开视频编解码器并分配必要的编码缓存。
(7.1)avcodec_find_encoder()寻找 c->codec_id 指定的视频编码器。
(7.2)avcodec_open()打开编码器。
(7.3)分配视频输出缓存: video_outbuf_s ize = 200000; video_outbuf = av_m alloc( video_outbuf_s ize );
(7.4)picture = alloc_picture()分配原始图像。
(7.4.1)avcodec_alloc_frame()分配一个 AVFram e 并设置默认值。
(7.4.2)s ize = avpicture_get_s ize()计算对于给定的图片格式以及宽和高,所需占用多少 内存。
(7.4.3)picture_buf = av_malloc( s ize )分配所需内存。
(7.4.4)avpicture_fill()填充 AVPicture 的域。
(7.5)可选。如果输出格式不是 YUV420P,那么临时的 YU V420P 格式的图像也是需要的,由 此再转换为 我们所需的格式,因此需要为临时的 YU V420P 图像分配缓存: tm p_picture = alloc_picture() 说明:tm p_picture,picture,video_outbuf。如果输出格式为 YUV420P,则直接通过 avcodec_ encode_video()函数将 picture 缓存中的原始图像编码保存到 video_outbuf 缓存中;如果输出格式不 是 YU V420P,则需要先通过 sws _s cale()函数,将 YUV420P 格式转换为目标格式,此时 tm p_picture 缓 存存放的是 YU V420P 格式的图像,而 picture 缓存为转换为目标格式后保存的图像,进而再将 picture 缓 存中的图像编码保存到 video_outbuf 缓存中。
(8)url_fopen()打开输出文件,如果需要的话。
(9)av_write_header()写流动头部。
(10)LOOP 循环{ 计算当前视频时间 video_pts 是否超时退出循环? write_video_fram e()视频编码 }
(10.1)write_video_frame() 如果图片不是 YU V420P,则需要用 sws _s cale()函数先进行格式转换。 若需要原始图像: av_init_packet()初始化一个包的选项域。 av_write_fram e()向输出媒体文件写一个包,该包会包含一个视频帧。 若需要编码图像: avcodec_encode_video()编码一视频帧。 av_init_packet() av_write_fram e()
(11)close_video()关闭每个编解码器。
(12)av_write_trailer()写流的尾部。
(13)释放资源 av_freep()释放 AVForm atContext 下的 AVS tream ->AVCodecContext 和 AVStream : for( i = 0; i < oc->nb_s treams ; i++ ){ av_freep( &oc->s treams [i]->codec ); av_freep( &oc->s treams [i] ); } url_fclose()关闭输出文件。 av_free()释放 AVForm atContext
原文:https://www.cnblogs.com/schips/p/12194267.html