ffmpeg | branch: master | Jan Ekström <jee...@gmail.com> | Wed Oct 19 11:44:03 
2022 +0200| [c889248647780753ec8b05138c7de4a707adb106] | committer: Thilo 
Borgmann

ffmpeg: Add display_{rotation, hflip, vflip} options

This enables overriding the rotation as well as horizontal/vertical
flip state of a specific video stream on the input side.

Additionally, switch the singular test that was utilizing the rotation
metadata to instead override the input display rotation, thus leading
to the same result.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=c889248647780753ec8b05138c7de4a707adb106
---

 doc/ffmpeg.texi             | 26 +++++++++++++++++++++++
 fftools/ffmpeg.h            |  6 ++++++
 fftools/ffmpeg_opt.c        | 50 +++++++++++++++++++++++++++++++++++++++++++++
 tests/fate/filter-video.mak |  2 +-
 4 files changed, 83 insertions(+), 1 deletion(-)

diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
index e9020b30d5..0367930a3b 100644
--- a/doc/ffmpeg.texi
+++ b/doc/ffmpeg.texi
@@ -912,6 +912,32 @@ If used together with @option{-vcodec copy}, it will 
affect the aspect ratio
 stored at container level, but not the aspect ratio stored in encoded
 frames, if it exists.
 
