如何在 FFMPEG 中填充/计算motion_val?

Posted

技术标签:

【中文标题】如何在 FFMPEG 中填充/计算motion_val?【英文标题】:How to fill/calculate motion_val in FFMPEG? 【发布时间】:2015-02-06 11:18:58 【问题描述】:

我正在尝试通过 ffmpeg(在 C++ 中)获取 mpeg 视频的运动矢量。 我遇到的问题是,motion_val 以及 AVFrame 类的 motion_subsample_log2 和 mb_type 保持为空和/或未初始化(调试器说 0x0)并且似乎它们仅由于兼容性原因才可用 我在ffmpeg wiki 中读到,您可以通过命令行调试视频的运动矢量

ffmpeg -vismv pf -i input.mp4 output.mp4

结果是 output.mp4 有运动矢量箭头。于是我在代码中搜索了–vismv参数,在libavcodec\options.c中发现了一长串选项:

"vismv", "visualize motion vectors (MVs)", OFFSET(debug_mv), FF_OPT_TYPE_INT, DEFAULT, 0, INT_MAX, V|D, "debug_mv",   

我想这条线会以某种方式影响 AVCodecContext 的 debug_mv。有了这个假设,我搜索了更多信息,发现了一些我认为可能有帮助的代码 sn-ps。

pAVCodecContext->debug_mv =  FF_DEBUG_VIS_MV_P_FOR | FF_DEBUG_VIS_MV_B_FOR | FF_DEBUG_MB_TYPE | FF_DEBUG_MV;

pAVCodecContext->debug |= FF_DEBUG_MV;    

但两者都没有触发motion_val数组的计算或填充。 顺便说一句,我的代码基于the code by Victor Hsieh and Jiasi Chen,而这段代码基本上是 ffmpeg 源代码 (libavcodec\mpegvideo.c)。我还尝试(也借助文档)找到触发计算的代码段,但由于代码的复杂性,我没有得到任何结果。 现在的问题是,是否有可能填充这些变量或开始计算运动矢量表,或者是否有任何其他替代方法来获取 mpeg 帧的每个块的运动矢量。

编辑:

我忘了说我的ffmpeg版本

Zeranoe 的 FFmpeg 版本:2014-07-08 git-14e2406

libavutil 52. 91.100 / 52. 91.100 libavcodec 55. 68.102 / 55. 68.102 libavformat 55. 45.100 / 55. 45.100 libavdevice 55. 13.101 / 55. 13.101 libavfilter 4.10.100 / 4.10.100 libswscale 2. 6.100 / 2. 6.100 libswresample 0. 19.100 / 0. 19.100 libpostproc 52. 3.100 / 52. 3.100

已更改为较新的版本 (2.5),但并未更改/解决问题。

【问题讨论】:

您可能正在寻找frame.c 中的函数av_frame_get_side_data() 以及vf_codecview.c 中与函数filter_frame 相关的一些代码。 codecview 过滤器更适合此目的,因为不推荐使用 vismv。我必须在某个时候更新 wiki 页面。 同时在mpegvideo.c 中检查ff_print_debug_info2。每张图片都应该填写motion_val 非常感谢,您是对的。 av_frame_get_side_data() 是有帮助的方法。您对vf_codecview.cfilter_frame 的提示也帮助了我很多。 太好了,我发布了官方答案 :) 随意使用您使用的确切代码对其进行编辑。 【参考方案1】:

运动矢量在文件frame.c中的函数av_frame_get_side_data()中可用。

此外,vf_codecview.c 文件定义了绘制运动矢量的过滤器 - 请参阅函数 filter_frame()

例如,如果你有一个AVFrame,你可以这样做:

AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_MOTION_VECTORS);

从那里开始:

 if (sd) 
        int i;
        const AVMotionVector *mvs = (const AVMotionVector *)sd->data;
        for (i = 0; i < sd->size / sizeof(*mvs); i++) 
            const AVMotionVector *mv = &mvs[i];
            const int direction = mv->source > 0;
             // do something with motion vector
        
    

【讨论】:

以上是关于如何在 FFMPEG 中填充/计算motion_val?的主要内容,如果未能解决你的问题,请参考以下文章

ffmpeg基本用法

黄聪:ffmpeg基本用法(转)

如何从 FFMPEG 生成 SDP 文件

ffmpeg填充翻动旋转视频的基础知识

如何在 Mac 上同时安装 ffmpeg 和应用程序?

使用 ffmpeg 创建 png 缩略图会给出错误消息“错误填充图片”