diff mbox series

[FFmpeg-devel,17/27] cbs_h264: Implement fill and extract for display orientation SEI message

Message ID 20210101213537.169546-18-sw@jkqxz.net
State New
Headers show
Series Metadata handling in CBS
Related show

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 Jan. 1, 2021, 9:35 p.m. UTC
---
 libavcodec/cbs_h2645.c | 64 ++++++++++++++++++++++++++++++++++++++++++
 libavcodec/cbs_sei.c   |  2 ++
 2 files changed, 66 insertions(+)
diff mbox series

Patch

diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c
index 53d5b50b42..4144948b7f 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"
@@ -1674,6 +1675,68 @@  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;
+
+    if (matrix[2] != 0 || matrix[5] != 0 ||
+        matrix[6] != 0 || matrix[7] != 0) {
+        // Not representable.
+        return;
+    }
+
+    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.
+        return;
+    }
+
+    *disp = (H264RawSEIDisplayOrientation) {
+        .hor_flip = hflip,
+        .ver_flip = vflip,
+        .anticlockwise_rotation =
+            (uint16_t)rint((angle >= 0.0 ? angle
+                            : angle + 2 * M_PI) *
+                           32768.0 / M_PI),
+        .display_orientation_repetition_period = 1,
+    };
+}
+
+static void cbs_h264_extract_sei_display_orientation
+    (int32_t matrix[9], const H264RawSEIDisplayOrientation *disp)
+{
+    av_display_rotation_set(matrix,
+                            disp->anticlockwise_rotation *
+                            180.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,
@@ -1704,6 +1767,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 0c05b2bdc9..9ea00dd724 100644
--- a/libavcodec/cbs_sei.c
+++ b/libavcodec/cbs_sei.c
@@ -379,6 +379,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