summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Storsjö <martin@martin.st>2015-04-29 17:59:01 +0300
committerMartin Storsjö <martin@martin.st>2015-05-02 22:09:06 +0300
commit16302246b1fcb7ad4e6f7bd31c49956a455336d2 (patch)
treec5c5a29b3f25d02b7e56cf0aa2bc679a07ac5d2d
parente2d50fc2f5f3600e13055acf1a10fec35e941f37 (diff)
avconv: Add an option for automatically rotating video according to display matrix
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ö <martin@martin.st>
-rw-r--r--Changelog1
-rw-r--r--avconv.c2
-rw-r--r--avconv.h3
-rw-r--r--avconv_filter.c43
-rw-r--r--avconv_opt.c6
-rw-r--r--doc/avconv.texi3
6 files changed, 58 insertions, 0 deletions
diff --git a/Changelog b/Changelog
index c3ea67c6e4..2fd1583c6e 100644
--- a/Changelog
+++ b/Changelog
@@ -28,6 +28,7 @@ version <next>:
- 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