diff --git a/index.d.ts b/index.d.ts index e7c8ee47fb..6332e9bdc8 100644 --- a/index.d.ts +++ b/index.d.ts @@ -523,14 +523,10 @@ declare namespace dashjs { representationCount: number; 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; + viewpoint: DescriptorType[] | null; + accessibility: DescriptorType[] | null; + audioChannelConfiguration: DescriptorType[] | null; + roles: DescriptorType[] | null; codec: string | null; mimeType: string | null; contentProtection: any | null; diff --git a/package-lock.json b/package-lock.json index e01b7fe8ad..2fd4dd5140 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "dashjs", - "version": "4.7.1", + "version": "5.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "dashjs", - "version": "4.7.1", + "version": "5.0.0", "license": "BSD-3-Clause", "dependencies": { "bcp-47-match": "^1.0.3", diff --git a/samples/multi-audio/multi-audio-default-lang-acc.html b/samples/multi-audio/multi-audio-default-lang-acc.html new file mode 100644 index 0000000000..c9badf9eea --- /dev/null +++ b/samples/multi-audio/multi-audio-default-lang-acc.html @@ -0,0 +1,157 @@ + + + + + Multiple audio tracks sample + + + + + + + + + + + + + + +
+
+
+ +
+
+
+
+

Multi audio - Initial Track

+

This example shows how an initial track is selected from content with multiple audio tracks based on preference settings.

+

Desired media settings are sanitized by a default schemeIdUri, if not provided.

+

Example requires support for Dolby Audio.

+
+
+
+
+
+ +
+
+ +
+ 00:00:00 +
+ +
+
+ +
+ +
+ +
+
+ +
+
+ +
+ 00:00:00 +
+
+
+
+
+
+
+
+
+
+
+
+
+
+

Get Initial Media Settings For Audio

+ + +
+
+
+
+

Get selected audio track

+ + +
+
+ +
+
+
+
+
+
+ +
+
+ + + + diff --git a/samples/samples.json b/samples/samples.json index 39e232480d..4348825863 100644 --- a/samples/samples.json +++ b/samples/samples.json @@ -568,6 +568,18 @@ "Video", "Audio" ] + }, + { + "title": "Multi Audio - Initial Track with language and accessibility", + "description": "This example illustrates how to select a default audio language and accessibility for playback.", + "href": "multi-audio/multi-audio-default-lang-acc.html", + "image": "http://webapi.streaming.dolby.com/v0_9/sources/media/v01/img/dolbyaudio_black2.png", + "labels": [ + "VoD", + "Multi Audio", + "Video", + "Audio" + ] } ] }, diff --git a/src/core/Settings.js b/src/core/Settings.js index 7a2f2ea1fc..418146f37a 100644 --- a/src/core/Settings.js +++ b/src/core/Settings.js @@ -267,7 +267,13 @@ import Events from './events/Events'; * applyMb: false, * etpWeightRatio: 0 * } - * } + * }, + * defaultSchemeIdUri: { + * viewpoint: '', + * audioChannelConfiguration: 'urn:mpeg:mpegB:cicp:ChannelConfiguration', + * role: 'urn:mpeg:dash:role:2011', + * accessibility: 'urn:mpeg:dash:role:2011' + * } * }, * errors: { * recoverAttempts: { @@ -847,6 +853,9 @@ import Events from './events/Events'; * Settings related to Common Media Client Data reporting. * @property {module:Settings~CmsdSettings} cmsd * Settings related to Common Media Server Data parsing. + * @property {module:Settings~defaultSchemeIdUri} defaultSchemeIdUri + * Default schemeIdUri for descriptor type elements + * These strings are used when not provided with setInitialMediaSettingsFor() */ @@ -1105,7 +1114,13 @@ function Settings() { applyMb: false, etpWeightRatio: 0 } - } + }, + defaultSchemeIdUri: { + viewpoint: '', + audioChannelConfiguration: 'urn:mpeg:mpegB:cicp:ChannelConfiguration', + role: 'urn:mpeg:dash:role:2011', + accessibility: 'urn:mpeg:dash:role:2011' + } }, errors: { recoverAttempts: { diff --git a/src/dash/DashAdapter.js b/src/dash/DashAdapter.js index 49862663a4..5618573ef0 100644 --- a/src/dash/DashAdapter.js +++ b/src/dash/DashAdapter.js @@ -76,7 +76,6 @@ function DashAdapter() { if (config.cea608parser) { cea608parser = config.cea608parser; } - if (config.errHandler) { dashManifestModel.setConfig({ errHandler: config.errHandler }); } @@ -201,17 +200,13 @@ 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 sameViewpoint = JSON.stringify(mInfoOne.viewpoint) === JSON.stringify(mInfoTwo.viewpoint); 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 && sameViewpointWithSchemeIdUri && sameLang && sameRoles && sameRolesWithSchemeIdUri && sameAccessibility && sameAccessibilityWithSchemeIdUri && sameAudioChannelConfiguration && sameAudioChannelConfigurationWithSchemeIdUri); + const sameRoles = JSON.stringify(mInfoOne.roles) === JSON.stringify(mInfoTwo.roles); + const sameAccessibility = JSON.stringify(mInfoOne.accessibility) === JSON.stringify(mInfoTwo.accessibility); + const sameAudioChannelConfiguration = JSON.stringify(mInfoOne.audioChannelConfiguration) === JSON.stringify(mInfoTwo.audioChannelConfiguration); + + return (sameId && sameCodec && sameViewpoint && sameLang && sameRoles && sameAccessibility && sameAudioChannelConfiguration); } function _getAllMediaInfo(manifest, period, streamInfo, adaptations, type, embeddedText) { @@ -241,32 +236,34 @@ function DashAdapter() { continue; } let accessibility = media.accessibility[j]; - if (accessibility.indexOf('cea-608:') === 0) { - let value = accessibility.substring(8); - let parts = value.split(';'); - if (parts[0].substring(0, 2) === 'CC') { - for (j = 0; j < parts.length; j++) { - if (!media) { - media = convertAdaptationToMediaInfo.call(this, voAdaptations[idx]); - } - convertVideoInfoToEmbeddedTextInfo(media, parts[j].substring(0, 3), parts[j].substring(4)); - mediaArr.push(media); - media = null; - } + if (accessibility.schemeIdUri === constants.ACCESSIBILITY_CEA608_SCHEME) { + if (accessibility.value === '') { + convertVideoInfoToEmbeddedTextInfo(media, constants.CC1, 'eng'); + mediaArr.push(media); + media = null; } else { - for (j = 0; j < parts.length; j++) { // Only languages for CC1, CC2, ... - if (!media) { - media = convertAdaptationToMediaInfo.call(this, voAdaptations[idx]); + let value = accessibility.value; + let parts = value.split(';'); + if (parts[0].substring(0, 2) === 'CC') { + for (j = 0; j < parts.length; j++) { + if (!media) { + media = convertAdaptationToMediaInfo.call(this, voAdaptations[idx]); + } + convertVideoInfoToEmbeddedTextInfo(media, parts[j].substring(0, 3), parts[j].substring(4)); + mediaArr.push(media); + media = null; + } + } else { + for (j = 0; j < parts.length; j++) { // Only languages for CC1, CC2, ... + if (!media) { + media = convertAdaptationToMediaInfo.call(this, voAdaptations[idx]); + } + convertVideoInfoToEmbeddedTextInfo(media, 'CC' + (j + 1), parts[j]); + mediaArr.push(media); + media = null; } - convertVideoInfoToEmbeddedTextInfo(media, 'CC' + (j + 1), parts[j]); - mediaArr.push(media); - media = null; } } - } else if (accessibility.indexOf('cea-608') === 0) { // Nothing known. We interpret it as CC1=eng - convertVideoInfoToEmbeddedTextInfo(media, constants.CC1, 'eng'); - mediaArr.push(media); - media = null; } } } else if (type === constants.IMAGE) { @@ -1026,7 +1023,6 @@ function DashAdapter() { let mediaInfo = new MediaInfo(); const realAdaptation = adaptation.period.mpd.manifest.Period[adaptation.period.index].AdaptationSet[adaptation.index]; - let viewpoint, acc, acc_rep, roles, accessibility; mediaInfo.id = adaptation.id; mediaInfo.index = adaptation.index; @@ -1037,47 +1033,16 @@ function DashAdapter() { mediaInfo.lang = dashManifestModel.getLanguageForAdaptation(realAdaptation); mediaInfo.segmentAlignment = dashManifestModel.getSegmentAlignment(realAdaptation); mediaInfo.subSegmentAlignment = dashManifestModel.getSubSegmentAlignment(realAdaptation); - - 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') { - if (accessibilityValue) { - accessibilityData = 'cea-608:' + accessibilityValue; - } else { - accessibilityData = 'cea-608'; - } - mediaInfo.embeddedCaptions = true; - } - return accessibilityData; - }); - mediaInfo.accessibilitiesWithSchemeIdUri = accessibility; - - acc = dashManifestModel.getAudioChannelConfigurationForAdaptation(realAdaptation); - mediaInfo.audioChannelConfiguration = acc.map(function (audioChannelConfiguration) { - return audioChannelConfiguration.value; - }); - mediaInfo.audioChannelConfigurationsWithSchemeIdUri = acc; - + mediaInfo.viewpoint = dashManifestModel.getViewpointForAdaptation(realAdaptation); + mediaInfo.accessibility = dashManifestModel.getAccessibilityForAdaptation(realAdaptation); + if (mediaInfo.accessibility.filter(function (accessibility) { + if (accessibility.schemeIdUri && (accessibility.schemeIdUri.search('cea-608') >= 0) && typeof (cea608parser) !== 'undefined') return true; + })[0]) mediaInfo.embeddedCaptions = true; + mediaInfo.audioChannelConfiguration = dashManifestModel.getAudioChannelConfigurationForAdaptation(realAdaptation); if (mediaInfo.audioChannelConfiguration.length === 0 && realAdaptation.Representation && realAdaptation.Representation.length > 0) { - acc_rep = dashManifestModel.getAudioChannelConfigurationForRepresentation(realAdaptation.Representation[0]); - mediaInfo.audioChannelConfiguration = acc_rep.map(function (audioChannelConfiguration) { - return audioChannelConfiguration.value; - }); - mediaInfo.audioChannelConfigurationsWithSchemeIdUri = acc_rep; + mediaInfo.audioChannelConfiguration = dashManifestModel.getAudioChannelConfigurationForRepresentation(realAdaptation.Representation[0]); } - - roles = dashManifestModel.getRolesForAdaptation(realAdaptation); - mediaInfo.roles = roles.map(function (role) { - return role.value; - }); - mediaInfo.rolesWithSchemeIdUri = roles; - + mediaInfo.roles = dashManifestModel.getRolesForAdaptation(realAdaptation); mediaInfo.codec = dashManifestModel.getCodec(realAdaptation); mediaInfo.mimeType = dashManifestModel.getMimeType(realAdaptation); mediaInfo.contentProtection = dashManifestModel.getContentProtectionData(realAdaptation); @@ -1121,8 +1086,7 @@ function DashAdapter() { mediaInfo.isEmbedded = true; mediaInfo.isFragmented = false; mediaInfo.lang = bcp47Normalize(lang); - mediaInfo.roles = ['caption']; - mediaInfo.rolesWithSchemeIdUri = [{schemeIdUri:'urn:mpeg:dash:role:2011', value:'caption'}]; + mediaInfo.roles = [{schemeIdUri:'urn:mpeg:dash:role:2011', value:'caption'}]; } function convertVideoInfoToThumbnailInfo(mediaInfo) { diff --git a/src/dash/vo/MediaInfo.js b/src/dash/vo/MediaInfo.js index d4f720c560..9650dce0d6 100644 --- a/src/dash/vo/MediaInfo.js +++ b/src/dash/vo/MediaInfo.js @@ -42,13 +42,9 @@ class MediaInfo { this.labels = null; this.lang = null; this.viewpoint = null; - this.viewpointsWithSchemeIdUri = null; this.accessibility = null; - this.accessibilitiesWithSchemeIdUri = null; this.audioChannelConfiguration = null; - this.audioChannelConfigurationsWithSchemeIdUri = null; this.roles = null; - this.rolesWithSchemeIdUri = null; this.codec = null; this.mimeType = null; this.contentProtection = null; diff --git a/src/streaming/MediaPlayer.js b/src/streaming/MediaPlayer.js index c3b820c317..5c6d96a9c2 100644 --- a/src/streaming/MediaPlayer.js +++ b/src/streaming/MediaPlayer.js @@ -119,6 +119,11 @@ function MediaPlayer() { * @inner */ const MEDIA_PLAYER_NOT_INITIALIZED_ERROR = 'MediaPlayer not initialized!'; + /** + * @constant {string} ARRAY_NOT_SUPPORTED_ERROR error string thrown when settings object was called using an array. + * @inner + */ + const ARRAY_NOT_SUPPORTED_ERROR = 'Array type not supported for settings!'; const context = this.context; const eventBus = EventBus(context).getInstance(); @@ -1575,10 +1580,11 @@ function MediaPlayer() { * is following:
* {lang: langValue (can be either a string primitive, a string object, or a RegExp object to match), * index: indexValue, - * viewpoint: viewpointValue, - * audioChannelConfiguration: audioChannelConfigurationValue, - * accessibility: accessibilityValue, - * role: roleValue} + * viewpoint: viewpointValue (object:{schemeIdUri,value} or value-primitive), + * audioChannelConfiguration: audioChannelConfigurationValue (object:{schemeIdUri,value} or value-primitive (assumes schemeIdUri='urn:mpeg:mpegB:cicp:ChannelConfiguration')), + * accessibility: accessibilityValue (object:{schemeIdUri,value} or value-primitive (assumes schemeIdUri='urn:mpeg:dash:role:2011')), + * role: roleValue (object:{schemeIdUri,value} or value-primitive (assumes schemeIdUri='urn:mpeg:dash:role:2011')) + * } * * @param {MediaType} type * @param {Object} value @@ -1590,7 +1596,8 @@ function MediaPlayer() { if (!mediaPlayerInitialized) { throw MEDIA_PLAYER_NOT_INITIALIZED_ERROR; } - mediaController.setInitialSettings(type, value); + let sanitizedValue = _sanitizeSettings(value); + mediaController.setInitialSettings(type, sanitizedValue); } /** @@ -2426,6 +2433,38 @@ function MediaPlayer() { return utcValue; } + function _sanitizeSettings(value) { + const defaults = settings.get().streaming.defaultSchemeIdUri; + let output = {}; + + function __sanitizeDescriptorType(name, val, defaultSchemeIdUri) { + let out = {}; + if (val) { + if (val instanceof Array) { + throw ARRAY_NOT_SUPPORTED_ERROR; + } else if (val instanceof Object) { + out.schemeIdUri = val.schemeIdUri ? val.schemeIdUri : ''; + out.value = val.value ? val.value : ''; + } else { + out.schemeIdUri = defaultSchemeIdUri; + out.value = val; + logger.warn('No schemeIdUri provided for ' + name + ', using default \"' + defaultSchemeIdUri + '\"'); + } + return out; + } + return null; + } + + if (value.lang) output.lang = value.lang; + if (value.index) output.index = value.index; + if (value.viewpoint) output.viewpoint = __sanitizeDescriptorType('viewpoint', value.viewpoint, defaults.viewpoint); + if (value.audioChannelConfiguration) output.audioChannelConfiguration = __sanitizeDescriptorType('audioChannelConfiguration', value.audioChannelConfiguration, defaults.audioChannelConfiguration); + if (value.role) output.role = __sanitizeDescriptorType('role', value.role, defaults.role); + if (value.accessibility) output.accessibility = __sanitizeDescriptorType('accessibility', value.accessibility, defaults.accessibility); + + return output; + } + /** * * @private diff --git a/src/streaming/constants/Constants.js b/src/streaming/constants/Constants.js index f7ebe63f25..6a9ca46fe9 100644 --- a/src/streaming/constants/Constants.js +++ b/src/streaming/constants/Constants.js @@ -217,6 +217,7 @@ export default { INITIALIZE: 'initialize', TEXT_SHOWING: 'showing', TEXT_HIDDEN: 'hidden', + ACCESSIBILITY_CEA608_SCHEME: 'urn:scte:dash:cc:cea-608:2015', CC1: 'CC1', CC3: 'CC3', UTF8: 'utf-8', diff --git a/src/streaming/controllers/MediaController.js b/src/streaming/controllers/MediaController.js index 030d872db4..980242f6b2 100644 --- a/src/streaming/controllers/MediaController.js +++ b/src/streaming/controllers/MediaController.js @@ -74,6 +74,7 @@ function MediaController() { if (settings) { tracks = Array.from(tracksForType); + logger.info('Filtering '+tracks.length+' '+type+' tracks based on settings'); tracks = filterTracksBySettings(tracks, matchSettingsLang, settings); tracks = filterTracksBySettings(tracks, matchSettingsIndex, settings); @@ -83,6 +84,7 @@ function MediaController() { } tracks = filterTracksBySettings(tracks, matchSettingsAccessibility, settings); tracks = filterTracksBySettings(tracks, matchSettingsAudioChannelConfig, settings); + logger.info('Filtering '+type+' tracks ended, found '+tracks.length+' matching track(s).'); } if (tracks.length === 0) { @@ -265,18 +267,14 @@ function MediaController() { } const sameId = t1.id === t2.id; - const sameViewpoint = t1.viewpoint === t2.viewpoint; - const sameViewpointDescriptors = JSON.stringify(t1.viewpointsWithSchemeIdUri) === JSON.stringify(t2.viewpointsWithSchemeIdUri); + const sameViewpoint = JSON.stringify(t1.viewpoint) === JSON.stringify(t2.viewpoint); const sameLang = t1.lang === t2.lang; const sameCodec = t1.codec === t2.codec; - const sameRoles = t1.roles.toString() === t2.roles.toString(); - const sameRoleDescriptors = JSON.stringify(t1.rolesWithSchemeIdUri) === JSON.stringify(t2.rolesWithSchemeIdUri); - const sameAccessibility = t1.accessibility.toString() === t2.accessibility.toString(); - const sameAccessibilityDescriptors = JSON.stringify(t1.accessibilitiesWithSchemeIdUri) === JSON.stringify(t2.accessibilitiesWithSchemeIdUri); - const sameAudioChannelConfiguration = t1.audioChannelConfiguration.toString() === t2.audioChannelConfiguration.toString(); - const sameAudioChannelConfigurationDescriptors = JSON.stringify(t1.audioChannelConfigurationsWithSchemeIdUri) === JSON.stringify(t2.audioChannelConfigurationsWithSchemeIdUri); - - return (sameId && sameCodec && sameViewpoint && sameViewpointDescriptors && sameLang && sameRoles && sameRoleDescriptors && sameAccessibility && sameAccessibilityDescriptors && sameAudioChannelConfiguration && sameAudioChannelConfigurationDescriptors); + const sameRoles = JSON.stringify(t1.roles) === JSON.stringify(t2.roles); + const sameAccessibility = JSON.stringify(t1.accessibility) === JSON.stringify(t2.accessibility); + const sameAudioChannelConfiguration = JSON.stringify(t1.audioChannelConfiguration) === JSON.stringify(t2.audioChannelConfiguration); + + return (sameId && sameCodec && sameViewpoint && sameLang && sameRoles && sameAccessibility && sameAudioChannelConfiguration); } function setConfig(config) { @@ -328,6 +326,8 @@ function MediaController() { }); if (tracksAfterMatcher.length !== 0) { return tracksAfterMatcher; + } else { + logger.info('Filter-Function ('+filterFn.name+') resulted in no tracks; setting ignored'); } return tracks; } @@ -344,37 +344,37 @@ function MediaController() { } function matchSettingsViewPoint(settings, track) { - return !settings.viewpoint || (settings.viewpoint === track.viewpoint); + const matchViewPoint = !settings.viewpoint || !!track.viewpoint.filter(function (item) { + return _compareDescriptorType(item, settings.viewpoint); + })[0]; + return matchViewPoint; } function matchSettingsRole(settings, track, isTrackActive = false) { const matchRole = !settings.role || !!track.roles.filter(function (item) { - return item === settings.role; + return _compareDescriptorType(item, settings.role); })[0]; return (matchRole || (track.type === Constants.AUDIO && isTrackActive)); } function matchSettingsAccessibility(settings, track) { let matchAccessibility; - if (!settings.accessibility) { // if no accessibility is requested (or request is empty string), // match only those tracks having no accessibility element present matchAccessibility = !track.accessibility.length; } else { matchAccessibility = !!track.accessibility.filter(function (item) { - return item === settings.accessibility; + return _compareDescriptorType(item, settings.accessibility); })[0]; } - return matchAccessibility; } function matchSettingsAudioChannelConfig(settings, track) { let matchAudioChannelConfiguration = !settings.audioChannelConfiguration || !!track.audioChannelConfiguration.filter(function (item) { - return item === settings.audioChannelConfiguration; + return _compareDescriptorType(item, settings.audioChannelConfiguration); })[0]; - return matchAudioChannelConfiguration; } @@ -401,18 +401,19 @@ function MediaController() { } const matchIndex = (settings.index === undefined) || (settings.index === null) || (track.index === settings.index); - const matchViewPoint = !settings.viewpoint || (settings.viewpoint === track.viewpoint); + const matchViewPoint = !settings.viewpoint || !!track.viewpoint.filter(function (item) { + return _compareDescriptorType(item, settings.viewpoint); + })[0]; const matchRole = !settings.role || !!track.roles.filter(function (item) { - return item === settings.role; + return _compareDescriptorType(item, settings.role); })[0]; let matchAccessibility = !settings.accessibility || !!track.accessibility.filter(function (item) { - return item === settings.accessibility; + return _compareDescriptorType(item, settings.accessibility); })[0]; let matchAudioChannelConfiguration = !settings.audioChannelConfiguration || !!track.audioChannelConfiguration.filter(function (item) { - return item === settings.audioChannelConfiguration; + return _compareDescriptorType(item, settings.audioChannelConfiguration); })[0]; - return (matchLang && matchIndex && matchViewPoint && (matchRole || (track.type === Constants.AUDIO && isTrackActive)) && matchAccessibility && matchAudioChannelConfiguration); } catch (e) { return false; @@ -599,6 +600,20 @@ function MediaController() { return tmpArr; } + function _compareDescriptorType(v1,v2) { + if (v1 && v2) { + let t1 = JSON.stringify({ + schemeIdUri: v1.schemeIdUri, + value: v1.value + }) + let t2 = JSON.stringify({ + schemeIdUri: v2.schemeIdUri, + value: v2.value + }) + return t1 === t2; + } + return false; + } function createTrackInfo() { const storeLastSettings = settings.get().streaming.saveLastMediaSettingsForCurrentStreamingSession; diff --git a/test/unit/dash.DashAdapter.js b/test/unit/dash.DashAdapter.js index 9e265df910..08b1b93419 100644 --- a/test/unit/dash.DashAdapter.js +++ b/test/unit/dash.DashAdapter.js @@ -23,12 +23,12 @@ const manifest_with_audio = { id: undefined, mimeType: Constants.AUDIO, lang: 'eng', - Role: [{ value: 'main' }] + Role: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'main' }] }, { id: undefined, mimeType: Constants.AUDIO, lang: 'deu', - Role: [{ value: 'main' }] + Role: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'main' }] }] }] }; @@ -533,7 +533,7 @@ describe('DashAdapter', function () { track.streamInfo = streamInfo; track.representationCount = 0; track.lang = 'deu'; - track.roles = ['main']; + track.roles = [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'main'}]; track.rolesWithSchemeIdUri = [{ schemeIdUri: 'aScheme', value: 'main' }]; track.codec = 'audio/mp4;codecs="mp4a.40.2"'; track.mimeType = 'audio/mp4'; @@ -647,6 +647,9 @@ describe('DashAdapter', function () { expect(mediaInfoArray[0].supplementalProperties).to.be.instanceOf(Array); expect(mediaInfoArray[0].supplementalProperties.length).equals(3); + + expect(mediaInfoArray[0].supplementalProperties[1].schemeIdUri).equals('test:scheme'); + expect(mediaInfoArray[0].supplementalProperties[1].value).equals('value2'); }); it('supplemental properties should not be filled if not set on all representations', function () { @@ -675,12 +678,11 @@ describe('DashAdapter', function () { expect(mediaInfoArray[0].audioChannelConfiguration).to.be.instanceOf(Array); expect(mediaInfoArray[0].audioChannelConfiguration.length).equals(2); - expect(mediaInfoArray[0].audioChannelConfiguration[0]).equals('6'); - - expect(mediaInfoArray[0].audioChannelConfigurationsWithSchemeIdUri).to.be.instanceOf(Array); - expect(mediaInfoArray[0].audioChannelConfigurationsWithSchemeIdUri.length).equals(2); - expect(mediaInfoArray[0].audioChannelConfigurationsWithSchemeIdUri[0]).to.be.instanceOf(DescriptorType); - expect(mediaInfoArray[0].audioChannelConfigurationsWithSchemeIdUri[1].value).equals('0xF801'); + expect(mediaInfoArray[0].audioChannelConfiguration[0]).to.be.instanceOf(DescriptorType); + expect(mediaInfoArray[0].audioChannelConfiguration[0].schemeIdUri).equals('urn:mpeg:mpegB:cicp:ChannelConfiguration'); + expect(mediaInfoArray[0].audioChannelConfiguration[0].value).equals('6'); + expect(mediaInfoArray[0].audioChannelConfiguration[1].schemeIdUri).equals('tag:dolby.com,2014:dash:audio_channel_configuration:2011'); + expect(mediaInfoArray[0].audioChannelConfiguration[1].value).equals('0xF801'); }); it('audio channel config should be filled when present on Representation', function () { @@ -695,12 +697,9 @@ describe('DashAdapter', function () { // Note: MediaInfo picks those AudioChannelConfig descriptor present on that Representation with lowest bandwidth expect(mediaInfoArray[0].audioChannelConfiguration).to.be.instanceOf(Array); expect(mediaInfoArray[0].audioChannelConfiguration.length).equals(4); - expect(mediaInfoArray[0].audioChannelConfiguration[0]).equals('21'); - - expect(mediaInfoArray[0].audioChannelConfigurationsWithSchemeIdUri).to.be.instanceOf(Array); - expect(mediaInfoArray[0].audioChannelConfigurationsWithSchemeIdUri.length).equals(4); - expect(mediaInfoArray[0].audioChannelConfigurationsWithSchemeIdUri[0]).to.be.instanceOf(DescriptorType); - expect(mediaInfoArray[0].audioChannelConfigurationsWithSchemeIdUri[3].value).equals('0xA000'); + expect(mediaInfoArray[0].audioChannelConfiguration[0]).to.be.instanceOf(DescriptorType); + expect(mediaInfoArray[0].audioChannelConfiguration[3].schemeIdUri).equals('tag:dolby.com,2014:dash:audio_channel_configuration:2011'); + expect(mediaInfoArray[0].audioChannelConfiguration[3].value).equals('0xA000'); }); it('role, accessibility and viewpoint should be empty if not defined', function () { @@ -716,15 +715,8 @@ describe('DashAdapter', function () { expect(mediaInfoArray[0].roles.length).equals(0); expect(mediaInfoArray[0].accessibility).to.be.instanceOf(Array); expect(mediaInfoArray[0].accessibility.length).equals(0); - expect(mediaInfoArray[0].viewpoint).to.be.undefined; - - expect(mediaInfoArray[0].rolesWithSchemeIdUri).to.be.instanceOf(Array); - expect(mediaInfoArray[0].rolesWithSchemeIdUri.length).equals(0); - expect(mediaInfoArray[0].accessibilitiesWithSchemeIdUri).to.be.instanceOf(Array); - expect(mediaInfoArray[0].accessibilitiesWithSchemeIdUri.length).equals(0); - expect(mediaInfoArray[0].accessibilitiesWithSchemeIdUri).to.be.instanceOf(Array); - expect(mediaInfoArray[0].viewpointsWithSchemeIdUri).to.be.instanceOf(Array); - expect(mediaInfoArray[0].viewpointsWithSchemeIdUri.length).equals(0); + expect(mediaInfoArray[0].viewpoint).to.be.instanceOf(Array); + expect(mediaInfoArray[0].viewpoint.length).equals(0); }); it('role should be filled', function () { @@ -738,12 +730,9 @@ describe('DashAdapter', function () { expect(mediaInfoArray[0].roles).to.be.instanceOf(Array); expect(mediaInfoArray[0].roles.length).equals(1); - expect(mediaInfoArray[0].roles[0]).equals('main'); - - expect(mediaInfoArray[0].rolesWithSchemeIdUri).to.be.instanceOf(Array); - expect(mediaInfoArray[0].rolesWithSchemeIdUri.length).equals(1); - expect(mediaInfoArray[0].rolesWithSchemeIdUri[0]).to.be.instanceOf(DescriptorType); - expect(mediaInfoArray[0].rolesWithSchemeIdUri[0].value).equals('main'); + expect(mediaInfoArray[0].roles[0]).to.be.instanceOf(DescriptorType); + expect(mediaInfoArray[0].roles[0].schemeIdUri).equals('urn:mpeg:dash:role:2011'); + expect(mediaInfoArray[0].roles[0].value).equals('main'); }); it('accessibility should be filled', function () { @@ -760,18 +749,12 @@ describe('DashAdapter', function () { expect(mediaInfoArray[0].accessibility).to.be.instanceOf(Array); expect(mediaInfoArray[0].accessibility.length).equals(1); - expect(mediaInfoArray[0].accessibility[0]).equals('cea-608:CC1=eng;CC3=swe'); - expect(mediaInfoArray[1].accessibility.length).equals(0); - - expect(mediaInfoArray[0].rolesWithSchemeIdUri).to.be.instanceOf(Array); - expect(mediaInfoArray[0].rolesWithSchemeIdUri.length).equals(0); + expect(mediaInfoArray[0].accessibility[0]).to.be.instanceOf(DescriptorType); + expect(mediaInfoArray[0].accessibility[0].schemeIdUri).equals('urn:scte:dash:cc:cea-608:2015'); + expect(mediaInfoArray[0].accessibility[0].value).equals('CC1=eng;CC3=swe'); + expect(mediaInfoArray[0].embeddedCaptions).equals(true); - expect(mediaInfoArray[0].accessibilitiesWithSchemeIdUri).to.be.instanceOf(Array); - expect(mediaInfoArray[0].accessibilitiesWithSchemeIdUri.length).equals(1); - expect(mediaInfoArray[0].accessibilitiesWithSchemeIdUri[0]).to.be.instanceOf(DescriptorType); - expect(mediaInfoArray[0].accessibilitiesWithSchemeIdUri[0].schemeIdUri).equals('urn:scte:dash:cc:cea-608:2015'); - expect(mediaInfoArray[0].accessibilitiesWithSchemeIdUri[0].value).equals('CC1=eng;CC3=swe'); - expect(mediaInfoArray[1].accessibilitiesWithSchemeIdUri.length).equals(0); + expect(mediaInfoArray[1].accessibility.length).equals(0); }); it('viewpoint should be filled', function () { @@ -783,20 +766,18 @@ describe('DashAdapter', function () { expect(mediaInfoArray).to.be.instanceOf(Array); expect(mediaInfoArray.length).equals(1); - expect(mediaInfoArray[0].viewpoint).equals('VP1'); - - expect(mediaInfoArray[0].viewpointsWithSchemeIdUri).to.be.instanceOf(Array); - expect(mediaInfoArray[0].viewpointsWithSchemeIdUri.length).equals(2); + expect(mediaInfoArray[0].viewpoint).to.be.instanceOf(Array); + expect(mediaInfoArray[0].viewpoint.length).equals(2); - expect(mediaInfoArray[0].viewpointsWithSchemeIdUri[0]).to.be.instanceOf(DescriptorType); - expect(mediaInfoArray[0].viewpointsWithSchemeIdUri[0].schemeIdUri).equals('urn:scheme:viewpoint'); - expect(mediaInfoArray[0].viewpointsWithSchemeIdUri[0].value).equals('VP1'); - expect(mediaInfoArray[0].viewpointsWithSchemeIdUri[0].id).to.be.null; + expect(mediaInfoArray[0].viewpoint[0]).to.be.instanceOf(DescriptorType); + expect(mediaInfoArray[0].viewpoint[0].schemeIdUri).equals('urn:scheme:viewpoint'); + expect(mediaInfoArray[0].viewpoint[0].value).equals('VP1'); + expect(mediaInfoArray[0].viewpoint[0].id).to.be.null; - expect(mediaInfoArray[0].viewpointsWithSchemeIdUri[1]).to.be.instanceOf(DescriptorType); - expect(mediaInfoArray[0].viewpointsWithSchemeIdUri[1].schemeIdUri).equals('urn:scheme:viewpoint'); - expect(mediaInfoArray[0].viewpointsWithSchemeIdUri[1].value).equals('VP2'); - expect(mediaInfoArray[0].viewpointsWithSchemeIdUri[1].id).to.be.null; + expect(mediaInfoArray[0].viewpoint[1]).to.be.instanceOf(DescriptorType); + expect(mediaInfoArray[0].viewpoint[1].schemeIdUri).equals('urn:scheme:viewpoint'); + expect(mediaInfoArray[0].viewpoint[1].value).equals('VP2'); + expect(mediaInfoArray[0].viewpoint[1].id).to.be.null; }); }); diff --git a/test/unit/streaming.MediaPlayer.js b/test/unit/streaming.MediaPlayer.js index 66a880a101..b24450aa4e 100644 --- a/test/unit/streaming.MediaPlayer.js +++ b/test/unit/streaming.MediaPlayer.js @@ -1034,14 +1034,80 @@ describe('MediaPlayer', function () { player.setInitialMediaSettingsFor('audio', 'settings'); initialSettings = player.getInitialMediaSettingsFor('audio'); - expect(initialSettings).to.equal('settings'); + expect(initialSettings).to.be.instanceOf(Object); + expect(initialSettings).to.deep.equal({}); - player.setInitialMediaSettingsFor('text', { lang: 'en', role: 'caption' }); + player.setInitialMediaSettingsFor('text', { lang: 'en', role: 'caption', accessibility: {schemeIdUri:'urn:mpeg:dash:role:2011', value:''} }); initialSettings = player.getInitialMediaSettingsFor('text'); - expect(initialSettings).to.exist; // jshint ignore:line + expect(initialSettings).to.be.instanceOf(Object); + + expect(initialSettings).to.have.property('lang'); + expect(initialSettings).to.have.property('role'); + expect(initialSettings).to.have.property('accessibility'); + expect(initialSettings).not.to.have.property('audioChannelConfiguration'); + expect(initialSettings).not.to.have.property('viewpoint'); + expect(initialSettings.lang).to.equal('en'); - expect(initialSettings.role).to.equal('caption'); + expect(initialSettings.role).to.have.property('schemeIdUri'); + expect(initialSettings.role).to.have.property('value'); + // dash.js asumes the MPEG role scheme as default, if not provided + expect(initialSettings.role.schemeIdUri).to.equal('urn:mpeg:dash:role:2011'); + expect(initialSettings.role.value).to.equal('caption'); + expect(initialSettings.accessibility.schemeIdUri).to.equal('urn:mpeg:dash:role:2011'); + expect(initialSettings.accessibility.value).to.equal(''); + }); + + it('should assume default schemeIdUri strings for initial media settings, if not provided', function () { + player.setInitialMediaSettingsFor('audio', { role: 'val1', accessibility: 'val2', viewpoint: 'val3', audioChannelConfiguration: 'val4'}); + let initialSettings = player.getInitialMediaSettingsFor('audio'); + expect(initialSettings).to.be.instanceOf(Object); + expect(initialSettings).to.have.property('role'); + expect(initialSettings).to.have.property('accessibility'); + expect(initialSettings).to.have.property('viewpoint'); + expect(initialSettings).to.have.property('audioChannelConfiguration'); + + expect(initialSettings.role).to.have.property('schemeIdUri'); + expect(initialSettings.role.schemeIdUri).to.equal('urn:mpeg:dash:role:2011'); + expect(initialSettings.accessibility).to.have.property('schemeIdUri'); + expect(initialSettings.accessibility.schemeIdUri).to.equal('urn:mpeg:dash:role:2011'); + + expect(initialSettings.viewpoint).to.have.property('schemeIdUri'); + expect(initialSettings.viewpoint.schemeIdUri).to.equal(''); + + expect(initialSettings.audioChannelConfiguration).to.have.property('schemeIdUri'); + expect(initialSettings.audioChannelConfiguration.schemeIdUri).to.equal('urn:mpeg:mpegB:cicp:ChannelConfiguration'); + }); + + it('should take schemeIdUri strings for initial media settings, if provided', function () { + player.setInitialMediaSettingsFor('audio', { + role: {schemeIdUri: 'test.scheme.1', value: 'val1'}, + accessibility: {schemeIdUri: 'test.scheme.2', value: 'val2'}, + viewpoint: {schemeIdUri: 'test.scheme.3', value: 'val3'}, + audioChannelConfiguration: {schemeIdUri: 'test.scheme.4', value: 'val4'} + }); + let initialSettings = player.getInitialMediaSettingsFor('audio'); + expect(initialSettings).to.be.instanceOf(Object); + expect(initialSettings).to.have.property('role'); + expect(initialSettings).to.have.property('accessibility'); + expect(initialSettings).to.have.property('viewpoint'); + expect(initialSettings).to.have.property('audioChannelConfiguration'); + + expect(initialSettings.role).to.have.property('schemeIdUri'); + expect(initialSettings.role.schemeIdUri).to.equal('test.scheme.1'); + expect(initialSettings.role.value).to.equal('val1'); + + expect(initialSettings.accessibility).to.have.property('schemeIdUri'); + expect(initialSettings.accessibility.schemeIdUri).to.equal('test.scheme.2'); + expect(initialSettings.accessibility.value).to.equal('val2'); + + expect(initialSettings.viewpoint).to.have.property('schemeIdUri'); + expect(initialSettings.viewpoint.schemeIdUri).to.equal('test.scheme.3'); + expect(initialSettings.viewpoint.value).to.equal('val3'); + + expect(initialSettings.audioChannelConfiguration).to.have.property('schemeIdUri'); + expect(initialSettings.audioChannelConfiguration.schemeIdUri).to.equal('test.scheme.4'); + expect(initialSettings.audioChannelConfiguration.value).to.equal('val4'); }); it('should set current track', function () { diff --git a/test/unit/streaming.controllers.MediaController.js b/test/unit/streaming.controllers.MediaController.js index e2e12c9e7b..3123701582 100644 --- a/test/unit/streaming.controllers.MediaController.js +++ b/test/unit/streaming.controllers.MediaController.js @@ -75,20 +75,20 @@ describe('MediaController', function () { let track1 = { id: 'id', - viewpoint: 'viewpoint', + viewpoint: null, lang: 'lang', - roles: 1, - accessibility: 1, - audioChannelConfiguration: 1 + roles: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'main' }], + accessibility: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'description' }], + audioChannelConfiguration: [{ schemeIdUri: 'urn:mpeg:mpegB:cicp:ChannelConfiguration', value: '2' }] }; let track2 = { id: 'id2', - viewpoint: 'viewpoint', + viewpoint: null, lang: 'lang', - roles: 1, - accessibility: 1, - audioChannelConfiguration: 1 + roles: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'main' }], + accessibility: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'description' }], + audioChannelConfiguration: [{ schemeIdUri: 'urn:mpeg:mpegB:cicp:ChannelConfiguration', value: '2' }] }; let equal = mediaController.isTracksEqual(track1, track2); @@ -100,22 +100,44 @@ describe('MediaController', function () { let track1 = { id: 'id', - viewpoint: 'viewpoint', + viewpoint: null, lang: 'lang', - roles: 1, - accessibility: 'description', - accessibilitiesWithSchemeIdUri: { schemeIdUri: 'urn:scheme:test:1:2023', value: 'description' }, - audioChannelConfiguration: 1 + roles: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'main' }], + accessibility: { schemeIdUri: 'urn:scheme:test:1:2023', value: 'description' }, + audioChannelConfiguration: [{ schemeIdUri: 'urn:mpeg:mpegB:cicp:ChannelConfiguration', value: '2' }] }; let track2 = { id: 'id', - viewpoint: 'viewpoint', + viewpoint: null, lang: 'lang', - roles: 1, - accessibility: 'description', - accessibilitiesWithSchemeIdUri: { schemeIdUri: 'urn:scheme:test:2:2023', value: 'description' }, - audioChannelConfiguration: 1 + roles: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'main' }], + accessibility: { schemeIdUri: 'urn:scheme:test:2:2023', value: 'description' }, + audioChannelConfiguration: [{ schemeIdUri: 'urn:mpeg:mpegB:cicp:ChannelConfiguration', value: '2' }] + }; + let equal = mediaController.isTracksEqual(track1, track2); + expect(equal).to.be.false; + + }); + + it('should return false if track are not equals (DescriptorType), case 2', function () { + + let track1 = { + id: 'id', + viewpoint: [{ schemeIdUri: 'test:scheme:2023', value: 'vp1' }], + lang: 'lang', + roles: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'main' }], + accessibility: { schemeIdUri: 'urn:scheme:test:2023', value: 'description' }, + audioChannelConfiguration: [{ schemeIdUri: 'urn:mpeg:mpegB:cicp:ChannelConfiguration', value: '2' }] + }; + + let track2 = { + id: 'id', + viewpoint: [{ schemeIdUri: 'test:scheme:2023', value: 'vp2' }], + lang: 'lang', + roles: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'main' }], + accessibility: { schemeIdUri: 'urn:scheme:test:2023', value: 'description' }, + audioChannelConfiguration: [{ schemeIdUri: 'urn:mpeg:mpegB:cicp:ChannelConfiguration', value: '2' }] }; let equal = mediaController.isTracksEqual(track1, track2); expect(equal).to.be.false; @@ -126,20 +148,20 @@ describe('MediaController', function () { let track1 = { id: 'id', - viewpoint: 'viewpoint', + viewpoint: [{ schemeIdUri: 'test:scheme:2023', value: 'vp1' }], lang: 'lang', - roles: 1, - accessibility: 1, - audioChannelConfiguration: 1 + roles: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'main' }], + accessibility: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'caption' }], + audioChannelConfiguration: [{ schemeIdUri: 'urn:mpeg:mpegB:cicp:ChannelConfiguration', value: '2' }] }; let track2 = { id: 'id', - viewpoint: 'viewpoint', + viewpoint: [{ schemeIdUri: 'test:scheme:2023', value: 'vp1' }], lang: 'lang', - roles: 1, - accessibility: 1, - audioChannelConfiguration: 1 + roles: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'main' }], + accessibility: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'caption' }], + audioChannelConfiguration: [{ schemeIdUri: 'urn:mpeg:mpegB:cicp:ChannelConfiguration', value: '2' }] }; let equal = mediaController.isTracksEqual(track1, track2); expect(equal).to.be.true; @@ -151,11 +173,11 @@ describe('MediaController', function () { let track2 = { id: 'id', - viewpoint: 'viewpoint', + viewpoint: null, lang: 'lang', - roles: 1, - accessibility: 1, - audioChannelConfiguration: 1 + roles: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'main' }], + accessibility: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'caption' }], + audioChannelConfiguration: [{ schemeIdUri: 'urn:mpeg:mpegB:cicp:ChannelConfiguration', value: '2' }] }; let equal = mediaController.isTracksEqual(track1, track2); expect(equal).to.be.false; @@ -165,11 +187,11 @@ describe('MediaController', function () { let track1 = { id: 'id', - viewpoint: 'viewpoint', + viewpoint: null, lang: 'lang', - roles: 1, - accessibility: 1, - audioChannelConfiguration: 1 + roles: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'main' }], + accessibility: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'caption' }], + audioChannelConfiguration: [{ schemeIdUri: 'urn:mpeg:mpegB:cicp:ChannelConfiguration', value: '2' }] }; let track2 = null; @@ -186,33 +208,6 @@ describe('MediaController', function () { let equal = mediaController.isTracksEqual(track1, track2); expect(equal).to.be.true; }); - - it('should return true if track are equals (DescriptorType)', function () { - - let track1 = { - id: 'id', - viewpoint: 'viewpoint', - lang: 'lang', - roles: 1, - accessibility: 'description', - accessibility_withSchemeIdUri: [{ schemeIdUri: 'urn:scheme:test:1:2023', value: 'description' }], - audioChannelConfiguration: 1 - }; - - let track2 = { - id: 'id', - viewpoint: 'viewpoint', - lang: 'lang', - roles: 1, - accessibility: 'description', - accessibility_withSchemeIdUri: [{ schemeIdUri: 'urn:scheme:test:1:2023', value: 'description' }], - audioChannelConfiguration: 1 - }; - let equal = mediaController.isTracksEqual(track1, track2); - expect(equal).to.be.true; - - }); - }); describe('Track Management', function () { @@ -290,10 +285,10 @@ describe('MediaController', function () { type: trackType, streamInfo: streamInfo, lang: 'fr', - viewpoint: 'viewpoint', - roles: 1, - accessibility: 1, - audioChannelConfiguration: 1 + viewpoint: null, + roles: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'main' }], + accessibility: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'description' }], + audioChannelConfiguration: [{ schemeIdUri: 'urn:mpeg:mpegB:cicp:ChannelConfiguration', value: '2' }] }; mediaController.addTrack(track); @@ -312,10 +307,10 @@ describe('MediaController', function () { type: trackType, streamInfo: streamInfo, lang: 'fr', - viewpoint: 'viewpoint', - roles: 1, - accessibility: 1, - audioChannelConfiguration: 1 + viewpoint: null, + roles: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'main' }], + accessibility: [], + audioChannelConfiguration: [{ schemeIdUri: 'urn:mpeg:mpegB:cicp:ChannelConfiguration', value: '2' }] }; mediaController.addTrack(track); @@ -335,10 +330,10 @@ describe('MediaController', function () { type: trackType, streamInfo: streamInfo, lang: 'fr', - viewpoint: 'viewpoint', - roles: 1, - accessibility: 1, - audioChannelConfiguration: 1, + viewpoint: null, + roles: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'main' }], + accessibility: [], + audioChannelConfiguration: [{ schemeIdUri: 'urn:mpeg:mpegB:cicp:ChannelConfiguration', value: '2' }], isFragmented: true }; @@ -346,10 +341,10 @@ describe('MediaController', function () { type: trackType, streamInfo: streamInfo, lang: 'en', - viewpoint: 'viewpoint', - roles: 1, - accessibility: 1, - audioChannelConfiguration: 1, + viewpoint: null, + roles: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'main' }], + accessibility: [], + audioChannelConfiguration: [{ schemeIdUri: 'urn:mpeg:mpegB:cicp:ChannelConfiguration', value: '2' }], isFragmented: true }; @@ -393,28 +388,28 @@ describe('MediaController', function () { type: trackType, streamInfo: streamInfo, lang: 'fr', - viewpoint: 'viewpoint', - roles: 1, + viewpoint: [{ schemeIdUri: 'test:scheme:2023', value: 'vp1' }], + roles: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'main' }], accessibility: 1, - audioChannelConfiguration: 1 + audioChannelConfiguration: [{ schemeIdUri: 'urn:mpeg:mpegB:cicp:ChannelConfiguration', value: '2' }] }; const qtzTrack = { type: trackType, streamInfo: streamInfo, lang: 'qtz', - viewpoint: 'viewpoint', - roles: 1, + viewpoint: [{ schemeIdUri: 'test:scheme:2023', value: 'vp2' }], + roles: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'main' }], accessibility: 1, - audioChannelConfiguration: 1 + audioChannelConfiguration: [{ schemeIdUri: 'urn:mpeg:mpegB:cicp:ChannelConfiguration', value: '2' }] }; const enTrack = { type: trackType, streamInfo: streamInfo, lang: 'en', viewpoint: null, - roles: ['Main'], + roles: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'main' }], accessibility: [], - audioChannelConfiguration: 6, + audioChannelConfiguration: [{ schemeIdUri: 'urn:mpeg:mpegB:cicp:ChannelConfiguration', value: '6' }], selectionPriority: 5 }; const enADTrack = { @@ -422,9 +417,9 @@ describe('MediaController', function () { streamInfo: streamInfo, lang: 'en', viewpoint: null, - roles: ['alternate'], - accessibility: ['1', 'description'], - audioChannelConfiguration: 6, + roles: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'alternate' }], + accessibility: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'description'}], + audioChannelConfiguration: [{ schemeIdUri: 'urn:mpeg:mpegB:cicp:ChannelConfiguration', value: '6' }], selectionPriority: 3 }; const esTrack = { @@ -432,9 +427,9 @@ describe('MediaController', function () { streamInfo: streamInfo, lang: 'es', viewpoint: null, - roles: ['dub'], + roles: [{ schemeIdUri: 'urn:mpeg:dash:role:2011', value: 'dub' }], accessibility: [], - audioChannelConfiguration: 2, + audioChannelConfiguration: [{ schemeIdUri: 'urn:mpeg:mpegB:cicp:ChannelConfiguration', value: '2' }], selectionPriority: 4 }; @@ -453,7 +448,7 @@ describe('MediaController', function () { // call to setInitialMediaSettingsForType mediaController.setInitialSettings(trackType, { lang: 'qtz', - viewpoint: 'viewpoint' + viewpoint: { schemeIdUri: 'test:scheme:2023', value: 'vp1' } }); mediaController.setInitialMediaSettingsForType(trackType, streamInfo); @@ -477,7 +472,7 @@ describe('MediaController', function () { // call to setInitialMediaSettingsForType mediaController.setInitialSettings(trackType, { lang: 'fre', - viewpoint: 'viewpoint' + viewpoint: null }); mediaController.setInitialMediaSettingsForType(trackType, streamInfo); @@ -500,7 +495,7 @@ describe('MediaController', function () { // call to setInitialMediaSettingsForType mediaController.setInitialSettings(trackType, { lang: /fr|en|qtz/, - viewpoint: 'viewpoint' + viewpoint: null }); mediaController.setInitialMediaSettingsForType(trackType, streamInfo); @@ -524,7 +519,7 @@ describe('MediaController', function () { // call to setInitialMediaSettingsForType mediaController.setInitialSettings(trackType, { lang: /qtz|mis/, - viewpoint: 'viewpoint' + viewpoint: null }); mediaController.setInitialMediaSettingsForType(trackType, streamInfo); @@ -536,7 +531,7 @@ describe('MediaController', function () { mediaController.addTrack(enTrack); mediaController.addTrack(enADTrack); mediaController.addTrack(esTrack); - + let trackList = mediaController.getTracksFor(trackType, streamInfo.id); expect(trackList).to.have.lengthOf(3); expect(objectUtils.areEqual(trackList[0], enTrack)).to.be.true; @@ -577,7 +572,7 @@ describe('MediaController', function () { // call to setInitialMediaSettingsForType mediaController.setInitialSettings(trackType, { lang: 'en', - accessibility: '' + accessibility: [] }); mediaController.setInitialMediaSettingsForType(trackType, streamInfo); @@ -604,7 +599,7 @@ describe('MediaController', function () { // call to setInitialMediaSettingsForType mediaController.setInitialSettings(trackType, { lang: 'en', - accessibility: 'description' + accessibility: {schemeIdUri:'urn:mpeg:dash:role:2011', value:'description'} }); mediaController.setInitialMediaSettingsForType(trackType, streamInfo); @@ -631,7 +626,7 @@ describe('MediaController', function () { // call to setInitialMediaSettingsForType mediaController.setInitialSettings(trackType, { lang: 'es', - accessibility: 'description' + accessibility: [{schemeIdUri:'urn:mpeg:dash:role:2011',value:'description'}] }); mediaController.setInitialMediaSettingsForType(trackType, streamInfo); @@ -639,6 +634,28 @@ describe('MediaController', function () { expect(objectUtils.areEqual(currentTrack, esTrack)).to.be.true; }); + it('should check initial media settings to choose initial track based on viewpoint', function () { + mediaController.addTrack(frTrack); + mediaController.addTrack(qtzTrack); + + let trackList = mediaController.getTracksFor(trackType, streamInfo.id); + expect(trackList).to.have.lengthOf(2); + expect(objectUtils.areEqual(trackList[0], frTrack)).to.be.true; + expect(objectUtils.areEqual(trackList[1], qtzTrack)).to.be.true; + + let currentTrack = mediaController.getCurrentTrackFor(trackType, streamInfo.id); + expect(objectUtils.areEqual(currentTrack, frTrack)).to.be.false; + + // call to setInitialMediaSettingsForType + mediaController.setInitialSettings(trackType, { + viewpoint: [{ schemeIdUri: 'test:scheme:2023', value: 'vp1' }] + }); + mediaController.setInitialMediaSettingsForType(trackType, streamInfo); + + currentTrack = mediaController.getCurrentTrackFor(trackType, streamInfo.id); + expect(objectUtils.areEqual(currentTrack, frTrack)).to.be.true; + }); + it('should not check initial media settings to choose initial track when it has already selected a track', function () { mediaController.addTrack(frTrack); mediaController.addTrack(qtzTrack);