Skip to content
Snippets Groups Projects

decklinkvideosrc: add HDR10 static metadata to src caps

Closed Jakub Adam requested to merge xhaakon/gst-plugins-bad:decklink-hdr into master
Compare and
2 files
+ 119
0
Compare changes
  • Side-by-side
  • Inline
Files
2
@@ -185,6 +185,9 @@ typedef struct
BMDPixelFormat format;
GstVideoTimeCode *tc;
gboolean no_signal;
gboolean has_hdr_metadata;
GstVideoMasteringDisplayInfo mdi;
GstVideoContentLightLevel cll;
} CaptureFrame;
static void
@@ -779,6 +782,95 @@ gst_decklink_video_src_update_time_mapping (GstDecklinkVideoSrc * self,
}
}
static void
gst_decklink_video_src_extract_hdr_metadata (GstDecklinkVideoSrc * self,
CaptureFrame *f)
{
f->has_hdr_metadata = f->frame->GetFlags() & bmdFrameContainsHDRMetadata;
if (f->has_hdr_metadata) {
IDeckLinkVideoFrameMetadataExtensions *meta;
HRESULT ret;
ret = f->frame->QueryInterface (IID_IDeckLinkVideoFrameMetadataExtensions,
(void **) &meta);
if (ret != S_OK) {
GST_WARNING ("frame does not have metadata extension: 0x%X", ret);
} else {
GstVideoMasteringDisplayInfo *mdi = &f->mdi;
GstVideoContentLightLevel *cll = &f->cll;
double val;
#define META_GET_FLOAT(ID) \
if (meta->GetFloat (ID, &val) != S_OK) { \
GST_WARNING ("could not read " #ID); \
goto invalid_meta; \
}
META_GET_FLOAT (bmdDeckLinkFrameMetadataHDRDisplayPrimariesRedX)
mdi->display_primaries[0].x = val / 0.00002;
META_GET_FLOAT (bmdDeckLinkFrameMetadataHDRDisplayPrimariesRedY)
mdi->display_primaries[0].y = val / 0.00002;
META_GET_FLOAT (bmdDeckLinkFrameMetadataHDRDisplayPrimariesGreenX)
mdi->display_primaries[1].x = val / 0.00002;
META_GET_FLOAT (bmdDeckLinkFrameMetadataHDRDisplayPrimariesGreenY)
mdi->display_primaries[1].y = val / 0.00002;
META_GET_FLOAT (bmdDeckLinkFrameMetadataHDRDisplayPrimariesBlueX)
mdi->display_primaries[2].x = val / 0.00002;
META_GET_FLOAT (bmdDeckLinkFrameMetadataHDRDisplayPrimariesBlueY)
mdi->display_primaries[2].y = val / 0.00002;
META_GET_FLOAT (bmdDeckLinkFrameMetadataHDRWhitePointX)
mdi->white_point.x = val / 0.00002;
META_GET_FLOAT (bmdDeckLinkFrameMetadataHDRWhitePointY)
mdi->white_point.y = val / 0.00002;
META_GET_FLOAT (bmdDeckLinkFrameMetadataHDRMaxDisplayMasteringLuminance)
mdi->max_display_mastering_luminance = val / 0.0001;
META_GET_FLOAT (bmdDeckLinkFrameMetadataHDRMinDisplayMasteringLuminance)
mdi->min_display_mastering_luminance = val / 0.0001;
META_GET_FLOAT (bmdDeckLinkFrameMetadataHDRMaximumContentLightLevel)
cll->max_content_light_level = val;
META_GET_FLOAT (bmdDeckLinkFrameMetadataHDRMaximumFrameAverageLightLevel)
cll->max_frame_average_light_level = val;
if (GST_LEVEL_TRACE <= gst_debug_category_get_threshold (GST_CAT_DEFAULT)) {
GST_LOG_OBJECT (self, "frame HDR metadata:\n"
"R: x=%f y=%f, G: x=%f y=%f, B: x=%f y=%f\n"
"White point: x=%f y=%f\n"
"Mastering display luminance: min=%f cd/m² max=%f cd/m²\n"
"Max light level: content=%d cd/m² frame_avg=%d cd/m²",
mdi->display_primaries[0].x * 0.00002, mdi->display_primaries[0].y * 0.00002,
mdi->display_primaries[1].x * 0.00002, mdi->display_primaries[1].y * 0.00002,
mdi->display_primaries[2].x * 0.00002, mdi->display_primaries[2].y * 0.00002,
mdi->white_point.x * 0.00002, mdi->white_point.y * 0.00002,
mdi->min_display_mastering_luminance * 0.0001, mdi->max_display_mastering_luminance * 0.0001,
cll->max_content_light_level, cll->max_frame_average_light_level);
}
goto done;
invalid_meta:
f->has_hdr_metadata = FALSE;
done:
meta->Release ();
}
} else {
GST_DEBUG_OBJECT (self, "frame has no HDR metadata");
}
}
static void
gst_decklink_video_src_got_frame (GstElement * element,
IDeckLinkVideoInputFrame * frame, GstDecklinkModeEnum mode,
@@ -931,6 +1023,8 @@ gst_decklink_video_src_got_frame (GstElement * element,
f.tc = NULL;
}
gst_decklink_video_src_extract_hdr_metadata (self, &f);
frame->AddRef ();
gst_queue_array_push_tail_struct (self->current_frames, &f);
g_cond_signal (&self->cond);
@@ -1280,6 +1374,24 @@ retry:
return GST_FLOW_NOT_NEGOTIATED;
}
}
if (self->caps_has_hdr_metadata != f.has_hdr_metadata) {
GST_DEBUG_OBJECT (self, "HDR metadata flag changed to %d",
f.has_hdr_metadata);
caps_changed = TRUE;
self->caps_has_hdr_metadata = f.has_hdr_metadata;
}
if (f.has_hdr_metadata) {
if (!gst_video_mastering_display_info_is_equal (&self->caps_mdi, &f.mdi)) {
GST_DEBUG_OBJECT (self, "Mastering display info changed");
caps_changed = TRUE;
self->caps_mdi = f.mdi;
}
if (!gst_video_content_light_level_is_equal (&self->caps_cll, &f.cll)) {
GST_DEBUG_OBJECT (self, "Content light level changed");
caps_changed = TRUE;
self->caps_cll = f.cll;
}
}
/* 1 ns error can be just a rounding error, so that's OK. The Decklink
* drivers give us a really steady stream time, so anything above 1 ns can't
@@ -1314,6 +1426,10 @@ retry:
self->last_afd_bar_vbi_line_field2 = -1;
caps = gst_decklink_mode_get_caps (f.mode, f.format, TRUE);
gst_video_info_from_caps (&self->info, caps);
if (self->caps_has_hdr_metadata) {
gst_video_mastering_display_info_add_to_caps (&f.mdi, caps);
gst_video_content_light_level_add_to_caps (&f.cll, caps);
}
gst_base_src_set_caps (GST_BASE_SRC_CAST (bsrc), caps);
gst_element_post_message (GST_ELEMENT_CAST (self),
gst_message_new_latency (GST_OBJECT_CAST (self)));
Loading