* 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>
... | ... |
@@ -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 }, |