Skip to content
Open
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
14 changes: 11 additions & 3 deletions src/dash/models/DashManifestModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,7 @@ function DashManifestModel() {
}

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

let allProperties = _getPropertiesCommonToAllRepresentations(propertyType, adaptation[DashConstants.REPRESENTATION]);

// now, only take those Properties from AdaptationSet which we didn't already get from Representations
if (adaptation.hasOwnProperty(propertyType) && adaptation[propertyType].length) {
allProperties.push(...adaptation[propertyType])
adaptation[propertyType].forEach( adaptationProp => {
const alreadyPresent = allProperties.some(d => {
return d.schemeIdUri === adaptationProp.schemeIdUri && d.value === adaptationProp.value
});
if (!alreadyPresent) {
allProperties.push(adaptationProp);
}
})
}
// we don't check whether there are duplicates on AdaptationSets and Representations

return allProperties.map(essentialProperty => {
const s = new DescriptorType();
Expand Down
7 changes: 6 additions & 1 deletion src/dash/parser/maps/MapNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@
import CommonProperty from './CommonProperty.js';

class MapNode {
constructor(name, properties, children) {
constructor(name, properties, exceptions, children) {
this._name = name || '';
this._properties = [];
this._exceptions = exceptions || {};
this._children = children || [];

if (Array.isArray(properties)) {
Expand All @@ -57,6 +58,10 @@ class MapNode {
get properties() {
return this._properties;
}

get exceptions() {
return this._exceptions;
}
}

export default MapNode;
20 changes: 17 additions & 3 deletions src/dash/parser/maps/RepresentationBaseValuesMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
*/
import MapNode from './MapNode.js';
import DashConstants from '../../constants/DashConstants.js';
import Constants from '../../../streaming/constants/Constants.js';

class RepresentationBaseValuesMap extends MapNode {
constructor() {
Expand All @@ -42,6 +43,7 @@ class RepresentationBaseValuesMap extends MapNode {
DashConstants.CODECS,
DashConstants.CODING_DEPENDENCY,
DashConstants.CONTENT_PROTECTION,
DashConstants.ESSENTIAL_PROPERTY,
DashConstants.FRAMERATE,
DashConstants.FRAME_PACKING,
DashConstants.HEIGHT,
Expand All @@ -55,12 +57,24 @@ class RepresentationBaseValuesMap extends MapNode {
DashConstants.SEGMENT_PROFILES,
DashConstants.SEGMENT_SEQUENCE_PROPERTIES,
DashConstants.START_WITH_SAP,
DashConstants.SUPPLEMENTAL_CODECS,
DashConstants.SUPPLEMENTAL_PROPERTY,
DashConstants.WIDTH,
];

super(DashConstants.ADAPTATION_SET, commonProperties, [
new MapNode(DashConstants.REPRESENTATION, commonProperties, [
new MapNode(DashConstants.SUB_REPRESENTATION, commonProperties)
// RegEx are supported
const exceptions = {
[DashConstants.SUPPLEMENTAL_PROPERTY]: {
schemeIdUri: [ Constants.URL_QUERY_INFO_SCHEME, Constants.EXT_URL_QUERY_INFO_SCHEME, Constants.ADV_URL_QUERY_INFO_SCHEME, /urn:mpeg:dash:state:/ ]
},
[DashConstants.ESSENTIAL_PROPERTY]: {
schemeIdUri: [ Constants.URL_QUERY_INFO_SCHEME, Constants.EXT_URL_QUERY_INFO_SCHEME, Constants.ADV_URL_QUERY_INFO_SCHEME, /urn:mpeg:dash:state:/ ]
}
};

super(DashConstants.ADAPTATION_SET, commonProperties, exceptions, [
new MapNode(DashConstants.REPRESENTATION, commonProperties, exceptions, [
new MapNode(DashConstants.SUB_REPRESENTATION, commonProperties, exceptions)
])
]);
}
Expand Down
63 changes: 40 additions & 23 deletions src/dash/parser/objectiron.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,37 +32,54 @@ import FactoryMaker from '../../core/FactoryMaker.js';

function ObjectIron(mappers) {

function mergeValues(parentItem, childItem) {
for (let name in parentItem) {
if (!childItem.hasOwnProperty(name)) {
childItem[name] = parentItem[name];
function _conditionallyMapProperty(exception, parentName, parentIsArray, parentEl, child, mergeFlag) {
let allowMapping = true;

// check, if element matches an exception
if (exception) {
for (const [key, values] of Object.entries(exception)) {
let attr = parentEl[key];
if (values.some(v => attr.match(v))) {
allowMapping = false;
}
}
}

// apply mapping
if (allowMapping) {
if (child[parentName]) {
// property already exists
// check to see if we should merge
if (mergeFlag) {
if (parentIsArray) {
child[parentName].push(parentEl);
}
}
} else {
// just add the property
if (parentIsArray) {
child[parentName] = [parentEl];
} else {
child[parentName] = parentEl;
}
}
}

}

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

if (parent[property.name]) {
if (child[property.name]) {
// check to see if we should merge
if (property.merge) {
const parentValue = parent[property.name];
const childValue = child[property.name];

// complex objects; merge properties
if (typeof parentValue === 'object' && typeof childValue === 'object') {
mergeValues(parentValue, childValue);
}
// simple objects; merge them together
else {
child[property.name] = parentValue + childValue;
}
}
const propertyParentElementArray = parent[property.name];

if (Array.isArray(propertyParentElementArray)) {
propertyParentElementArray.forEach(propParentEl => {
_conditionallyMapProperty(exceptions[property.name], property.name, true, propParentEl, child, property.merge);
});
} else {
// just add the property
child[property.name] = parent[property.name];
_conditionallyMapProperty(exceptions[property.name], property.name, false, propertyParentElementArray, child, property.merge);
}
}
}
Expand All @@ -76,7 +93,7 @@ function ObjectIron(mappers) {
if (array) {
for (let v = 0, len2 = array.length; v < len2; ++v) {
const childNode = array[v];
mapProperties(item.properties, node, childNode);
mapProperties(item.properties, item.exceptions, node, childNode);
mapItem(childItem, childNode);
}
}
Expand Down
1 change: 1 addition & 0 deletions src/streaming/constants/Constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ export default {
COLOUR_PRIMARIES_SCHEME_ID_URI: 'urn:mpeg:mpegB:cicp:ColourPrimaries',
URL_QUERY_INFO_SCHEME: 'urn:mpeg:dash:urlparam:2014',
EXT_URL_QUERY_INFO_SCHEME: 'urn:mpeg:dash:urlparam:2016',
ADV_URL_QUERY_INFO_SCHEME: 'urn:mpeg:dash:urlparam:2025',
MATRIX_COEFFICIENTS_SCHEME_ID_URI: 'urn:mpeg:mpegB:cicp:MatrixCoefficients',
TRANSFER_CHARACTERISTICS_SCHEME_ID_URI: 'urn:mpeg:mpegB:cicp:TransferCharacteristics',
SEGMENT_SEQUENCE_REPRESENTATION_SCHEME_ID_URI: 'urn:mpeg:dash:ssr:2023',
Expand Down
21 changes: 21 additions & 0 deletions test/unit/data/dash/manifest_properties.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<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">
<BaseURL>./</BaseURL>
<Period>
<AdaptationSet mimeType="audio/mp4" contentType="audio" subsegmentAlignment="true" subsegmentStartsWithSAP="1" lang="es">
<Label lang="en">English Label</Label>
<Label lang="fre">French Label</Label>
<AudioChannelConfiguration schemeIdUri="urn:mpeg:mpegB:cicp:ChannelConfiguration" value="6"/>
<Accessibility schemeIdUri="urn:tva:metadata:cs:AudioPurposeCS:2007" value="6"/>
<SupplementalProperty schemeIdUri="urn:ABC" value="Instance1" />
<SupplementalProperty schemeIdUri="urn:XYZ" value="OK" />
<SupplementalProperty schemeIdUri="urn:mpeg:dash:state:lang#audio" />
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"/>
<SegmentTemplate duration="192512" timescale="48000" media="$RepresentationID$/$RepresentationID$_$Number$.m4a" startNumber="1" initialization="$RepresentationID$/$RepresentationID$_0.m4a"/>
<Representation id="bbb_a64k" codecs="mp4a.40.5" bandwidth="67071" audioSamplingRate="48000">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
<SupplementalProperty schemeIdUri="urn:ABC" value="Instance2" />
<SupplementalProperty schemeIdUri="urn:ABC" value="Instance3" />
</Representation>
</AdaptationSet>
</Period>
</MPD>
35 changes: 35 additions & 0 deletions test/unit/test/dash/dash.DashParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,41 @@ describe('DashParser', function () {
expect(labelArray[1].lang).to.equal('fr');
});
});

describe('DashParser - ObjectIron', async () => {
beforeEach(function () {
dashManifestModel.setConfig({
errHandler: errorHandlerMock
});
});

let manifest_prop = await FileLoader.loadTextFile('/data/dash/manifest_properties.xml');

it('should map AudioChannelConfig even if another instance is present on Representation', async () => {
let parsedMpd = dashParser.parse(manifest_prop);
let audioAdaptationsArray = dashManifestModel.getAdaptationsForType(parsedMpd, 0, 'audio');
let audiorepresentation = dashManifestModel.getRepresentationFor(0, audioAdaptationsArray[0]);

let acc = dashManifestModel.getAudioChannelConfigurationForRepresentation(audiorepresentation);

expect(acc).to.be.instanceOf(Array);
expect(acc.length).to.equal(2);
});

it('should map allowed SupplementalProperties from AdaptationSet to Representation', async () => {
let parsedMpd = dashParser.parse(manifest_prop);
let rawAdaptationSet = parsedMpd.Period[0].AdaptationSet[0];

expect(rawAdaptationSet.SupplementalProperty).to.be.instanceOf(Array);
expect(rawAdaptationSet.SupplementalProperty.length).to.equal(3);

let rawRepresentation = rawAdaptationSet.Representation[0];

expect(rawRepresentation.SupplementalProperty).to.be.instanceOf(Array);
expect(rawRepresentation.SupplementalProperty.length).to.equal(4);
});

});
})


Expand Down
Loading