diff --git a/demo/config.js b/demo/config.js index dc0cbde3f7..0cc0076b91 100644 --- a/demo/config.js +++ b/demo/config.js @@ -751,7 +751,8 @@ shakaDemo.Config = class { .addTextInput_('Preferred Audio Language', 'preferredAudioLanguage') .addTextInput_('Preferred Audio Label', 'preferredAudioLabel') .addTextInput_('Preferred Video Label', 'preferredVideoLabel') - .addTextInput_('Preferred Variant Role', 'preferredVariantRole') + .addTextInput_('Preferred Audio Role', 'preferredAudioRole') + .addTextInput_('Preferred Video Role', 'preferredVideoRole') .addTextInput_('Preferred Text Language', 'preferredTextLanguage') .addTextInput_('Preferred Text Role', 'preferredTextRole') .addSelectInput_('Auto-Show Text', diff --git a/docs/tutorials/upgrade.md b/docs/tutorials/upgrade.md index 9be049028d..e6622deda0 100644 --- a/docs/tutorials/upgrade.md +++ b/docs/tutorials/upgrade.md @@ -121,6 +121,7 @@ application: - `streaming.forceHTTPS` has been renamed to `networking.forceHTTPS` (deprecated in v4.15.0) - `streaming.minBytesForProgressEvents` has been renamed to `networking.minBytesForProgressEvents` (deprecated in v4.15.0) - `manifest.dash.enableAudioGroups` has been renamed to `manifest.enableAudioGroups` + - `preferredVariantRole` has been renamed to `preferredAudioRole` (deprecated in v4.16.0) - Plugin changes: - `TextDisplayer` plugins must implement the `configure()` method. diff --git a/externs/shaka/player.js b/externs/shaka/player.js index 1fa03f3e9b..fb78d163d1 100644 --- a/externs/shaka/player.js +++ b/externs/shaka/player.js @@ -252,6 +252,7 @@ shaka.extern.BufferedInfo; * * language: string, * label: ?string, + * videoLabel: ?string, * kind: ?string, * width: ?number, * height: ?number, @@ -269,6 +270,7 @@ shaka.extern.BufferedInfo; * primary: boolean, * roles: !Array, * audioRoles: Array, + * videoRoles: Array, * accessibilityPurpose: ?shaka.media.ManifestParser.AccessibilityPurpose, * forced: boolean, * videoId: ?number, @@ -311,6 +313,9 @@ shaka.extern.BufferedInfo; * i.e. 'en-US'. * @property {?string} label * The track label, which is unique text that should describe the track. + * @property {?string} videoLabel + * The video track label, which is unique text that should describe the video + * track. * @property {?string} kind * (only for text tracks) The kind of text track, either * 'caption' or 'subtitle'. @@ -353,6 +358,10 @@ shaka.extern.BufferedInfo; * The roles of the audio in the track, e.g. 'main' or * 'commentary'. Will be null for text tracks or variant tracks * without audio. + * @property {Array} videoRoles + * The roles of the video in the track, e.g. 'main' or + * 'sign'. Will be null for text tracks or variant tracks + * without video. * @property {?shaka.media.ManifestParser.AccessibilityPurpose * } accessibilityPurpose * The DASH accessibility descriptor, if one was provided for this track. @@ -552,7 +561,9 @@ shaka.extern.TextTrack; * colorGamut: ?string, * videoLayout: ?string, * mimeType: ?string, - * codecs: ?string + * codecs: ?string, + * roles: !Array, + * label: ?string, * }} * * @description @@ -582,6 +593,10 @@ shaka.extern.TextTrack; * The video MIME type of the content provided in the manifest. * @property {?string} codecs * The video codecs string provided in the manifest, if present. + * @property {!Array} roles + * The roles of the track, e.g. 'main', 'sign'. + * @property {?string} label + * The track label, which is unique text that should describe the track. * @exportDoc */ shaka.extern.VideoTrack; @@ -2747,7 +2762,8 @@ shaka.extern.TextDisplayerConfiguration; * preferredAudioLanguage: string, * preferredAudioLabel: string, * preferredTextLanguage: string, - * preferredVariantRole: string, + * preferredAudioRole: string, + * preferredVideoRole: string, * preferredTextRole: string, * preferredVideoCodecs: !Array, * preferredAudioCodecs: !Array, @@ -2826,8 +2842,12 @@ shaka.extern.TextDisplayerConfiguration; * Changing this during playback will not affect the current playback. *
* Defaults to ''. - * @property {string} preferredVariantRole - * The preferred role to use for variants. + * @property {string} preferredAudioRole + * The preferred audio role to use for variants. + *
+ * Defaults to ''. + * @property {string} preferredVideoRole + * The preferred video role to use for variants. *
* Defaults to ''. * @property {string} preferredTextRole diff --git a/lib/media/adaptation_set_criteria.js b/lib/media/adaptation_set_criteria.js index 13475a302e..732a7d3f03 100644 --- a/lib/media/adaptation_set_criteria.js +++ b/lib/media/adaptation_set_criteria.js @@ -58,6 +58,7 @@ shaka.media.AdaptationSetCriteria.Factory; * @typedef {{ * language: string, * role: string, + * videoRole: string, * channelCount: number, * hdrLevel: string, * spatialAudio: boolean, @@ -75,7 +76,9 @@ shaka.media.AdaptationSetCriteria.Factory; * @property {string} language * The language used to filter variants. * @property {string} role - * The adaptation role used to filter variants. + * The adaptation audio role used to filter variants. + * @property {string} videoRole + * The adaptation video role used to filter variants. * @property {string} channelCount * The audio channel count used to filter variants. * @property {string} hdrLevel diff --git a/lib/media/gap_jumping_controller.js b/lib/media/gap_jumping_controller.js index 78599d9263..4f8c8f3aa6 100644 --- a/lib/media/gap_jumping_controller.js +++ b/lib/media/gap_jumping_controller.js @@ -62,6 +62,9 @@ shaka.media.GapJumpingController = class { /** @private {number} */ this.startTime_ = 0; + /** @private {boolean} */ + this.isJumpingGap_ = false; + /** @private {number} */ this.gapsJumped_ = 0; @@ -178,6 +181,15 @@ shaka.media.GapJumpingController = class { return this.stallsDetected_; } + /** + * Returns whether the player is currently jumping a gap. + * + * @return {boolean} + */ + getIsJumpingGap() { + return this.isJumpingGap_; + } + /** * Called on a recurring timer to check for gaps in the media. This is also @@ -273,7 +285,7 @@ shaka.media.GapJumpingController = class { buffered.end(gapIndex - 1), 'and ending at', jumpTo); } - this.video_.currentTime = jumpTo; + this.seek_(jumpTo); // This accounts for the possibility that we jump a gap at the start // position but we jump _into_ another gap. By setting the start // position to the new jumpTo we ensure that the check above will @@ -286,6 +298,19 @@ shaka.media.GapJumpingController = class { new shaka.util.FakeEvent(shaka.util.FakeEvent.EventName.GapJumped)); } + /** + * Seek to a specific time in the video. + * @param {number} time The time to seek to, in seconds. + * @private + */ + seek_(time) { + this.isJumpingGap_ = true; + this.eventManager_.listenOnce(this.video_, 'seeked', () => { + this.isJumpingGap_ = false; + }); + this.video_.currentTime = time; + } + /** * Create and configure a stall detector using the player's streaming * configuration settings. If the player is configured to have no stall diff --git a/lib/media/playhead.js b/lib/media/playhead.js index 967ae7bf93..8820cf703a 100644 --- a/lib/media/playhead.js +++ b/lib/media/playhead.js @@ -56,6 +56,13 @@ shaka.media.Playhead = class { */ getStallsDetected() {} + /** + * Get whether the playhead is currently jumping a gap. + * + * @return {boolean} + */ + getIsJumpingGap() {} + /** * Get the number of playback gaps jumped by the GapJumpingController. * @@ -209,6 +216,11 @@ shaka.media.SrcEqualsPlayhead = class { return 0; } + /** @override */ + getIsJumpingGap() { + return false; + } + /** @override */ notifyOfBufferingChange() {} @@ -401,6 +413,11 @@ shaka.media.MediaSourcePlayhead = class { return this.gapController_.getGapsJumped(); } + /** @override */ + getIsJumpingGap() { + return this.gapController_.getIsJumpingGap(); + } + /** * Gets the playhead's initial position in seconds. * diff --git a/lib/media/playhead_observer.js b/lib/media/playhead_observer.js index 341e243021..3529a1212b 100644 --- a/lib/media/playhead_observer.js +++ b/lib/media/playhead_observer.js @@ -113,9 +113,11 @@ shaka.media.PlayheadObserverManager = class { /** * Notify all the observers that we just seeked. + * + * @param {boolean} seeking */ - notifyOfSeek() { - this.pollAllObservers_(/* seeking= */ true); + notifyOfSeek(seeking) { + this.pollAllObservers_(seeking); } /** diff --git a/lib/media/preference_based_criteria.js b/lib/media/preference_based_criteria.js index c5c8c89725..f06fc0dd08 100644 --- a/lib/media/preference_based_criteria.js +++ b/lib/media/preference_based_criteria.js @@ -64,13 +64,26 @@ shaka.media.PreferenceBasedCriteria = class { } } - // Now refine the choice based on role preference. Even the empty string - // works here, and will match variants without any roles. - const byRole = Class.filterVariantsByRole_(current, this.config_.role); - if (byRole.length) { - current = byRole; + // Now refine the choice based on audio role preference. Even the empty + // string works here, and will match variants without any roles. + const byAudioRole = + Class.filterVariantsByAudioRole_(current, this.config_.role); + if (byAudioRole.length) { + current = byAudioRole; } else { - shaka.log.warning('No exact match for variant role could be found.'); + shaka.log.warning( + 'No exact match for variant audio role could be found.'); + } + + // Now refine the choice based on video role preference. Even the empty + // string works here, and will match variants without any roles. + const byVideoRole = + Class.filterVariantsByVideoRole_(current, this.config_.videoRole); + if (byVideoRole.length) { + current = byVideoRole; + } else { + shaka.log.warning( + 'No exact match for variant video role could be found.'); } if (this.config_.videoLayout) { @@ -210,14 +223,14 @@ shaka.media.PreferenceBasedCriteria = class { } /** - * Filter Variants by role. + * Filter Variants by audio role. * * @param {!Array} variants * @param {string} preferredRole * @return {!Array} * @private */ - static filterVariantsByRole_(variants, preferredRole) { + static filterVariantsByAudioRole_(variants, preferredRole) { return variants.filter((variant) => { if (!variant.audio) { return false; @@ -231,6 +244,28 @@ shaka.media.PreferenceBasedCriteria = class { }); } + /** + * Filter Variants by video role. + * + * @param {!Array} variants + * @param {string} preferredRole + * @return {!Array} + * @private + */ + static filterVariantsByVideoRole_(variants, preferredRole) { + return variants.filter((variant) => { + if (!variant.video) { + return false; + } + + if (preferredRole) { + return variant.video.roles.includes(preferredRole); + } else { + return variant.video.roles.length == 0; + } + }); + } + /** * Filter Variants by audio label. * diff --git a/lib/media/preload_manager.js b/lib/media/preload_manager.js index d0da1f6a4d..02605e2e40 100644 --- a/lib/media/preload_manager.js +++ b/lib/media/preload_manager.js @@ -651,7 +651,8 @@ shaka.media.PreloadManager = class extends shaka.util.FakeEventTarget { this.config_.adaptationSetCriteriaFactory(); this.currentAdaptationSetCriteria_.configure({ language: this.config_.preferredAudioLanguage, - role: this.config_.preferredVariantRole, + role: this.config_.preferredAudioRole, + videoRole: this.config_.preferredVideoRole, channelCount: this.config_.preferredAudioChannelCount, hdrLevel: this.config_.preferredVideoHdrLevel, spatialAudio: this.config_.preferSpatialAudio, diff --git a/lib/player.js b/lib/player.js index 54245edc99..3d1025b6ef 100644 --- a/lib/player.js +++ b/lib/player.js @@ -43,6 +43,7 @@ goog.require('shaka.text.TextEngine'); goog.require('shaka.text.Utils'); goog.require('shaka.text.UITextDisplayer'); goog.require('shaka.text.WebVttGenerator'); +goog.require('shaka.util.ArrayUtils'); goog.require('shaka.util.BufferUtils'); goog.require('shaka.util.CmcdManager'); goog.require('shaka.util.CmsdManager'); @@ -883,7 +884,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget { this.config_.adaptationSetCriteriaFactory(); this.currentAdaptationSetCriteria_.configure({ language: this.config_.preferredAudioLanguage, - role: this.config_.preferredVariantRole, + role: this.config_.preferredAudioRole, + videoRole: this.config_.preferredVideoRole, channelCount: 0, hdrLevel: this.config_.preferredVideoHdrLevel, spatialAudio: this.config_.preferSpatialAudio, @@ -3448,8 +3450,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget { return; } - const preferredVariantRole = this.config_.preferredVariantRole; - this.selectAudioLanguage(preferredAudioLanguage, preferredVariantRole); + const preferredAudioRole = this.config_.preferredAudioRole; + this.selectAudioLanguage(preferredAudioLanguage, preferredAudioRole); } /** @@ -4241,6 +4243,15 @@ shaka.Player = class extends shaka.util.FakeEventTarget { goog.asserts.assert(typeof(config) == 'object', 'Should be an object!'); + // Deprecate 'preferredVariantRole' configuration. + if ('preferredVariantRole' in config) { + shaka.Deprecate.deprecateFeature(5, + 'preferredVariantRole configuration', + 'Please Use preferredAudioRole instead.'); + config['preferredAudioRole'] = config['preferredVariantRole']; + delete config['preferredVariantRole']; + } + // Deprecate 'streaming.forceTransmuxTS' configuration. if (config['streaming'] && 'forceTransmuxTS' in config['streaming']) { shaka.Deprecate.deprecateFeature(5, @@ -5777,6 +5788,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget { language: variant.language, role: (variant.audio && variant.audio.roles && variant.audio.roles[0]) || '', + videoRole: (variant.video && variant.video.roles && + variant.video.roles[0]) || '', channelCount: variant.audio && variant.audio.channelsCount ? variant.audio.channelsCount : 0, hdrLevel: variant.video && variant.video.hdr ? variant.video.hdr : '', @@ -5786,7 +5799,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget { variant.video.videoLayout : '', audioLabel: variant.audio && variant.audio.label ? variant.audio.label : '', - videoLabel: '', + videoLabel: variant.video && variant.video.label ? + variant.video.label : '', codecSwitchingStrategy: this.config_.mediaSource.codecSwitchingStrategy, audioCodec: variant.audio && variant.audio.codecs ? variant.audio.codecs : '', @@ -5967,6 +5981,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget { * @export */ selectVideoTrack(videoTrack, clearBuffer = false, safeMargin = 0) { + const ArrayUtils = shaka.util.ArrayUtils; const variants = this.getVariantTracks(); if (!variants.length) { return; @@ -5986,7 +6001,9 @@ shaka.Player = class extends shaka.util.FakeEventTarget { t.colorGamut == videoTrack.colorGamut && t.videoLayout == videoTrack.videoLayout && t.videoMimeType == videoTrack.mimeType && - t.videoCodec == videoTrack.codecs; + t.videoCodec == videoTrack.codecs && + ArrayUtils.equal(t.videoRoles, videoTrack.roles) && + t.videoLabel == videoTrack.label; }); if (validVariant && !validVariant.active) { this.selectVariantTrack(validVariant, clearBuffer, safeMargin); @@ -6046,6 +6063,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget { videoLayout: track.videoLayout, mimeType: track.videoMimeType, codecs: track.videoCodec, + roles: track.videoRoles || [], + label: track.videoLabel, }; videoTracksMap.set(id, videoTrack); } @@ -6149,6 +6168,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget { this.currentAdaptationSetCriteria_.configure({ language, role: role || '', + videoRole: (active.video && active.video.roles && + active.video.roles[0]) || '', channelCount: channelsCount || 0, hdrLevel: '', spatialAudio: spatialAudio || false, @@ -6324,6 +6345,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget { this.currentAdaptationSetCriteria_.configure({ language: firstVariantWithLabel.language, role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -8181,7 +8203,10 @@ shaka.Player = class extends shaka.util.FakeEventTarget { */ onSeek_() { if (this.playheadObservers_) { - this.playheadObservers_.notifyOfSeek(); + // Gap jump is a seek that is not caused by user interaction and needs + // to be handled differently for things like event streams and timeline + // regions. + this.playheadObservers_.notifyOfSeek(!this.playhead_.getIsJumpingGap()); } if (this.streamingEngine_) { this.streamingEngine_.seeked(); diff --git a/lib/util/player_configuration.js b/lib/util/player_configuration.js index d870346133..ca0acf4c8f 100644 --- a/lib/util/player_configuration.js +++ b/lib/util/player_configuration.js @@ -434,7 +434,8 @@ shaka.util.PlayerConfiguration = class { preferredAudioLanguage: '', preferredAudioLabel: '', preferredTextLanguage: '', - preferredVariantRole: '', + preferredAudioRole: '', + preferredVideoRole: '', preferredTextRole: '', preferredAudioChannelCount: 2, preferredVideoHdrLevel: 'AUTO', diff --git a/lib/util/stream_utils.js b/lib/util/stream_utils.js index 4bd3740f80..d7b5c6ab60 100644 --- a/lib/util/stream_utils.js +++ b/lib/util/stream_utils.js @@ -1357,6 +1357,7 @@ shaka.util.StreamUtils = class { bandwidth: variant.bandwidth, language: variant.language, label: null, + videoLabel: null, kind: kind, width: null, height: null, @@ -1374,6 +1375,7 @@ shaka.util.StreamUtils = class { primary: variant.primary, roles: Array.from(roles), audioRoles: null, + videoRoles: null, forced: false, videoId: null, audioId: null, @@ -1403,6 +1405,8 @@ shaka.util.StreamUtils = class { track.hdr = video.hdr || null; track.colorGamut = video.colorGamut || null; track.videoLayout = video.videoLayout || null; + track.videoRoles = video.roles; + track.videoLabel = video.label; const dependencyStream = video.dependencyStream; if (dependencyStream) { @@ -1657,6 +1661,7 @@ shaka.util.StreamUtils = class { bandwidth: 0, language: LanguageUtils.normalize(language || 'und'), label: audioTrack ? audioTrack.label : null, + videoLabel: null, kind: audioTrack ? audioTrack.kind : null, width: null, height: null, @@ -1675,6 +1680,7 @@ shaka.util.StreamUtils = class { roles: [], forced: false, audioRoles: null, + videoRoles: null, videoId: null, audioId: null, audioGroupId: null, diff --git a/test/media/adaptation_set_criteria_unit.js b/test/media/adaptation_set_criteria_unit.js index b3faeec10b..3ef3743e74 100644 --- a/test/media/adaptation_set_criteria_unit.js +++ b/test/media/adaptation_set_criteria_unit.js @@ -23,6 +23,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: 'en', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -60,6 +61,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: 'en', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -122,6 +124,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: 'en', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -177,6 +180,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: 'en', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -221,6 +225,46 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: 'en', role: 'main', + videoRole: '', + channelCount: 0, + hdrLevel: '', + spatialAudio: false, + videoLayout: '', + audioLabel: '', + videoLabel: '', + codecSwitchingStrategy: shaka.config.CodecSwitchingStrategy.RELOAD, + audioCodec: '', + activeAudioCodec: '', + activeAudioChannelCount: 0, + preferredAudioCodecs: [], + preferredAudioChannelCount: 0, + }); + const set = builder.create(manifest.variants); + + checkSet(set, [ + manifest.variants[0], + ]); + }); + + it('chooses variants in preferred video role', () => { + const manifest = shaka.test.ManifestGenerator.generate((manifest) => { + manifest.addVariant(1, (variant) => { + variant.addVideo(10, (stream) => { + stream.roles = ['sign']; + }); + }); + manifest.addVariant(2, (variant) => { + variant.addVideo(20, (stream) => { + stream.roles = ['main']; + }); + }); + }); + + const builder = new shaka.media.PreferenceBasedCriteria(); + builder.configure({ + language: 'en', + role: 'main', + videoRole: 'sign', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -286,6 +330,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: 'en', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -360,6 +405,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: 'zh', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -412,6 +458,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: 'zh', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -484,6 +531,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: 'zh', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -557,6 +605,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: 'zh', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -601,6 +650,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: '', role: '', + videoRole: '', channelCount: 0, hdrLevel: 'PQ', spatialAudio: false, @@ -645,6 +695,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: '', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -689,6 +740,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: '', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -732,6 +784,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: '', role: '', + videoRole: '', channelCount: 2, hdrLevel: '', spatialAudio: false, @@ -782,6 +835,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: '', role: '', + videoRole: '', channelCount: 6, hdrLevel: '', spatialAudio: false, @@ -827,6 +881,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: '', role: '', + videoRole: '', channelCount: 2, hdrLevel: '', spatialAudio: false, @@ -872,6 +927,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: '', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -917,6 +973,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: '', role: '', + videoRole: '', channelCount: 6, hdrLevel: '', spatialAudio: false, @@ -961,6 +1018,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: '', role: '', + videoRole: '', channelCount: 6, hdrLevel: '', spatialAudio: false, @@ -1004,6 +1062,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: '', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -1043,6 +1102,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: '', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: true, @@ -1081,6 +1141,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: '', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -1137,6 +1198,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: 'zh', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -1181,6 +1243,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: '', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -1231,6 +1294,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: 'en', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -1270,6 +1334,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: 'en', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -1308,6 +1373,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: 'en', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -1346,6 +1412,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: 'en', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -1385,6 +1452,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: 'en', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -1424,6 +1492,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: 'en', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -1463,6 +1532,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: 'en', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, @@ -1502,6 +1572,7 @@ describe('AdaptationSetCriteria', () => { builder.configure({ language: 'en', role: '', + videoRole: '', channelCount: 0, hdrLevel: '', spatialAudio: false, diff --git a/test/offline/storage_integration.js b/test/offline/storage_integration.js index f7eeec07fd..d1f013ffe9 100644 --- a/test/offline/storage_integration.js +++ b/test/offline/storage_integration.js @@ -1376,6 +1376,7 @@ filterDescribe('Storage', storageSupport, () => { language: language, originalLanguage: language, label: null, + videoLabel: null, kind: null, width: height * (16 / 9), height: height, @@ -1393,6 +1394,7 @@ filterDescribe('Storage', storageSupport, () => { primary: false, roles: [], audioRoles: [], + videoRoles: [], forced: false, videoId: videoId, audioId: audioId, @@ -1425,6 +1427,7 @@ filterDescribe('Storage', storageSupport, () => { language: language, originalLanguage: language, label: null, + videoLabel: null, kind: null, width: null, height: null, @@ -1442,6 +1445,7 @@ filterDescribe('Storage', storageSupport, () => { primary: false, roles: [], audioRoles: null, + videoRoles: null, forced: false, videoId: null, audioId: null, diff --git a/test/player_unit.js b/test/player_unit.js index 77ab7fb493..9c13fca798 100644 --- a/test/player_unit.js +++ b/test/player_unit.js @@ -1685,12 +1685,13 @@ describe('Player', () => { variantTracks = [ { id: 100, - active: true, + active: false, type: 'variant', bandwidth: 1300, language: 'en', originalLanguage: 'en', label: null, + videoLabel: null, kind: null, width: 100, height: 200, @@ -1708,6 +1709,7 @@ describe('Player', () => { primary: false, roles: ['main'], audioRoles: ['main'], + videoRoles: ['main'], forced: false, videoId: 1, audioId: 3, @@ -1726,12 +1728,13 @@ describe('Player', () => { }, { id: 101, - active: false, + active: true, type: 'variant', bandwidth: 2300, language: 'en', originalLanguage: 'en', label: null, + videoLabel: null, kind: null, width: 200, height: 400, @@ -1749,6 +1752,7 @@ describe('Player', () => { primary: false, roles: ['main'], audioRoles: ['main'], + videoRoles: [], forced: false, videoId: 2, audioId: 3, @@ -1773,6 +1777,7 @@ describe('Player', () => { language: 'en', originalLanguage: 'en', label: null, + videoLabel: null, kind: null, width: 100, height: 200, @@ -1790,6 +1795,7 @@ describe('Player', () => { primary: false, roles: ['main'], audioRoles: ['main'], + videoRoles: ['main'], forced: false, videoId: 1, audioId: 4, @@ -1814,6 +1820,7 @@ describe('Player', () => { language: 'en', originalLanguage: 'en', label: null, + videoLabel: null, kind: null, width: 200, height: 400, @@ -1831,6 +1838,7 @@ describe('Player', () => { primary: false, roles: ['main'], audioRoles: ['main'], + videoRoles: [], forced: false, videoId: 2, audioId: 4, @@ -1855,6 +1863,7 @@ describe('Player', () => { language: 'en', originalLanguage: 'en', label: null, + videoLabel: null, kind: null, width: 100, height: 200, @@ -1872,6 +1881,7 @@ describe('Player', () => { primary: false, roles: ['commentary', 'main'], audioRoles: ['commentary'], + videoRoles: ['main'], forced: false, videoId: 1, audioId: 5, @@ -1896,6 +1906,7 @@ describe('Player', () => { language: 'en', originalLanguage: 'en', label: null, + videoLabel: null, kind: null, width: 200, height: 400, @@ -1913,6 +1924,7 @@ describe('Player', () => { primary: false, roles: ['commentary'], audioRoles: ['commentary'], + videoRoles: [], forced: false, videoId: 2, audioId: 5, @@ -1936,6 +1948,7 @@ describe('Player', () => { bandwidth: 1100, language: 'es', label: 'es-label', + videoLabel: null, originalLanguage: 'es', kind: null, width: 100, @@ -1954,6 +1967,7 @@ describe('Player', () => { primary: false, roles: ['main'], audioRoles: [], + videoRoles: ['main'], forced: false, videoId: 1, audioId: 6, @@ -1977,6 +1991,7 @@ describe('Player', () => { bandwidth: 2100, language: 'es', label: 'es-label', + videoLabel: null, originalLanguage: 'es', kind: null, width: 200, @@ -1995,6 +2010,7 @@ describe('Player', () => { primary: false, roles: [], audioRoles: [], + videoRoles: [], forced: false, videoId: 2, audioId: 6, @@ -2019,6 +2035,7 @@ describe('Player', () => { language: 'es', originalLanguage: 'es', label: null, + videoLabel: null, kind: null, width: 100, height: 200, @@ -2036,6 +2053,7 @@ describe('Player', () => { primary: false, roles: ['main'], audioRoles: [], + videoRoles: ['main'], forced: false, videoId: 1, audioId: 7, @@ -2060,6 +2078,7 @@ describe('Player', () => { language: 'es', originalLanguage: 'es', label: null, + videoLabel: null, kind: null, width: 200, height: 400, @@ -2077,6 +2096,7 @@ describe('Player', () => { primary: false, roles: [], audioRoles: [], + videoRoles: [], forced: false, videoId: 2, audioId: 7, @@ -2170,7 +2190,7 @@ describe('Player', () => { videoTracks = [ { - active: true, + active: false, bandwidth: 1000, width: 100, height: 200, @@ -2181,9 +2201,11 @@ describe('Player', () => { videoLayout: null, mimeType: 'video/mp4', codecs: 'avc1.4d401f', + roles: ['main'], + label: null, }, { - active: false, + active: true, bandwidth: 2000, width: 200, height: 400, @@ -2194,6 +2216,8 @@ describe('Player', () => { videoLayout: null, mimeType: 'video/mp4', codecs: 'avc1.4d401f', + roles: [], + label: null, }, ]; @@ -2411,10 +2435,11 @@ describe('Player', () => { it('selectAudioLanguage() applies role only to audio', () => { expect(getActiveVariantTrack().roles).not.toContain('commentary'); + const videoRoles = getActiveVariantTrack().videoRoles; player.selectAudioLanguage('en', 'commentary'); let args = streamingEngine.switchVariant.calls.argsFor(0); expect(args[0].audio.roles).toContain('commentary'); - expect(args[0].video.roles).toContain('main'); + expect(args[0].video.roles).toBe(videoRoles); // Switch audio role from 'commentary' to 'main'. streamingEngine.switchVariant.calls.reset(); @@ -2422,7 +2447,7 @@ describe('Player', () => { expect(streamingEngine.switchVariant).toHaveBeenCalled(); args = streamingEngine.switchVariant.calls.argsFor(0); expect(args[0].audio.roles).toContain('main'); - expect(args[0].video.roles).toContain('main'); + expect(args[0].video.roles).toBe(videoRoles); }); it('selectAudioLanguage() does not change selected text track', () => {