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

此前写了好几篇ffmpeg源代码分析文章,列表如下:

图解FFMPEG打开媒体的函数avformat_open_input
ffmpeg 源代码简单分析 : av_register_all()
ffmpeg 源代码简单分析 : avcodec_register_all()
ffmpeg 源代码简单分析 : av_read_frame()
ffmpeg 源代码简单分析 : avcodec_decode_video2()

============================


ffmpeg中的avcodec_decode_video2()的作用是解码一帧视频数据。输入一个压缩编码的结构体AVPacket,输出一个解码后的结构体AVFrame。


查看源代码之后发现,这个函数竟然十分的简单,源代码如下:

[cpp]  view plain copy
  1. int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,  
  2.                          int *got_picture_ptr,  
  3.                          const AVPacket *avpkt)  
  4. {  
  5.     int ret;  
  6.     // copy to ensure we do not change avpkt  
  7.     AVPacket tmp = *avpkt;  
  8.   
  9.     *got_picture_ptr= 0;  
  10.     if((avctx->coded_width||avctx->coded_height) && av_image_check_size(avctx->coded_width, avctx->coded_height, 0, avctx))  
  11.         return -1;  
  12.   
  13.     if((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size || (avctx->active_thread_type&FF_THREAD_FRAME)){  
  14.         int did_split = av_packet_split_side_data(&tmp);  
  15.         apply_param_change(avctx, &tmp);  
  16.         avctx->pkt = &tmp;  
  17.         if (HAVE_THREADS && avctx->active_thread_type&FF_THREAD_FRAME)  
  18.              ret = ff_thread_decode_frame(avctx, picture, got_picture_ptr,  
  19.                                           &tmp);  
  20.         else {  
  21.             ret = avctx->codec->decode(avctx, picture, got_picture_ptr,  
  22.                               &tmp);  
  23.             picture->pkt_dts= avpkt->dts;  
  24.   
  25.             if(!avctx->has_b_frames){  
  26.             picture->pkt_pos= avpkt->pos;  
  27.             }  
  28.             //FIXME these should be under if(!avctx->has_b_frames)  
  29.             if (!picture->sample_aspect_ratio.num)  
  30.                 picture->sample_aspect_ratio = avctx->sample_aspect_ratio;  
  31.             if (!picture->width)  
  32.                 picture->width = avctx->width;  
  33.             if (!picture->height)  
  34.                 picture->height = avctx->height;  
  35.             if (picture->format == PIX_FMT_NONE)  
  36.                 picture->format = avctx->pix_fmt;  
  37.         }  
  38.   
  39.         emms_c(); //needed to avoid an emms_c() call before every return;  
  40.   
  41.         avctx->pkt = NULL;  
  42.         if (did_split)  
  43.             ff_packet_free_side_data(&tmp);  
  44.   
  45.         if (*got_picture_ptr){  
  46.             avctx->frame_number++;  
  47.             picture->best_effort_timestamp = guess_correct_pts(avctx,  
  48.                                                             picture->pkt_pts,  
  49.                                                             picture->pkt_dts);  
  50.         }  
  51.     }else  
  52.         ret= 0;  
  53.   
  54.     return ret;  
  55. }  

从代码中可以看出,通过ret = avctx->codec->decode(avctx, picture, got_picture_ptr,&tmp)这句代码,调用了相应解码器的decode()函数,完成了解码操作。

// 类成员变量声明 class Decode_AVS { private: AVCodecContext* codec_ctx = nullptr; // 解码器上下文 AVFrame* frame = nullptr; // 解码后帧容器 AVPacket* pkt = nullptr; // 数据包容器 }; // 初始化函数(在构造函数或单独方法中) bool Decode_AVS::initDecoder() { const AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_CAVS); if (!codec) return false; codec_ctx = avcodec_alloc_context3(codec); if (!codec_ctx) return false; if (avcodec_open2(codec_ctx, codec, nullptr) < 0) { avcodec_free_context(&codec_ctx); return false; } frame = av_frame_alloc(); pkt = av_packet_alloc(); return true; } // 数据接收处理函数 void Decode_AVS::onDataReady(const QByteArray &data) { // 将QByteArray转换为AVPacket pkt->data = reinterpret_cast<uint8_t*>(data.data()); pkt->size = data.size(); // 发送数据到解码器 int ret = avcodec_send_packet(codec_ctx, pkt); if (ret < 0) { qWarning() << "发送解码包失败:" << av_err2str(ret); return; } // 循环获取解码帧 while (ret >= 0) { ret = avcodec_receive_frame(codec_ctx, frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } else if (ret < 0) { qWarning() << "解码错误:" << av_err2str(ret); break; } // 处理解码后的帧数据(示例:输出分辨率信息) qDebug() << "解码成功!分辨率:" << frame->width << "x" << frame->height << " 格式:" << av_get_pix_fmt_name((AVPixelFormat)frame->format); // 此处可添加帧处理逻辑(如渲染、存储等) processFrame(frame); av_frame_unref(frame); // 释放帧引用 } } // 资源释放(在析构函数中) Decode_AVS::~Decode_AVS() { if (codec_ctx) avcodec_free_context(&codec_ctx); if (frame) av_frame_free(&frame); if (pkt) av_packet_free(&pkt); } 请把添加帧处理逻辑的代码补充完整,例如我要在qt页面上显示视频
最新发布
03-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值