2 * Copyright (c) 2012 Stefano Sabatini
3 * Copyright (c) 2014 Clément Bœsch
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 #include <libavutil/motion_vector.h>
25 #include <libavformat/avformat.h>
27 static AVFormatContext
*fmt_ctx
= NULL
;
28 static AVCodecContext
*video_dec_ctx
= NULL
;
29 static AVStream
*video_stream
= NULL
;
30 static const char *src_filename
= NULL
;
32 static int video_stream_idx
= -1;
33 static AVFrame
*frame
= NULL
;
35 static int video_frame_count
= 0;
37 static int decode_packet(int *got_frame
, int cached
)
39 int decoded
= pkt
.size
;
43 if (pkt
.stream_index
== video_stream_idx
) {
44 int ret
= avcodec_decode_video2(video_dec_ctx
, frame
, got_frame
, &pkt
);
46 fprintf(stderr
, "Error decoding video frame (%s)\n", av_err2str(ret
));
55 sd
= av_frame_get_side_data(frame
, AV_FRAME_DATA_MOTION_VECTORS
);
57 const AVMotionVector
*mvs
= (const AVMotionVector
*)sd
->data
;
58 for (i
= 0; i
< sd
->size
/ sizeof(*mvs
); i
++) {
59 const AVMotionVector
*mv
= &mvs
[i
];
60 printf("%d,%2d,%2d,%2d,%4d,%4d,%4d,%4d,0x%"PRIx64
"\n",
61 video_frame_count
, mv
->source
,
62 mv
->w
, mv
->h
, mv
->src_x
, mv
->src_y
,
63 mv
->dst_x
, mv
->dst_y
, mv
->flags
);
72 static int open_codec_context(int *stream_idx
,
73 AVFormatContext
*fmt_ctx
, enum AVMediaType type
)
77 AVCodecContext
*dec_ctx
= NULL
;
79 AVDictionary
*opts
= NULL
;
81 ret
= av_find_best_stream(fmt_ctx
, type
, -1, -1, NULL
, 0);
83 fprintf(stderr
, "Could not find %s stream in input file '%s'\n",
84 av_get_media_type_string(type
), src_filename
);
88 st
= fmt_ctx
->streams
[*stream_idx
];
90 /* find decoder for the stream */
92 dec
= avcodec_find_decoder(dec_ctx
->codec_id
);
94 fprintf(stderr
, "Failed to find %s codec\n",
95 av_get_media_type_string(type
));
96 return AVERROR(EINVAL
);
99 /* Init the video decoder */
100 av_dict_set(&opts
, "flags2", "+export_mvs", 0);
101 if ((ret
= avcodec_open2(dec_ctx
, dec
, &opts
)) < 0) {
102 fprintf(stderr
, "Failed to open %s codec\n",
103 av_get_media_type_string(type
));
111 int main(int argc
, char **argv
)
113 int ret
= 0, got_frame
;
116 fprintf(stderr
, "Usage: %s <video>\n", argv
[0]);
119 src_filename
= argv
[1];
123 if (avformat_open_input(&fmt_ctx
, src_filename
, NULL
, NULL
) < 0) {
124 fprintf(stderr
, "Could not open source file %s\n", src_filename
);
128 if (avformat_find_stream_info(fmt_ctx
, NULL
) < 0) {
129 fprintf(stderr
, "Could not find stream information\n");
133 if (open_codec_context(&video_stream_idx
, fmt_ctx
, AVMEDIA_TYPE_VIDEO
) >= 0) {
134 video_stream
= fmt_ctx
->streams
[video_stream_idx
];
135 video_dec_ctx
= video_stream
->codec
;
138 av_dump_format(fmt_ctx
, 0, src_filename
, 0);
141 fprintf(stderr
, "Could not find video stream in the input, aborting\n");
146 frame
= av_frame_alloc();
148 fprintf(stderr
, "Could not allocate frame\n");
149 ret
= AVERROR(ENOMEM
);
153 printf("framenum,source,blockw,blockh,srcx,srcy,dstx,dsty,flags\n");
155 /* initialize packet, set data to NULL, let the demuxer fill it */
156 av_init_packet(&pkt
);
160 /* read frames from the file */
161 while (av_read_frame(fmt_ctx
, &pkt
) >= 0) {
162 AVPacket orig_pkt
= pkt
;
164 ret
= decode_packet(&got_frame
, 0);
169 } while (pkt
.size
> 0);
170 av_free_packet(&orig_pkt
);
173 /* flush cached frames */
177 decode_packet(&got_frame
, 1);
181 avcodec_close(video_dec_ctx
);
182 avformat_close_input(&fmt_ctx
);
183 av_frame_free(&frame
);