diff mbox series

[FFmpeg-devel,v2,06/18] cbs_h264: Implement fill and extract for display orientation SEI message

Message ID 20210221195125.1901683-6-sw@jkqxz.net
State New
Headers show
Series [FFmpeg-devel,v2,01/18] cbs_sei: Delete SEI NAL units containing no messages | expand

Checks

Context Check Description
andriy/x86_make success Make finished
andriy/x86_make_fate success Make fate finished
andriy/PPC64_make success Make finished
andriy/PPC64_make_fate success Make fate finished

Commit Message

Mark Thompson Feb. 21, 2021, 7:51 p.m. UTC
---
 libavcodec/cbs_h2645.c | 79 ++++++++++++++++++++++++++++++++++++++++++
 libavcodec/cbs_sei.c   |  2 ++
 2 files changed, 81 insertions(+)
diff mbox series

Patch

diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c
index ecd2001816..c01d243455 100644
--- a/libavcodec/cbs_h2645.c
+++ b/libavcodec/cbs_h2645.c
@@ -18,6 +18,7 @@ 
 
 #include "libavutil/attributes.h"
 #include "libavutil/avassert.h"
+#include "libavutil/display.h"
 #include "libavutil/mastering_display_metadata.h"
 
 #include "bytestream.h"
@@ -1683,6 +1684,83 @@  static const SEIMessageTypeDescriptor cbs_sei_common_types[] = {
     SEI_MESSAGE_TYPE_END,
 };
 
+static void cbs_h264_fill_sei_display_orientation
+    (H264RawSEIDisplayOrientation *disp, const int32_t matrix[9])
+{
+    double dmatrix[9];
+    int hflip, vflip, i;
+    double scale_x, scale_y, angle;
+    uint16_t rotation;
+
+    if (matrix[2] != 0 || matrix[5] != 0 ||
+        matrix[6] != 0 || matrix[7] != 0) {
+        // Not representable.
+        goto cancel;
+    }
+
+    for (i = 0; i < 9; i++)
+        dmatrix[i] = matrix[i] / 65536.0;
+
+    // Extract scale factors.
+    scale_x = hypot(dmatrix[0], dmatrix[3]);
+    scale_y = hypot(dmatrix[1], dmatrix[4]);
+
+    // Select flips to make the main diagonal positive.
+    hflip = dmatrix[0] < 0.0;
+    vflip = dmatrix[4] < 0.0;
+    if (hflip)
+        scale_x = -scale_x;
+    if (vflip)
+        scale_y = -scale_y;
+
+    // Rescale.
+    for (i = 0; i < 9; i += 3) {
+        dmatrix[i]     /= scale_x;
+        dmatrix[i + 1] /= scale_y;
+    }
+
+    // Extract rotation.
+    angle = -atan2(dmatrix[3], dmatrix[0]);
+    if (!(angle >= -M_PI && angle <= M_PI)) {
+        // Not representable.
+        goto cancel;
+    }
+    if (angle < 0.0)
+        angle += 2 * M_PI;
+    rotation = (uint16_t)lrint(angle * 32768.0 / M_PI);
+
+    if (!hflip && !vflip && rotation == 0) {
+        // This is the identity transformation, so rather than setting
+        // values for a new display orientation we should instead cancel
+        // any previous message.
+    cancel:
+        *disp = (H264RawSEIDisplayOrientation) {
+            .display_orientation_cancel_flag = 1,
+        };
+    } else {
+        *disp = (H264RawSEIDisplayOrientation) {
+            .hor_flip = hflip,
+            .ver_flip = vflip,
+            .anticlockwise_rotation = rotation,
+            .display_orientation_repetition_period = 1,
+        };
+    }
+}
+
+static void cbs_h264_extract_sei_display_orientation
+    (int32_t matrix[9], const H264RawSEIDisplayOrientation *disp)
+{
+    if (disp->display_orientation_cancel_flag) {
+        // Set identity matrix.
+        av_display_rotation_set(matrix, 0.0);
+    } else {
+        av_display_rotation_set(matrix,
+                                disp->anticlockwise_rotation *
+                                360.0 / 65536.0);
+        av_display_matrix_flip(matrix, disp->hor_flip, disp->ver_flip);
+    }
+}
+
 static const SEIMessageTypeDescriptor cbs_sei_h264_types[] = {
     {
         SEI_TYPE_BUFFERING_PERIOD,
@@ -1719,6 +1797,7 @@  static const SEIMessageTypeDescriptor cbs_sei_h264_types[] = {
         1, 0,
         sizeof(H264RawSEIDisplayOrientation),
         SEI_MESSAGE_RW(h264, sei_display_orientation),
+        SEI_MESSAGE_FE(h264, sei_display_orientation),
     },
     SEI_MESSAGE_TYPE_END
 };
diff --git a/libavcodec/cbs_sei.c b/libavcodec/cbs_sei.c
index a5990205d0..27b5997e47 100644
--- a/libavcodec/cbs_sei.c
+++ b/libavcodec/cbs_sei.c
@@ -384,6 +384,8 @@  static const SEIMetadata cbs_sei_metadata[] = {
       SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME },
     { CBS_METADATA_CONTENT_LIGHT_LEVEL,
       SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO },
+    { CBS_METADATA_DISPLAY_MATRIX,
+      SEI_TYPE_DISPLAY_ORIENTATION },
 };
 
 static const SEIMessageTypeDescriptor *cbs_sei_find_type_from_metadata