From 16302246b1fcb7ad4e6f7bd31c49956a455336d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 29 Apr 2015 17:59:01 +0300 Subject: [PATCH] avconv: Add an option for automatically rotating video according to display matrix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The option is enabled by default, but can be disabled. If this is enabled, such side data isn't copied into the output stream (except when doing stream copy). Signed-off-by: Martin Storsjö --- Changelog | 1 + avconv.c | 2 ++ avconv.h | 3 +++ avconv_filter.c | 43 +++++++++++++++++++++++++++++++++++++++++++ avconv_opt.c | 6 ++++++ doc/avconv.texi | 3 +++ 6 files changed, 58 insertions(+) diff --git a/Changelog b/Changelog index c3ea67c6e4..2fd1583c6e 100644 --- a/Changelog +++ b/Changelog @@ -28,6 +28,7 @@ version : - MMAL-accelerated H.264 decoding - DTS decoding through libdcadec - Canopus HQ/HQA decoder +- Automatically rotate videos based on metadata in avconv version 11: diff --git a/avconv.c b/avconv.c index 1ad6e5e5de..275c3eb268 100644 --- a/avconv.c +++ b/avconv.c @@ -2433,6 +2433,8 @@ static int process_input(void) 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) diff --git a/avconv.h b/avconv.h index b932d7e8db..5fddf98127 100644 --- a/avconv.h +++ b/avconv.h @@ -113,6 +113,8 @@ typedef struct OptionsContext { int nb_hwaccels; SpecifierOpt *hwaccel_devices; int nb_hwaccel_devices; + SpecifierOpt *autorotate; + int nb_autorotate; /* output options */ StreamMap *stream_maps; @@ -236,6 +238,7 @@ typedef struct InputStream { AVDictionary *decoder_opts; AVRational framerate; /* framerate forced with -r */ + int autorotate; int resample_height; int resample_width; int resample_pix_fmt; diff --git a/avconv_filter.c b/avconv_filter.c index e54da56c7a..c3360f1741 100644 --- a/avconv_filter.c +++ b/avconv_filter.c @@ -29,6 +29,7 @@ #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" +#include "libavutil/display.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavutil/pixfmt.h" @@ -226,6 +227,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; @@ -446,6 +469,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/avconv_opt.c b/avconv_opt.c index 16254299e2..29fc2be6dd 100644 --- a/avconv_opt.c +++ b/avconv_opt.c @@ -488,6 +488,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); @@ -2372,6 +2375,9 @@ const OptionDef options[] = { { "hwaccel_device", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT | OPT_SPEC | OPT_INPUT, { .off = OFFSET(hwaccel_devices) }, "select a device for HW acceleration" "devicename" }, + { "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 }, diff --git a/doc/avconv.texi b/doc/avconv.texi index 37733bc2a9..aea41d9eec 100644 --- a/doc/avconv.texi +++ b/doc/avconv.texi @@ -401,6 +401,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