解码
ffmpeg3版本的解码接口做了调整,之前的视频解码接口avcodec_decode_video2
和音频解码接口avcodec_decode_audio4
被设置为deprecated,对这两个接口做了合并,使用同一的接口.并且将音视频解码步骤分成了两步,第一步avcodec_send_packet
,第二步avcodec_receive_frame
,
旧版本avcodec_decode_video2
旧版本avcodec_decode_audio4
1 | int got_picture; |
将AVPacket的pkt解码成AVFrame的pcm
新版本avcodec_send_packet
接口源码:
1 | /** |
参数分析
AVCodecContext *avctx
:第一个参数与旧的接口一致,是视频解码的上下文,包含解码器。const AVPacket *avpkt
: 编码的音视频帧数据
为什么要传递空的avpkt 这里有一个说明是可以传递NULL,什么情况下需要传递NULL,你平时看一些视频播放器,播放经常会少最后几帧,很多情况就是因为没有处理好缓冲帧的问题,ffmpeg内部会缓冲几帧,要想取出来就需要传递空的AVPacket进去。
新版本avcodec_receive_frame
接口源码
1 | /** |
参数分析
AVCodecContext *avctx
:第一个参数视频解码的上下文,与上面接口一致。AVFrame *frame
:解码后的视频帧数据。
空间申请和释放问题
解码后图像空间由函数内部申请,你所做的只需要分配 AVFrame 对象空间,如果你每次调用avcodec_receive_frame传递同一个对象,接口内部会判断空间是否已经分配,如果没有分配会在函数内部分配。 avcodec_send_packet和avcodec_receive_frame调用关系并不一定是一对一的,比如一些音频数据一个AVPacket中包含了1秒钟的音频,调用一次avcodec_send_packet之后,可能需要调用25次 avcodec_receive_frame才能获取全部的解码音频数据,所以要做如下处理:
1 | int re = avcodec_send_packet(codec, pkt); |