3

I'm trying to get motion vectors of a mpeg video via ffmpeg (in c++). The problem that I have is, that motion_val along with motion_subsample_log2 and mb_type of the AVFrame class remain empty and/or aren’t initialized (debugger says 0x0) and it seems that they are only available because of compatibility reasons I’ve read in the ffmpeg wiki, that you can debug the motion vectors of the video via command line with

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

The result is that the output.mp4 has motion vector arrows. So I searched for the –vismv parameter in the code and found in libavcodec\options.c a long list of options:

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

I suppose that this line affects somehow debug_mv of AVCodecContext. With this assumption I searched for further information and I found some code snippets which I thought might help.

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

and

pAVCodecContext->debug |= FF_DEBUG_MV;    

But both didn’t trigger the calculation or filling of the motion_val array. By the way my code is based on the code by Victor Hsieh and Jiasi Chen and this code is basically the ffmpeg sourcecode (libavcodec\mpegvideo.c). I also tried to find (also with help of the documentation) the piece of code that triggers the calculation, but because of the complexity of the code I didn’t get any results. The question is now, if is there any possibility to fill this variables or start the calculation of the motion vector table or is there any other alternative way to get the motion vectors of every block of the mpeg-frames.

Edit:

I forgot to mention my ffmpeg version

Zeranoe's FFmpeg version: 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

Changed to a newer version (2.5), but it didn't change/solve the problem.

MenuItem42
  • 143
  • 2
  • 11
  • 1
    You might be looking for the function `av_frame_get_side_data()` in `frame.c` and some of the code in `vf_codecview.c` related to the function `filter_frame`. The codecview filter is better suited for this purpose as `vismv` is deprecated. I have to update the wiki page at some point. – slhck Feb 07 '15 at 12:24
  • 1
    Also check `ff_print_debug_info2` in `mpegvideo.c`. There should be `motion_val` filled for every picture. – slhck Feb 07 '15 at 13:07
  • Thanks a lot, you were right. `av_frame_get_side_data()` was the method that helped. Also your hint with `vf_codecview.c` and `filter_frame` helped me a lot. – MenuItem42 Feb 10 '15 at 07:02
  • Great, I posted an official answer :) Feel free to edit it with the exact code you were using. – slhck Feb 10 '15 at 07:17

1 Answers1

5

The motion vectors are available in the function av_frame_get_side_data() in the file frame.c.

Also, the vf_codecview.c file defines the filter that draws motion vectors—see the function filter_frame().

For example, if you have an AVFrame, you can do:

AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_MOTION_VECTORS);

and from there:

 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
        }
    }
slhck
  • 36,575
  • 28
  • 148
  • 201