diff mbox series

[FFmpeg-devel,v4,21/21] h264_metadata_bsf: Improve interpretation of input display matrices

Message ID 20200223234124.17689-21-sw@jkqxz.net
State New
Headers show
Series [FFmpeg-devel,v4,01/21] cbs: Mention all codecs in unit type comment
Related show

Checks

Context Check Description
andriy/ffmpeg-patchwork pending
andriy/ffmpeg-patchwork success Applied patch
andriy/ffmpeg-patchwork success Configure finished
andriy/ffmpeg-patchwork success Make finished
andriy/ffmpeg-patchwork success Make fate finished

Commit Message

Mark Thompson Feb. 23, 2020, 11:41 p.m. UTC
The previous code here only worked in more limited cases.
---
 libavcodec/h264_metadata_bsf.c | 42 +++++++++++++++++++++++-----------
 1 file changed, 29 insertions(+), 13 deletions(-)
diff mbox series

Patch

diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c
index b2304373bf..8fc02c5f41 100644
--- a/libavcodec/h264_metadata_bsf.c
+++ b/libavcodec/h264_metadata_bsf.c
@@ -397,23 +397,39 @@  static int h264_metadata_handle_display_orientation(AVBSFContext *bsf,
         data = av_packet_get_side_data(pkt, AV_PKT_DATA_DISPLAYMATRIX, &size);
         if (data && size >= 9 * sizeof(int32_t)) {
             int32_t matrix[9];
+            double dmatrix[9];
             int hflip, vflip;
-            double angle;
+            double scale_x, scale_y, angle;
 
             memcpy(matrix, data, sizeof(matrix));
 
-            hflip = vflip = 0;
-            if (matrix[0] < 0 && matrix[4] > 0)
-                hflip = 1;
-            else if (matrix[0] > 0 && matrix[4] < 0)
-                vflip = 1;
-            av_display_matrix_flip(matrix, hflip, vflip);
+            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;
+            }
 
-            angle = av_display_rotation_get(matrix);
+            // Extract rotation.
+            angle = atan2(dmatrix[3], dmatrix[0]);
 
-            if (!(angle >= -180.0 && angle <= 180.0 /* also excludes NaN */) ||
-                matrix[2] != 0 || matrix[5] != 0 ||
-                matrix[6] != 0 || matrix[7] != 0) {
+            if (!(angle >= -M_PI && angle <= M_PI) ||
+                matrix[2] != 0.0 || matrix[5] != 0.0 ||
+                matrix[6] != 0.0 || matrix[7] != 0.0) {
                 av_log(bsf, AV_LOG_WARNING, "Input display matrix is not "
                        "representable in H.264 parameters.\n");
             } else {
@@ -421,8 +437,8 @@  static int h264_metadata_handle_display_orientation(AVBSFContext *bsf,
                 disp->ver_flip = vflip;
                 disp->anticlockwise_rotation =
                     (uint16_t)rint((angle >= 0.0 ? angle
-                                                 : angle + 360.0) *
-                                   65536.0 / 360.0);
+                                                 : angle + 2 * M_PI) *
+                                   32768.0 / M_PI);
                 write = 1;
             }
         }