Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

supported essentialProp Scheme+Value using RegExp in Settings.js #4411

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
});
});
});