msdk: Insert hdr sei at hevc encoder
authorMengkejiergeli Ba <mengkejiergeli.ba@intel.com>
Wed, 20 Oct 2021 09:46:10 +0000 (17:46 +0800)
committerHaihao Xiang <haihao.xiang@intel.com>
Thu, 28 Oct 2021 08:36:05 +0000 (08:36 +0000)
There are two HDR SEIs defined in spec: mastering display colour volume and
content light level. Add insertion of HDR SEIs when they are available
during encoding.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1242>

subprojects/gst-plugins-bad/sys/msdk/gstmsdkh265enc.c

index bd8914f..a68e5d3 100644 (file)
@@ -248,13 +248,119 @@ gst_msdkh265enc_add_cc (GstMsdkH265Enc * thiz, GstVideoCodecFrame * frame)
   gst_memory_unref (mem);
 }
 
+static void
+gst_msdkh265enc_add_mdcv_sei (GstMsdkEnc * encoder, GstVideoCodecFrame * frame)
+{
+  GstMsdkH265Enc *thiz = GST_MSDKH265ENC (encoder);
+  GstVideoMasteringDisplayInfo *mastering_display_info
+      = encoder->input_state->mastering_display_info;
+  GstH265SEIMessage sei;
+  GstH265MasteringDisplayColourVolume *mdcv;
+  GstMemory *mem = NULL;
+  guint i = 0;
+
+  memset (&sei, 0, sizeof (GstH265SEIMessage));
+  sei.payloadType = GST_H265_SEI_MASTERING_DISPLAY_COLOUR_VOLUME;
+  mdcv = &sei.payload.mastering_display_colour_volume;
+
+  for (i = 0; i < 3; i++) {
+    mdcv->display_primaries_x[i] =
+        mastering_display_info->display_primaries[i].x;
+    mdcv->display_primaries_y[i] =
+        mastering_display_info->display_primaries[i].y;
+  }
+
+  mdcv->white_point_x = mastering_display_info->white_point.x;
+  mdcv->white_point_y = mastering_display_info->white_point.y;
+  mdcv->max_display_mastering_luminance =
+      mastering_display_info->max_display_mastering_luminance;
+  mdcv->min_display_mastering_luminance =
+      mastering_display_info->min_display_mastering_luminance;
+
+  if (!thiz->cc_sei_array)
+    thiz->cc_sei_array = g_array_new (FALSE, FALSE, sizeof (GstH265SEIMessage));
+  else
+    g_array_set_size (thiz->cc_sei_array, 0);
+
+  g_array_append_val (thiz->cc_sei_array, sei);
+
+  if (!thiz->cc_sei_array || !thiz->cc_sei_array->len)
+    return;
+
+  /* layer_id and temporal_id will be updated by parser later */
+  mem = gst_h265_create_sei_memory (0, 1, 4, thiz->cc_sei_array);
+
+  if (!mem) {
+    GST_WARNING_OBJECT (thiz, "Cannot create SEI nal unit");
+    return;
+  }
+
+  GST_DEBUG_OBJECT (thiz,
+      "Inserting %d mastering display colout volume SEI message(s)",
+      thiz->cc_sei_array->len);
+
+  gst_msdkh265enc_insert_sei (thiz, frame, mem);
+  gst_memory_unref (mem);
+}
+
+static void
+gst_msdkh265enc_add_cll_sei (GstMsdkEnc * encoder, GstVideoCodecFrame * frame)
+{
+  GstMsdkH265Enc *thiz = GST_MSDKH265ENC (encoder);
+  GstVideoContentLightLevel *content_light_level
+      = encoder->input_state->content_light_level;
+  GstH265ContentLightLevel *cll;
+  GstH265SEIMessage sei;
+  GstMemory *mem = NULL;
+
+  memset (&sei, 0, sizeof (GstH265SEIMessage));
+  sei.payloadType = GST_H265_SEI_CONTENT_LIGHT_LEVEL;
+  cll = &sei.payload.content_light_level;
+
+  cll->max_content_light_level = content_light_level->max_content_light_level;
+  cll->max_pic_average_light_level =
+      content_light_level->max_frame_average_light_level;
+
+  if (!thiz->cc_sei_array)
+    thiz->cc_sei_array = g_array_new (FALSE, FALSE, sizeof (GstH265SEIMessage));
+  else
+    g_array_set_size (thiz->cc_sei_array, 0);
+
+  g_array_append_val (thiz->cc_sei_array, sei);
+
+  if (!thiz->cc_sei_array || !thiz->cc_sei_array->len)
+    return;
+
+  /* layer_id and temporal_id will be updated by parser later */
+  mem = gst_h265_create_sei_memory (0, 1, 4, thiz->cc_sei_array);
+
+  if (!mem) {
+    GST_WARNING_OBJECT (thiz, "Cannot create SEI nal unit");
+    return;
+  }
+
+  GST_DEBUG_OBJECT (thiz,
+      "Inserting %d content light level SEI message(s)",
+      thiz->cc_sei_array->len);
+
+  gst_msdkh265enc_insert_sei (thiz, frame, mem);
+  gst_memory_unref (mem);
+}
+
 static GstFlowReturn
 gst_msdkh265enc_pre_push (GstVideoEncoder * encoder, GstVideoCodecFrame * frame)
 {
   GstMsdkH265Enc *thiz = GST_MSDKH265ENC (encoder);
+  GstMsdkEnc *msdk_encoder = GST_MSDKENC (encoder);
 
   gst_msdkh265enc_add_cc (thiz, frame);
 
+  if (msdk_encoder->input_state->mastering_display_info)
+    gst_msdkh265enc_add_mdcv_sei (msdk_encoder, frame);
+
+  if (msdk_encoder->input_state->content_light_level)
+    gst_msdkh265enc_add_cll_sei (msdk_encoder, frame);
+
   return GST_FLOW_OK;
 }