shaka-player 3.2.1 → 3.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
- package/.github/ISSUE_TEMPLATE/feature_request.md +1 -1
- package/.github/ISSUE_TEMPLATE/question.md +1 -1
- package/AUTHORS +9 -5
- package/CHANGELOG.md +358 -0
- package/CONTRIBUTORS +7 -2
- package/build/conformance.textproto +183 -169
- package/build/generateExterns.js +1 -1
- package/build/types/core +3 -0
- package/build/types/offline +1 -0
- package/build/types/polyfill +1 -0
- package/build/types/ui +2 -0
- package/demo/common/assets.js +19 -1
- package/demo/common/message_ids.js +13 -1
- package/demo/config.js +31 -1
- package/demo/index.html +1 -1
- package/demo/locales/en.json +12 -0
- package/demo/locales/source.json +48 -0
- package/dist/controls.css +26 -2
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +20 -17
- package/dist/demo.compiled.debug.map +3 -3
- package/dist/demo.compiled.js +20 -17
- package/dist/demo.compiled.map +3 -3
- package/dist/deps.js +19 -12
- package/dist/locales.js +39 -37
- package/dist/receiver.compiled.debug.js +12 -10
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +12 -10
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.d.ts +231 -18
- package/dist/shaka-player.compiled.debug.d.ts +231 -18
- package/dist/shaka-player.compiled.debug.externs.js +279 -8
- package/dist/shaka-player.compiled.debug.js +512 -449
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +279 -8
- package/dist/shaka-player.compiled.js +854 -821
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +247 -19
- package/dist/shaka-player.ui.debug.d.ts +247 -19
- package/dist/shaka-player.ui.debug.externs.js +307 -9
- package/dist/shaka-player.ui.debug.js +662 -580
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +307 -9
- package/dist/shaka-player.ui.js +1047 -1000
- package/dist/shaka-player.ui.map +4 -4
- package/docs/design/bg-fetch-after.gv +29 -0
- package/docs/design/bg-fetch-after.gv.png +0 -0
- package/docs/design/bg-fetch-before.gv +18 -0
- package/docs/design/bg-fetch-before.gv.png +0 -0
- package/docs/design/bg-fetch.md +134 -0
- package/docs/tutorials/blob-url.md +15 -0
- package/docs/tutorials/fairplay.md +1 -1
- package/docs/tutorials/index.json +1 -0
- package/docs/tutorials/ui-customization.md +66 -0
- package/docs/tutorials/ui.md +5 -5
- package/externs/cmcd.js +186 -0
- package/externs/ima.js +3 -0
- package/externs/shaka/ads.js +5 -0
- package/externs/shaka/manifest.js +12 -1
- package/externs/shaka/manifest_parser.js +10 -1
- package/externs/shaka/net.js +20 -4
- package/externs/shaka/offline.js +31 -2
- package/externs/shaka/player.js +138 -5
- package/externs/shaka/text.js +24 -0
- package/externs/webcrypto.js +18 -0
- package/karma.conf.js +1 -0
- package/lib/abr/ewma.js +14 -0
- package/lib/abr/ewma_bandwidth_estimator.js +16 -2
- package/lib/abr/simple_abr_manager.js +6 -0
- package/lib/ads/client_side_ad.js +8 -0
- package/lib/ads/client_side_ad_manager.js +54 -90
- package/lib/ads/server_side_ad.js +7 -0
- package/lib/ads/server_side_ad_manager.js +7 -10
- package/lib/cast/cast_proxy.js +3 -2
- package/lib/cast/cast_receiver.js +2 -1
- package/lib/cast/cast_sender.js +2 -2
- package/lib/cast/cast_utils.js +1 -0
- package/lib/dash/dash_parser.js +141 -16
- package/lib/dash/segment_base.js +25 -1
- package/lib/dash/segment_list.js +19 -10
- package/lib/dash/segment_template.js +24 -11
- package/lib/hls/hls_parser.js +146 -40
- package/lib/media/drm_engine.js +7 -0
- package/lib/media/gap_jumping_controller.js +4 -2
- package/lib/media/media_source_engine.js +1 -2
- package/lib/media/quality_observer.js +291 -0
- package/lib/media/segment_index.js +8 -1
- package/lib/media/segment_reference.js +37 -4
- package/lib/media/streaming_engine.js +49 -7
- package/lib/net/http_fetch_plugin.js +31 -11
- package/lib/net/http_plugin_utils.js +1 -0
- package/lib/net/http_xhr_plugin.js +40 -14
- package/lib/net/networking_engine.js +83 -19
- package/lib/offline/download_info.js +68 -0
- package/lib/offline/download_manager.js +13 -5
- package/lib/offline/indexeddb/base_storage_cell.js +35 -0
- package/lib/offline/indexeddb/storage_mechanism.js +1 -1
- package/lib/offline/indexeddb/v5_storage_cell.js +5 -0
- package/lib/offline/storage.js +393 -284
- package/lib/offline/stored_content_utils.js +2 -0
- package/lib/player.js +249 -43
- package/lib/polyfill/media_capabilities.js +36 -15
- package/lib/polyfill/mediasource.js +6 -0
- package/lib/polyfill/orientation.js +1 -1
- package/lib/polyfill/patchedmediakeys_apple.js +4 -4
- package/lib/polyfill/patchedmediakeys_ms.js +4 -4
- package/lib/polyfill/patchedmediakeys_webkit.js +4 -4
- package/lib/polyfill/random_uuid.js +52 -0
- package/lib/text/cue.js +18 -0
- package/lib/text/mp4_ttml_parser.js +3 -0
- package/lib/text/text_engine.js +14 -2
- package/lib/text/ttml_text_parser.js +114 -60
- package/lib/text/ui_text_displayer.js +95 -41
- package/lib/util/cmcd_manager.js +672 -0
- package/lib/util/error.js +6 -0
- package/lib/util/fake_event.js +53 -7
- package/lib/util/language_utils.js +12 -0
- package/lib/util/mutex.js +52 -0
- package/lib/util/periods.js +102 -65
- package/lib/util/platform.js +13 -1
- package/lib/util/player_configuration.js +18 -0
- package/lib/util/stream_utils.js +99 -10
- package/lib/util/xml_utils.js +19 -0
- package/package.json +2 -2
- package/shaka-player.uncompiled.js +3 -0
- package/test/cast/cast_proxy_unit.js +12 -6
- package/test/cast/cast_utils_unit.js +1 -1
- package/test/dash/dash_parser_content_protection_unit.js +2 -0
- package/test/dash/dash_parser_live_unit.js +101 -1
- package/test/dash/dash_parser_manifest_unit.js +222 -2
- package/test/dash/dash_parser_segment_base_unit.js +2 -0
- package/test/dash/dash_parser_segment_list_unit.js +2 -1
- package/test/dash/dash_parser_segment_template_unit.js +2 -1
- package/test/hls/hls_live_unit.js +2 -0
- package/test/hls/hls_parser_unit.js +7 -1
- package/test/media/closed_caption_parser_unit.js +6 -1
- package/test/media/drm_engine_unit.js +47 -3
- package/test/media/quality_observer_unit.js +139 -0
- package/test/media/segment_reference_unit.js +16 -1
- package/test/media/streaming_engine_integration.js +4 -2
- package/test/media/streaming_engine_unit.js +147 -0
- package/test/net/http_plugin_unit.js +20 -15
- package/test/offline/storage_integration.js +108 -4
- package/test/player_integration.js +178 -8
- package/test/player_src_equals_integration.js +41 -8
- package/test/player_unit.js +19 -9
- package/test/test/assets/3675/chunk-stream0-00001.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00002.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00003.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00004.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00005.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00006.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00007.m4s +0 -0
- package/test/test/assets/3675/dash_0.mpd +30 -0
- package/test/test/assets/3675/dash_1.mpd +30 -0
- package/test/test/assets/3675/dash_2.mpd +30 -0
- package/test/test/assets/3675/dash_3.mpd +30 -0
- package/test/test/assets/3675/dash_4.mpd +30 -0
- package/test/test/assets/3675/dash_5.mpd +26 -0
- package/test/test/assets/3675/init-stream0.m4s +0 -0
- package/test/test/assets/chapters.vtt +2 -2
- package/test/test/assets/chapters2.vtt +10 -0
- package/test/test/util/dash_parser_util.js +4 -0
- package/test/test/util/fake_ad.js +7 -0
- package/test/test/util/fake_ad_manager.js +1 -1
- package/test/test/util/fake_drm_engine.js +9 -2
- package/test/test/util/manifest_generator.js +3 -2
- package/test/test/util/test_scheme.js +14 -1
- package/test/test/util/ttml_utils.js +81 -0
- package/test/text/mp4_ttml_parser_unit.js +11 -18
- package/test/text/ttml_text_parser_unit.js +552 -227
- package/test/text/ui_text_displayer_unit.js +29 -17
- package/test/ui/localization_unit.js +15 -14
- package/test/ui/text_displayer_layout_unit.js +13 -1
- package/test/ui/ui_unit.js +250 -0
- package/test/util/cmcd_manager_unit.js +291 -0
- package/test/util/stream_utils_unit.js +45 -4
- package/third_party/closure-uri/uri.js +21 -0
- package/ui/airplay_button.js +1 -0
- package/ui/audio_language_selection.js +7 -0
- package/ui/cast_button.js +3 -3
- package/ui/context_menu.js +109 -0
- package/ui/controls.js +45 -13
- package/ui/controls.less +1 -0
- package/ui/enums.js +4 -0
- package/ui/externs/ui.js +28 -1
- package/ui/fast_forward_button.js +14 -5
- package/ui/fullscreen_button.js +1 -0
- package/ui/less/buttons.less +0 -4
- package/ui/less/containers.less +77 -7
- package/ui/less/overflow_menu.less +0 -10
- package/ui/less/tooltip.less +97 -0
- package/ui/locales/en.json +1 -0
- package/ui/locales/ru.json +6 -6
- package/ui/locales/source.json +4 -0
- package/ui/localization.js +28 -51
- package/ui/loop_button.js +5 -0
- package/ui/mute_button.js +2 -1
- package/ui/overflow_menu.js +5 -25
- package/ui/pip_button.js +7 -3
- package/ui/play_button.js +2 -2
- package/ui/playback_rate_selection.js +8 -9
- package/ui/resolution_selection.js +7 -0
- package/ui/rewind_button.js +15 -6
- package/ui/seek_bar.js +4 -2
- package/ui/settings_menu.js +36 -4
- package/ui/small_play_button.js +1 -0
- package/ui/statistics_button.js +253 -0
- package/ui/text_selection.js +12 -4
- package/ui/ui.js +30 -0
- package/ui/volume_bar.js +1 -1
- package/externs/media_capabilities.js +0 -16
|
@@ -47,6 +47,7 @@ shaka.offline.StoredContentUtils = class {
|
|
|
47
47
|
expiration: Infinity,
|
|
48
48
|
tracks: tracks,
|
|
49
49
|
appMetadata: metadata,
|
|
50
|
+
isIncomplete: false,
|
|
50
51
|
};
|
|
51
52
|
|
|
52
53
|
return content;
|
|
@@ -87,6 +88,7 @@ shaka.offline.StoredContentUtils = class {
|
|
|
87
88
|
expiration: manifestDB.expiration,
|
|
88
89
|
tracks: tracks,
|
|
89
90
|
appMetadata: metadata,
|
|
91
|
+
isIncomplete: (manifestDB.isIncomplete || false),
|
|
90
92
|
};
|
|
91
93
|
|
|
92
94
|
return content;
|
package/lib/player.js
CHANGED
|
@@ -22,6 +22,7 @@ goog.require('shaka.media.PlayRateController');
|
|
|
22
22
|
goog.require('shaka.media.Playhead');
|
|
23
23
|
goog.require('shaka.media.PlayheadObserverManager');
|
|
24
24
|
goog.require('shaka.media.PreferenceBasedCriteria');
|
|
25
|
+
goog.require('shaka.media.QualityObserver');
|
|
25
26
|
goog.require('shaka.media.RegionObserver');
|
|
26
27
|
goog.require('shaka.media.RegionTimeline');
|
|
27
28
|
goog.require('shaka.media.SegmentIndex');
|
|
@@ -36,6 +37,7 @@ goog.require('shaka.text.UITextDisplayer');
|
|
|
36
37
|
goog.require('shaka.text.WebVttGenerator');
|
|
37
38
|
goog.require('shaka.util.AbortableOperation');
|
|
38
39
|
goog.require('shaka.util.BufferUtils');
|
|
40
|
+
goog.require('shaka.util.CmcdManager');
|
|
39
41
|
goog.require('shaka.util.ConfigUtils');
|
|
40
42
|
goog.require('shaka.util.Error');
|
|
41
43
|
goog.require('shaka.util.EventManager');
|
|
@@ -106,6 +108,32 @@ goog.requireType('shaka.routing.Payload');
|
|
|
106
108
|
*/
|
|
107
109
|
|
|
108
110
|
|
|
111
|
+
/**
|
|
112
|
+
* @event shaka.Player.DownloadFailed
|
|
113
|
+
* @description Fired when a download has failed, for any reason.
|
|
114
|
+
* 'downloadfailed'
|
|
115
|
+
* @property {!shaka.extern.Request} request
|
|
116
|
+
* @property {?shaka.util.Error} error
|
|
117
|
+
* @param {number} httpResponseCode
|
|
118
|
+
* @param {boolean} aborted
|
|
119
|
+
* @exportDoc
|
|
120
|
+
*/
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @event shaka.Player.DownloadHeadersReceived
|
|
125
|
+
* @description Fired when the networking engine has received the headers for
|
|
126
|
+
* a download, but before the body has been downloaded.
|
|
127
|
+
* If the HTTP plugin being used does not track this information, this event
|
|
128
|
+
* will default to being fired when the body is received, instead.
|
|
129
|
+
* @property {!Object.<string, string>} headers
|
|
130
|
+
* @property {!shaka.extern.Request} request
|
|
131
|
+
* @property {!shaka.net.NetworkingEngine.RequestType} type
|
|
132
|
+
* 'downloadheadersreceived'
|
|
133
|
+
* @exportDoc
|
|
134
|
+
*/
|
|
135
|
+
|
|
136
|
+
|
|
109
137
|
/**
|
|
110
138
|
* @event shaka.Player.DrmSessionUpdateEvent
|
|
111
139
|
* @description Fired when the CDM has accepted the license response.
|
|
@@ -147,6 +175,21 @@ goog.requireType('shaka.routing.Payload');
|
|
|
147
175
|
* @exportDoc
|
|
148
176
|
*/
|
|
149
177
|
|
|
178
|
+
/**
|
|
179
|
+
* @event shaka.Player.MediaQualityChangedEvent
|
|
180
|
+
* @description Fired when the media quality changes at the playhead.
|
|
181
|
+
* That may be caused by an adaptation change or a DASH period transition.
|
|
182
|
+
* Separate events are emitted for audio and video contentTypes.
|
|
183
|
+
* This is supported for only DASH streams at this time.
|
|
184
|
+
* @property {string} type
|
|
185
|
+
* 'mediaqualitychanged'
|
|
186
|
+
* @property {shaka.extern.MediaQualityInfo} mediaQuality
|
|
187
|
+
* Information about media quality at the playhead position.
|
|
188
|
+
* @property {number} position
|
|
189
|
+
* The playhead position.
|
|
190
|
+
* @exportDoc
|
|
191
|
+
*/
|
|
192
|
+
|
|
150
193
|
|
|
151
194
|
/**
|
|
152
195
|
* @event shaka.Player.BufferingEvent
|
|
@@ -441,6 +484,12 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
441
484
|
/** @private {shaka.media.RegionTimeline} */
|
|
442
485
|
this.regionTimeline_ = null;
|
|
443
486
|
|
|
487
|
+
/** @private {shaka.util.CmcdManager} */
|
|
488
|
+
this.cmcdManager_ = null;
|
|
489
|
+
|
|
490
|
+
/** @private {shaka.media.QualityObserver} */
|
|
491
|
+
this.qualityObserver_ = null;
|
|
492
|
+
|
|
444
493
|
/** @private {shaka.media.StreamingEngine} */
|
|
445
494
|
this.streamingEngine_ = null;
|
|
446
495
|
|
|
@@ -507,6 +556,15 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
507
556
|
/** @private {!Array.<function():(!Promise|undefined)>} */
|
|
508
557
|
this.cleanupOnUnload_ = [];
|
|
509
558
|
|
|
559
|
+
/**
|
|
560
|
+
* This playback start position will be used when
|
|
561
|
+
* <code>updateStartTime()</code> has been called to provide an updated
|
|
562
|
+
* start position during the media loading process.
|
|
563
|
+
*
|
|
564
|
+
* @private {?number}
|
|
565
|
+
*/
|
|
566
|
+
this.updatedStartTime_ = null;
|
|
567
|
+
|
|
510
568
|
if (dependencyInjector) {
|
|
511
569
|
dependencyInjector(this);
|
|
512
570
|
}
|
|
@@ -598,7 +656,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
598
656
|
enterNode: (node, has, wants) => {
|
|
599
657
|
this.dispatchEvent(this.makeEvent_(
|
|
600
658
|
/* name= */ shaka.Player.EventName.OnStateChange,
|
|
601
|
-
/* data= */
|
|
659
|
+
/* data= */ (new Map()).set('state', node.name)));
|
|
602
660
|
|
|
603
661
|
const action = actions.get(node);
|
|
604
662
|
return action(has, wants);
|
|
@@ -629,7 +687,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
629
687
|
onIdle: (node) => {
|
|
630
688
|
this.dispatchEvent(this.makeEvent_(
|
|
631
689
|
/* name= */ shaka.Player.EventName.OnStateIdle,
|
|
632
|
-
/* data= */
|
|
690
|
+
/* data= */ (new Map()).set('state', node.name)));
|
|
633
691
|
},
|
|
634
692
|
};
|
|
635
693
|
|
|
@@ -649,7 +707,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
649
707
|
|
|
650
708
|
/**
|
|
651
709
|
* @param {!shaka.Player.EventName} name
|
|
652
|
-
* @param {Object
|
|
710
|
+
* @param {Map.<string, Object>=} data
|
|
653
711
|
* @return {!shaka.util.FakeEvent}
|
|
654
712
|
* @private
|
|
655
713
|
*/
|
|
@@ -723,6 +781,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
723
781
|
this.config_ = null;
|
|
724
782
|
this.stats_ = null;
|
|
725
783
|
this.videoContainer_ = null;
|
|
784
|
+
this.cmcdManager_ = null;
|
|
726
785
|
|
|
727
786
|
if (this.networkingEngine_) {
|
|
728
787
|
await this.networkingEngine_.destroy();
|
|
@@ -1020,6 +1079,19 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
1020
1079
|
return this.wrapWalkerListenersWithPromise_(events);
|
|
1021
1080
|
}
|
|
1022
1081
|
|
|
1082
|
+
/**
|
|
1083
|
+
* Provides a way to update the stream start position during the media loading
|
|
1084
|
+
* process. Can for example be called from the <code>manifestparsed</code>
|
|
1085
|
+
* event handler to update the start position based on information in the
|
|
1086
|
+
* manifest.
|
|
1087
|
+
*
|
|
1088
|
+
* @param {number} startTime
|
|
1089
|
+
* @export
|
|
1090
|
+
*/
|
|
1091
|
+
updateStartTime(startTime) {
|
|
1092
|
+
this.updatedStartTime_ = startTime;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1023
1095
|
/**
|
|
1024
1096
|
* Tell the player to load the content at <code>assetUri</code> and start
|
|
1025
1097
|
* playback at <code>startTime</code>. Before calling <code>load</code>,
|
|
@@ -1040,6 +1112,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
1040
1112
|
* @export
|
|
1041
1113
|
*/
|
|
1042
1114
|
load(assetUri, startTime, mimeType) {
|
|
1115
|
+
this.updatedStartTime_ = null;
|
|
1116
|
+
|
|
1043
1117
|
// Do not allow the player to be used after |destroy| is called.
|
|
1044
1118
|
if (this.loadMode_ == shaka.Player.LoadMode.DESTROYED) {
|
|
1045
1119
|
return Promise.reject(this.createAbortLoadError_());
|
|
@@ -1093,6 +1167,9 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
1093
1167
|
// before we allow calls to |updateStateHistory|.
|
|
1094
1168
|
this.stats_ = new shaka.util.Stats();
|
|
1095
1169
|
|
|
1170
|
+
// Create the CMCD manager so client data can be attached to all requests
|
|
1171
|
+
this.cmcdManager_ = this.createCmcd_();
|
|
1172
|
+
|
|
1096
1173
|
// Load's request is a little different, so we can't use our normal
|
|
1097
1174
|
// listeners-to-promise method. It is the only request where we may skip the
|
|
1098
1175
|
// request, so we need to set the on skip callback to reject with a specific
|
|
@@ -1594,6 +1671,9 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
1594
1671
|
goog.asserts.assert(
|
|
1595
1672
|
this.networkingEngine_,
|
|
1596
1673
|
'Need networking engine to parse manifest.');
|
|
1674
|
+
goog.asserts.assert(
|
|
1675
|
+
this.cmcdManager_,
|
|
1676
|
+
'Need CMCD manager to populate manifest request data.');
|
|
1597
1677
|
goog.asserts.assert(
|
|
1598
1678
|
this.config_,
|
|
1599
1679
|
'Need player config to parse manifest.');
|
|
@@ -1617,9 +1697,23 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
1617
1697
|
this.adManager_.onDashTimedMetadata(region);
|
|
1618
1698
|
}
|
|
1619
1699
|
});
|
|
1700
|
+
this.qualityObserver_ = null;
|
|
1701
|
+
if (this.config_.streaming.observeQualityChanges) {
|
|
1702
|
+
this.qualityObserver_ = new shaka.media.QualityObserver(
|
|
1703
|
+
() => this.getBufferedInfo());
|
|
1704
|
+
this.qualityObserver_.setListeners((mediaQualityInfo, position) => {
|
|
1705
|
+
this.onMediaQualityChange_(mediaQualityInfo, position);
|
|
1706
|
+
});
|
|
1707
|
+
}
|
|
1620
1708
|
|
|
1621
1709
|
const playerInterface = {
|
|
1622
1710
|
networkingEngine: networkingEngine,
|
|
1711
|
+
modifyManifestRequest: (request, manifestInfo) => {
|
|
1712
|
+
this.cmcdManager_.applyManifestData(request, manifestInfo);
|
|
1713
|
+
},
|
|
1714
|
+
modifySegmentRequest: (request, segmentInfo) => {
|
|
1715
|
+
this.cmcdManager_.applySegmentData(request, segmentInfo);
|
|
1716
|
+
},
|
|
1623
1717
|
filter: (manifest) => this.filterManifest_(manifest),
|
|
1624
1718
|
makeTextStreamsForClosedCaptions: (manifest) => {
|
|
1625
1719
|
return this.makeTextStreamsForClosedCaptions_(manifest);
|
|
@@ -1780,6 +1874,13 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
1780
1874
|
// something we are now depending on.
|
|
1781
1875
|
has.startTime = wants.startTime;
|
|
1782
1876
|
|
|
1877
|
+
// If updateStartTime() has been called since load() was invoked use the
|
|
1878
|
+
// requested startTime
|
|
1879
|
+
if (this.updatedStartTime_ != null) {
|
|
1880
|
+
has.startTime = this.updatedStartTime_;
|
|
1881
|
+
this.updatedStartTime_ = null;
|
|
1882
|
+
}
|
|
1883
|
+
|
|
1783
1884
|
// Store a reference to values in |has| after asserting so that closure will
|
|
1784
1885
|
// know that they will still be non-null between calls to await.
|
|
1785
1886
|
const mediaElement = has.mediaElement;
|
|
@@ -2177,9 +2278,13 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2177
2278
|
this.video_.textTracks, 'change', () => this.onTracksChanged_());
|
|
2178
2279
|
}
|
|
2179
2280
|
|
|
2281
|
+
const extension = shaka.media.ManifestParser.getExtension(has.uri);
|
|
2282
|
+
const mimeType =
|
|
2283
|
+
shaka.Player.SRC_EQUAL_EXTENSIONS_TO_MIME_TYPES_[extension];
|
|
2284
|
+
|
|
2180
2285
|
// By setting |src| we are done "loading" with src=. We don't need to set
|
|
2181
2286
|
// the current time because |playhead| will do that for us.
|
|
2182
|
-
has.mediaElement.src = has.uri;
|
|
2287
|
+
has.mediaElement.src = this.cmcdManager_.appendSrcData(has.uri, mimeType);
|
|
2183
2288
|
|
|
2184
2289
|
// Tizen 3 / WebOS won't load anything unless you call load() explicitly,
|
|
2185
2290
|
// no matter the value of the preload attribute. This is harmful on some
|
|
@@ -2417,12 +2522,11 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2417
2522
|
goog.asserts.assert(!endTime || startTime <= endTime,
|
|
2418
2523
|
'Metadata start time should be less or equal to the end time!');
|
|
2419
2524
|
const eventName = shaka.Player.EventName.Metadata;
|
|
2420
|
-
const data =
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
};
|
|
2525
|
+
const data = new Map()
|
|
2526
|
+
.set('startTime', startTime)
|
|
2527
|
+
.set('endTime', endTime)
|
|
2528
|
+
.set('metadataType', metadataType)
|
|
2529
|
+
.set('payload', payload);
|
|
2426
2530
|
this.dispatchEvent(this.makeEvent_(eventName, data));
|
|
2427
2531
|
}
|
|
2428
2532
|
|
|
@@ -2510,8 +2614,30 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2510
2614
|
this.abrManager_.segmentDownloaded(deltaTimeMs, bytesDownloaded);
|
|
2511
2615
|
}
|
|
2512
2616
|
};
|
|
2617
|
+
/** @type {shaka.net.NetworkingEngine.OnHeadersReceived} */
|
|
2618
|
+
const onHeadersReceived_ = (headers, request, requestType) => {
|
|
2619
|
+
// Release a 'downloadheadersreceived' event.
|
|
2620
|
+
const name = shaka.Player.EventName.DownloadHeadersReceived;
|
|
2621
|
+
const data = new Map()
|
|
2622
|
+
.set('headers', headers)
|
|
2623
|
+
.set('request', request)
|
|
2624
|
+
.set('requestType', requestType);
|
|
2625
|
+
this.dispatchEvent(this.makeEvent_(name, data));
|
|
2626
|
+
};
|
|
2627
|
+
/** @type {shaka.net.NetworkingEngine.OnDownloadFailed} */
|
|
2628
|
+
const onDownloadFailed_ = (request, error, httpResponseCode, aborted) => {
|
|
2629
|
+
// Release a 'downloadfailed' event.
|
|
2630
|
+
const name = shaka.Player.EventName.DownloadFailed;
|
|
2631
|
+
const data = new Map()
|
|
2632
|
+
.set('request', request)
|
|
2633
|
+
.set('error', error)
|
|
2634
|
+
.set('httpResponseCode', httpResponseCode)
|
|
2635
|
+
.set('aborted', aborted);
|
|
2636
|
+
this.dispatchEvent(this.makeEvent_(name, data));
|
|
2637
|
+
};
|
|
2513
2638
|
|
|
2514
|
-
return new shaka.net.NetworkingEngine(
|
|
2639
|
+
return new shaka.net.NetworkingEngine(
|
|
2640
|
+
onProgressUpdated_, onHeadersReceived_, onDownloadFailed_);
|
|
2515
2641
|
}
|
|
2516
2642
|
|
|
2517
2643
|
/**
|
|
@@ -2567,7 +2693,9 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2567
2693
|
// Now that we have all our observers, create a manager for them.
|
|
2568
2694
|
const manager = new shaka.media.PlayheadObserverManager(this.video_);
|
|
2569
2695
|
manager.manage(regionObserver);
|
|
2570
|
-
|
|
2696
|
+
if (this.qualityObserver_) {
|
|
2697
|
+
manager.manage(this.qualityObserver_);
|
|
2698
|
+
}
|
|
2571
2699
|
return manager;
|
|
2572
2700
|
}
|
|
2573
2701
|
|
|
@@ -2683,6 +2811,26 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2683
2811
|
mediaElement, closedCaptionsParser, textDisplayer, onMetadata);
|
|
2684
2812
|
}
|
|
2685
2813
|
|
|
2814
|
+
/**
|
|
2815
|
+
* Create a new CMCD manager.
|
|
2816
|
+
*
|
|
2817
|
+
* @private
|
|
2818
|
+
*/
|
|
2819
|
+
createCmcd_() {
|
|
2820
|
+
/** @type {shaka.util.CmcdManager.PlayerInterface} */
|
|
2821
|
+
const playerInterface = {
|
|
2822
|
+
getBandwidthEstimate: () => this.abrManager_ ?
|
|
2823
|
+
this.abrManager_.getBandwidthEstimate() : NaN,
|
|
2824
|
+
getBufferedInfo: () => this.getBufferedInfo(),
|
|
2825
|
+
getCurrentTime: () => this.video_ ? this.video_.currentTime : 0,
|
|
2826
|
+
getVariantTracks: () => this.getVariantTracks(),
|
|
2827
|
+
getPlaybackRate: () => this.getPlaybackRate(),
|
|
2828
|
+
isLive: () => this.isLive(),
|
|
2829
|
+
};
|
|
2830
|
+
|
|
2831
|
+
return new shaka.util.CmcdManager(playerInterface, this.config_.cmcd);
|
|
2832
|
+
}
|
|
2833
|
+
|
|
2686
2834
|
/**
|
|
2687
2835
|
* Creates a new instance of StreamingEngine. This can be replaced by tests
|
|
2688
2836
|
* to create fake instances instead.
|
|
@@ -2692,19 +2840,28 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2692
2840
|
createStreamingEngine() {
|
|
2693
2841
|
goog.asserts.assert(
|
|
2694
2842
|
this.playhead_ && this.abrManager_ && this.mediaSourceEngine_ &&
|
|
2695
|
-
this.manifest_,
|
|
2843
|
+
this.cmcdManager_ && this.manifest_,
|
|
2696
2844
|
'Must not be destroyed');
|
|
2697
2845
|
|
|
2698
2846
|
/** @type {shaka.media.StreamingEngine.PlayerInterface} */
|
|
2699
2847
|
const playerInterface = {
|
|
2700
2848
|
getPresentationTime: () => this.playhead_.getTime(),
|
|
2701
2849
|
getBandwidthEstimate: () => this.abrManager_.getBandwidthEstimate(),
|
|
2850
|
+
modifySegmentRequest: (request, segmentInfo) => {
|
|
2851
|
+
this.cmcdManager_.applySegmentData(request, segmentInfo);
|
|
2852
|
+
},
|
|
2702
2853
|
mediaSourceEngine: this.mediaSourceEngine_,
|
|
2703
2854
|
netEngine: this.networkingEngine_,
|
|
2704
2855
|
onError: (error) => this.onError_(error),
|
|
2705
2856
|
onEvent: (event) => this.dispatchEvent(event),
|
|
2706
2857
|
onManifestUpdate: () => this.onManifestUpdate_(),
|
|
2707
2858
|
onSegmentAppended: () => this.onSegmentAppended_(),
|
|
2859
|
+
onInitSegmentAppended: (position, initSegment) => {
|
|
2860
|
+
const mediaQuality = initSegment.getMediaQuality();
|
|
2861
|
+
if (mediaQuality && this.qualityObserver_) {
|
|
2862
|
+
this.qualityObserver_.addMediaQualityChange(mediaQuality, position);
|
|
2863
|
+
}
|
|
2864
|
+
},
|
|
2708
2865
|
};
|
|
2709
2866
|
|
|
2710
2867
|
return new shaka.media.StreamingEngine(this.manifest_, playerInterface);
|
|
@@ -3455,7 +3612,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3455
3612
|
const height = fullImageHeight / rows;
|
|
3456
3613
|
const totalImages = columns * rows;
|
|
3457
3614
|
const segmentDuration = reference.trueEndTime - reference.startTime;
|
|
3458
|
-
const thumbnailDuration =
|
|
3615
|
+
const thumbnailDuration =
|
|
3616
|
+
reference.getTileDuration() || (segmentDuration / totalImages);
|
|
3459
3617
|
let thumbnailTime = reference.startTime;
|
|
3460
3618
|
let positionX = 0;
|
|
3461
3619
|
let positionY = 0;
|
|
@@ -3478,6 +3636,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3478
3636
|
positionY = Math.floor(thumbnailPosition / columns) * height;
|
|
3479
3637
|
}
|
|
3480
3638
|
return {
|
|
3639
|
+
imageHeight: fullImageHeight,
|
|
3640
|
+
imageWidth: fullImageWidth,
|
|
3481
3641
|
height: height,
|
|
3482
3642
|
positionX: positionX,
|
|
3483
3643
|
positionY: positionY,
|
|
@@ -3879,20 +4039,24 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3879
4039
|
const LanguageUtils = shaka.util.LanguageUtils;
|
|
3880
4040
|
const inputlanguage = LanguageUtils.normalize(language);
|
|
3881
4041
|
const chaptersTracks = this.getChaptersTracks_();
|
|
3882
|
-
const
|
|
3883
|
-
.
|
|
3884
|
-
if (!
|
|
4042
|
+
const chaptersTracksWithLanguage = chaptersTracks
|
|
4043
|
+
.filter((t) => LanguageUtils.normalize(t.language) == inputlanguage);
|
|
4044
|
+
if (!chaptersTracksWithLanguage || !chaptersTracksWithLanguage.length) {
|
|
3885
4045
|
return [];
|
|
3886
4046
|
}
|
|
3887
4047
|
const chapters = [];
|
|
3888
|
-
for (const
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
4048
|
+
for (const chaptersTrack of chaptersTracksWithLanguage) {
|
|
4049
|
+
if (chaptersTrack && chaptersTrack.cues) {
|
|
4050
|
+
for (const cue of chaptersTrack.cues) {
|
|
4051
|
+
/** @type {shaka.extern.Chapter} */
|
|
4052
|
+
const chapter = {
|
|
4053
|
+
title: cue.text,
|
|
4054
|
+
startTime: cue.startTime,
|
|
4055
|
+
endTime: cue.endTime,
|
|
4056
|
+
};
|
|
4057
|
+
chapters.push(chapter);
|
|
4058
|
+
}
|
|
4059
|
+
}
|
|
3896
4060
|
}
|
|
3897
4061
|
return chapters;
|
|
3898
4062
|
}
|
|
@@ -4268,7 +4432,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
4268
4432
|
}
|
|
4269
4433
|
const trackElement =
|
|
4270
4434
|
/** @type {!HTMLTrackElement} */(document.createElement('track'));
|
|
4271
|
-
trackElement.src = uri;
|
|
4435
|
+
trackElement.src = this.cmcdManager_.appendTextTrackData(uri);
|
|
4272
4436
|
trackElement.label = label || '';
|
|
4273
4437
|
trackElement.kind = kind;
|
|
4274
4438
|
trackElement.srclang = language;
|
|
@@ -4606,7 +4770,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
4606
4770
|
}
|
|
4607
4771
|
const trackElement =
|
|
4608
4772
|
/** @type {!HTMLTrackElement} */(document.createElement('track'));
|
|
4609
|
-
trackElement.src = uri;
|
|
4773
|
+
trackElement.src = this.cmcdManager_.appendTextTrackData(uri);
|
|
4610
4774
|
trackElement.label = label;
|
|
4611
4775
|
trackElement.kind = kind;
|
|
4612
4776
|
trackElement.srclang = language;
|
|
@@ -4635,6 +4799,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
4635
4799
|
const request = shaka.net.NetworkingEngine.makeRequest([uri], retryParams);
|
|
4636
4800
|
request.method = 'GET';
|
|
4637
4801
|
|
|
4802
|
+
this.cmcdManager_.applyTextData(request);
|
|
4803
|
+
|
|
4638
4804
|
const response = await netEngine.request(type, request).promise;
|
|
4639
4805
|
|
|
4640
4806
|
return response.data;
|
|
@@ -5032,13 +5198,17 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5032
5198
|
|
|
5033
5199
|
if (loaded) {
|
|
5034
5200
|
this.playRateController_.setBuffering(isBuffering);
|
|
5201
|
+
if (this.cmcdManager_) {
|
|
5202
|
+
this.cmcdManager_.setBuffering(isBuffering);
|
|
5203
|
+
}
|
|
5035
5204
|
this.updateStateHistory_();
|
|
5036
5205
|
}
|
|
5037
5206
|
|
|
5038
5207
|
// Surface the buffering event so that the app knows if/when we are
|
|
5039
5208
|
// buffering.
|
|
5040
5209
|
const eventName = shaka.Player.EventName.Buffering;
|
|
5041
|
-
|
|
5210
|
+
const data = (new Map()).set('buffering', isBuffering);
|
|
5211
|
+
this.dispatchEvent(this.makeEvent_(eventName, data));
|
|
5042
5212
|
}
|
|
5043
5213
|
|
|
5044
5214
|
/**
|
|
@@ -5400,10 +5570,10 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5400
5570
|
onAdaptation_(from, to) {
|
|
5401
5571
|
// Delay the 'adaptation' event so that StreamingEngine has time to absorb
|
|
5402
5572
|
// the changes before the user tries to query it.
|
|
5403
|
-
const
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5573
|
+
const data = new Map()
|
|
5574
|
+
.set('oldTrack', from)
|
|
5575
|
+
.set('newTrack', to);
|
|
5576
|
+
const event = this.makeEvent_(shaka.Player.EventName.Adaptation, data);
|
|
5407
5577
|
this.delayDispatchEvent_(event);
|
|
5408
5578
|
}
|
|
5409
5579
|
|
|
@@ -5427,10 +5597,10 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5427
5597
|
onVariantChanged_(from, to) {
|
|
5428
5598
|
// Delay the 'variantchanged' event so StreamingEngine has time to absorb
|
|
5429
5599
|
// the changes before the user tries to query it.
|
|
5430
|
-
const
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
|
|
5600
|
+
const data = new Map()
|
|
5601
|
+
.set('oldTrack', from)
|
|
5602
|
+
.set('newTrack', to);
|
|
5603
|
+
const event = this.makeEvent_(shaka.Player.EventName.VariantChanged, data);
|
|
5434
5604
|
this.delayDispatchEvent_(event);
|
|
5435
5605
|
}
|
|
5436
5606
|
|
|
@@ -5453,10 +5623,9 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5453
5623
|
|
|
5454
5624
|
/** @private */
|
|
5455
5625
|
onAbrStatusChanged_() {
|
|
5456
|
-
const
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
this.delayDispatchEvent_(event);
|
|
5626
|
+
const data = (new Map()).set('newStatus', this.config_.abr.enabled);
|
|
5627
|
+
this.delayDispatchEvent_(this.makeEvent_(
|
|
5628
|
+
shaka.Player.EventName.AbrStatusChanged, data));
|
|
5460
5629
|
}
|
|
5461
5630
|
|
|
5462
5631
|
/**
|
|
@@ -5473,7 +5642,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5473
5642
|
}
|
|
5474
5643
|
|
|
5475
5644
|
const eventName = shaka.Player.EventName.Error;
|
|
5476
|
-
const event = this.makeEvent_(eventName,
|
|
5645
|
+
const event = this.makeEvent_(eventName, (new Map()).set('detail', error));
|
|
5477
5646
|
this.dispatchEvent(event);
|
|
5478
5647
|
if (event.defaultPrevented) {
|
|
5479
5648
|
error.handled = true;
|
|
@@ -5502,7 +5671,40 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5502
5671
|
eventElement: region.eventElement,
|
|
5503
5672
|
};
|
|
5504
5673
|
|
|
5505
|
-
|
|
5674
|
+
const data = (new Map()).set('detail', clone);
|
|
5675
|
+
this.dispatchEvent(this.makeEvent_(eventName, data));
|
|
5676
|
+
}
|
|
5677
|
+
|
|
5678
|
+
/**
|
|
5679
|
+
* When notified of a media quality change we need to emit a
|
|
5680
|
+
* MediaQualityChange event to the app.
|
|
5681
|
+
*
|
|
5682
|
+
* @param {shaka.extern.MediaQualityInfo} mediaQuality
|
|
5683
|
+
* @param {number} position
|
|
5684
|
+
*
|
|
5685
|
+
* @private
|
|
5686
|
+
*/
|
|
5687
|
+
onMediaQualityChange_(mediaQuality, position) {
|
|
5688
|
+
// Always make a copy to avoid exposing our internal data to the app.
|
|
5689
|
+
const clone = {
|
|
5690
|
+
bandwidth: mediaQuality.bandwidth,
|
|
5691
|
+
audioSamplingRate: mediaQuality.audioSamplingRate,
|
|
5692
|
+
codecs: mediaQuality.codecs,
|
|
5693
|
+
contentType: mediaQuality.contentType,
|
|
5694
|
+
frameRate: mediaQuality.frameRate,
|
|
5695
|
+
height: mediaQuality.height,
|
|
5696
|
+
mimeType: mediaQuality.mimeType,
|
|
5697
|
+
channelsCount: mediaQuality.channelsCount,
|
|
5698
|
+
pixelAspectRatio: mediaQuality.pixelAspectRatio,
|
|
5699
|
+
width: mediaQuality.width,
|
|
5700
|
+
};
|
|
5701
|
+
|
|
5702
|
+
const data = new Map()
|
|
5703
|
+
.set('mediaQuality', clone)
|
|
5704
|
+
.set('position', position);
|
|
5705
|
+
|
|
5706
|
+
this.dispatchEvent(this.makeEvent_(
|
|
5707
|
+
shaka.Player.EventName.MediaQualityChanged, data));
|
|
5506
5708
|
}
|
|
5507
5709
|
|
|
5508
5710
|
/**
|
|
@@ -6268,6 +6470,8 @@ shaka.Player.EventName = {
|
|
|
6268
6470
|
AbrStatusChanged: 'abrstatuschanged',
|
|
6269
6471
|
Adaptation: 'adaptation',
|
|
6270
6472
|
Buffering: 'buffering',
|
|
6473
|
+
DownloadFailed: 'downloadfailed',
|
|
6474
|
+
DownloadHeadersReceived: 'downloadheadersreceived',
|
|
6271
6475
|
DrmSessionUpdate: 'drmsessionupdate',
|
|
6272
6476
|
Emsg: 'emsg',
|
|
6273
6477
|
Error: 'error',
|
|
@@ -6276,6 +6480,7 @@ shaka.Player.EventName = {
|
|
|
6276
6480
|
Loaded: 'loaded',
|
|
6277
6481
|
Loading: 'loading',
|
|
6278
6482
|
ManifestParsed: 'manifestparsed',
|
|
6483
|
+
MediaQualityChanged: 'mediaqualitychanged',
|
|
6279
6484
|
Metadata: 'metadata',
|
|
6280
6485
|
OnStateChange: 'onstatechange',
|
|
6281
6486
|
OnStateIdle: 'onstateidle',
|
|
@@ -6331,7 +6536,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
|
|
|
6331
6536
|
* @define {string} A version number taken from git at compile time.
|
|
6332
6537
|
* @export
|
|
6333
6538
|
*/
|
|
6334
|
-
shaka.Player.version = 'v3.
|
|
6539
|
+
shaka.Player.version = 'v3.3.1-uncompiled';
|
|
6335
6540
|
|
|
6336
6541
|
// Initialize the deprecation system using the version string we just set
|
|
6337
6542
|
// on the player.
|
|
@@ -6375,6 +6580,7 @@ shaka.Player.SRC_EQUAL_EXTENSIONS_TO_MIME_TYPES_ = {
|
|
|
6375
6580
|
'mpg': 'video/mpeg',
|
|
6376
6581
|
'mpeg': 'video/mpeg',
|
|
6377
6582
|
'm3u8': 'application/x-mpegurl',
|
|
6583
|
+
'mpd': 'application/dash+xml',
|
|
6378
6584
|
'mp3': 'audio/mpeg',
|
|
6379
6585
|
'aac': 'audio/aac',
|
|
6380
6586
|
'flac': 'audio/flac',
|
|
@@ -24,8 +24,6 @@ shaka.polyfill.MediaCapabilities = class {
|
|
|
24
24
|
* @export
|
|
25
25
|
*/
|
|
26
26
|
static install() {
|
|
27
|
-
shaka.log.debug('MediaCapabilities: install');
|
|
28
|
-
|
|
29
27
|
// Since MediaCapabilities is not fully supported on Chromecast yet, we
|
|
30
28
|
// should always install polyfill for Chromecast.
|
|
31
29
|
// TODO: re-evaluate MediaCapabilities in the future versions of Chromecast.
|
|
@@ -34,21 +32,34 @@ shaka.polyfill.MediaCapabilities = class {
|
|
|
34
32
|
// See: https://github.com/google/shaka-player/issues/3530
|
|
35
33
|
// TODO: re-evaluate MediaCapabilities in the future versions of Apple
|
|
36
34
|
// Browsers.
|
|
35
|
+
// Since MediaCapabilities implementation is buggy in PS5 browsers, we
|
|
36
|
+
// should always install polyfill for PS5 browsers.
|
|
37
|
+
// See: https://github.com/google/shaka-player/issues/3582
|
|
38
|
+
// TODO: re-evaluate MediaCapabilities in the future versions of PS5
|
|
39
|
+
// Browsers.
|
|
37
40
|
if (!shaka.util.Platform.isChromecast() &&
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
!shaka.util.Platform.isApple() &&
|
|
42
|
+
!shaka.util.Platform.isPS5() &&
|
|
43
|
+
navigator.mediaCapabilities) {
|
|
44
|
+
shaka.log.info(
|
|
41
45
|
'MediaCapabilities: Native mediaCapabilities support found.');
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
shaka.log.info('MediaCapabilities: install');
|
|
50
|
+
|
|
51
|
+
if (!navigator.mediaCapabilities) {
|
|
52
|
+
navigator.mediaCapabilities = /** @type {!MediaCapabilities} */ ({});
|
|
48
53
|
}
|
|
49
|
-
|
|
50
|
-
// MediaCapabilities
|
|
51
|
-
|
|
54
|
+
|
|
55
|
+
// Keep the patched MediaCapabilities object from being garbage-collected in
|
|
56
|
+
// Safari.
|
|
57
|
+
// See https://github.com/google/shaka-player/issues/3696#issuecomment-1009472718
|
|
58
|
+
shaka.polyfill.MediaCapabilities.originalMcap =
|
|
59
|
+
navigator.mediaCapabilities;
|
|
60
|
+
|
|
61
|
+
navigator.mediaCapabilities.decodingInfo =
|
|
62
|
+
shaka.polyfill.MediaCapabilities.decodingInfo_;
|
|
52
63
|
}
|
|
53
64
|
|
|
54
65
|
/**
|
|
@@ -149,7 +160,7 @@ shaka.polyfill.MediaCapabilities = class {
|
|
|
149
160
|
sessionTypes: mediaCapkeySystemConfig.sessionTypes,
|
|
150
161
|
};
|
|
151
162
|
|
|
152
|
-
// Only add the audio video
|
|
163
|
+
// Only add the audio video capabilities if they have valid data.
|
|
153
164
|
// Otherwise the query will fail.
|
|
154
165
|
if (audioCapabilities.length) {
|
|
155
166
|
mediaKeySystemConfig.audioCapabilities = audioCapabilities;
|
|
@@ -176,6 +187,16 @@ shaka.polyfill.MediaCapabilities = class {
|
|
|
176
187
|
}
|
|
177
188
|
};
|
|
178
189
|
|
|
190
|
+
/**
|
|
191
|
+
* A copy of the MediaCapabilities instance, to prevent Safari from
|
|
192
|
+
* garbage-collecting the polyfilled method on it. We make it public and export
|
|
193
|
+
* it to ensure that it is not stripped out by the compiler.
|
|
194
|
+
*
|
|
195
|
+
* @type {MediaCapabilities}
|
|
196
|
+
* @export
|
|
197
|
+
*/
|
|
198
|
+
shaka.polyfill.MediaCapabilities.originalMcap = null;
|
|
199
|
+
|
|
179
200
|
// Install at a lower priority than MediaSource polyfill, so that we have
|
|
180
201
|
// MediaSource available first.
|
|
181
202
|
shaka.polyfill.register(shaka.polyfill.MediaCapabilities.install, -1);
|
|
@@ -208,6 +208,12 @@ shaka.polyfill.MediaSource = class {
|
|
|
208
208
|
static patchVp09_() {
|
|
209
209
|
const originalIsTypeSupported = MediaSource.isTypeSupported;
|
|
210
210
|
|
|
211
|
+
if (shaka.util.Platform.isWebOS()) {
|
|
212
|
+
// Don't do this on LG webOS as otherwise it is unable
|
|
213
|
+
// to play vp09 at all.
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
211
217
|
MediaSource.isTypeSupported = (mimeType) => {
|
|
212
218
|
// Split the MIME type into its various parameters.
|
|
213
219
|
const pieces = mimeType.split(/ *; */);
|