当前位置: 首页> 科技> 数码 > 【FFmpeg】avcodec_receive_frame函数

【FFmpeg】avcodec_receive_frame函数

时间:2025/9/17 17:06:46来源:https://blog.csdn.net/weixin_42877471/article/details/140179999 浏览次数:0次

目录

  • 1.avcodec_receive_frame
    • 1.1 返回解码帧(ff_decode_receive_frame)
    • 1.2 返回重建帧(ff_encode_receive_frame)
  • 2.小结

FFmpeg相关记录:

示例工程:
【FFmpeg】调用ffmpeg库实现264软编
【FFmpeg】调用ffmpeg库实现264软解
【FFmpeg】调用ffmpeg库进行RTMP推流和拉流
【FFmpeg】调用ffmpeg库进行SDL2解码后渲染

流程分析:
【FFmpeg】编码链路上主要函数的简单分析
【FFmpeg】解码链路上主要函数的简单分析

结构体分析:
【FFmpeg】AVCodec结构体
【FFmpeg】AVCodecContext结构体
【FFmpeg】AVStream结构体
【FFmpeg】AVFormatContext结构体
【FFmpeg】AVIOContext结构体
【FFmpeg】AVPacket结构体

函数分析:
【通用】
【FFmpeg】avcodec_find_encoder和avcodec_find_decoder
【FFmpeg】关键结构体的初始化和释放(AVFormatContext、AVIOContext等)
【FFmpeg】avcodec_open2函数
【FFmpeg】内存分配和释放(av_malloc、av_realloc等)

【推流】
【FFmpeg】avformat_open_input函数
【FFmpeg】avformat_find_stream_info函数
【FFmpeg】avformat_alloc_output_context2函数
【FFmpeg】avio_open2函数
【FFmpeg】avformat_write_header函数
【FFmpeg】av_write_frame函数

【编码】
【FFmpeg】avcodec_send_frame函数

【解码】
【FFmpeg】avcodec_send_packet函数

1.avcodec_receive_frame

函数的主要功能是从解码器或编码器返回解码后的输出数据(当使用AV_CODEC_FLAG_RECON_FRAME标志时)

/*** Return decoded output data from a decoder or encoder (when the* @ref AV_CODEC_FLAG_RECON_FRAME flag is used).** @param avctx codec context* @param frame This will be set to a reference-counted video or audio*              frame (depending on the decoder type) allocated by the*              codec. Note that the function will always call*              av_frame_unref(frame) before doing anything else.** @retval 0                success, a frame was returned* @retval AVERROR(EAGAIN)  output is not available in this state - user must*                          try to send new input* @retval AVERROR_EOF      the codec has been fully flushed, and there will be*                          no more output frames* @retval AVERROR(EINVAL)  codec not opened, or it is an encoder without the*                          @ref AV_CODEC_FLAG_RECON_FRAME flag enabled* @retval "other negative error code" legitimate decoding errors*/
int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)
{av_frame_unref(frame);// 1.如果是解码器,返回decoded frame(一般情况)if (av_codec_is_decoder(avctx->codec))return ff_decode_receive_frame(avctx, frame);// 2.如果是编码器,返回重建帧return ff_encode_receive_frame(avctx, frame);
}

1.1 返回解码帧(ff_decode_receive_frame)

函数的主要功能是返回解码的帧,定义位于libavcodec\avcodec.c中。如果代码需要从已编码的缓冲区中取出数据,会调用这个函数。这个函数的主要流程是检查缓冲区是否有数据,如果有则直接取出,否则尝试进行解码,随后会进行一些其他的检查和处理

/*** avcodec_receive_frame() implementation for decoders.*/
int ff_decode_receive_frame(AVCodecContext *avctx, AVFrame *frame)
{AVCodecInternal *avci = avctx->internal;int ret;if (!avcodec_is_open(avctx) || !av_codec_is_decoder(avctx->codec))return AVERROR(EINVAL);// 1.如果缓冲区有数据,则直接取出if (avci->buffer_frame->buf[0]) {av_frame_move_ref(frame, avci->buffer_frame);} else {// 2.如果缓冲区没有数据,尝试进行解码ret = decode_receive_frame_internal(avctx, frame);if (ret < 0)return ret;}// 3.确保返回给调用者的帧是有效的// 主要是检查frame的format, width, height这些信息ret = frame_validate(avctx, frame);if (ret < 0)goto fail;if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {// Video decode only// 4.某些视频编解码器支持裁剪,这意味着只有被解码帧的子矩形用于显示, 这个选项控制libavcodec如何处理裁剪ret = apply_cropping(avctx, frame);if (ret < 0)goto fail;}avctx->frame_num++;#if FF_API_DROPCHANGED// AV_CODEC_FLAG_DROPCHANGED表示不要输出与流中第一个解码帧参数不同的帧if (avctx->flags & AV_CODEC_FLAG_DROPCHANGED) {if (avctx->frame_num == 1) {avci->initial_format = frame->format;switch(avctx->codec_type) {case AVMEDIA_TYPE_VIDEO:avci->initial_width  = frame->width;avci->initial_height = frame->height;break;case AVMEDIA_TYPE_AUDIO:avci->initial_sample_rate = frame->sample_rate ? frame->sample_rate :avctx->sample_rate;ret = av_channel_layout_copy(&avci->initial_ch_layout, &frame->ch_layout);if (ret < 0)goto fail;break;}}if (avctx->frame_num > 1) {int changed = avci->initial_format != frame->format;switch(avctx->codec_type) {case AVMEDIA_TYPE_VIDEO:changed |= avci->initial_width  != frame->width ||avci->initial_height != frame->height;break;case AVMEDIA_TYPE_AUDIO:changed |= avci->initial_sample_rate    != frame->sample_rate ||avci->initial_sample_rate    != avctx->sample_rate ||av_channel_layout_compare(&avci->initial_ch_layout, &frame->ch_layout);break;}if (changed) {avci->changed_frames_dropped++;av_log(avctx, AV_LOG_INFO, "dropped changed frame #%"PRId64" pts %"PRId64" drop count: %d \n",avctx->frame_num, frame->pts,avci->changed_frames_dropped);ret = AVERROR_INPUT_CHANGED;goto fail;}}}
#endifreturn 0;
fail:av_frame_unref(frame);return ret;
}

1.2 返回重建帧(ff_encode_receive_frame)

如果不是decoder,会进入到下面函数,去调重建帧

/*** avcodec_receive_frame() implementation for encoders.*/
int ff_encode_receive_frame(AVCodecContext *avctx, AVFrame *frame)
{AVCodecInternal *avci = avctx->internal;// 不存在重建帧,报错if (!avci->recon_frame)return AVERROR(EINVAL);if (!avci->recon_frame->buf[0])return avci->draining_done ? AVERROR_EOF : AVERROR(EAGAIN);// 返回重建帧av_frame_move_ref(frame, avci->recon_frame);return 0;
}

2.小结

avcodec_receive_frame函数比较简单,可以概述为从已编码的缓冲区buffer中将frame取出,使用的函数是av_frame_move_ref,这个在其他文中记录过,不再记录

CSDN : https://blog.csdn.net/weixin_42877471
Github : https://github.com/DoFulangChen

关键字:【FFmpeg】avcodec_receive_frame函数

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: