参考博客:https://blog.csdn.net/leixiaohua1020/article/details/12679719


int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,int *got_picture_ptr,const AVPacket *avpkt)
{//调用compat_decode函数return compat_decode(avctx, picture, got_picture_ptr, avpkt);
}//===============================================static int compat_decode(AVCodecContext *avctx, AVFrame *frame,int *got_frame, const AVPacket *pkt)
{AVCodecInternal *avci = avctx->internal;int ret = 0;av_assert0(avci->compat_decode_consumed == 0);if (avci->draining_done && pkt && pkt->size != 0) {av_log(avctx, AV_LOG_WARNING, "Got unexpected packet after EOF\n");avcodec_flush_buffers(avctx);}*got_frame = 0;if (avci->compat_decode_partial_size > 0 &&avci->compat_decode_partial_size != pkt->size) {av_log(avctx, AV_LOG_ERROR,"Got unexpected packet size after a partial decode\n");ret = AVERROR(EINVAL);goto finish;}//调用函数 avcodec_send_packet函数if (!avci->compat_decode_partial_size) {ret = avcodec_send_packet(avctx, pkt);if (ret == AVERROR_EOF)ret = 0;else if (ret == AVERROR(EAGAIN)) {/* we fully drain all the output in each decode call, so this should not* ever happen */ret = AVERROR_BUG;goto finish;} else if (ret < 0)goto finish;}while (ret >= 0) {//循环调用avcodec_receive_frame函数ret = avcodec_receive_frame(avctx, frame);if (ret < 0) {if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)ret = 0;goto finish;}if (frame != avci->compat_decode_frame) {if (!avctx->refcounted_frames) {ret = unrefcount_frame(avci, frame);if (ret < 0)goto finish;}*got_frame = 1;frame = avci->compat_decode_frame;} else {if (!avci->compat_decode_warned) {av_log(avctx, AV_LOG_WARNING, "The deprecated avcodec_decode_* ""API cannot return all the frames for this decoder. ""Some frames will be dropped. Update your code to the ""new decoding API to fix this.\n");avci->compat_decode_warned = 1;}}if (avci->draining || (!avctx->codec->bsfs && avci->compat_decode_consumed < pkt->size))break;}finish:if (ret == 0) {/* if there are any bsfs then assume full packet is always consumed */if (avctx->codec->bsfs)ret = pkt->size;elseret = FFMIN(avci->compat_decode_consumed, pkt->size);}avci->compat_decode_consumed = 0;avci->compat_decode_partial_size = (ret >= 0) ? pkt->size - ret : 0;return ret;
}
//===========================================================int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt)
{AVCodecInternal *avci = avctx->internal;int ret;if (!avcodec_is_open(avctx) || !av_codec_is_decoder(avctx->codec))return AVERROR(EINVAL);if (avctx->internal->draining)return AVERROR_EOF;if (avpkt && !avpkt->size && avpkt->data)return AVERROR(EINVAL);av_packet_unref(avci->buffer_pkt);if (avpkt && (avpkt->data || avpkt->side_data_elems)) {ret = av_packet_ref(avci->buffer_pkt, avpkt);if (ret < 0)return ret;}ret = av_bsf_send_packet(avci->bsf, avci->buffer_pkt);if (ret < 0) {av_packet_unref(avci->buffer_pkt);return ret;}if (!avci->buffer_frame->buf[0]) {ret = decode_receive_frame_internal(avctx, avci->buffer_frame);if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)return ret;}return 0;
}//============================================================int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)
{AVCodecInternal *avci = avctx->internal;int ret, changed;av_frame_unref(frame);if (!avcodec_is_open(avctx) || !av_codec_is_decoder(avctx->codec))return AVERROR(EINVAL);if (avci->buffer_frame->buf[0]) {av_frame_move_ref(frame, avci->buffer_frame);} else {ret = decode_receive_frame_internal(avctx, frame);if (ret < 0)return ret;}//检查视频类型if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {ret = apply_cropping(avctx, frame);if (ret < 0) {av_frame_unref(frame);return ret;}}//帧数++avctx->frame_number++;if (avctx->flags & AV_CODEC_FLAG_DROPCHANGED) {//如果number=1if (avctx->frame_number == 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;avci->initial_channels       = frame->channels;avci->initial_channel_layout = frame->channel_layout;break;}}//如果number > 1,则if (avctx->frame_number > 1) {//初始化格式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 ||avci->initial_channels       != frame->channels ||avci->initial_channel_layout != frame->channel_layout;break;}if (changed) {//变化?丢弃avci->changed_frames_dropped++;av_log(avctx, AV_LOG_INFO, "dropped changed frame #%d pts %"PRId64" drop count: %d \n",avctx->frame_number, frame->pts,avci->changed_frames_dropped);av_frame_unref(frame);return AVERROR_INPUT_CHANGED;}}}return 0;
}//==============================================================static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame)
{AVCodecInternal *avci = avctx->internal;int ret;av_assert0(!frame->buf[0]);if (avctx->codec->receive_frame) {ret = avctx->codec->receive_frame(avctx, frame);if (ret != AVERROR(EAGAIN))av_packet_unref(avci->last_pkt_props);} elseret = decode_simple_receive_frame(avctx, frame);if (ret == AVERROR_EOF)avci->draining_done = 1;if (!ret) {frame->best_effort_timestamp = guess_correct_pts(avctx,frame->pts,frame->pkt_dts);/* the only case where decode data is not set should be decoders* that do not call ff_get_buffer() */av_assert0((frame->private_ref && frame->private_ref->size == sizeof(FrameDecodeData)) ||!(avctx->codec->capabilities & AV_CODEC_CAP_DR1));if (frame->private_ref) {FrameDecodeData *fdd = (FrameDecodeData*)frame->private_ref->data;if (fdd->post_process) {ret = fdd->post_process(avctx, frame);if (ret < 0) {av_frame_unref(frame);return ret;}}}}/* free the per-frame decode data */av_buffer_unref(&frame->private_ref);return ret;
}

ffmpeg 源代码简单学习 : avcodec_decode_video2()相关推荐

  1. FFmpeg源代码简单学习:avformat_find_stream_info()

    参考博客:https://blog.csdn.net/leixiaohua1020/article/details/44084321 int avformat_find_stream_info(AVF ...

  2. ffmpeg 源代码简单分析 : avcodec_decode_video2()

    2019独角兽企业重金招聘Python工程师标准>>> 此前写了好几篇ffmpeg源代码分析文章,列表如下: 图解FFMPEG打开媒体的函数avformat_open_input f ...

  3. FFmpeg源代码简单分析:libavdevice的gdigrab

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  4. FFmpeg源代码简单分析:libavdevice的avdevice_register_all()

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  5. FFmpeg源代码简单分析:configure

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  6. FFmpeg源代码简单分析:makefile

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  7. FFmpeg源代码简单分析:libswscale的sws_getContext()

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  8. FFmpeg源代码简单分析:结构体成员管理系统-AVOption

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  9. FFmpeg源代码简单分析:结构体成员管理系统-AVClass

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

最新文章

  1. 设计模式之享元模式学习笔记
  2. 计算机专插本专业考哪些科目,2020年广东专插本要考什么?专插本考试科目有哪些?...
  3. SSH服务理论+实践
  4. 罗泾数据中心顺利投产 中国太保科技建设正式步入“两地三中心”时代
  5. 利用BBRSACryptor实现iOS端的RSA加解密
  6. python里元组和列表的共同点和不同点_Python_列表,元组和字典的异同
  7. 使用 ADO.NET 和 Oracle 进行高级数据访问
  8. ceph集群报错:HEALTH_ERR 1 pgs inconsistent; 1 scrub errors
  9. mysql 所有外键_mysql中的外键
  10. HighCharts:饼图判断是否选中
  11. 树莓派迅雷远程下载服务搭建
  12. 如何使用xposed强制开启android webview debug模式
  13. 安装Ubuntu VMware Workstation 不可恢复错误
  14. 2022年科技期刊最新影响因子在线查询
  15. 危险进程集粹(附说明)
  16. 1926163-51-0|肽基脯氨酰异构酶底物:WFY(p)SPR-7-氨基-4-甲基香豆素
  17. 基于3D CNN的深度学习卫星图像土地覆盖分类
  18. python_faker使用
  19. android源码编译失败,编译android源码遇到错误及其解决方法
  20. 开发者来稿|AMD赛灵思中文论坛分享 - 提问的智慧

热门文章

  1. js对象深拷贝(深克隆)
  2. 测试OpenSIPS3.2的uac_registrant模块
  3. 【常见问题汇总--持续更新】Keystone常见问题
  4. 《学习如何学习》Week 4 1.5 Change your thoughts, change your life改变你的思维,改变你的人生
  5. 三棱柱以及多棱柱的实现
  6. sendto和recvfrom
  7. 【踩坑】mirai挂机运行经常自动退出怎么办?
  8. pagehelper+sqlserver 不支持该sql转换为分页查询
  9. 查看gym中的内置游戏环境
  10. 医学计算机应用基础项目五思维导图,【羊五小•项目学习】“一千零一夜+思维导图”学习成果发布会(五年级)...