2015-02-06 28 views
3

我试图通过ffmpeg(在C++中)获得mpeg视频的运动矢量。 我遇到的问题是,motion_val以及AVFrame类的motion_subsample_log2和mb_type保持为空和/或未初始化(调试器表示为0x0),似乎它们仅因兼容性原因而可用 我读过在ffmpeg wiki,您可以与如何在FFMPEG中填充/计算motion_val?

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

其结果是,该output.mp4具有运动矢量的箭头调试通过命令行的视频的运动矢量。所以,我搜索了在代码中-vismv参数,发现的libavcodec \选项无法选项一个长长的清单:

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

我想,这条线影响莫名其妙debug_mv AVCodecContext的。有了这个假设,我搜索了更多信息,并找到了一些我认为可能有所帮助的代码片段。

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年7月8日的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/13.101 55.
  • libavfilter 4. 10.100/10.100 4.
  • libswscale 2. 6.100/2 6.100
  • libswresample 0 19.100/19.100 0
  • libpostproc 52. 3.100/52. 3.100

更改为新的版本(2.5),但没有更改/解决问题。

+0

你可能会寻找'帧功能'av_frame_get_side_data()'。 c'和'vf_codecview.c'中与'filter_frame'函数相关的一些代码。 codecview过滤器更适合于这个目的,因为'vismv'已被弃用。我必须在某个时候更新wiki页面。 – slhck 2015-02-07 12:24:36

+0

同时检查'mpegvideo.c'中的'ff_print_debug_info2'。每张照片都应该有'motion_val'填充。 – slhck 2015-02-07 13:07:14

+0

非常感谢,你是对的。 'av_frame_get_side_data()'是有帮助的方法。同时你的'vf_codecview.c'和'filter_frame'提示帮助了我很多。 – MenuItem42 2015-02-10 07:02:10

回答

3

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

此外,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 
     } 
    }