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

本文详细解读了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()函数,完成了解码操作。

<think>我们正在处理一个关于torchvision视频解码的错误,具体错误信息是:"No such operator video_reader::probe_video_from_memory"。根据错误信息,这通常是由于torchvision版本与PyTorch版本不匹配,或者编译时没有包含对应的视频解码操作符。 根据引用[2],我们知道视频解码涉及AVStream、AVCodecContext和AVCodec等结构。torchvision的视频解码功能依赖于底层的FFmpeg库,并且通过C++扩展实现。错误信息中的`video_reader::probe_video_from_memory`是torchvision内部的一个操作符,用于从内存中探测视频信息。如果这个操作符不存在,可能是由于以下原因: 1. torchvision版本过低,该操作符是在较新的版本中引入的。 2. torchvision编译时没有启用视频功能。 3. PyTorch版本与torchvision版本不兼容。 解决方案: 1. 确保安装了正确版本的torchvision,并且与PyTorch版本兼容。可以查看torchvision官方文档的兼容性表格。 2. 如果从源代码编译torchvision,确保在编译时启用了视频支持(通常需要安装FFmpeg开发库)。 另外,引用[1]中提到了同样的错误,说明这是一个已知问题,通常通过升级或重新安装匹配的版本解决。 步骤: 1. 检查当前安装的torchvision和PyTorch版本。 2. 根据PyTorch版本安装对应版本的torchvision。例如,如果使用PyTorch 1.7.1,则安装torchvision 0.8.2。 3. 如果问题仍然存在,尝试从源代码重新安装torchvision,并确保安装过程中启用了视频支持。 具体操作: 首先,检查版本: ```bash pip list | grep torch ``` 然后,根据[官方兼容性表格](https://github.com/pytorch/vision#installation)安装匹配版本。例如: ```bash pip install torch==1.8.0 torchvision==0.9.0 ``` 如果从源码安装,步骤如下(以Linux为例): ```bash # 安装依赖(FFmpeg) sudo apt-get install -y libavcodec-dev libavformat-dev libswscale-dev # 克隆torchvision仓库 git clone https://github.com/pytorch/vision.git cd vision # 如果使用特定版本的torchvision,切换到对应tag git checkout v0.9.0 # 安装 python setup.py install ``` 注意:在Windows上,安装FFmpeg可能更复杂,可以考虑使用预编译的二进制包。 如果问题仍然存在,可能需要检查环境是否干净,或者尝试在虚拟环境中重新安装。 如果用户是在内存中探测视频(即使用`probe_video_from_memory`函数),那么需要确保torchvision版本在0.7.0以上(该函数在0.7.0版本引入)。如果用户使用的是旧版本,升级即可。 另外,引用[3]提到的是一个测试文件,可能与问题无关。 因此,我们建议用户首先尝试升级torchvision和PyTorch到兼容的版本。 相关问题: 1. 如何检查torchvision和PyTorch的版本兼容性? 2. 在Windows上如何安装支持视频解码的torchvision? 3. torchvision的视频解码功能支持哪些视频格式?</think>### 解决 torchvision 视频解码中的 `probe_video_from_memory` 属性错误 #### 错误原因分析 该错误表明您的 torchvision 版本缺少 `video_reader::probe_video_from_memory` 操作符实现,通常由以下原因导致: 1. **版本不兼容**:PyTorch 与 torchvision 版本不匹配(如 PyTorch 1.8+ 需对应 torchvision 0.9+) 2. **缺失视频编解码支持**:编译 torchvision 时未启用 FFmpeg 支持(底层依赖 FFmpegAVCodec、AVStream 等组件[^2]) 3. **内存探测限制**:旧版 torchvision 不支持直接从内存解码视频(需文件路径) #### 解决方案 ##### 方法1:升级版本(推荐) ```bash # 确保 PyTorch 和 torchvision 版本兼容 pip install torch==1.13.1 torchvision==0.14.1 -f https://download.pytorch.org/whl/cu117/torch_stable.html ``` * 验证兼容性:[官方版本对照表](https://pytorch.org/get-started/previous-versions/) ##### 方法2:源码编译(支持内存解码) 1. 安装 FFmpeg 开发库: ```bash # Ubuntu sudo apt install libavcodec-dev libavformat-dev libswscale-dev ``` 2. 从源码编译 torchvision: ```bash pip uninstall torchvision git clone https://github.com/pytorch/vision.git cd vision FORCE_CUDA=1 BUILD_VIDEO_DECODER=1 python setup.py install ``` ##### 方法3:改用文件路径输入(临时方案) ```python # 将视频数据写入临时文件 import tempfile with tempfile.NamedTemporaryFile(suffix=".mp4") as tmp: tmp.write(video_bytes) frames, audio, info = torchvision.io.read_video(tmp.name) ``` #### 验证修复 ```python import torchvision # 检查是否支持内存解码 print(hasattr(torchvision.io, "probe_video_from_memory")) # 应输出 True ``` #### 关键技术说明 1. torchvision 视频解码依赖 FFmpeg 的编解码器上下文(AVCodecContext)和流处理(AVStream)[^2] 2. `probe_video_from_memory` 是较新版本(≥0.8.0)加入的特性 3. 若需硬件加速解码,需确保系统安装 GPU 版 FFmpeg(如 NVIDIA Video Codec SDK)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值