diff --git a/lib/dash/dash_parser.js b/lib/dash/dash_parser.js index 08346116e5..aff6e43444 100644 --- a/lib/dash/dash_parser.js +++ b/lib/dash/dash_parser.js @@ -896,7 +896,19 @@ shaka.dash.DashParser = class { // Parallel for HLS VIDEO-RANGE as defined in DASH-IF IOP v4.3 6.2.5.1. let videoRange; - const videoRangeScheme = 'urn:mpeg:mpegB:cicp:TransferCharacteristics'; + + // Ref. https://dashif.org/docs/DASH-IF-IOP-v4.3.pdf + // If signaled, a Supplemental or Essential Property descriptor + // shall be used, with the schemeIdUri set to + // urn:mpeg:mpegB:cicp: as defined in + // ISO/IEC 23001-8 [49] and one of the + // following: ColourPrimaries, TransferCharacteristics, + // or MatrixCoefficients. + const scheme = 'urn:mpeg:mpegB:cicp'; + const transferCharacteristicsScheme = `${scheme}:TransferCharacteristics`; + const colourPrimariesScheme = `${scheme}:ColourPrimaries`; + const matrixCoefficientsScheme = `${scheme}:MatrixCoefficients`; + const getVideoRangeFromTransferCharacteristicCICP = (cicp) => { switch (cicp) { case 1: @@ -922,10 +934,13 @@ shaka.dash.DashParser = class { const schemeId = prop.getAttribute('schemeIdUri'); if (schemeId == 'http://dashif.org/guidelines/trickmode') { trickModeFor = prop.getAttribute('value'); - } else if (schemeId == videoRangeScheme) { + } else if (schemeId == transferCharacteristicsScheme) { videoRange = getVideoRangeFromTransferCharacteristicCICP( parseInt(prop.getAttribute('value'), 10), ); + } else if (schemeId == colourPrimariesScheme || + schemeId == matrixCoefficientsScheme) { + continue; } else { unrecognizedEssentialProperty = true; } @@ -935,7 +950,7 @@ shaka.dash.DashParser = class { XmlUtils.findChildren(elem, 'SupplementalProperty'); for (const prop of supplementalProperties) { const schemeId = prop.getAttribute('schemeIdUri'); - if (schemeId == videoRangeScheme) { + if (schemeId == transferCharacteristicsScheme) { videoRange = getVideoRangeFromTransferCharacteristicCICP( parseInt(prop.getAttribute('value'), 10), ); diff --git a/test/dash/dash_parser_manifest_unit.js b/test/dash/dash_parser_manifest_unit.js index e0d073a6e9..9da853692d 100644 --- a/test/dash/dash_parser_manifest_unit.js +++ b/test/dash/dash_parser_manifest_unit.js @@ -2068,6 +2068,66 @@ describe('DashParser Manifest', () => { expect(stream.hdr).toBe('PQ'); }); + it('supports SupplementalProperty MatrixCoefficients', async () => { + // (DASH-IF IOP v4.3 6.2.5.1.) + const scheme = cicpScheme('MatrixCoefficients'); + const manifestText = [ + '', + ' ', + ' ', + ` `, + ' ', + ' v-sd.mp4', + ' ', + ' ', + ' ', + ' ', + ' ', + ' a-en.mp4', + ' ', + ' ', + ' ', + ' ', + '', + ].join('\n'); + + fakeNetEngine.setResponseText('dummy://foo', manifestText); + + /** @type {shaka.extern.Manifest} */ + const manifest = await parser.start('dummy://foo', playerInterface); + expect(manifest.variants.length).toBe(1); + }); + + it('supports SupplementalProperty ColourPrimaries', async () => { + // (DASH-IF IOP v4.3 6.2.5.1.) + const scheme = cicpScheme('ColourPrimaries'); + const manifestText = [ + '', + ' ', + ' ', + ` `, + ' ', + ' v-sd.mp4', + ' ', + ' ', + ' ', + ' ', + ' ', + ' a-en.mp4', + ' ', + ' ', + ' ', + ' ', + '', + ].join('\n'); + + fakeNetEngine.setResponseText('dummy://foo', manifestText); + + /** @type {shaka.extern.Manifest} */ + const manifest = await parser.start('dummy://foo', playerInterface); + expect(manifest.variants.length).toBe(1); + }); + it('supports HDR signaling via EssentialProperty', async () => { // (DASH-IF IOP v4.3 6.2.5.1.) const hdrScheme = cicpScheme('TransferCharacteristics'); @@ -2101,6 +2161,66 @@ describe('DashParser Manifest', () => { expect(stream.hdr).toBe('HLG'); }); + it('supports EssentialProperty MatrixCoefficients', async () => { + // (DASH-IF IOP v4.3 6.2.5.1.) + const hdrScheme = cicpScheme('MatrixCoefficients'); + const manifestText = [ + '', + ' ', + ' ', + ` `, + ' ', + ' v-sd.mp4', + ' ', + ' ', + ' ', + ' ', + ' ', + ' a-en.mp4', + ' ', + ' ', + ' ', + ' ', + '', + ].join('\n'); + + fakeNetEngine.setResponseText('dummy://foo', manifestText); + + /** @type {shaka.extern.Manifest} */ + const manifest = await parser.start('dummy://foo', playerInterface); + expect(manifest.variants.length).toBe(1); + }); + + it('supports EssentialProperty ColourPrimaries', async () => { + // (DASH-IF IOP v4.3 6.2.5.1.) + const hdrScheme = cicpScheme('ColourPrimaries'); + const manifestText = [ + '', + ' ', + ' ', + ` `, + ' ', + ' v-sd.mp4', + ' ', + ' ', + ' ', + ' ', + ' ', + ' a-en.mp4', + ' ', + ' ', + ' ', + ' ', + '', + ].join('\n'); + + fakeNetEngine.setResponseText('dummy://foo', manifestText); + + /** @type {shaka.extern.Manifest} */ + const manifest = await parser.start('dummy://foo', playerInterface); + expect(manifest.variants.length).toBe(1); + }); + it('supports SDR signalling via EssentialProperty', async () => { // (DASH-IF IOP v4.3 6.2.5.1.) const scheme = cicpScheme('TransferCharacteristics');