diff --git a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkh265enc.c b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkh265enc.c index 2b9761cda97..bf3effa9cdf 100644 --- a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkh265enc.c +++ b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkh265enc.c @@ -234,119 +234,13 @@ 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; } @@ -394,6 +288,67 @@ gst_msdkh265enc_set_format (GstMsdkEnc * encoder) return TRUE; } +static void +_get_hdr_sei (GstMsdkEnc * encoder) +{ + GstVideoCodecState *state; + GstVideoMasteringDisplayInfo mdcv_info; + GstVideoContentLightLevel cll_info; + GstMsdkH265Enc *h265enc = GST_MSDKH265ENC (encoder); + const guint chroma_den = 50000; + const guint luma_den = 10000; + + h265enc->have_mdcv = h265enc->have_cll = FALSE; + state = encoder->input_state; + if (gst_video_mastering_display_info_from_caps (&mdcv_info, state->caps)) { + memset (&h265enc->mdcv, 0, sizeof (mfxExtMasteringDisplayColourVolume)); + h265enc->mdcv.Header.BufferId = MFX_EXTBUFF_MASTERING_DISPLAY_COLOUR_VOLUME; + h265enc->mdcv.Header.BufferSz = sizeof (mfxExtMasteringDisplayColourVolume); + h265enc->mdcv.InsertPayloadToggle = MFX_PAYLOAD_IDR; + + /* According to HEVC spec, display primaries order is G,B,R */ + h265enc->mdcv.DisplayPrimariesX[0] = + MIN ((mdcv_info.display_primaries[1].x * chroma_den), chroma_den); + h265enc->mdcv.DisplayPrimariesY[0] = + MIN ((mdcv_info.display_primaries[1].y * chroma_den), chroma_den); + h265enc->mdcv.DisplayPrimariesX[1] = + MIN ((mdcv_info.display_primaries[2].x * chroma_den), chroma_den); + h265enc->mdcv.DisplayPrimariesY[1] = + MIN ((mdcv_info.display_primaries[2].y * chroma_den), chroma_den); + h265enc->mdcv.DisplayPrimariesX[2] = + MIN ((mdcv_info.display_primaries[0].x * chroma_den), chroma_den); + h265enc->mdcv.DisplayPrimariesY[2] = + MIN ((mdcv_info.display_primaries[0].y * chroma_den), chroma_den); + + h265enc->mdcv.WhitePointX = + MIN ((mdcv_info.white_point.x * chroma_den), chroma_den); + h265enc->mdcv.WhitePointY = + MIN ((mdcv_info.white_point.y * chroma_den), chroma_den); + + h265enc->mdcv.MaxDisplayMasteringLuminance = + mdcv_info.max_display_mastering_luminance * luma_den; + h265enc->mdcv.MinDisplayMasteringLuminance = + MIN ((mdcv_info.min_display_mastering_luminance * luma_den), + h265enc->mdcv.MaxDisplayMasteringLuminance); + h265enc->have_mdcv = TRUE; + } + + if (gst_video_content_light_level_from_caps (&cll_info, state->caps)) { + memset (&h265enc->cll, 0, sizeof (mfxExtContentLightLevelInfo)); + h265enc->cll.Header.BufferId = MFX_EXTBUFF_CONTENT_LIGHT_LEVEL_INFO; + h265enc->cll.Header.BufferSz = sizeof (mfxExtContentLightLevelInfo); + h265enc->cll.InsertPayloadToggle = MFX_PAYLOAD_IDR; + + h265enc->cll.MaxContentLightLevel = + MIN (cll_info.max_content_light_level, 65535); + h265enc->cll.MaxPicAverageLightLevel = + MIN (cll_info.max_frame_average_light_level, 65535); + h265enc->have_cll = TRUE; + } + + return; +} + static gboolean gst_msdkh265enc_configure (GstMsdkEnc * encoder) { @@ -543,6 +498,13 @@ gst_msdkh265enc_configure (GstMsdkEnc * encoder) encoder->param.mfx.LowPower = h265enc->tune_mode; + /* Set HDR SEI */ + _get_hdr_sei (encoder); + if (h265enc->have_mdcv) + gst_msdkenc_add_extra_param (encoder, (mfxExtBuffer *) & h265enc->mdcv); + if (h265enc->have_cll) + gst_msdkenc_add_extra_param (encoder, (mfxExtBuffer *) & h265enc->cll); + return TRUE; } diff --git a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkh265enc.h b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkh265enc.h index 1d871066df7..6a255b9415b 100644 --- a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkh265enc.h +++ b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkh265enc.h @@ -76,6 +76,12 @@ struct _GstMsdkH265Enc /* roi[0] for current ROI and roi[1] for previous ROI */ mfxExtEncoderROI roi[2]; + /* HDR SEI */ + mfxExtMasteringDisplayColourVolume mdcv; + mfxExtContentLightLevelInfo cll; + gboolean have_mdcv; + gboolean have_cll; + GstH265Parser *parser; GArray *cc_sei_array; };