diff --git a/.gitignore b/.gitignore index cb370bb9c5..480fbe0171 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,7 @@ /doc/examples/avio_reading /doc/examples/decoding_encoding /doc/examples/demuxing_decoding +/doc/examples/extract_mvs /doc/examples/filter_audio /doc/examples/filtering_audio /doc/examples/filtering_video diff --git a/configure b/configure index 1224362e77..f355dad1d7 100755 --- a/configure +++ b/configure @@ -1305,6 +1305,7 @@ EXAMPLE_LIST=" avio_reading_example decoding_encoding_example demuxing_decoding_example + extract_mvs_example filter_audio_example filtering_audio_example filtering_video_example @@ -2586,6 +2587,7 @@ zoompan_filter_deps="swscale" avio_reading="avformat avcodec avutil" avcodec_example_deps="avcodec avutil" demuxing_decoding_example_deps="avcodec avformat avutil" +extract_mvs_example_deps="avcodec avformat avutil" filter_audio_example_deps="avfilter avutil" filtering_audio_example_deps="avfilter avcodec avformat avutil" filtering_video_example_deps="avfilter avcodec avformat avutil" diff --git a/doc/APIchanges b/doc/APIchanges index 8b3051c255..1bed10778d 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2014-08-09 API changes, most recent first: +2014-08-xx - xxxxxxx - lavu 54.5.100 - frame.h motion_vector.h + Add AV_FRAME_DATA_MOTION_VECTORS side data and AVMotionVector structure + 2014-08-16 - xxxxxxx - lswr 1.1.100 - swresample.h Add AVFrame based API diff --git a/doc/Makefile b/doc/Makefile index 99f588ac05..2fb9058e6a 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -39,6 +39,7 @@ DOCS = $(DOCS-yes) DOC_EXAMPLES-$(CONFIG_AVIO_READING_EXAMPLE) += avio_reading DOC_EXAMPLES-$(CONFIG_AVCODEC_EXAMPLE) += avcodec DOC_EXAMPLES-$(CONFIG_DEMUXING_DECODING_EXAMPLE) += demuxing_decoding +DOC_EXAMPLES-$(CONFIG_EXTRACT_MVS_EXAMPLE) += extract_mvs DOC_EXAMPLES-$(CONFIG_FILTER_AUDIO_EXAMPLE) += filter_audio DOC_EXAMPLES-$(CONFIG_FILTERING_AUDIO_EXAMPLE) += filtering_audio DOC_EXAMPLES-$(CONFIG_FILTERING_VIDEO_EXAMPLE) += filtering_video diff --git a/doc/codecs.texi b/doc/codecs.texi index 1160e5d800..820dce51e6 100644 --- a/doc/codecs.texi +++ b/doc/codecs.texi @@ -797,6 +797,9 @@ Frame data might be split into multiple chunks. Show all frames before the first keyframe. @item skiprd Deprecated, use mpegvideo private options instead. +@item export_mvs +Export motion vectors into frame side-data (see @code{AV_FRAME_DATA_MOTION_VECTORS}) +for codecs that support it. See also @file{doc/examples/export_mvs.c}. @end table @item error @var{integer} (@emph{encoding,video}) diff --git a/doc/examples/Makefile b/doc/examples/Makefile index 03c7021e8b..07251fe3c2 100644 --- a/doc/examples/Makefile +++ b/doc/examples/Makefile @@ -14,6 +14,7 @@ LDLIBS := $(shell pkg-config --libs $(FFMPEG_LIBS)) $(LDLIBS) EXAMPLES= avio_reading \ decoding_encoding \ demuxing_decoding \ + extract_mvs \ filtering_video \ filtering_audio \ metadata \ diff --git a/doc/examples/extract_mvs.c b/doc/examples/extract_mvs.c new file mode 100644 index 0000000000..d6fd61335e --- /dev/null +++ b/doc/examples/extract_mvs.c @@ -0,0 +1,185 @@ +/* + * 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 + +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 AVPacket pkt; +static int video_frame_count = 0; + +static int decode_packet(int *got_frame, int cached) +{ + int decoded = pkt.size; + + *got_frame = 0; + + if (pkt.stream_index == video_stream_idx) { + int ret = avcodec_decode_video2(video_dec_ctx, frame, got_frame, &pkt); + if (ret < 0) { + fprintf(stderr, "Error decoding video frame (%s)\n", av_err2str(ret)); + return ret; + } + + if (*got_frame) { + 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); + } + } + } + } + + return decoded; +} + +static int open_codec_context(int *stream_idx, + AVFormatContext *fmt_ctx, enum AVMediaType type) +{ + int ret; + AVStream *st; + AVCodecContext *dec_ctx = NULL; + AVCodec *dec = NULL; + AVDictionary *opts = NULL; + + ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 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 { + *stream_idx = ret; + st = fmt_ctx->streams[*stream_idx]; + + /* find decoder for the stream */ + dec_ctx = st->codec; + dec = avcodec_find_decoder(dec_ctx->codec_id); + if (!dec) { + fprintf(stderr, "Failed to find %s codec\n", + av_get_media_type_string(type)); + return AVERROR(EINVAL); + } + + /* Init the video decoder */ + av_dict_set(&opts, "flags2", "+export_mvs", 0); + if ((ret = avcodec_open2(dec_ctx, dec, &opts)) < 0) { + fprintf(stderr, "Failed to open %s codec\n", + av_get_media_type_string(type)); + return ret; + } + } + + return 0; +} + +int main(int argc, char **argv) +{ + int ret = 0, got_frame; + + if (argc != 2) { + fprintf(stderr, "Usage: %s