+@item -display_rotation[:@var{stream_specifier}] @var{rotation} 
(@emph{input,per-stream})
+Set video rotation metadata.
+
+@var{rotation} is a decimal number specifying the amount in degree by
+which the video should be rotated counter-clockwise before being
+displayed.
+
+This option overrides the rotation/display transform metadata stored in
+the file, if any. When the video is being transcoded (rather than
+copied) and @code{-autorotate} is enabled, the video will be rotated at
+the filtering stage. Otherwise, the metadata will be written into the
+output file if the muxer supports it.
+
+If the @code{-display_hflip} and/or @code{-display_vflip} options are
+given, they are applied after the rotation specified by this option.
+
+@item -display_hflip[:@var{stream_specifier}] (@emph{input,per-stream})
+Set whether on display the image should be horizontally flipped.
+
+See the @code{-display_rotation} option for more details.
+
+@item -display_vflip[:@var{stream_specifier}] (@emph{input,per-stream})
+Set whether on display the image should be vertically flipped.
+
+See the @code{-display_rotation} option for more details.
+
 @item -vn (@emph{input/output})
 As an input option, blocks all video streams of a file from being filtered or
 being automatically selected or mapped for any output. See @code{-discard}
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 91c5cfa3ab..13a2100439 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -194,6 +194,12 @@ typedef struct OptionsContext {
     int        nb_force_fps;
     SpecifierOpt *frame_aspect_ratios;
     int        nb_frame_aspect_ratios;
+    SpecifierOpt *display_rotations;
+    int        nb_display_rotations;
+    SpecifierOpt *display_hflips;
+    int        nb_display_hflips;
+    SpecifierOpt *display_vflips;
+    int        nb_display_vflips;
     SpecifierOpt *rc_overrides;
     int        nb_rc_overrides;
     SpecifierOpt *intra_matrices;
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index 7fdbf08a18..ead4ee1b38 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -20,6 +20,7 @@
 
 #include "config.h"
 
+#include <float.h>
 #include <stdint.h>
 
 #if HAVE_SYS_RESOURCE_H
@@ -44,6 +45,7 @@
 #include "libavutil/avutil.h"
 #include "libavutil/bprint.h"
 #include "libavutil/channel_layout.h"
+#include "libavutil/display.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/fifo.h"
 #include "libavutil/mathematics.h"
@@ -66,6 +68,9 @@ static const char *const opt_name_fix_sub_duration[]          
= {"fix_sub_durati
 static const char *const opt_name_canvas_sizes[]              = 
{"canvas_size", NULL};
 static const char *const opt_name_guess_layout_max[]          = 
{"guess_layout_max", NULL};
 static const char *const opt_name_discard[]                   = {"discard", 
NULL};
+static const char *const opt_name_display_rotations[]         = 
{"display_rotation", NULL};
+static const char *const opt_name_display_hflips[]            = 
{"display_hflip", NULL};
+static const char *const opt_name_display_vflips[]            = 
{"display_vflip", NULL};
 
 HWDevice *filter_hw_device;
 
@@ -595,6 +600,39 @@ static int opt_recording_timestamp(void *optctx, const 
char *opt, const char *ar
     return 0;
 }
 
+static void add_display_matrix_to_stream(OptionsContext *o,
+                                         AVFormatContext *ctx, AVStream *st)
+{
+    double rotation = DBL_MAX;
+    int hflip = -1, vflip = -1;
+    int hflip_set = 0, vflip_set = 0, rotation_set = 0;
+    int32_t *buf;
+
+    MATCH_PER_STREAM_OPT(display_rotations, dbl, rotation, ctx, st);
+    MATCH_PER_STREAM_OPT(display_hflips,    i,   hflip,    ctx, st);
+    MATCH_PER_STREAM_OPT(display_vflips,    i,   vflip,    ctx, st);
+
+    rotation_set = rotation != DBL_MAX;
+    hflip_set    = hflip != -1;
+    vflip_set    = vflip != -1;
+
+    if (!rotation_set && !hflip_set && !vflip_set)
+        return;
+
+    buf = (int32_t *)av_stream_new_side_data(st, AV_PKT_DATA_DISPLAYMATRIX, 
sizeof(int32_t) * 9);
+    if (!buf) {
+        av_log(NULL, AV_LOG_FATAL, "Failed to generate a display matrix!\n");
+        exit_program(1);
+    }
+
+    av_display_rotation_set(buf,
+                            rotation_set ? -(rotation) : -0.0f);
+
+    av_display_matrix_flip(buf,
+                           hflip_set ? hflip : 0,
+                           vflip_set ? vflip : 0);
+}
+
 const AVCodec *find_codec_or_die(const char *name, enum AVMediaType type, int 
encoder)
 {
     const AVCodecDescriptor *desc;
@@ -729,6 +767,8 @@ static void add_input_streams(OptionsContext *o, 
AVFormatContext *ic)
         }
 
         if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
+            add_display_matrix_to_stream(o, ic, st);
+
             MATCH_PER_STREAM_OPT(hwaccels, str, hwaccel, ic, st);
             MATCH_PER_STREAM_OPT(hwaccel_output_formats, str,
                                  hwaccel_output_format, ic, st);
@@ -2127,6 +2167,16 @@ const OptionDef options[] = {
     { "pix_fmt",      OPT_VIDEO | HAS_ARG | OPT_EXPERT  | OPT_STRING | 
OPT_SPEC |
                       OPT_INPUT | OPT_OUTPUT,                                  
  { .off = OFFSET(frame_pix_fmts) },
         "set pixel format", "format" },
+    { "display_rotation", OPT_VIDEO | HAS_ARG | OPT_DOUBLE | OPT_SPEC |
+                          OPT_INPUT,                                           
  { .off = OFFSET(display_rotations) },
+        "set pure counter-clockwise rotation in degrees for stream(s)",
+        "angle" },
+    { "display_hflip", OPT_VIDEO | OPT_BOOL | OPT_SPEC | OPT_INPUT,            
  { .off = OFFSET(display_hflips) },
+        "set display horizontal flip for stream(s) "
+        "(overrides any display rotation if it is not set)"},
+    { "display_vflip", OPT_VIDEO | OPT_BOOL | OPT_SPEC | OPT_INPUT,            
  { .off = OFFSET(display_vflips) },
+        "set display vertical flip for stream(s) "
+        "(overrides any display rotation if it is not set)"},
     { "vn",           OPT_VIDEO | OPT_BOOL  | OPT_OFFSET | OPT_INPUT | 
OPT_OUTPUT,{ .off = OFFSET(video_disable) },
         "disable video" },
     { "rc_override",  OPT_VIDEO | HAS_ARG | OPT_EXPERT  | OPT_STRING | 
OPT_SPEC |
diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak
index 372c70bba7..f3c27ed1c8 100644
--- a/tests/fate/filter-video.mak
+++ b/tests/fate/filter-video.mak
@@ -691,7 +691,7 @@ fate-filter-metadata-avf-aphase-meter-out-of-phase: SRC = 
$(TARGET_SAMPLES)/filt
 fate-filter-metadata-avf-aphase-meter-out-of-phase: CMD = run 
$(FILTER_METADATA_COMMAND) "amovie='$(SRC)',aphasemeter=video=0"
 
 FATE_FILTER_SAMPLES-$(call TRANSCODE, RAWVIDEO H264, MOV, ARESAMPLE_FILTER  
AAC_FIXED_DECODER) += fate-filter-meta-4560-rotate0
-fate-filter-meta-4560-rotate0: CMD = transcode mov 
$(TARGET_SAMPLES)/filter/sample-in-issue-505.mov mov "-c copy -metadata:s:v:0 
rotate=0" "-af aresample" "" "" "-flags +bitexact -c:a aac_fixed"
+fate-filter-meta-4560-rotate0: CMD = transcode "mov -display_rotation:v:0 0" 
$(TARGET_SAMPLES)/filter/sample-in-issue-505.mov mov "-c copy" "-af aresample" 
"" "" "-flags +bitexact -c:a aac_fixed"
 
 FATE_FILTER_CMP_METADATA-$(CONFIG_BLOCKDETECT_FILTER) += 
fate-filter-refcmp-blockdetect-yuv
 fate-filter-refcmp-blockdetect-yuv: CMD = cmp_metadata blockdetect yuv420p 
0.015

_______________________________________________
ffmpeg-cvslog mailing list
ffmpeg-cvslog@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-cvslog

To unsubscribe, visit link above, or email
ffmpeg-cvslog-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to