From 6f168fba1f46edbcf954386f4d8a34d1a0a2cbc5 Mon Sep 17 00:00:00 2001 From: Alvaro Velad Galvan Date: Thu, 29 Sep 2022 19:22:34 +0200 Subject: [PATCH] feat: Allow add extra features to MediaSource.addSourceBuffer --- demo/common/message_ids.js | 2 ++ demo/config.js | 10 ++++++++++ demo/locales/en.json | 2 ++ demo/locales/source.json | 8 ++++++++ externs/shaka/player.js | 19 +++++++++++++++++++ lib/media/media_source_engine.js | 18 ++++++++++++++++-- lib/player.js | 2 ++ lib/util/player_configuration.js | 5 +++++ test/media/media_source_engine_integration.js | 2 ++ test/media/media_source_engine_unit.js | 2 ++ test/test/util/fake_media_source_engine.js | 3 +++ 11 files changed, 71 insertions(+), 2 deletions(-) diff --git a/demo/common/message_ids.js b/demo/common/message_ids.js index 0b53985fd53..84a4cb7ea91 100644 --- a/demo/common/message_ids.js +++ b/demo/common/message_ids.js @@ -222,6 +222,7 @@ shakaDemo.MessageIds = { MAX_HEIGHT: 'DEMO_MAX_HEIGHT', MAX_PIXELS: 'DEMO_MAX_PIXELS', MAX_WIDTH: 'DEMO_MAX_WIDTH', + MEDIA_SOURCE_SECTION_HEADER: 'DEMO_MEDIA_SOURCE_SECTION_HEADER', MIN_BANDWIDTH: 'DEMO_MIN_BANDWIDTH', MIN_BYTES: 'DEMO_MIN_BYTES', MIN_FRAMERATE: 'DEMO_MIN_FRAMERATE', @@ -248,6 +249,7 @@ shakaDemo.MessageIds = { SESSION_ID: 'DEMO_SESSION_ID', SHAKA_CONTROLS: 'DEMO_SHAKA_CONTROLS', SLOW_HALF_LIFE: 'DEMO_SLOW_HALF_LIFE', + SOURCE_BUFFER_EXTRA_FEATURES: 'DEMO_SOURCE_BUFFER_EXTRA_FEATURES', STALL_DETECTOR_ENABLED: 'DEMO_STALL_DETECTOR_ENABLED', STALL_THRESHOLD: 'DEMO_STALL_THRESHOLD', STALL_TIMEOUT: 'DEMO_STALL_TIMEOUT', diff --git a/demo/config.js b/demo/config.js index 58524f68f7f..e9d41ed6b37 100644 --- a/demo/config.js +++ b/demo/config.js @@ -92,6 +92,7 @@ shakaDemo.Config = class { this.addOfflineSection_(); this.addDrmSection_(); this.addStreamingSection_(); + this.addMediaSourceSection_(); this.addManifestSection_(); this.addRetrictionsSection_('', shakaDemo.MessageIds.RESTRICTIONS_SECTION_HEADER); @@ -428,6 +429,15 @@ shakaDemo.Config = class { MessageIds.STREAMING_RETRY_SECTION_HEADER); } + /** @private */ + addMediaSourceSection_() { + const MessageIds = shakaDemo.MessageIds; + const docLink = this.resolveExternLink_('.MediaSourceConfiguration'); + this.addSection_(MessageIds.MEDIA_SOURCE_SECTION_HEADER, docLink) + .addTextInput_(MessageIds.SOURCE_BUFFER_EXTRA_FEATURES, + 'mediaSource.sourceBufferExtraFeatures'); + } + /** @private */ addLanguageSection_() { const MessageIds = shakaDemo.MessageIds; diff --git a/demo/locales/en.json b/demo/locales/en.json index d7684fc40dd..976c822c8a7 100644 --- a/demo/locales/en.json +++ b/demo/locales/en.json @@ -144,6 +144,7 @@ "DEMO_MAX_HEIGHT": "Max Height", "DEMO_MAX_PIXELS": "Max Pixels", "DEMO_MAX_WIDTH": "Max Width", + "DEMO_MEDIA_SOURCE_SECTION_HEADER": "Media source", "DEMO_METACDN": "MetaCDN", "DEMO_MICROSOFT": "Microsoft", "DEMO_MIME_TYPE": "MIME Type", @@ -195,6 +196,7 @@ "DEMO_SHAKA_CONTROLS": "Shaka Controls", "DEMO_SLOW_HALF_LIFE": "Slow half life", "DEMO_SOURCE": "Source on GitHub", + "DEMO_SOURCE_BUFFER_EXTRA_FEATURES": "Source buffer extra features", "DEMO_SOURCE_SEARCH": "Source", "DEMO_STALL_DETECTOR_ENABLED": "Stall Detector Enabled", "DEMO_STALL_THRESHOLD": "Stall Threshold", diff --git a/demo/locales/source.json b/demo/locales/source.json index 37c9af9a12d..fede82ad591 100644 --- a/demo/locales/source.json +++ b/demo/locales/source.json @@ -579,6 +579,10 @@ "description": "The name of a configuration value.", "message": "Max Width" }, + "DEMO_MEDIA_SOURCE_SECTION_HEADER": { + "description": "The header for a section of configuration values.", + "message": "Media source" + }, "DEMO_METACDN": { "description": "Text that describes an asset that comes from the MetaCDN asset library.", "message": "[PROPER_NAME:MetaCDN]" @@ -783,6 +787,10 @@ "description": "A link in the footer, to the Shaka Player source on GitHub.", "message": "Source on [PROPER_NAME:GitHub]" }, + "DEMO_SOURCE_BUFFER_EXTRA_FEATURES": { + "description": "The name of a configuration value.", + "message": "Source buffer extra features" + }, "DEMO_SOURCE_SEARCH": { "description": "A header on a search field that filters by the source of the asset.", "message": "Source" diff --git a/externs/shaka/player.js b/externs/shaka/player.js index fa85935b4fa..f6fa85f87ff 100644 --- a/externs/shaka/player.js +++ b/externs/shaka/player.js @@ -1017,6 +1017,22 @@ shaka.extern.ManifestConfiguration; shaka.extern.StreamingConfiguration; +/** + * @typedef {{ + * sourceBufferExtraFeatures: string + * }} + * + * @description + * Media source configuration. + * + * @property {string} sourceBufferExtraFeatures + * Some platforms may need to pass features when initializing the + * sourceBuffer. + * @exportDoc + */ +shaka.extern.MediaSourceConfiguration; + + /** * @typedef {{ * enabled: boolean, @@ -1185,6 +1201,7 @@ shaka.extern.OfflineConfiguration; * drm: shaka.extern.DrmConfiguration, * manifest: shaka.extern.ManifestConfiguration, * streaming: shaka.extern.StreamingConfiguration, + * mediaSource: shaka.extern.MediaSourceConfiguration, * abrFactory: shaka.extern.AbrManager.Factory, * abr: shaka.extern.AbrConfiguration, * cmcd: shaka.extern.CmcdConfiguration, @@ -1212,6 +1229,8 @@ shaka.extern.OfflineConfiguration; * Manifest configuration and settings. * @property {shaka.extern.StreamingConfiguration} streaming * Streaming configuration and settings. + * @property {shaka.extern.MediaSourceConfiguration} mediaSource + * Media source configuration and settings. * @property {shaka.extern.AbrManager.Factory} abrFactory * A factory to construct an abr manager. * @property {shaka.extern.AbrConfiguration} abr diff --git a/lib/media/media_source_engine.js b/lib/media/media_source_engine.js index c303adce028..a8df88bd68f 100644 --- a/lib/media/media_source_engine.js +++ b/lib/media/media_source_engine.js @@ -53,6 +53,9 @@ shaka.media.MediaSourceEngine = class { /** @private {HTMLMediaElement} */ this.video_ = video; + /** @private {?shaka.extern.MediaSourceConfiguration} */ + this.config_ = null; + /** @private {shaka.extern.TextDisplayer} */ this.textDisplayer_ = textDisplayer; @@ -291,6 +294,7 @@ shaka.media.MediaSourceEngine = class { this.video_ = null; } + this.config_ = null; this.mediaSource_ = null; this.textEngine_ = null; this.textDisplayer_ = null; @@ -357,8 +361,8 @@ shaka.media.MediaSourceEngine = class { mimeType = shaka.media.Transmuxer.convertTsCodecs(contentType, mimeType); } - - const sourceBuffer = this.mediaSource_.addSourceBuffer(mimeType); + const type = mimeType + this.config_.sourceBufferExtraFeatures; + const sourceBuffer = this.mediaSource_.addSourceBuffer(type); this.eventManager_.listen( sourceBuffer, 'error', @@ -374,6 +378,16 @@ shaka.media.MediaSourceEngine = class { } } + /** + * Called by the Player to provide an updated configuration any time it + * changes. Must be called at least once before init(). + * + * @param {shaka.extern.MediaSourceConfiguration} config + */ + configure(config) { + this.config_ = config; + } + /** * Reinitialize the TextEngine for a new text type. * @param {string} mimeType diff --git a/lib/player.js b/lib/player.js index d1d4147fbbc..98282426a3f 100644 --- a/lib/player.js +++ b/lib/player.js @@ -1611,6 +1611,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget { (metadata, offset, endTime) => { this.processTimedMetadataMediaSrc_(metadata, offset, endTime); }); + mediaSourceEngine.configure(this.config_.mediaSource); const {segmentRelativeVttTiming} = this.config_.manifest; mediaSourceEngine.setSegmentRelativeVttTiming(segmentRelativeVttTiming); @@ -3084,6 +3085,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget { } if (this.mediaSourceEngine_) { + this.mediaSourceEngine_.configure(this.config_.mediaSource); const {segmentRelativeVttTiming} = this.config_.manifest; this.mediaSourceEngine_.setSegmentRelativeVttTiming( segmentRelativeVttTiming); diff --git a/lib/util/player_configuration.js b/lib/util/player_configuration.js index 6b03e492595..fcffb12d596 100644 --- a/lib/util/player_configuration.js +++ b/lib/util/player_configuration.js @@ -258,6 +258,10 @@ shaka.util.PlayerConfiguration = class { useHeaders: false, }; + const mediaSource = { + sourceBufferExtraFeatures: '', + }; + const AutoShowText = shaka.config.AutoShowText; /** @type {shaka.extern.PlayerConfiguration} */ @@ -265,6 +269,7 @@ shaka.util.PlayerConfiguration = class { drm: drm, manifest: manifest, streaming: streaming, + mediaSource: mediaSource, offline: offline, abrFactory: () => new shaka.abr.SimpleAbrManager(), abr: abr, diff --git a/test/media/media_source_engine_integration.js b/test/media/media_source_engine_integration.js index ebbd49a3700..b9501299673 100644 --- a/test/media/media_source_engine_integration.js +++ b/test/media/media_source_engine_integration.js @@ -41,6 +41,8 @@ describe('MediaSourceEngine', () => { video, new shaka.media.ClosedCaptionParser(), textDisplayer); + const config = shaka.util.PlayerConfiguration.createDefault().mediaSource; + mediaSourceEngine.configure(config); mediaSource = /** @type {?} */(mediaSourceEngine)['mediaSource_']; expect(video.src).toBeTruthy(); diff --git a/test/media/media_source_engine_unit.js b/test/media/media_source_engine_unit.js index 2ef9e190db2..8a805d5e7e1 100644 --- a/test/media/media_source_engine_unit.js +++ b/test/media/media_source_engine_unit.js @@ -150,6 +150,8 @@ describe('MediaSourceEngine', () => { video, mockClosedCaptionParser, mockTextDisplayer); + const config = shaka.util.PlayerConfiguration.createDefault().mediaSource; + mediaSourceEngine.configure(config); }); afterEach(() => { diff --git a/test/test/util/fake_media_source_engine.js b/test/test/util/fake_media_source_engine.js index f7e784bc325..b13d6836017 100644 --- a/test/test/util/fake_media_source_engine.js +++ b/test/test/util/fake_media_source_engine.js @@ -129,6 +129,9 @@ shaka.test.FakeMediaSourceEngine = class { /** @type {!jasmine.Spy} */ this.setSegmentRelativeVttTiming = jasmine.createSpy('setSegmentRelativeVttTiming').and.stub(); + + /** @type {!jasmine.Spy} */ + this.configure = jasmine.createSpy('configure'); } /** @override */