mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
matroskademux: Add support parsing HDR metadata
Set SMPTE ST 2086 mastering-display-metadata and content-light-level to caps, if any
This commit is contained in:
parent
53fedc43ae
commit
61f9a2a415
3 changed files with 175 additions and 1 deletions
|
@ -463,6 +463,110 @@ gst_matroska_demux_add_stream_headers_to_caps (GstMatroskaDemux * demux,
|
|||
g_value_unset (&buf_val);
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_matroska_demux_parse_mastering_metadata (GstMatroskaDemux * demux,
|
||||
GstEbmlRead * ebml, GstMatroskaTrackVideoContext * video_context)
|
||||
{
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
GstVideoMasteringDisplayInfo minfo;
|
||||
guint32 id;
|
||||
gdouble num;
|
||||
/* Precision defined by HEVC specification */
|
||||
const guint chroma_den = 50000;
|
||||
const guint luma_den = 10000;
|
||||
|
||||
gst_video_mastering_display_info_init (&minfo);
|
||||
|
||||
DEBUG_ELEMENT_START (demux, ebml, "MasteringMetadata");
|
||||
|
||||
if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
|
||||
goto beach;
|
||||
|
||||
while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
|
||||
if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
|
||||
goto beach;
|
||||
|
||||
/* all sub elements have float type */
|
||||
if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK)
|
||||
goto beach;
|
||||
|
||||
/* chromaticity should be in [0, 1] range */
|
||||
if (id >= GST_MATROSKA_ID_PRIMARYRCHROMATICITYX &&
|
||||
id <= GST_MATROSKA_ID_WHITEPOINTCHROMATICITYY) {
|
||||
if (num < 0 || num > 1.0) {
|
||||
GST_WARNING_OBJECT (demux, "0x%x has invalid value %f", id, num);
|
||||
goto beach;
|
||||
}
|
||||
} else if (id == GST_MATROSKA_ID_LUMINANCEMAX ||
|
||||
id == GST_MATROSKA_ID_LUMINANCEMIN) {
|
||||
/* Note: webM spec said valid range is [0, 999.9999] but
|
||||
* 1000 cd/m^2 is generally used value on HDR. Just check guint range here.
|
||||
* See https://www.webmproject.org/docs/container/#LuminanceMax
|
||||
*/
|
||||
if (num < 0 || num > (gdouble) (G_MAXUINT32 / luma_den)) {
|
||||
GST_WARNING_OBJECT (demux, "0x%x has invalid value %f", id, num);
|
||||
goto beach;
|
||||
}
|
||||
}
|
||||
|
||||
switch (id) {
|
||||
case GST_MATROSKA_ID_PRIMARYRCHROMATICITYX:
|
||||
minfo.Rx_n = (guint) round (num * chroma_den);
|
||||
minfo.Rx_d = chroma_den;
|
||||
break;
|
||||
case GST_MATROSKA_ID_PRIMARYRCHROMATICITYY:
|
||||
minfo.Ry_n = (guint) round (num * chroma_den);
|
||||
minfo.Ry_d = chroma_den;
|
||||
break;
|
||||
case GST_MATROSKA_ID_PRIMARYGCHROMATICITYX:
|
||||
minfo.Gx_n = (guint) round (num * chroma_den);
|
||||
minfo.Gx_d = chroma_den;
|
||||
break;
|
||||
case GST_MATROSKA_ID_PRIMARYGCHROMATICITYY:
|
||||
minfo.Gy_n = (guint) round (num * chroma_den);
|
||||
minfo.Gy_d = chroma_den;
|
||||
break;
|
||||
case GST_MATROSKA_ID_PRIMARYBCHROMATICITYX:
|
||||
minfo.Bx_n = (guint) round (num * chroma_den);
|
||||
minfo.Bx_d = chroma_den;
|
||||
break;
|
||||
case GST_MATROSKA_ID_PRIMARYBCHROMATICITYY:
|
||||
minfo.By_n = (guint) round (num * chroma_den);
|
||||
minfo.By_d = chroma_den;
|
||||
break;
|
||||
case GST_MATROSKA_ID_WHITEPOINTCHROMATICITYX:
|
||||
minfo.Wx_n = (guint) round (num * chroma_den);
|
||||
minfo.Wx_d = chroma_den;
|
||||
break;
|
||||
case GST_MATROSKA_ID_WHITEPOINTCHROMATICITYY:
|
||||
minfo.Wy_n = (guint) round (num * chroma_den);
|
||||
minfo.Wy_d = chroma_den;
|
||||
break;
|
||||
case GST_MATROSKA_ID_LUMINANCEMAX:
|
||||
minfo.max_luma_n = (guint) round (num * luma_den);
|
||||
minfo.max_luma_d = luma_den;
|
||||
break;
|
||||
case GST_MATROSKA_ID_LUMINANCEMIN:
|
||||
minfo.min_luma_n = (guint) round (num * luma_den);
|
||||
minfo.min_luma_d = luma_den;
|
||||
break;
|
||||
default:
|
||||
GST_FIXME_OBJECT (demux,
|
||||
"Unsupported subelement 0x%x in MasteringMetadata", id);
|
||||
ret = gst_ebml_read_skip (ebml);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
video_context->mastering_display_info = minfo;
|
||||
video_context->mastering_display_info_present = TRUE;
|
||||
|
||||
beach:
|
||||
DEBUG_ELEMENT_STOP (demux, ebml, "MasteringMetadata", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_matroska_demux_parse_colour (GstMatroskaDemux * demux, GstEbmlRead * ebml,
|
||||
GstMatroskaTrackVideoContext * video_context)
|
||||
|
@ -631,6 +735,40 @@ gst_matroska_demux_parse_colour (GstMatroskaDemux * demux, GstEbmlRead * ebml,
|
|||
break;
|
||||
}
|
||||
|
||||
case GST_MATROSKA_ID_MASTERINGMETADATA:{
|
||||
if ((ret =
|
||||
gst_matroska_demux_parse_mastering_metadata (demux, ebml,
|
||||
video_context)) != GST_FLOW_OK)
|
||||
goto beach;
|
||||
break;
|
||||
}
|
||||
|
||||
case GST_MATROSKA_ID_MAXCLL:{
|
||||
if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
|
||||
goto beach;
|
||||
if (num >= G_MAXUINT32) {
|
||||
GST_WARNING_OBJECT (demux,
|
||||
"Too large maxCLL value %" G_GUINT64_FORMAT, num);
|
||||
} else {
|
||||
video_context->content_light_level.maxCLL_n = num;
|
||||
video_context->content_light_level.maxCLL_d = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case GST_MATROSKA_ID_MAXFALL:{
|
||||
if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
|
||||
goto beach;
|
||||
if (num >= G_MAXUINT32) {
|
||||
GST_WARNING_OBJECT (demux,
|
||||
"Too large maxFALL value %" G_GUINT64_FORMAT, num);
|
||||
} else {
|
||||
video_context->content_light_level.maxFALL_n = num;
|
||||
video_context->content_light_level.maxFALL_d = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
GST_FIXME_OBJECT (demux, "Unsupported subelement 0x%x in Colour", id);
|
||||
ret = gst_ebml_read_skip (ebml);
|
||||
|
@ -6429,6 +6567,21 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *
|
|||
g_free (colorimetry);
|
||||
}
|
||||
|
||||
if (videocontext->mastering_display_info_present) {
|
||||
if (!gst_video_mastering_display_info_add_to_caps
|
||||
(&videocontext->mastering_display_info, caps)) {
|
||||
GST_WARNING ("couldn't set mastering display info to caps");
|
||||
}
|
||||
}
|
||||
|
||||
if (videocontext->content_light_level.maxCLL_n &&
|
||||
videocontext->content_light_level.maxFALL_n) {
|
||||
if (!gst_video_content_light_level_add_to_caps
|
||||
(&videocontext->content_light_level, caps)) {
|
||||
GST_WARNING ("couldn't set content light level to caps");
|
||||
}
|
||||
}
|
||||
|
||||
caps = gst_caps_simplify (caps);
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,9 @@ gst_matroska_track_init_video_context (GstMatroskaTrackContext ** p_context)
|
|||
video_context->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_UNKNOWN;
|
||||
video_context->colorimetry.transfer = GST_VIDEO_TRANSFER_UNKNOWN;
|
||||
video_context->colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_UNKNOWN;
|
||||
|
||||
gst_video_mastering_display_info_init
|
||||
(&video_context->mastering_display_info);
|
||||
gst_video_content_light_level_init (&video_context->content_light_level);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -145,6 +145,20 @@
|
|||
#define GST_MATROSKA_ID_VIDEORANGE 0x55B9
|
||||
#define GST_MATROSKA_ID_VIDEOTRANSFERCHARACTERISTICS 0x55BA
|
||||
#define GST_MATROSKA_ID_VIDEOPRIMARIES 0x55BB
|
||||
#define GST_MATROSKA_ID_MAXCLL 0x55BC
|
||||
#define GST_MATROSKA_ID_MAXFALL 0x55BD
|
||||
#define GST_MATROSKA_ID_MASTERINGMETADATA 0x55D0
|
||||
/* IDs in the MasteringMetadata */
|
||||
#define GST_MATROSKA_ID_PRIMARYRCHROMATICITYX 0x55D1
|
||||
#define GST_MATROSKA_ID_PRIMARYRCHROMATICITYY 0x55D2
|
||||
#define GST_MATROSKA_ID_PRIMARYGCHROMATICITYX 0x55D3
|
||||
#define GST_MATROSKA_ID_PRIMARYGCHROMATICITYY 0x55D4
|
||||
#define GST_MATROSKA_ID_PRIMARYBCHROMATICITYX 0x55D5
|
||||
#define GST_MATROSKA_ID_PRIMARYBCHROMATICITYY 0x55D6
|
||||
#define GST_MATROSKA_ID_WHITEPOINTCHROMATICITYX 0x55D7
|
||||
#define GST_MATROSKA_ID_WHITEPOINTCHROMATICITYY 0x55D8
|
||||
#define GST_MATROSKA_ID_LUMINANCEMAX 0x55D9
|
||||
#define GST_MATROSKA_ID_LUMINANCEMIN 0x55DA
|
||||
|
||||
/* IDs in the TrackAudio master */
|
||||
#define GST_MATROSKA_ID_AUDIOSAMPLINGFREQ 0xB5
|
||||
|
@ -627,6 +641,11 @@ typedef struct _GstMatroskaTrackVideoContext {
|
|||
|
||||
GstBuffer *dirac_unit;
|
||||
GstVideoColorimetry colorimetry;
|
||||
|
||||
GstVideoMasteringDisplayInfo mastering_display_info;
|
||||
gboolean mastering_display_info_present;
|
||||
|
||||
GstVideoContentLightLevel content_light_level;
|
||||
} GstMatroskaTrackVideoContext;
|
||||
|
||||
typedef struct _GstMatroskaTrackAudioContext {
|
||||
|
|
Loading…
Reference in a new issue