Browse code

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>

Michael Niedermayer authored on 2015/05/03 05:39:00
Showing 6 changed files
... ...
@@ -18,6 +18,7 @@ version <next>:
18 18
 - nvenc level and tier options
19 19
 - chorus filter
20 20
 - Canopus HQ/HQA decoder
21
+- Automatically rotate videos based on metadata in ffmpeg
21 22
 
22 23
 
23 24
 version 2.6:
... ...
@@ -462,6 +462,9 @@ Technical note -- attachments are implemented as codec extradata, so this
462 462
 option can actually be used to extract extradata from any stream, not just
463 463
 attachments.
464 464
 
465
+@item -noautorotate
466
+Disable automatically rotating video based on file metadata.
467
+
465 468
 @end table
466 469
 
467 470
 @section Video Options
... ...
@@ -3647,6 +3647,8 @@ static int process_input(int file_index)
3647 3647
 
3648 3648
             if (av_packet_get_side_data(&pkt, src_sd->type, NULL))
3649 3649
                 continue;
3650
+            if (ist->autorotate && src_sd->type == AV_PKT_DATA_DISPLAYMATRIX)
3651
+                continue;
3650 3652
 
3651 3653
             dst_data = av_packet_new_side_data(&pkt, src_sd->type, src_sd->size);
3652 3654
             if (!dst_data)
... ...
@@ -122,6 +122,8 @@ typedef struct OptionsContext {
122 122
     int        nb_hwaccels;
123 123
     SpecifierOpt *hwaccel_devices;
124 124
     int        nb_hwaccel_devices;
125
+    SpecifierOpt *autorotate;
126
+    int        nb_autorotate;
125 127
 
126 128
     /* output options */
127 129
     StreamMap *stream_maps;
... ...
@@ -276,6 +278,7 @@ typedef struct InputStream {
276 276
     int top_field_first;
277 277
     int guess_layout_max;
278 278
 
279
+    int autorotate;
279 280
     int resample_height;
280 281
     int resample_width;
281 282
     int resample_pix_fmt;
... ...
@@ -31,6 +31,7 @@
31 31
 #include "libavutil/avstring.h"
32 32
 #include "libavutil/bprint.h"
33 33
 #include "libavutil/channel_layout.h"
34
+#include "libavutil/display.h"
34 35
 #include "libavutil/opt.h"
35 36
 #include "libavutil/pixdesc.h"
36 37
 #include "libavutil/pixfmt.h"
... ...
@@ -339,6 +340,28 @@ static int insert_trim(int64_t start_time, int64_t duration,
339 339
     return 0;
340 340
 }
341 341
 
342
+static int insert_filter(AVFilterContext **last_filter, int *pad_idx,
343
+                         const char *filter_name, const char *args)
344
+{
345
+    AVFilterGraph *graph = (*last_filter)->graph;
346
+    AVFilterContext *ctx;
347
+    int ret;
348
+
349
+    ret = avfilter_graph_create_filter(&ctx,
350
+                                       avfilter_get_by_name(filter_name),
351
+                                       filter_name, args, NULL, graph);
352
+    if (ret < 0)
353
+        return ret;
354
+
355
+    ret = avfilter_link(*last_filter, *pad_idx, ctx, 0);
356
+    if (ret < 0)
357
+        return ret;
358
+
359
+    *last_filter = ctx;
360
+    *pad_idx     = 0;
361
+    return 0;
362
+}
363
+
342 364
 static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out)
343 365
 {
344 366
     char *pix_fmts;
... ...
@@ -676,6 +699,26 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter,
676 676
         return ret;
677 677
     last_filter = ifilter->filter;
678 678
 
679
+    if (ist->autorotate) {
680
+        uint8_t* displaymatrix = av_stream_get_side_data(ist->st,
681
+                                                         AV_PKT_DATA_DISPLAYMATRIX, NULL);
682
+        if (displaymatrix) {
683
+            double rot = av_display_rotation_get((int32_t*) displaymatrix);
684
+            if (rot < -135 || rot > 135) {
685
+                ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL);
686
+                if (ret < 0)
687
+                    return ret;
688
+                ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL);
689
+            } else if (rot < -45) {
690
+                ret = insert_filter(&last_filter, &pad_idx, "transpose", "dir=clock");
691
+            } else if (rot > 45) {
692
+                ret = insert_filter(&last_filter, &pad_idx, "transpose", "dir=cclock");
693
+            }
694
+            if (ret < 0)
695
+                return ret;
696
+        }
697
+    }
698
+
679 699
     if (ist->framerate.num) {
680 700
         AVFilterContext *setpts;
681 701
 
... ...
@@ -602,6 +602,9 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
602 602
         ist->ts_scale = 1.0;
603 603
         MATCH_PER_STREAM_OPT(ts_scale, dbl, ist->ts_scale, ic, st);
604 604
 
605
+        ist->autorotate = 1;
606
+        MATCH_PER_STREAM_OPT(autorotate, i, ist->autorotate, ic, st);
607
+
605 608
         MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, ic, st);
606 609
         if (codec_tag) {
607 610
             uint32_t tag = strtol(codec_tag, &next, 0);
... ...
@@ -3069,6 +3072,9 @@ const OptionDef options[] = {
3069 3069
 #if HAVE_VDPAU_X11
3070 3070
     { "vdpau_api_ver", HAS_ARG | OPT_INT | OPT_EXPERT, { &vdpau_api_ver }, "" },
3071 3071
 #endif
3072
+    { "autorotate",       HAS_ARG | OPT_BOOL | OPT_SPEC |
3073
+                          OPT_EXPERT | OPT_INPUT,                                { .off = OFFSET(autorotate) },
3074
+        "automatically insert correct rotate filters" },
3072 3075
 
3073 3076
     /* audio options */
3074 3077
     { "aframes",        OPT_AUDIO | HAS_ARG  | OPT_PERFILE | OPT_OUTPUT,           { .func_arg = opt_audio_frames },