Skip to content

Commit 8631c07

Browse files
committed
Fix HDR metadata property name in decklink consumer
and adds HDR metadata clamping and yaml docs for them.
1 parent e4f2c2a commit 8631c07

2 files changed

Lines changed: 204 additions & 32 deletions

File tree

src/modules/decklink/consumer_decklink.cpp

Lines changed: 69 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#define __STDC_FORMAT_MACROS /* see inttypes.h */
2121
#include "common.h"
2222
#include "mltdecklink_export.h"
23+
#include <algorithm>
2324
#include <framework/mlt.h>
2425
#include <limits.h>
2526
#include <pthread.h>
@@ -51,6 +52,18 @@ static const unsigned PREROLL_MINIMUM = 3;
5152
enum { OP_NONE = 0, OP_OPEN, OP_START, OP_STOP, OP_EXIT };
5253
enum { EOTF_SDR = 0, EOTF_HDR = 1, EOTF_PQ = 2, EOTF_HLG = 3 }; ///< CEA 861.3
5354

55+
static double clamp_hdr_metadata(mlt_properties properties,
56+
const char *name,
57+
double defaultValue,
58+
double minimum,
59+
double maximum)
60+
{
61+
double value = defaultValue;
62+
if (mlt_properties_get(properties, name))
63+
value = mlt_properties_get_double(properties, name);
64+
return std::clamp(value, minimum, maximum);
65+
}
66+
5467
class DeckLinkConsumer : public IDeckLinkVideoOutputCallback, public IDeckLinkAudioOutputCallback
5568
{
5669
private:
@@ -720,43 +733,70 @@ class DeckLinkConsumer : public IDeckLinkVideoOutputCallback, public IDeckLinkAu
720733
frameMeta->SetInt(bmdDeckLinkFrameMetadataHDRElectroOpticalTransferFunc,
721734
EOTF_PQ);
722735
// CEA/SMPTE HDR metadata
723-
// TODO: document and provide defaults for these
736+
const double hdrRedX
737+
= clamp_hdr_metadata(consumer_properties, "hdr_red_x", 0.7080, 0.0, 1.0);
738+
const double hdrRedY
739+
= clamp_hdr_metadata(consumer_properties, "hdr_red_y", 0.2920, 0.0, 1.0);
740+
const double hdrGreenX
741+
= clamp_hdr_metadata(consumer_properties, "hdr_green_x", 0.1700, 0.0, 1.0);
742+
const double hdrGreenY
743+
= clamp_hdr_metadata(consumer_properties, "hdr_green_y", 0.7970, 0.0, 1.0);
744+
const double hdrBlueX
745+
= clamp_hdr_metadata(consumer_properties, "hdr_blue_x", 0.1310, 0.0, 1.0);
746+
const double hdrBlueY
747+
= clamp_hdr_metadata(consumer_properties, "hdr_blue_y", 0.0460, 0.0, 1.0);
748+
const double hdrWhiteX
749+
= clamp_hdr_metadata(consumer_properties, "hdr_white_x", 0.3127, 0.0, 1.0);
750+
const double hdrWhiteY
751+
= clamp_hdr_metadata(consumer_properties, "hdr_white_y", 0.3290, 0.0, 1.0);
752+
const double hdrMaxLuminance = clamp_hdr_metadata(consumer_properties,
753+
"hdr_max_luminance",
754+
1000.0,
755+
1.0,
756+
65535.0);
757+
const double hdrMinLuminance = clamp_hdr_metadata(consumer_properties,
758+
"hdr_min_luminance",
759+
0.01,
760+
0.0001,
761+
6.5535);
762+
const double hdrMaxCll = clamp_hdr_metadata(consumer_properties,
763+
"hdr_max_cll",
764+
1000.0,
765+
1.0,
766+
65535.0);
767+
const double hdrMaxFall = clamp_hdr_metadata(consumer_properties,
768+
"hdr_max_fall",
769+
400.0,
770+
1.0,
771+
65535.0);
724772
decklinkFrame->SetFlags(decklinkFrame->GetFlags() | bmdFrameContainsHDRMetadata);
725-
frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRDisplayPrimariesRedX,
726-
mlt_properties_get_double(consumer_properties, "hdr_red_x"));
727-
frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRDisplayPrimariesRedY,
728-
mlt_properties_get_double(consumer_properties, "hdr_red_y"));
773+
frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRDisplayPrimariesRedX, hdrRedX);
774+
frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRDisplayPrimariesRedY, hdrRedY);
729775
frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRDisplayPrimariesGreenX,
730-
mlt_properties_get_double(consumer_properties,
731-
"hdr_green_x"));
776+
hdrGreenX);
732777
frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRDisplayPrimariesGreenY,
733-
mlt_properties_get_double(consumer_properties,
734-
"hdr.green_y"));
735-
frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRDisplayPrimariesBlueX,
736-
mlt_properties_get_double(consumer_properties,
737-
"hdr_blue_x"));
738-
frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRDisplayPrimariesBlueY,
739-
mlt_properties_get_double(consumer_properties,
740-
"hdr_blue_y"));
741-
frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRWhitePointX,
742-
mlt_properties_get_double(consumer_properties,
743-
"hdr_white_x"));
744-
frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRWhitePointY,
745-
mlt_properties_get_double(consumer_properties,
746-
"hdr_white_y"));
778+
hdrGreenY);
779+
frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRDisplayPrimariesBlueX, hdrBlueX);
780+
frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRDisplayPrimariesBlueY, hdrBlueY);
781+
frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRWhitePointX, hdrWhiteX);
782+
frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRWhitePointY, hdrWhiteY);
747783
frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRMaxDisplayMasteringLuminance,
748-
mlt_properties_get_double(consumer_properties,
749-
"hdr_max_luminance"));
784+
hdrMaxLuminance);
750785
frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRMinDisplayMasteringLuminance,
751-
mlt_properties_get_double(consumer_properties,
752-
"hdr_min_luminance"));
786+
hdrMinLuminance);
753787
frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRMaximumContentLightLevel,
754-
mlt_properties_get_double(consumer_properties,
755-
"hdr_max_cll"));
788+
hdrMaxCll);
756789
frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRMaximumFrameAverageLightLevel,
757-
mlt_properties_get_double(consumer_properties,
758-
"hdr_max_fall"));
790+
hdrMaxFall);
791+
} else {
792+
// Frames are reused from a pool, so explicitly clear any stale HDR transfer
793+
// and static metadata flag left behind by prior PQ/HLG output.
794+
frameMeta->SetInt(bmdDeckLinkFrameMetadataHDRElectroOpticalTransferFunc,
795+
EOTF_SDR);
796+
decklinkFrame->SetFlags(decklinkFrame->GetFlags()
797+
& ~bmdFrameContainsHDRMetadata);
759798
}
799+
frameMeta->Release();
760800
} else {
761801
mlt_log_debug(getConsumer(),
762802
"Unable to get IDeckLinkVideoFrameMutableMetadataExtensions\n");

src/modules/decklink/consumer_decklink.yml

Lines changed: 135 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ type: consumer
33
identifier: decklink
44
title: Blackmagic Design DeckLink Output
55
version: 4
6-
copyright: Copyright (C) 2010-2025 Meltytech, LLC
6+
copyright: Copyright (C) 2010-2026 Meltytech, LLC
77
license: LGPL
88
language: en
99
creator: Dan Dennedy
@@ -15,7 +15,12 @@ description: >
1515
HDMI cards.
1616
notes: >
1717
Please ensure that you use a MLT profile that is compatible with a broadcast
18-
standard which the card you are using supports.
18+
standard which the card you are using supports. HDR output metadata follows
19+
the consumer's color transfer characteristic. When color_trc is set to
20+
arib-std-b67, the DeckLink output advertises HLG. When color_trc is set to
21+
smpte2084, the DeckLink output advertises PQ and the HDR static metadata
22+
properties documented below are applied. Any other transfer clears HDR
23+
metadata and advertises SDR.
1924
bugs:
2025
- Only internal keying is supported at this time.
2126
- Only 8-bit Y'CbCr or RGBA (key) is supported at this time.
@@ -108,11 +113,138 @@ parameters:
108113
default: 0
109114
widget: checkbox
110115

116+
- identifier: colorspace
117+
title: Colorspace
118+
type: integer
119+
description: >
120+
Set the output colorspace metadata. BT.2020 maps to DeckLink Rec.2020,
121+
BT.601 maps to DeckLink Rec.601, and all other values default to Rec.709.
122+
values:
123+
- 240 # SMPTE 240M
124+
- 601 # ITU-R BT.601
125+
- 709 # ITU-R BT.709
126+
- 2020 # ITU-R BT.2020 non-constant luminance
127+
128+
- identifier: color_trc
129+
title: Transfer characteristic
130+
type: string
131+
description: >
132+
Set the output transfer characteristic metadata. Use arib-std-b67 for
133+
HLG or smpte2084 for PQ HDR10-style signaling. Any other value is treated
134+
as SDR and clears the DeckLink HDR metadata flag.
135+
values:
136+
- bt709
137+
- smpte170m
138+
- smpte240m
139+
- bt470bg
140+
- arib-std-b67
141+
- smpte2084
142+
143+
- identifier: hdr_red_x
144+
title: HDR primary red X
145+
type: float
146+
description: PQ-only static HDR metadata. Red display primary chromaticity X.
147+
minimum: 0
148+
maximum: 1
149+
default: 0.708
150+
151+
- identifier: hdr_red_y
152+
title: HDR primary red Y
153+
type: float
154+
description: PQ-only static HDR metadata. Red display primary chromaticity Y.
155+
minimum: 0
156+
maximum: 1
157+
default: 0.292
158+
159+
- identifier: hdr_green_x
160+
title: HDR primary green X
161+
type: float
162+
description: PQ-only static HDR metadata. Green display primary chromaticity X.
163+
minimum: 0
164+
maximum: 1
165+
default: 0.170
166+
167+
- identifier: hdr_green_y
168+
title: HDR primary green Y
169+
type: float
170+
description: PQ-only static HDR metadata. Green display primary chromaticity Y.
171+
minimum: 0
172+
maximum: 1
173+
default: 0.797
174+
175+
- identifier: hdr_blue_x
176+
title: HDR primary blue X
177+
type: float
178+
description: PQ-only static HDR metadata. Blue display primary chromaticity X.
179+
minimum: 0
180+
maximum: 1
181+
default: 0.131
182+
183+
- identifier: hdr_blue_y
184+
title: HDR primary blue Y
185+
type: float
186+
description: PQ-only static HDR metadata. Blue display primary chromaticity Y.
187+
minimum: 0
188+
maximum: 1
189+
default: 0.046
190+
191+
- identifier: hdr_white_x
192+
title: HDR white point X
193+
type: float
194+
description: PQ-only static HDR metadata. Display white point chromaticity X.
195+
minimum: 0
196+
maximum: 1
197+
default: 0.3127
198+
199+
- identifier: hdr_white_y
200+
title: HDR white point Y
201+
type: float
202+
description: PQ-only static HDR metadata. Display white point chromaticity Y.
203+
minimum: 0
204+
maximum: 1
205+
default: 0.329
206+
207+
- identifier: hdr_max_luminance
208+
title: HDR mastering max luminance
209+
type: float
210+
description: PQ-only static HDR metadata. Maximum mastering display luminance.
211+
minimum: 1
212+
maximum: 65535
213+
default: 1000
214+
unit: cd/m2
215+
216+
- identifier: hdr_min_luminance
217+
title: HDR mastering min luminance
218+
type: float
219+
description: PQ-only static HDR metadata. Minimum mastering display luminance.
220+
minimum: 0.0001
221+
maximum: 6.5535
222+
default: 0.01
223+
unit: cd/m2
224+
225+
- identifier: hdr_max_cll
226+
title: HDR MaxCLL
227+
type: float
228+
description: PQ-only static HDR metadata. Maximum Content Light Level.
229+
minimum: 1
230+
maximum: 65535
231+
default: 1000
232+
unit: cd/m2
233+
234+
- identifier: hdr_max_fall
235+
title: HDR MaxFALL
236+
type: float
237+
description: PQ-only static HDR metadata. Maximum Frame-Average Light Level.
238+
minimum: 1
239+
maximum: 65535
240+
default: 400
241+
unit: cd/m2
242+
111243
- identifier: terminate_on_pause
112244
title: Stop automatically
113245
type: boolean
114246
description: >
115247
Whether to stop playback at the end of the producer or when playback
116248
is paused.
117-
default: 0
249+
default: no
118250
widget: checkbox

0 commit comments

Comments
 (0)