Skip to content

Commit

Permalink
supported essentialProp Scheme+Value using RegExp in Settings.js (#4411)
Browse files Browse the repository at this point in the history
* add capability to pre-define supported essentialProperty scheme+value pairs in addition to scheme-only settings, value may use RegExp; added SDR-settings (Rec.601) as known properties.

* move essential property descriptor definition

* rename constants

* rename constants (also in comment)

* changing constants to DescriptorType
  • Loading branch information
stschr authored Mar 14, 2024
1 parent c93a08e commit 6155a68
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 21 deletions.
20 changes: 16 additions & 4 deletions src/core/Settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,13 @@ import Events from './events/Events.js';
* enableManifestTimescaleMismatchFix: false,
* capabilities: {
* filterUnsupportedEssentialProperties: true,
* supportedEssentialProperties: Constants.THUMBNAILS_SCHEME_ID_URIS,
* supportedEssentialProperties: [
{ schemeIdUri: Constants.FONT_DOWNLOAD_DVB_SCHEME },
{ schemeIdUri: Constants.COLOUR_PRIMARIES_SCHEME_ID_URI, value: /5|6/ },
{ schemeIdUri: Constants.MATRIX_COEFFICIENTS_SCHEME_ID_URI, value: /5|6/ },
{ schemeIdUri: Constants.TRANSFER_CHARACTERISTICS_SCHEME_ID_URI, value: '6' },
...Constants.THUMBNAILS_SCHEME_ID_URIS.map(ep => { return { 'schemeIdUri': ep }; })
],
* useMediaCapabilitiesApi: false
* },
* timeShiftBuffer: {
Expand Down Expand Up @@ -650,7 +656,7 @@ import Events from './events/Events.js';
* @typedef {Object} Capabilities
* @property {boolean} [filterUnsupportedEssentialProperties=true]
* Enable to filter all the AdaptationSets and Representations which contain an unsupported \<EssentialProperty\> element.
* @property {Array.<string>} [supportedEssentialProperties=Constants.THUMBNAILS_SCHEME_ID_URIS]
* @property {Array.<string>} [supportedEssentialProperties]
* List of supported \<EssentialProperty\> elements
* @property {boolean} [useMediaCapabilitiesApi=false]
* Enable to use the MediaCapabilities API to check whether codecs are supported. If disabled MSE.isTypeSupported will be used instead.
Expand Down Expand Up @@ -1032,7 +1038,13 @@ function Settings() {
enableManifestTimescaleMismatchFix: false,
capabilities: {
filterUnsupportedEssentialProperties: true,
supportedEssentialProperties: [Constants.FONT_DOWNLOAD_DVB_SCHEME, ...Constants.THUMBNAILS_SCHEME_ID_URIS],
supportedEssentialProperties: [
{ schemeIdUri: Constants.FONT_DOWNLOAD_DVB_SCHEME },
{ schemeIdUri: Constants.COLOUR_PRIMARIES_SCHEME_ID_URI, value: /5|6/ },
{ schemeIdUri: Constants.MATRIX_COEFFICIENTS_SCHEME_ID_URI, value: /5|6/ },
{ schemeIdUri: Constants.TRANSFER_CHARACTERISTICS_SCHEME_ID_URI, value: '6' },
...Constants.THUMBNAILS_SCHEME_ID_URIS.map(ep => { return { 'schemeIdUri': ep }; })
],
useMediaCapabilitiesApi: false
},
timeShiftBuffer: {
Expand Down Expand Up @@ -1297,7 +1309,7 @@ function Settings() {
for (let n in source) {
if (source.hasOwnProperty(n)) {
if (dest.hasOwnProperty(n)) {
if (typeof source[n] === 'object' && !(source[n] instanceof Array) && source[n] !== null) {
if (typeof source[n] === 'object' && !(source[n] instanceof RegExp) && !(source[n] instanceof Array) && source[n] !== null) {
mixinSettings(source[n], dest[n], path.slice() + n + '.');
} else {
dest[n] = Utils.clone(source[n]);
Expand Down
3 changes: 3 additions & 0 deletions src/core/Utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ class Utils {
if (!src || typeof src !== 'object') {
return src; // anything
}
if (src instanceof RegExp) {
return new RegExp(src);
}
let r;
if (src instanceof Array) {
// array
Expand Down
15 changes: 15 additions & 0 deletions src/dash/vo/DescriptorType.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,21 @@ class DescriptorType {
}
}
}

inArray(arr) {
if (arr) {
return arr.some((entry) => {
return (
this.schemeIdUri === entry.schemeIdUri && (
this.value ?
(this.value.match(entry.value)) : // check if provided value matches RegExp
(''.match(entry.value)) // check if RegExp allows absent value
)
);
})
}
return false;
}
}

export default DescriptorType;
3 changes: 3 additions & 0 deletions src/streaming/constants/Constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,9 @@ export default {
SUPPLEMENTAL_PROPERTY_DVB_LL_SCHEME: 'urn:dvb:dash:lowlatency:critical:2019',
THUMBNAILS_SCHEME_ID_URIS: ['http://dashif.org/thumbnail_tile', 'http://dashif.org/guidelines/thumbnail_tile'],
FONT_DOWNLOAD_DVB_SCHEME: 'urn:dvb:dash:fontdownload:2014',
COLOUR_PRIMARIES_SCHEME_ID_URI: 'urn:mpeg:mpegB:cicp:ColourPrimaries',
MATRIX_COEFFICIENTS_SCHEME_ID_URI: 'urn:mpeg:mpegB:cicp:MatrixCoefficients',
TRANSFER_CHARACTERISTICS_SCHEME_ID_URI: 'urn:mpeg:mpegB:cicp:TransferCharacteristics',
XML: 'XML',
ARRAY_BUFFER: 'ArrayBuffer',
DVB_REPORTING_URL: 'dvb:reportingUrl',
Expand Down
5 changes: 3 additions & 2 deletions src/streaming/utils/Capabilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,13 +187,14 @@ function Capabilities() {

/**
* Check if a specific EssentialProperty is supported
* @param {object} ep
* @param {DescriptorType} ep
* @return {boolean}
*/
function supportsEssentialProperty(ep) {
let supportedEssentialProps = settings.get().streaming.capabilities.supportedEssentialProperties;

try {
return supportedEssentialProps.indexOf(ep.schemeIdUri) !== -1;
return ep.inArray(supportedEssentialProps);
} catch (e) {
return true;
}
Expand Down
140 changes: 125 additions & 15 deletions test/unit/streaming.utils.Capabilities.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,64 @@
import Capabilities from '../../src/streaming/utils/Capabilities.js';
import Settings from '../../src/core/Settings.js';

import {expect} from 'chai';
import { expect } from 'chai';
import DescriptorType from '../../src/dash/vo/DescriptorType.js';

let settings;
let capabilities;

const EssentialPropertyThumbNail = {
let EssentialPropertyThumbNail = new DescriptorType;
EssentialPropertyThumbNail.init({
schemeIdUri: 'http://dashif.org/thumbnail_tile',
value: 'somevalue'
value: 'myvalue'
});

const EssentialPropertyThumbNailnoVal = {
schemeIdUri: 'http://dashif.org/thumbnail_tile'
};
const EssentialPropertyOwn = {

let EssentialPropertyThumbNailemptyVal = new DescriptorType;
EssentialPropertyThumbNailemptyVal.init({
schemeIdUri: 'http://dashif.org/thumbnail_tile',
value: ''
});

let EssentialPropertyOwn = new DescriptorType;
EssentialPropertyOwn.init({
schemeIdUri: 'tag:dashif.org:myOwnFeature',
value: 'somevalue'
};
const EssentialPropertyOwnSecond = {
});

let EssentialPropertyOwnSecond = new DescriptorType;
EssentialPropertyOwnSecond.init({
schemeIdUri: 'tag:dashif.org:mySecondOwnFeature',
value: 'somevalue'
};
});

describe('CapabilitiesFilter', function () {
let EssentialPropertySDR = new DescriptorType;
EssentialPropertySDR.init({
schemeIdUri: 'urn:mpeg:mpegB:cicp:ColourPrimaries',
value: '5'
});

let EssentialPropertynoVal = new DescriptorType;
EssentialPropertynoVal.init({
schemeIdUri: 'urn:mpeg:mpegB:cicp:ColourPrimaries'
});

let EssentialPropertyemptyVal = new DescriptorType;
EssentialPropertyemptyVal.init({
schemeIdUri: 'urn:mpeg:mpegB:cicp:ColourPrimaries',
value: ''
});

let EssentialPropertyHDR = new DescriptorType;
EssentialPropertyHDR.init({
schemeIdUri: 'urn:mpeg:mpegB:cicp:ColourPrimaries',
value: '9'
});

describe('Capabilities', function () {
beforeEach(function () {
settings = Settings({}).getInstance();
capabilities = Capabilities({}).getInstance();
Expand All @@ -35,36 +74,107 @@ describe('CapabilitiesFilter', function () {
expect(res).to.be.true;
});

it('should return true if EssentialProperty value is absent if supported by scheme', function () {
let res = capabilities.supportsEssentialProperty(EssentialPropertyThumbNailnoVal);
expect(res).to.be.true;
});

it('should return true if EssentialProperty value is empty if supported by scheme', function () {
let res = capabilities.supportsEssentialProperty(EssentialPropertyThumbNailemptyVal);
expect(res).to.be.true;
});

it('should return false if EssentialProperty value is not known', function () {
let res = capabilities.supportsEssentialProperty(EssentialPropertyOwn);
expect(res).to.be.false;
});

it('should return false if EssentialProperty value is absent for known schemeId+value', function () {
let res = capabilities.supportsEssentialProperty(EssentialPropertynoVal);
expect(res).to.be.false;
});

it('should return false if EssentialProperty value is empty for known schemeId+value', function () {
let res = capabilities.supportsEssentialProperty(EssentialPropertyemptyVal);
expect(res).to.be.false;
});

it('should return false if EssentialProperty value is not known when new values are registered in settings', function () {
let props = settings.get().streaming.capabilities.supportedEssentialProperties;
props.push(...[EssentialPropertyOwn.schemeIdUri]);
settings.update({ streaming: { capabilities: { supportedEssentialProperties: props }} });
props.push(...[EssentialPropertyOwn]);
settings.update({ streaming: { capabilities: { supportedEssentialProperties: props } } });

let res = capabilities.supportsEssentialProperty(EssentialPropertyOwnSecond);
expect(res).to.be.false;
});

it('should return true if EssentialProperty value is registered in settings', function () {
let props = settings.get().streaming.capabilities.supportedEssentialProperties;
props.push(...[EssentialPropertyOwn.schemeIdUri]);
settings.update({ streaming: { capabilities: { supportedEssentialProperties: props }} });
props.push(...[EssentialPropertyOwn]);
settings.update({ streaming: { capabilities: { supportedEssentialProperties: props } } });

let res = capabilities.supportsEssentialProperty(EssentialPropertyOwn);
expect(res).to.be.true;
});

it('should return true for internally known EssentialProperties when new values are registered in settings', function () {
let props = settings.get().streaming.capabilities.supportedEssentialProperties;
props.push(...[EssentialPropertyOwn.schemeIdUri]);
settings.update({ streaming: { capabilities: { supportedEssentialProperties: props }} });
props.push(...[EssentialPropertyOwn]);
settings.update({ streaming: { capabilities: { supportedEssentialProperties: props } } });

let res = capabilities.supportsEssentialProperty(EssentialPropertyThumbNail);
expect(res).to.be.true;
});

it('should return true if schemeIdUri+value pair is registered as known feature', function () {
let res = capabilities.supportsEssentialProperty(EssentialPropertySDR);
expect(res).to.be.true;
});

it('should return true if schemeIdUri+RegExp-value pair is registered as known feature', function () {
const newFeature = {
schemeIdUri: 'urn:mpeg:mpegB:cicp:ColourPrimaries',
value: /1|5|9/
};

let props = settings.get().streaming.capabilities.supportedEssentialProperties;
props.push(...[newFeature]);
settings.update({ streaming: { capabilities: { supportedEssentialProperties: props } } });

let res = capabilities.supportsEssentialProperty(EssentialPropertyHDR);
expect(res).to.be.true;
});

it('should return false if schemeIdUri, but unknown RegExp-value pair is registered as known feature', function () {
const newFeature = {
schemeIdUri: 'urn:mpeg:mpegB:cicp:ColourPrimaries',
value: /1|5|7/
};

let props = settings.get().streaming.capabilities.supportedEssentialProperties;
props.push(...[newFeature]);
settings.update({ streaming: { capabilities: { supportedEssentialProperties: props } } });

let res = capabilities.supportsEssentialProperty(EssentialPropertyHDR);
expect(res).to.be.false;
});

it('should return false if schemeIdUri, but different value are registered as known feature', function () {
let res = capabilities.supportsEssentialProperty(EssentialPropertyHDR);
expect(res).to.be.false;
});

it('should default missing EssentialProp.value in Settings to match-all', function () {
let props = settings.get().streaming.capabilities.supportedEssentialProperties;
props.push(...[{ schemeIdUri: 'tag:dashif.org:scheme:value:test' }]);
settings.update({ streaming: { capabilities: { supportedEssentialProperties: props } } })

let res = capabilities.supportsEssentialProperty({ schemeIdUri: 'tag:dashif.org:scheme:value:test', value: '' });
expect(res).to.be.true;
res = capabilities.supportsEssentialProperty({ schemeIdUri: 'tag:dashif.org:scheme:value:test' });
expect(res).to.be.true;
res = capabilities.supportsEssentialProperty({ schemeIdUri: 'tag:dashif.org:scheme:value:test', value: '5' });
expect(res).to.be.true;
});
});
});

0 comments on commit 6155a68

Please sign in to comment.