From b491a6b7caa5d4a8167adf18cf90b23c30a5a1be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Velad=20Galv=C3=A1n?= Date: Wed, 7 Dec 2022 20:52:12 +0100 Subject: [PATCH] feat: Move forceTransmux from streaming to mediasource config (#4783) --- demo/config.js | 10 +++--- externs/shaka/player.js | 12 +++---- lib/media/media_source_engine.js | 6 ++-- lib/media/streaming_engine.js | 4 +-- lib/player.js | 18 +++++++--- lib/util/player_configuration.js | 2 +- test/media/media_source_engine_integration.js | 33 +++++++++++-------- test/media/media_source_engine_unit.js | 6 ++-- test/media/streaming_engine_unit.js | 2 +- 9 files changed, 52 insertions(+), 41 deletions(-) diff --git a/demo/config.js b/demo/config.js index a23048b720..0baca4b6eb 100644 --- a/demo/config.js +++ b/demo/config.js @@ -436,10 +436,8 @@ shakaDemo.Config = class { this.latestInput_.input().checked = true; } - this.addBoolInput_(MessageIds.FORCE_TRANSMUX, - 'streaming.forceTransmux') - .addBoolInput_(MessageIds.START_AT_SEGMENT_BOUNDARY, - 'streaming.startAtSegmentBoundary') + this.addBoolInput_(MessageIds.START_AT_SEGMENT_BOUNDARY, + 'streaming.startAtSegmentBoundary') .addBoolInput_(MessageIds.IGNORE_TEXT_FAILURES, 'streaming.ignoreTextStreamFailures') .addBoolInput_(MessageIds.STALL_DETECTOR_ENABLED, @@ -456,7 +454,9 @@ shakaDemo.Config = class { const docLink = this.resolveExternLink_('.MediaSourceConfiguration'); this.addSection_(MessageIds.MEDIA_SOURCE_SECTION_HEADER, docLink) .addTextInput_(MessageIds.SOURCE_BUFFER_EXTRA_FEATURES, - 'mediaSource.sourceBufferExtraFeatures'); + 'mediaSource.sourceBufferExtraFeatures') + .addBoolInput_(MessageIds.FORCE_TRANSMUX, + 'mediaSource.forceTransmux'); } /** @private */ diff --git a/externs/shaka/player.js b/externs/shaka/player.js index 7ee17f3f33..dbb718065d 100644 --- a/externs/shaka/player.js +++ b/externs/shaka/player.js @@ -948,7 +948,6 @@ shaka.extern.ManifestConfiguration; * startAtSegmentBoundary: boolean, * gapDetectionThreshold: number, * durationBackoff: number, - * forceTransmux: boolean, * safeSeekOffset: number, * stallEnabled: boolean, * stallThreshold: number, @@ -1011,10 +1010,6 @@ shaka.extern.ManifestConfiguration; * seek to when the user tries to seek to or start playback at the duration. * To disable this behavior, the config can be set to 0. We recommend using * the default value unless you have a good reason not to. - * @property {boolean} forceTransmux - * If this is true, we will transmux AAC and TS content even if - * not strictly necessary for the assets to be played. - * This value defaults to false. * @property {number} safeSeekOffset * The amount of seconds that should be added when repositioning the playhead * after falling out of the availability window or seek. This gives the player @@ -1084,7 +1079,8 @@ shaka.extern.StreamingConfiguration; /** * @typedef {{ - * sourceBufferExtraFeatures: string + * sourceBufferExtraFeatures: string, + * forceTransmux: boolean * }} * * @description @@ -1094,6 +1090,10 @@ shaka.extern.StreamingConfiguration; * Some platforms may need to pass features when initializing the * sourceBuffer. * This string is ultimately appended to MIME types in addSourceBuffer(). + * @property {boolean} forceTransmux + * If this is true, we will transmux AAC and TS content even if + * not strictly necessary for the assets to be played. + * This value defaults to false. * @exportDoc */ shaka.extern.MediaSourceConfiguration; diff --git a/lib/media/media_source_engine.js b/lib/media/media_source_engine.js index d5ff5af8cb..c2a1f123b2 100644 --- a/lib/media/media_source_engine.js +++ b/lib/media/media_source_engine.js @@ -339,16 +339,13 @@ shaka.media.MediaSourceEngine = class { * shaka.extern.Stream>} streamsByType * A map of content types to streams. All streams must be supported * according to MediaSourceEngine.isStreamSupported. - * @param {boolean} forceTransmux - * If true, this will transmux AAC and TS content even if it is natively - * supported. * @param {boolean=} sequenceMode * If true, the media segments are appended to the SourceBuffer in strict * sequence. * * @return {!Promise} */ - async init(streamsByType, forceTransmux, sequenceMode=false) { + async init(streamsByType, sequenceMode=false) { const ContentType = shaka.util.ManifestParserUtils.ContentType; await this.mediaSourceOpen_; @@ -366,6 +363,7 @@ shaka.media.MediaSourceEngine = class { if (contentType == ContentType.TEXT) { this.reinitText(mimeType, sequenceMode); } else { + const forceTransmux = this.config_.forceTransmux; if ((forceTransmux || !shaka.media.Capabilities.isTypeSupported(mimeType)) && shaka.media.Transmuxer.isSupported(mimeType, contentType)) { diff --git a/lib/media/streaming_engine.js b/lib/media/streaming_engine.js index c0d7cc4ebe..295f002edd 100644 --- a/lib/media/streaming_engine.js +++ b/lib/media/streaming_engine.js @@ -784,10 +784,8 @@ shaka.media.StreamingEngine = class { // Init MediaSourceEngine. const mediaSourceEngine = this.playerInterface_.mediaSourceEngine; - const forceTransmux = this.config_.forceTransmux; - await mediaSourceEngine.init(streamsByType, forceTransmux, - this.manifest_.sequenceMode); + await mediaSourceEngine.init(streamsByType, this.manifest_.sequenceMode); this.destroyer_.ensureNotDestroyed(); this.updateDuration(); diff --git a/lib/player.js b/lib/player.js index 24db39ccdc..279782b61d 100644 --- a/lib/player.js +++ b/lib/player.js @@ -797,13 +797,13 @@ shaka.Player = class extends shaka.util.FakeEventTarget { const edge = shaka.util.Platform.isEdge() || shaka.util.Platform.isLegacyEdge(); if (edge) { - if (!config.streaming.forceTransmux) { + if (!config.mediaSource.forceTransmux) { // If forceTransmux is disabled for Microsoft Edge, LCEVC data // is stripped out in case of a MPEG-2 TS container. // Hence the warning for Microsoft Edge when playing content with // MPEG-2 TS container. shaka.log.alwaysWarn('LCEVC Warning: For MPEG-2 TS decoding '+ - 'the config.streaming.forceTransmux must be enabled.'); + 'the config.mediaSource.forceTransmux must be enabled.'); } } } @@ -3175,12 +3175,22 @@ shaka.Player = class extends shaka.util.FakeEventTarget { if (config['streaming'] && 'forceTransmuxTS' in config['streaming']) { shaka.Deprecate.deprecateFeature(5, 'streaming.forceTransmuxTS configuration', - 'Please Use streaming.forceTransmux instead.'); - config['streaming']['forceTransmux'] = + 'Please Use mediaSource.forceTransmux instead.'); + config['mediaSource']['mediaSource'] = config['streaming']['forceTransmuxTS']; delete config['streaming']['forceTransmuxTS']; } + // Deprecate 'streaming.forceTransmux' configuration. + if (config['streaming'] && 'forceTransmux' in config['streaming']) { + shaka.Deprecate.deprecateFeature(5, + 'streaming.forceTransmux configuration', + 'Please Use mediaSource.forceTransmux instead.'); + config['mediaSource']['mediaSource'] = + config['streaming']['forceTransmux']; + delete config['streaming']['forceTransmux']; + } + // If lowLatencyMode is enabled, and inaccurateManifestTolerance and // rebufferingGoal are not specified, set inaccurateManifestTolerance to 0 // and rebufferingGoal to 0.01 by default for low latency streaming. diff --git a/lib/util/player_configuration.js b/lib/util/player_configuration.js index 46f388ca18..b9c19816ca 100644 --- a/lib/util/player_configuration.js +++ b/lib/util/player_configuration.js @@ -157,7 +157,6 @@ shaka.util.PlayerConfiguration = class { startAtSegmentBoundary: false, gapDetectionThreshold: 0.5, durationBackoff: 1, - forceTransmux: false, // Offset by 5 seconds since Chromecast takes a few seconds to start // playing after a seek, even when buffered. safeSeekOffset: 5, @@ -274,6 +273,7 @@ shaka.util.PlayerConfiguration = class { const mediaSource = { sourceBufferExtraFeatures: '', + forceTransmux: false, }; const AutoShowText = shaka.config.AutoShowText; diff --git a/test/media/media_source_engine_integration.js b/test/media/media_source_engine_integration.js index a917d8ff97..663646dafb 100644 --- a/test/media/media_source_engine_integration.js +++ b/test/media/media_source_engine_integration.js @@ -510,9 +510,10 @@ describe('MediaSourceEngine', () => { const initObject = new Map(); initObject.set(ContentType.VIDEO, getFakeStream(metadata.video)); initObject.set(ContentType.TEXT, getFakeStream(metadata.text)); - // Call with forceTransmux = true, so that it will transmux even on - // platforms with native TS support. - await mediaSourceEngine.init(initObject, /* forceTransmux= */ true); + const config = shaka.util.PlayerConfiguration.createDefault().mediaSource; + config.forceTransmux = true; + mediaSourceEngine.configure(config); + await mediaSourceEngine.init(initObject); mediaSourceEngine.setSelectedClosedCaptionId('CC1'); await appendWithClosedCaptions(ContentType.VIDEO, 0); @@ -531,9 +532,10 @@ describe('MediaSourceEngine', () => { const initObject = new Map(); initObject.set(ContentType.VIDEO, getFakeStream(metadata.video)); initObject.set(ContentType.TEXT, getFakeStream(metadata.text)); - // Call with forceTransmux = true, so that it will transmux even on - // platforms with native TS support. - await mediaSourceEngine.init(initObject, /* forceTransmux= */ true); + const config = shaka.util.PlayerConfiguration.createDefault().mediaSource; + config.forceTransmux = true; + mediaSourceEngine.configure(config); + await mediaSourceEngine.init(initObject); mediaSourceEngine.setSelectedClosedCaptionId('CC1'); await appendWithClosedCaptions(ContentType.VIDEO, 2); @@ -560,8 +562,7 @@ describe('MediaSourceEngine', () => { const initObject = new Map(); initObject.set(videoType, getFakeStream(metadata.video)); - await mediaSourceEngine.init( - initObject, /* forceTransmux= */ false, /* sequenceMode= */ true); + await mediaSourceEngine.init(initObject, /* sequenceMode= */ true); await mediaSourceEngine.setDuration(presentationDuration); await mediaSourceEngine.setStreamProperties( videoType, @@ -596,7 +597,7 @@ describe('MediaSourceEngine', () => { const initObject = new Map(); initObject.set(ContentType.VIDEO, getFakeStream(metadata.video)); - await mediaSourceEngine.init(initObject, /* forceTransmux= */ false); + await mediaSourceEngine.init(initObject); await mediaSourceEngine.setDuration(presentationDuration); await appendInitWithClosedCaptions(ContentType.VIDEO); mediaSourceEngine.setSelectedClosedCaptionId('CC1'); @@ -613,7 +614,7 @@ describe('MediaSourceEngine', () => { const audioType = ContentType.AUDIO; const initObject = new Map(); initObject.set(audioType, getFakeStream(metadata.audio)); - await mediaSourceEngine.init(initObject, /* forceTransmux= */ false); + await mediaSourceEngine.init(initObject); await append(ContentType.AUDIO, 0); expect(onMetadata).toHaveBeenCalled(); @@ -626,7 +627,10 @@ describe('MediaSourceEngine', () => { const audioType = ContentType.AUDIO; const initObject = new Map(); initObject.set(audioType, getFakeStream(metadata.audio)); - await mediaSourceEngine.init(initObject, /* forceTransmux= */ true); + const config = shaka.util.PlayerConfiguration.createDefault().mediaSource; + config.forceTransmux = true; + mediaSourceEngine.configure(config); + await mediaSourceEngine.init(initObject); await append(ContentType.AUDIO, 0); expect(onMetadata).toHaveBeenCalled(); @@ -642,7 +646,7 @@ describe('MediaSourceEngine', () => { const audioType = ContentType.AUDIO; const initObject = new Map(); initObject.set(audioType, getFakeStream(metadata.audio)); - await mediaSourceEngine.init(initObject, /* forceTransmux= */ false); + await mediaSourceEngine.init(initObject); await append(ContentType.AUDIO, 0); expect(onMetadata).toHaveBeenCalled(); @@ -658,7 +662,10 @@ describe('MediaSourceEngine', () => { const audioType = ContentType.AUDIO; const initObject = new Map(); initObject.set(audioType, getFakeStream(metadata.audio)); - await mediaSourceEngine.init(initObject, /* forceTransmux= */ true); + const config = shaka.util.PlayerConfiguration.createDefault().mediaSource; + config.forceTransmux = true; + mediaSourceEngine.configure(config); + await mediaSourceEngine.init(initObject); await append(ContentType.AUDIO, 0); expect(onMetadata).toHaveBeenCalled(); diff --git a/test/media/media_source_engine_unit.js b/test/media/media_source_engine_unit.js index cd3665df46..f1d98f8387 100644 --- a/test/media/media_source_engine_unit.js +++ b/test/media/media_source_engine_unit.js @@ -602,8 +602,7 @@ describe('MediaSourceEngine', () => { initObject.set(ContentType.VIDEO, fakeVideoStream); videoSourceBuffer.mode = 'sequence'; - await mediaSourceEngine.init( - initObject, /* forceTransmux= */ false, /* sequenceMode= */ true); + await mediaSourceEngine.init(initObject, /* sequenceMode= */ true); expect(videoSourceBuffer.timestampOffset).toBe(0); @@ -628,8 +627,7 @@ describe('MediaSourceEngine', () => { const initObject = new Map(); initObject.set(ContentType.VIDEO, fakeVideoStream); - await mediaSourceEngine.init( - initObject, /* forceTransmux= */ false, /* sequenceMode= */ true); + await mediaSourceEngine.init(initObject, /* sequenceMode= */ true); // First, mock the scenario where timestampOffset is set to help align // text segments. In this case, SourceBuffer mode is still 'segments'. diff --git a/test/media/streaming_engine_unit.js b/test/media/streaming_engine_unit.js index b9a3d43c90..c1798bea05 100644 --- a/test/media/streaming_engine_unit.js +++ b/test/media/streaming_engine_unit.js @@ -521,7 +521,7 @@ describe('StreamingEngine', () => { expectedMseInit.set(ContentType.TEXT, textStream); expect(mediaSourceEngine.init).toHaveBeenCalledWith(expectedMseInit, - /** forceTransmux= */ false, /** sequenceMode= */ false); + /** sequenceMode= */ false); expect(mediaSourceEngine.init).toHaveBeenCalledTimes(1); expect(mediaSourceEngine.setDuration).toHaveBeenCalledTimes(1);