Skip to content

Commit 90ddbda

Browse files
committed
enable RegEx for Exceptions
1 parent 1b7135d commit 90ddbda

File tree

8 files changed

+260
-120
lines changed

8 files changed

+260
-120
lines changed

src/dash/models/DashManifestModel.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,7 @@ function DashManifestModel() {
676676
}
677677

678678
// now, only return properties present on all Representations
679-
// repr.legth is always >= 2
679+
// repr.length is always >= 2
680680
return propertiesOfFirstRepresentation.filter(prop => {
681681
return repr.slice(1).every(currRep => {
682682
return currRep.hasOwnProperty(propertyType) && currRep[propertyType].some(e => {
@@ -692,10 +692,18 @@ function DashManifestModel() {
692692
}
693693

694694
let allProperties = _getPropertiesCommonToAllRepresentations(propertyType, adaptation[DashConstants.REPRESENTATION]);
695+
696+
// now, only take those Properties from AdaptationSet which we didn't already get from Representations
695697
if (adaptation.hasOwnProperty(propertyType) && adaptation[propertyType].length) {
696-
allProperties.push(...adaptation[propertyType])
698+
adaptation[propertyType].forEach( adaptationProp => {
699+
const alreadyPresent = allProperties.some(d => {
700+
return d.schemeIdUri === adaptationProp.schemeIdUri && d.value === adaptationProp.value
701+
});
702+
if (!alreadyPresent) {
703+
allProperties.push(adaptationProp);
704+
}
705+
})
697706
}
698-
// we don't check whether there are duplicates on AdaptationSets and Representations
699707

700708
return allProperties.map(essentialProperty => {
701709
const s = new DescriptorType();

src/dash/parser/maps/MapNode.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,10 @@
3434
import CommonProperty from './CommonProperty.js';
3535

3636
class MapNode {
37-
constructor(name, properties, children) {
37+
constructor(name, properties, exceptions, children) {
3838
this._name = name || '';
3939
this._properties = [];
40+
this._exceptions = exceptions || {};
4041
this._children = children || [];
4142

4243
if (Array.isArray(properties)) {
@@ -57,6 +58,10 @@ class MapNode {
5758
get properties() {
5859
return this._properties;
5960
}
61+
62+
get exceptions() {
63+
return this._exceptions;
64+
}
6065
}
6166

6267
export default MapNode;

src/dash/parser/maps/RepresentationBaseValuesMap.js

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
*/
3434
import MapNode from './MapNode.js';
3535
import DashConstants from '../../constants/DashConstants.js';
36+
import Constants from '../../../streaming/constants/Constants.js';
3637

3738
class RepresentationBaseValuesMap extends MapNode {
3839
constructor() {
@@ -42,6 +43,7 @@ class RepresentationBaseValuesMap extends MapNode {
4243
DashConstants.CODECS,
4344
DashConstants.CODING_DEPENDENCY,
4445
DashConstants.CONTENT_PROTECTION,
46+
DashConstants.ESSENTIAL_PROPERTY,
4547
DashConstants.FRAMERATE,
4648
DashConstants.FRAME_PACKING,
4749
DashConstants.HEIGHT,
@@ -55,12 +57,24 @@ class RepresentationBaseValuesMap extends MapNode {
5557
DashConstants.SEGMENT_PROFILES,
5658
DashConstants.SEGMENT_SEQUENCE_PROPERTIES,
5759
DashConstants.START_WITH_SAP,
60+
DashConstants.SUPPLEMENTAL_CODECS,
61+
DashConstants.SUPPLEMENTAL_PROPERTY,
5862
DashConstants.WIDTH,
5963
];
6064

61-
super(DashConstants.ADAPTATION_SET, commonProperties, [
62-
new MapNode(DashConstants.REPRESENTATION, commonProperties, [
63-
new MapNode(DashConstants.SUB_REPRESENTATION, commonProperties)
65+
// RegEx are supported
66+
const exceptions = {
67+
[DashConstants.SUPPLEMENTAL_PROPERTY]: {
68+
schemeIdUri: [ Constants.URL_QUERY_INFO_SCHEME, Constants.EXT_URL_QUERY_INFO_SCHEME, Constants.ADV_URL_QUERY_INFO_SCHEME, /urn:mpeg:dash:state:/ ]
69+
},
70+
[DashConstants.ESSENTIAL_PROPERTY]: {
71+
schemeIdUri: [ Constants.URL_QUERY_INFO_SCHEME, Constants.EXT_URL_QUERY_INFO_SCHEME, Constants.ADV_URL_QUERY_INFO_SCHEME, /urn:mpeg:dash:state:/ ]
72+
}
73+
};
74+
75+
super(DashConstants.ADAPTATION_SET, commonProperties, exceptions, [
76+
new MapNode(DashConstants.REPRESENTATION, commonProperties, exceptions, [
77+
new MapNode(DashConstants.SUB_REPRESENTATION, commonProperties, exceptions)
6478
])
6579
]);
6680
}

src/dash/parser/objectiron.js

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -32,37 +32,54 @@ import FactoryMaker from '../../core/FactoryMaker.js';
3232

3333
function ObjectIron(mappers) {
3434

35-
function mergeValues(parentItem, childItem) {
36-
for (let name in parentItem) {
37-
if (!childItem.hasOwnProperty(name)) {
38-
childItem[name] = parentItem[name];
35+
function _conditionallyMapProperty(exception, parentName, parentIsArray, parentEl, child, mergeFlag) {
36+
let allowMapping = true;
37+
38+
// check, if element matches an exception
39+
if (exception) {
40+
for (const [key, values] of Object.entries(exception)) {
41+
let attr = parentEl[key];
42+
if (values.some(v => attr.match(v))) {
43+
allowMapping = false;
44+
}
45+
}
46+
}
47+
48+
// apply mapping
49+
if (allowMapping) {
50+
if (child[parentName]) {
51+
// property already exists
52+
// check to see if we should merge
53+
if (mergeFlag) {
54+
if (parentIsArray) {
55+
child[parentName].push(parentEl);
56+
}
57+
}
58+
} else {
59+
// just add the property
60+
if (parentIsArray) {
61+
child[parentName] = [parentEl];
62+
} else {
63+
child[parentName] = parentEl;
64+
}
3965
}
4066
}
67+
4168
}
4269

43-
function mapProperties(properties, parent, child) {
70+
function mapProperties(properties, exceptions, parent, child) {
4471
for (let i = 0, len = properties.length; i < len; ++i) {
4572
const property = properties[i];
4673

4774
if (parent[property.name]) {
48-
if (child[property.name]) {
49-
// check to see if we should merge
50-
if (property.merge) {
51-
const parentValue = parent[property.name];
52-
const childValue = child[property.name];
53-
54-
// complex objects; merge properties
55-
if (typeof parentValue === 'object' && typeof childValue === 'object') {
56-
mergeValues(parentValue, childValue);
57-
}
58-
// simple objects; merge them together
59-
else {
60-
child[property.name] = parentValue + childValue;
61-
}
62-
}
75+
const propertyParentElementArray = parent[property.name];
76+
77+
if (Array.isArray(propertyParentElementArray)) {
78+
propertyParentElementArray.forEach(propParentEl => {
79+
_conditionallyMapProperty(exceptions[property.name], property.name, true, propParentEl, child, property.merge);
80+
});
6381
} else {
64-
// just add the property
65-
child[property.name] = parent[property.name];
82+
_conditionallyMapProperty(exceptions[property.name], property.name, false, propertyParentElementArray, child, property.merge);
6683
}
6784
}
6885
}
@@ -76,7 +93,7 @@ function ObjectIron(mappers) {
7693
if (array) {
7794
for (let v = 0, len2 = array.length; v < len2; ++v) {
7895
const childNode = array[v];
79-
mapProperties(item.properties, node, childNode);
96+
mapProperties(item.properties, item.exceptions, node, childNode);
8097
mapItem(childItem, childNode);
8198
}
8299
}

src/streaming/constants/Constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ export default {
268268
COLOUR_PRIMARIES_SCHEME_ID_URI: 'urn:mpeg:mpegB:cicp:ColourPrimaries',
269269
URL_QUERY_INFO_SCHEME: 'urn:mpeg:dash:urlparam:2014',
270270
EXT_URL_QUERY_INFO_SCHEME: 'urn:mpeg:dash:urlparam:2016',
271+
ADV_URL_QUERY_INFO_SCHEME: 'urn:mpeg:dash:urlparam:2025',
271272
MATRIX_COEFFICIENTS_SCHEME_ID_URI: 'urn:mpeg:mpegB:cicp:MatrixCoefficients',
272273
TRANSFER_CHARACTERISTICS_SCHEME_ID_URI: 'urn:mpeg:mpegB:cicp:TransferCharacteristics',
273274
SEGMENT_SEQUENCE_REPRESENTATION_SCHEME_ID_URI: 'urn:mpeg:dash:ssr:2023',
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<MPD mediaPresentationDuration="PT634.566S" minBufferTime="PT2.00S" profiles="urn:hbbtv:dash:profile:isoff-live:2012,urn:mpeg:dash:profile:isoff-live:2011" type="static" xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd">
2+
<BaseURL>./</BaseURL>
3+
<Period>
4+
<AdaptationSet mimeType="audio/mp4" contentType="audio" subsegmentAlignment="true" subsegmentStartsWithSAP="1" lang="es">
5+
<Label lang="en">English Label</Label>
6+
<Label lang="fre">French Label</Label>
7+
<AudioChannelConfiguration schemeIdUri="urn:mpeg:mpegB:cicp:ChannelConfiguration" value="6"/>
8+
<Accessibility schemeIdUri="urn:tva:metadata:cs:AudioPurposeCS:2007" value="6"/>
9+
<SupplementalProperty schemeIdUri="urn:ABC" value="Instance1" />
10+
<SupplementalProperty schemeIdUri="urn:XYZ" value="OK" />
11+
<SupplementalProperty schemeIdUri="urn:mpeg:dash:state:lang#audio" />
12+
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"/>
13+
<SegmentTemplate duration="192512" timescale="48000" media="$RepresentationID$/$RepresentationID$_$Number$.m4a" startNumber="1" initialization="$RepresentationID$/$RepresentationID$_0.m4a"/>
14+
<Representation id="bbb_a64k" codecs="mp4a.40.5" bandwidth="67071" audioSamplingRate="48000">
15+
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
16+
<SupplementalProperty schemeIdUri="urn:ABC" value="Instance2" />
17+
<SupplementalProperty schemeIdUri="urn:ABC" value="Instance3" />
18+
</Representation>
19+
</AdaptationSet>
20+
</Period>
21+
</MPD>

test/unit/test/dash/dash.DashParser.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,41 @@ describe('DashParser', function () {
5656
expect(labelArray[1].lang).to.equal('fr');
5757
});
5858
});
59+
60+
describe('DashParser - ObjectIron', async () => {
61+
beforeEach(function () {
62+
dashManifestModel.setConfig({
63+
errHandler: errorHandlerMock
64+
});
65+
});
66+
67+
let manifest_prop = await FileLoader.loadTextFile('/data/dash/manifest_properties.xml');
68+
69+
it('should map AudioChannelConfig even if another instance is present on Representation', async () => {
70+
let parsedMpd = dashParser.parse(manifest_prop);
71+
let audioAdaptationsArray = dashManifestModel.getAdaptationsForType(parsedMpd, 0, 'audio');
72+
let audiorepresentation = dashManifestModel.getRepresentationFor(0, audioAdaptationsArray[0]);
73+
74+
let acc = dashManifestModel.getAudioChannelConfigurationForRepresentation(audiorepresentation);
75+
76+
expect(acc).to.be.instanceOf(Array);
77+
expect(acc.length).to.equal(2);
78+
});
79+
80+
it('should map allowed SupplementalProperties from AdaptationSet to Representation', async () => {
81+
let parsedMpd = dashParser.parse(manifest_prop);
82+
let rawAdaptationSet = parsedMpd.Period[0].AdaptationSet[0];
83+
84+
expect(rawAdaptationSet.SupplementalProperty).to.be.instanceOf(Array);
85+
expect(rawAdaptationSet.SupplementalProperty.length).to.equal(3);
86+
87+
let rawRepresentation = rawAdaptationSet.Representation[0];
88+
89+
expect(rawRepresentation.SupplementalProperty).to.be.instanceOf(Array);
90+
expect(rawRepresentation.SupplementalProperty.length).to.equal(4);
91+
});
92+
93+
});
5994
})
6095

6196

0 commit comments

Comments
 (0)