/* * Copyright (c) 2012 Stefano Sabatini * Copyright (c) 2014 Clément Bœsch * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include static AVFormatContext *fmt_ctx = NULL; static AVCodecContext *video_dec_ctx = NULL; static AVStream *video_stream = NULL; static const char *src_filename = NULL; static int video_stream_idx = -1; static AVFrame *frame = NULL; static int video_frame_count = 0; static int decode_packet(const AVPacket *pkt) { int ret = avcodec_send_packet(video_dec_ctx, pkt); if (ret < 0) { fprintf(stderr, "Error while sending a packet to the decoder: %s\n", av_err2str(ret)); return ret; } while (ret >= 0) { ret = avcodec_receive_frame(video_dec_ctx, frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } else if (ret < 0) { fprintf(stderr, "Error while receiving a frame from the decoder: %s\n", av_err2str(ret)); return ret; } if (ret >= 0) { int i; AVFrameSideData *sd; video_frame_count++; sd = av_frame_get_side_data(frame, AV_FRAME_DATA_MOTION_VECTORS); if (sd) { const AVMotionVector *mvs = (const AVMotionVector *)sd->data; for (i = 0; i < sd->size / sizeof(*mvs); i++) { const AVMotionVector *mv = &mvs[i]; printf("%d,%2d,%2d,%2d,%4d,%4d,%4d,%4d,0x%"PRIx64"\n", video_frame_count, mv->source, mv->w, mv->h, mv->src_x, mv->src_y, mv->dst_x, mv->dst_y, mv->flags); } } av_frame_unref(frame); } } return 0; } static int open_codec_context(AVFormatContext *fmt_ctx, enum AVMediaType type) { int ret; AVStream *st; AVCodecContext *dec_ctx = NULL; const AVCodec *dec = NULL; AVDictionary *opts = NULL; ret = av_find_best_stream(fmt_ctx, type, -1, -1, &dec, 0); if (ret < 0) { fprintf(stderr, "Could not find %s stream in input file '%s'\n", av_get_media_type_string(type), src_filename); return ret; } else { int stream_idx = ret; st = fmt_ctx->streams[stream_idx]; dec_ctx = avcodec_alloc_context3(dec); if (!dec_ctx) { fprintf(stderr, "Failed to allocate codec\n"); return AVERROR(EINVAL); } ret = avcodec_parameters_to_context(dec_ctx, st->codecpar); if (ret < 0) { fprintf(stderr, "Failed to copy codec parameters to codec context\n"); return ret; } /* Init the video decoder */ av_dict_set(&opts, "flags2", "+export_mvs", 0); ret = avcodec_open2(dec_ctx, dec, &opts); av_dict_free(&opts); if (ret < 0) { fprintf(stderr, "Failed to open %s codec\n", av_get_media_type_string(type)); return ret; } video_stream_idx = stream_idx; video_stream = fmt_ctx->streams[video_stream_idx]; video_dec_ctx = dec_ctx; } return 0; } int main(int argc, char **argv) { int ret = 0; AVPacket *pkt = NULL; if (argc != 2) { fprintf(stderr, "Usage: %s