diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2015-05-02 22:39:00 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2015-05-02 22:39:00 +0200 |
commit | f5b26fbc2f564831b337f1de9faaaf6753a03871 (patch) | |
tree | d6983d185fdc2a2df77795a739493c0569872e2c | |
parent | deedf3e590027e53cf999b11a25fc9be9615b5f2 (diff) | |
parent | 16302246b1fcb7ad4e6f7bd31c49956a455336d2 (diff) | |
download | ffmpeg-f5b26fbc2f564831b337f1de9faaaf6753a03871.tar.gz |
Merge commit '16302246b1fcb7ad4e6f7bd31c49956a455336d2'
* commit '16302246b1fcb7ad4e6f7bd31c49956a455336d2':
avconv: Add an option for automatically rotating video according to display matrix
Conflicts:
Changelog
ffmpeg_opt.c
Merged-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | Changelog | 1 | ||||
-rw-r--r-- | doc/ffmpeg.texi | 3 | ||||
-rw-r--r-- | ffmpeg.c | 2 | ||||
-rw-r--r-- | ffmpeg.h | 3 | ||||
-rw-r--r-- | ffmpeg_filter.c | 43 | ||||
-rw-r--r-- | ffmpeg_opt.c | 6 |
6 files changed, 58 insertions, 0 deletions
@@ -18,6 +18,7 @@ version <next>: - nvenc level and tier options - chorus filter - Canopus HQ/HQA decoder +- Automatically rotate videos based on metadata in ffmpeg version 2.6: diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index c66cb16d64..7cd81b080a 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -462,6 +462,9 @@ Technical note -- attachments are implemented as codec extradata, so this option can actually be used to extract extradata from any stream, not just attachments. +@item -noautorotate +Disable automatically rotating video based on file metadata. + @end table @section Video Options @@ -3647,6 +3647,8 @@ static int process_input(int file_index) if (av_packet_get_side_data(&pkt, src_sd->type, NULL)) continue; + if (ist->autorotate && src_sd->type == AV_PKT_DATA_DISPLAYMATRIX) + continue; dst_data = av_packet_new_side_data(&pkt, src_sd->type, src_sd->size); if (!dst_data) @@ -122,6 +122,8 @@ typedef struct OptionsContext { int nb_hwaccels; SpecifierOpt *hwaccel_devices; int nb_hwaccel_devices; + SpecifierOpt *autorotate; + int nb_autorotate; /* output options */ StreamMap *stream_maps; @@ -276,6 +278,7 @@ typedef struct InputStream { int top_field_first; int guess_layout_max; + int autorotate; int resample_height; int resample_width; int resample_pix_fmt; diff --git a/ffmpeg_filter.c b/ffmpeg_filter.c index 264840b2e9..6a891d3d10 100644 --- a/ffmpeg_filter.c +++ b/ffmpeg_filter.c @@ -31,6 +31,7 @@ #include "libavutil/avstring.h" #include "libavutil/bprint.h" #include "libavutil/channel_layout.h" +#include "libavutil/display.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavutil/pixfmt.h" @@ -339,6 +340,28 @@ static int insert_trim(int64_t start_time, int64_t duration, return 0; } +static int insert_filter(AVFilterContext **last_filter, int *pad_idx, + const char *filter_name, const char *args) +{ + AVFilterGraph *graph = (*last_filter)->graph; + AVFilterContext *ctx; + int ret; + + ret = avfilter_graph_create_filter(&ctx, + avfilter_get_by_name(filter_name), + filter_name, args, NULL, graph); + if (ret < 0) + return ret; + + ret = avfilter_link(*last_filter, *pad_idx, ctx, 0); + if (ret < 0) + return ret; + + *last_filter = ctx; + *pad_idx = 0; + return 0; +} + static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out) { char *pix_fmts; @@ -676,6 +699,26 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, return ret; last_filter = ifilter->filter; + if (ist->autorotate) { + uint8_t* displaymatrix = av_stream_get_side_data(ist->st, + AV_PKT_DATA_DISPLAYMATRIX, NULL); + if (displaymatrix) { + double rot = av_display_rotation_get((int32_t*) displaymatrix); + if (rot < -135 || rot > 135) { + ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL); + if (ret < 0) + return ret; + ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL); + } else if (rot < -45) { + ret = insert_filter(&last_filter, &pad_idx, "transpose", "dir=clock"); + } else if (rot > 45) { + ret = insert_filter(&last_filter, &pad_idx, "transpose", "dir=cclock"); + } + if (ret < 0) + return ret; + } + } + if (ist->framerate.num) { AVFilterContext *setpts; diff --git a/ffmpeg_opt.c b/ffmpeg_opt.c index 75c80e792e..f59b93bba6 100644 --- a/ffmpeg_opt.c +++ b/ffmpeg_opt.c @@ -602,6 +602,9 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) ist->ts_scale = 1.0; MATCH_PER_STREAM_OPT(ts_scale, dbl, ist->ts_scale, ic, st); + ist->autorotate = 1; + MATCH_PER_STREAM_OPT(autorotate, i, ist->autorotate, ic, st); + MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, ic, st); if (codec_tag) { uint32_t tag = strtol(codec_tag, &next, 0); @@ -3069,6 +3072,9 @@ const OptionDef options[] = { #if HAVE_VDPAU_X11 { "vdpau_api_ver", HAS_ARG | OPT_INT | OPT_EXPERT, { &vdpau_api_ver }, "" }, #endif + { "autorotate", HAS_ARG | OPT_BOOL | OPT_SPEC | + OPT_EXPERT | OPT_INPUT, { .off = OFFSET(autorotate) }, + "automatically insert correct rotate filters" }, /* audio options */ { "aframes", OPT_AUDIO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_audio_frames }, |