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

MediaInfo: introduce DescriptorType #4158

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
497c039
resolve rebase conflicts
Mar 13, 2023
4aae079
add secure init function for descriptorType
Mar 13, 2023
37d0f29
make use of new DescriptroType class
Mar 13, 2023
a69d5a1
fix issue with accessibility
Mar 14, 2023
f0b5107
change getter to array.map functions
Mar 14, 2023
7dfff97
issue #4123: propagate supplProp from Repr to AdaptSet if all equal
Mar 14, 2023
73073e2
take new DescriptorType into account
Mar 14, 2023
e8a5164
make supplementalProp avail as DescriptorType
Mar 23, 2023
aeac8cd
resolve reabse conflicts
Mar 23, 2023
1be392b
fix TS
Mar 23, 2023
57ced3e
resolve rebase conflicts
Mar 23, 2023
0a15fa6
implement first new unit tests
Mar 24, 2023
1f68663
enable mocha grep with karma runner
Mar 24, 2023
91c8d83
encapsulate mediaInfo test
Mar 24, 2023
d168976
a few more tests on Mediainfo from DashAdapter
Mar 24, 2023
6d1d391
add test for DashAdapter.AreMediaInfosEqual
Mar 24, 2023
25e87a9
bugfix comparing content of object
Mar 27, 2023
4e1b27d
test supplementalProp on Representations
Mar 27, 2023
3a67b35
added test for viewpoint descriptor
Mar 27, 2023
a5e46bc
adding test for trackEquality with DescriptorType
Mar 27, 2023
46f663f
enhance trackEquality to use DescriptorType
Mar 27, 2023
38bf1e6
adding unit tests for DashManifestModel
Mar 28, 2023
59b70b6
coding style: use single space, no alignment
Apr 12, 2023
b9688b6
use strong equality
Apr 12, 2023
a5b924a
use () with constructur invokation
Apr 12, 2023
e56e410
use plural + camel case
Apr 12, 2023
5050211
use DashConstants
Apr 12, 2023
5db0bc7
fix new names
Apr 12, 2023
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: 15 additions & 5 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,15 +145,15 @@ declare namespace dashjs {

getLanguageForAdaptation(adaptation: object): string;

getViewpointForAdaptation(adaptation: object): any;
getViewpointForAdaptation(adaptation: object): DescriptorType[];

getRolesForAdaptation(adaptation: object): any[];
getRolesForAdaptation(adaptation: object): DescriptorType[];

getAccessibilityForAdaotation(adaptation: object): any[];
getAccessibilityForAdaptation(adaptation: object): DescriptorType[];

getAudioChannelConfigurationForAdaptation(adaptation: object): any[];
getAudioChannelConfigurationForAdaptation(adaptation: object): DescriptorType[];

getAudioChannelConfigurationForRepresentation(adaptation: object): any[];
getAudioChannelConfigurationForRepresentation(adaptation: object): DescriptorType[];

getRepresentationSortFunction(): (a: object, b: object) => number;

Expand Down Expand Up @@ -426,9 +426,13 @@ declare namespace dashjs {
labels: { text: string, lang?: string }[];
lang: string | null;
viewpoint: any | undefined | null;
viewpointsWithSchemeIdUri: DescriptorType[] | null;
accessibility: any[] | null;
accessibilitiesWithSchemeIdUri: DescriptorType[] | null;
audioChannelConfiguration: any[] | null;
audioChannelConfigurationsWithSchemeIdUri: DescriptorType[] | null;
roles: string[] | null;
rolesWithSchemeIdUri: DescriptorType[] | null;
codec: string | null;
mimeType: string | null;
contentProtection: any | null;
Expand Down Expand Up @@ -545,6 +549,12 @@ declare namespace dashjs {
value: string;
}

export class DescriptorType {
schemeIdUri: string;
value: string;
id: string;
}

/**
* Dash
**/
Expand Down
3 changes: 2 additions & 1 deletion karma.unit.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ module.exports = function (config) {
client: {
useIframe: false,
mocha: {
timeout: 90000
timeout: 90000,
grep: config.grep
}
},

Expand Down
57 changes: 47 additions & 10 deletions src/dash/DashAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,12 +202,16 @@ function DashAdapter() {
const sameId = mInfoOne.id === mInfoTwo.id;
const sameCodec = mInfoOne.codec === mInfoTwo.codec;
const sameViewpoint = mInfoOne.viewpoint === mInfoTwo.viewpoint;
const sameViewpointWithSchemeIdUri = JSON.stringify(mInfoOne.viewpointsWithSchemeIdUri) === JSON.stringify(mInfoTwo.viewpointsWithSchemeIdUri);
const sameLang = mInfoOne.lang === mInfoTwo.lang;
const sameRoles = mInfoOne.roles.toString() === mInfoTwo.roles.toString();
const sameRolesWithSchemeIdUri = JSON.stringify(mInfoOne.rolesWithSchemeIdUri) === JSON.stringify(mInfoTwo.rolesWithSchemeIdUri);
const sameAccessibility = mInfoOne.accessibility.toString() === mInfoTwo.accessibility.toString();
const sameAccessibilityWithSchemeIdUri = JSON.stringify(mInfoOne.accessibilitiesWithSchemeIdUri) === JSON.stringify(mInfoTwo.accessibilitiesWithSchemeIdUri);
const sameAudioChannelConfiguration = mInfoOne.audioChannelConfiguration.toString() === mInfoTwo.audioChannelConfiguration.toString();
const sameAudioChannelConfigurationWithSchemeIdUri = JSON.stringify(mInfoOne.audioChannelConfigurationsWithSchemeIdUri) === JSON.stringify(mInfoTwo.audioChannelConfigurationsWithSchemeIdUri);

return (sameId && sameCodec && sameViewpoint && sameLang && sameRoles && sameAccessibility && sameAudioChannelConfiguration);
return (sameId && sameCodec && sameViewpoint && sameViewpointWithSchemeIdUri && sameLang && sameRoles && sameRolesWithSchemeIdUri && sameAccessibility && sameAccessibilityWithSchemeIdUri && sameAudioChannelConfiguration && sameAudioChannelConfigurationWithSchemeIdUri);
}

function _getAllMediaInfo(manifest, period, streamInfo, adaptations, type, embeddedText) {
Expand Down Expand Up @@ -1035,7 +1039,7 @@ function DashAdapter() {

let mediaInfo = new MediaInfo();
const realAdaptation = adaptation.period.mpd.manifest.Period_asArray[adaptation.period.index].AdaptationSet_asArray[adaptation.index];
let viewpoint;
let viewpoint, acc, acc_rep, roles, accessibility;

mediaInfo.id = adaptation.id;
mediaInfo.index = adaptation.index;
Expand All @@ -1044,11 +1048,15 @@ function DashAdapter() {
mediaInfo.representationCount = dashManifestModel.getRepresentationCount(realAdaptation);
mediaInfo.labels = dashManifestModel.getLabelsForAdaptation(realAdaptation);
mediaInfo.lang = dashManifestModel.getLanguageForAdaptation(realAdaptation);
viewpoint = dashManifestModel.getViewpointForAdaptation(realAdaptation);
mediaInfo.viewpoint = viewpoint ? viewpoint.value : undefined;
mediaInfo.segmentAlignment = dashManifestModel.getSegmentAlignment(realAdaptation);
mediaInfo.subSegmentAlignment = dashManifestModel.getSubSegmentAlignment(realAdaptation);
mediaInfo.accessibility = dashManifestModel.getAccessibilityForAdaptation(realAdaptation).map(function (accessibility) {

viewpoint = dashManifestModel.getViewpointForAdaptation(realAdaptation);
mediaInfo.viewpoint = viewpoint.length ? viewpoint[0].value : undefined;
mediaInfo.viewpointsWithSchemeIdUri = viewpoint;

accessibility = dashManifestModel.getAccessibilityForAdaptation(realAdaptation);
mediaInfo.accessibility = accessibility.map(function (accessibility) {
let accessibilityValue = accessibility.value;
let accessibilityData = accessibilityValue;
if (accessibility.schemeIdUri && (accessibility.schemeIdUri.search('cea-608') >= 0) && typeof (cea608parser) !== 'undefined') {
Expand All @@ -1061,19 +1069,28 @@ function DashAdapter() {
}
return accessibilityData;
});
mediaInfo.accessibilitiesWithSchemeIdUri = accessibility;

mediaInfo.audioChannelConfiguration = dashManifestModel.getAudioChannelConfigurationForAdaptation(realAdaptation).map(function (audioChannelConfiguration) {
acc = dashManifestModel.getAudioChannelConfigurationForAdaptation(realAdaptation);
mediaInfo.audioChannelConfiguration = acc.map(function (audioChannelConfiguration) {
return audioChannelConfiguration.value;
});
mediaInfo.audioChannelConfigurationsWithSchemeIdUri = acc;

if (mediaInfo.audioChannelConfiguration.length === 0 && Array.isArray(realAdaptation.Representation_asArray) && realAdaptation.Representation_asArray.length > 0) {
mediaInfo.audioChannelConfiguration = dashManifestModel.getAudioChannelConfigurationForRepresentation(realAdaptation.Representation_asArray[0]).map(function (audioChannelConfiguration) {
acc_rep = dashManifestModel.getAudioChannelConfigurationForRepresentation(realAdaptation.Representation_asArray[0]);
mediaInfo.audioChannelConfiguration = acc_rep.map(function (audioChannelConfiguration) {
return audioChannelConfiguration.value;
});
mediaInfo.audioChannelConfigurationsWithSchemeIdUri = acc_rep;
}
mediaInfo.roles = dashManifestModel.getRolesForAdaptation(realAdaptation).map(function (role) {

roles = dashManifestModel.getRolesForAdaptation(realAdaptation);
mediaInfo.roles = roles.map(function (role) {
return role.value;
});
mediaInfo.rolesWithSchemeIdUri = roles;

mediaInfo.codec = dashManifestModel.getCodec(realAdaptation);
mediaInfo.mimeType = dashManifestModel.getMimeType(realAdaptation);
mediaInfo.contentProtection = dashManifestModel.getContentProtectionData(realAdaptation);
Expand All @@ -1092,8 +1109,27 @@ function DashAdapter() {
}

mediaInfo.isText = dashManifestModel.getIsText(realAdaptation);
mediaInfo.supplementalProperties = dashManifestModel.getSupplementalProperties(realAdaptation);

mediaInfo.supplementalProperties = dashManifestModel.getSupplementalPropertiesForAdaptation(realAdaptation);
dsilhavy marked this conversation as resolved.
Show resolved Hide resolved
if ( (!mediaInfo.supplementalProperties || Object.keys(mediaInfo.supplementalProperties).length === 0) && Array.isArray(realAdaptation.Representation_asArray) && realAdaptation.Representation_asArray.length > 0) {
let arr = realAdaptation.Representation_asArray.map( repr => {
return dashManifestModel.getSupplementalPropertiesForRepresentation(repr);
});
if ( arr.every( v => JSON.stringify(v) === JSON.stringify(arr[0]) ) ) {
// only output Representation.supplementalProperties to mediaInfo, if they are present on all Representations
mediaInfo.supplementalProperties = arr[0];
}
}
mediaInfo.supplementalPropertiesAsArray = dashManifestModel.getSupplementalPropertiesAsArrayForAdaptation(realAdaptation);
if ( (!mediaInfo.supplementalPropertiesAsArray || mediaInfo.supplementalPropertiesAsArray.length === 0) && Array.isArray(realAdaptation.Representation_asArray) && realAdaptation.Representation_asArray.length > 0) {
let arr = realAdaptation.Representation_asArray.map( repr => {
return dashManifestModel.getSupplementalPropertiesAsArrayForRepresentation(repr);
});
if ( arr.every( v => JSON.stringify(v) === JSON.stringify(arr[0]) ) ) {
// only output Representation.supplementalProperties to mediaInfo, if they are present on all Representations
mediaInfo.supplementalPropertiesAsArray = arr[0];
}
}

mediaInfo.isFragmented = dashManifestModel.getIsFragmented(realAdaptation);
mediaInfo.isEmbedded = false;

Expand All @@ -1109,6 +1145,7 @@ function DashAdapter() {
mediaInfo.isFragmented = false;
mediaInfo.lang = bcp47Normalize(lang);
mediaInfo.roles = ['caption'];
mediaInfo.rolesWithSchemeIdUri = [{schemeIdUri:'urn:mpeg:dash:role:2011', value:'caption'}];
}

function convertVideoInfoToThumbnailInfo(mediaInfo) {
Expand Down
2 changes: 2 additions & 0 deletions src/dash/constants/DashConstants.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class DashConstants {
this.CONTENT_PROTECTION = 'ContentProtection';
this.ESSENTIAL_PROPERTY = 'EssentialProperty';
this.SUPPLEMENTAL_PROPERTY = 'SupplementalProperty';
this.SUPPLEMENTAL_PROPERTY_ASARRAY = 'SupplementalProperty_asArray';
this.INBAND_EVENT_STREAM = 'InbandEventStream';
this.PRODUCER_REFERENCE_TIME = 'ProducerReferenceTime';
this.INBAND = 'inband';
Expand All @@ -100,6 +101,7 @@ class DashConstants {
this.SUBSET = 'Subset';
this.LANG = 'lang';
this.VIEWPOINT = 'Viewpoint';
this.VIEWPOINT_ASARRAY = 'Viewpoint_asArray';
this.ROLE_ASARRAY = 'Role_asArray';
this.REPRESENTATION_ASARRAY = 'Representation_asArray';
this.PRODUCERREFERENCETIME_ASARRAY = 'ProducerReferenceTime_asArray';
Expand Down
73 changes: 63 additions & 10 deletions src/dash/models/DashManifestModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import BaseURL from '../vo/BaseURL';
import EventStream from '../vo/EventStream';
import ProducerReferenceTime from '../vo/ProducerReferenceTime';
import ContentSteering from '../vo/ContentSteering';
import DescriptorType from '../vo/DescriptorType';
import ObjectUtils from '../../streaming/utils/ObjectUtils';
import URLUtils from '../../streaming/utils/URLUtils';
import FactoryMaker from '../../core/FactoryMaker';
Expand Down Expand Up @@ -230,23 +231,43 @@ function DashManifestModel() {
}

function getViewpointForAdaptation(adaptation) {
return adaptation && adaptation.hasOwnProperty(DashConstants.VIEWPOINT) ? adaptation.Viewpoint : null;
if (!adaptation || !adaptation.hasOwnProperty(DashConstants.VIEWPOINT_ASARRAY) || !adaptation[DashConstants.VIEWPOINT_ASARRAY].length) return [];
return adaptation[DashConstants.VIEWPOINT_ASARRAY].map( viewpoint => {
const vp = new DescriptorType();
return vp.init(viewpoint);
});
}

function getRolesForAdaptation(adaptation) {
return adaptation && adaptation.hasOwnProperty(DashConstants.ROLE_ASARRAY) ? adaptation.Role_asArray : [];
if (!adaptation || !adaptation.hasOwnProperty(DashConstants.ROLE_ASARRAY) || !adaptation[DashConstants.ROLE_ASARRAY].length) return [];
return adaptation[DashConstants.ROLE_ASARRAY].map( role => {
const r = new DescriptorType();
return r.init(role);
});
}

function getAccessibilityForAdaptation(adaptation) {
return adaptation && adaptation.hasOwnProperty(DashConstants.ACCESSIBILITY_ASARRAY) ? adaptation.Accessibility_asArray : [];
if (!adaptation || !adaptation.hasOwnProperty(DashConstants.ACCESSIBILITY_ASARRAY) || !adaptation[DashConstants.ACCESSIBILITY_ASARRAY].length) return [];
return adaptation[DashConstants.ACCESSIBILITY_ASARRAY].map( accessibility => {
const a = new DescriptorType();
return a.init(accessibility);
});
}

function getAudioChannelConfigurationForAdaptation(adaptation) {
return adaptation && adaptation.hasOwnProperty(DashConstants.AUDIOCHANNELCONFIGURATION_ASARRAY) ? adaptation.AudioChannelConfiguration_asArray : [];
if (!adaptation || !adaptation.hasOwnProperty(DashConstants.AUDIOCHANNELCONFIGURATION_ASARRAY) || !adaptation[DashConstants.AUDIOCHANNELCONFIGURATION_ASARRAY].length) return [];
return adaptation[DashConstants.AUDIOCHANNELCONFIGURATION_ASARRAY].map( audioChanCfg => {
const acc = new DescriptorType();
return acc.init(audioChanCfg);
});
}

function getAudioChannelConfigurationForRepresentation(representation) {
return representation && representation.hasOwnProperty(DashConstants.AUDIOCHANNELCONFIGURATION_ASARRAY) ? representation.AudioChannelConfiguration_asArray : [];
if (!representation || !representation.hasOwnProperty(DashConstants.AUDIOCHANNELCONFIGURATION_ASARRAY) || !representation[DashConstants.AUDIOCHANNELCONFIGURATION_ASARRAY].length) return [];
return representation[DashConstants.AUDIOCHANNELCONFIGURATION_ASARRAY].map( audioChanCfg => {
const acc = new DescriptorType();
return acc.init(audioChanCfg);
});
}

function getRepresentationSortFunction() {
Expand Down Expand Up @@ -1263,10 +1284,10 @@ function DashManifestModel() {
return serviceDescriptions;
}

function getSupplementalProperties(adaptation) {
function getSupplementalPropertiesForAdaptation(adaptation) {
const supplementalProperties = {};

if (adaptation && adaptation.hasOwnProperty(DashConstants.SUPPLEMENTAL_PROPERTY)) {
if (adaptation && adaptation.hasOwnProperty(DashConstants.SUPPLEMENTAL_PROPERTY_ASARRAY)) {
for (const sp of adaptation.SupplementalProperty_asArray) {
if (sp.hasOwnProperty(Constants.SCHEME_ID_URI) && sp.hasOwnProperty(DashConstants.VALUE)) {
supplementalProperties[sp[Constants.SCHEME_ID_URI]] = sp[DashConstants.VALUE];
Expand All @@ -1276,6 +1297,35 @@ function DashManifestModel() {
return supplementalProperties;
}

function getSupplementalPropertiesAsArrayForAdaptation(adaptation) {
if (!adaptation || !adaptation.hasOwnProperty(DashConstants.SUPPLEMENTAL_PROPERTY_ASARRAY) || !adaptation.SupplementalProperty_asArray.length) return [];
return adaptation.SupplementalProperty_asArray.map( supp => {
const s = new DescriptorType();
return s.init(supp);
});
}

function getSupplementalPropertiesForRepresentation(representation) {
const supplementalProperties = {};

if (representation && representation.hasOwnProperty(DashConstants.SUPPLEMENTAL_PROPERTY_ASARRAY)) {
for (const sp of representation.SupplementalProperty_asArray) {
if (sp.hasOwnProperty(Constants.SCHEME_ID_URI) && sp.hasOwnProperty(DashConstants.VALUE)) {
supplementalProperties[sp[Constants.SCHEME_ID_URI]] = sp[DashConstants.VALUE];
}
}
}
return supplementalProperties;
}

function getSupplementalPropertiesAsArrayForRepresentation(representation) {
if (!representation || !representation.hasOwnProperty(DashConstants.SUPPLEMENTAL_PROPERTY_ASARRAY) || !representation.SupplementalProperty_asArray.length) return [];
return representation.SupplementalProperty_asArray.map( supp => {
const s = new DescriptorType();
return s.init(supp);
});
}

function setConfig(config) {
if (!config) return;

Expand Down Expand Up @@ -1338,10 +1388,13 @@ function DashManifestModel() {
getSuggestedPresentationDelay,
getAvailabilityStartTime,
getServiceDescriptions,
getSupplementalProperties,
setConfig,
getSegmentAlignment,
getSubSegmentAlignment
getSubSegmentAlignment,
getSupplementalPropertiesForAdaptation,
getSupplementalPropertiesAsArrayForAdaptation,
getSupplementalPropertiesForRepresentation,
getSupplementalPropertiesAsArrayForRepresentation,
setConfig
};

setup();
Expand Down
52 changes: 52 additions & 0 deletions src/dash/vo/DescriptorType.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* The copyright in this software is being made available under the BSD License,
* included below. This software may be subject to other third party and contributor
* rights, including patent rights, and no such rights are granted under this license.
*
* Copyright (c) 2023, Dash Industry Forum.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* * Neither the name of Dash Industry Forum nor the names of its
* contributors may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @class
* @ignore
*/
class DescriptorType {
constructor() {
this.schemeIdUri = null;
this.value = null;
this.id = null;
}

init(data) {
if (data) {
this.schemeIdUri = data.schemeIdUri ? data.schemeIdUri : null;
dsilhavy marked this conversation as resolved.
Show resolved Hide resolved
this.value = data.value ? data.value : null;
this.id = data.id ? data.id : null;
}
return this;
}
}

export default DescriptorType;
Loading