[FFmpeg-devel] [PATCH v2 16/18] vaapi_encode_h265: Ensure that HDR metadata is included with seek points

Mark Thompson sw at jkqxz.net
Sun Feb 21 21:51:23 EET 2021


Save the most recent HDR side data structures and use them when
generating an IDR or CRA frame.
---
 libavcodec/vaapi_encode_h265.c | 93 ++++++++++++----------------------
 1 file changed, 32 insertions(+), 61 deletions(-)

diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c
index 33acbf23f2..75ebb63e74 100644
--- a/libavcodec/vaapi_encode_h265.c
+++ b/libavcodec/vaapi_encode_h265.c
@@ -30,6 +30,7 @@
 #include "avcodec.h"
 #include "cbs.h"
 #include "cbs_h265.h"
+#include "cbs_metadata.h"
 #include "h265_profile_level.h"
 #include "hevc.h"
 #include "hevc_sei.h"
@@ -70,13 +71,15 @@ typedef struct VAAPIEncodeH265Context {
     H265RawPPS   raw_pps;
     H265RawSlice raw_slice;
 
-    SEIRawMasteringDisplayColourVolume sei_mastering_display;
-    SEIRawContentLightLevelInfo        sei_content_light_level;
-
     CodedBitstreamContext *cbc;
     CodedBitstreamFragment current_access_unit;
     int aud_needed;
     int sei_needed;
+
+    int                   have_mastering_display;
+    AVMasteringDisplayMetadata mastering_display;
+    int                   have_content_light_level;
+    AVContentLightMetadata     content_light_level;
 } VAAPIEncodeH265Context;
 
 
@@ -200,17 +203,17 @@ static int vaapi_encode_h265_write_extra_header(AVCodecContext *avctx,
         }
 
         if (priv->sei_needed & SEI_MASTERING_DISPLAY) {
-            err = ff_cbs_sei_add_message(priv->cbc, au, 1,
-                                         SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME,
-                                         &priv->sei_mastering_display, NULL);
+            err = ff_cbs_insert_metadata(priv->cbc, au,
+                                         CBS_METADATA_MASTERING_DISPLAY,
+                                         &priv->mastering_display);
             if (err < 0)
                 goto fail;
         }
 
         if (priv->sei_needed & SEI_CONTENT_LIGHT_LEVEL) {
-            err = ff_cbs_sei_add_message(priv->cbc, au, 1,
-                                         SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO,
-                                         &priv->sei_content_light_level, NULL);
+            err = ff_cbs_insert_metadata(priv->cbc, au,
+                                         CBS_METADATA_CONTENT_LIGHT_LEVEL,
+                                         &priv->content_light_level);
             if (err < 0)
                 goto fail;
         }
@@ -746,72 +749,40 @@ static int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx,
 
     priv->sei_needed = 0;
 
-    // Only look for the metadata on I/IDR frame on the output. We
-    // may force an IDR frame on the output where the medadata gets
-    // changed on the input frame.
-    if ((priv->sei & SEI_MASTERING_DISPLAY) &&
-        (pic->type == PICTURE_TYPE_I || pic->type == PICTURE_TYPE_IDR)) {
+    // We check for new metadata on every frame, but only include the
+    // SEI with IRAP frames.
+    if (priv->sei & SEI_MASTERING_DISPLAY) {
         AVFrameSideData *sd =
             av_frame_get_side_data(pic->input_image,
                                    AV_FRAME_DATA_MASTERING_DISPLAY_METADATA);
 
         if (sd) {
-            AVMasteringDisplayMetadata *mdm =
-                (AVMasteringDisplayMetadata *)sd->data;
-
-            // SEI is needed when both the primaries and luminance are set
-            if (mdm->has_primaries && mdm->has_luminance) {
-                SEIRawMasteringDisplayColourVolume *mdcv =
-                    &priv->sei_mastering_display;
-                const int mapping[3] = {1, 2, 0};
-                const int chroma_den = 50000;
-                const int luma_den   = 10000;
-
-                for (i = 0; i < 3; i++) {
-                    const int j = mapping[i];
-                    mdcv->display_primaries_x[i] =
-                        FFMIN(lrint(chroma_den *
-                                    av_q2d(mdm->display_primaries[j][0])),
-                              chroma_den);
-                    mdcv->display_primaries_y[i] =
-                        FFMIN(lrint(chroma_den *
-                                    av_q2d(mdm->display_primaries[j][1])),
-                              chroma_den);
-                }
-
-                mdcv->white_point_x =
-                    FFMIN(lrint(chroma_den * av_q2d(mdm->white_point[0])),
-                          chroma_den);
-                mdcv->white_point_y =
-                    FFMIN(lrint(chroma_den * av_q2d(mdm->white_point[1])),
-                          chroma_den);
-
-                mdcv->max_display_mastering_luminance =
-                    lrint(luma_den * av_q2d(mdm->max_luminance));
-                mdcv->min_display_mastering_luminance =
-                    FFMIN(lrint(luma_den * av_q2d(mdm->min_luminance)),
-                          mdcv->max_display_mastering_luminance);
-
-                priv->sei_needed |= SEI_MASTERING_DISPLAY;
-            }
+            av_assert0(sd->size >= sizeof(priv->mastering_display));
+            priv->have_mastering_display = 1;
+            memcpy(&priv->mastering_display, sd->data,
+                   sizeof(priv->mastering_display));
+        }
+
+        if (priv->have_mastering_display &&
+            (pic->type == PICTURE_TYPE_IDR || pic->type == PICTURE_TYPE_I)) {
+            priv->sei_needed |= SEI_MASTERING_DISPLAY;
         }
     }
 
-    if ((priv->sei & SEI_CONTENT_LIGHT_LEVEL) &&
-        (pic->type == PICTURE_TYPE_I || pic->type == PICTURE_TYPE_IDR)) {
+    if (priv->sei & SEI_CONTENT_LIGHT_LEVEL) {
         AVFrameSideData *sd =
             av_frame_get_side_data(pic->input_image,
                                    AV_FRAME_DATA_CONTENT_LIGHT_LEVEL);
 
         if (sd) {
-            AVContentLightMetadata *clm =
-                (AVContentLightMetadata *)sd->data;
-            SEIRawContentLightLevelInfo *clli =
-                &priv->sei_content_light_level;
-
-            clli->max_content_light_level     = FFMIN(clm->MaxCLL,  65535);
-            clli->max_pic_average_light_level = FFMIN(clm->MaxFALL, 65535);
+            av_assert0(sd->size >= sizeof(priv->content_light_level));
+            priv->have_mastering_display = 1;
+            memcpy(&priv->content_light_level, sd->data,
+                   sizeof(priv->content_light_level));
+        }
 
+        if (priv->have_content_light_level &&
+            (pic->type == PICTURE_TYPE_IDR || pic->type == PICTURE_TYPE_I)) {
             priv->sei_needed |= SEI_CONTENT_LIGHT_LEVEL;
         }
     }
-- 
2.30.0



More information about the ffmpeg-devel mailing list