shaka-player 2.5.1 → 2.5.5
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/.csslintrc +13 -0
- package/AUTHORS +3 -0
- package/CHANGELOG.md +156 -0
- package/CONTRIBUTORS +3 -0
- package/README.md +3 -0
- package/build/README.md +5 -5
- package/build/apps.py +3 -1
- package/build/build.py +5 -2
- package/build/check.py +17 -0
- package/build/compiler.py +49 -0
- package/build/conformance.textproto +1 -0
- package/build/docs.py +0 -6
- package/build/generateExterns.js +72 -20
- package/build/install-linux-prereqs.sh +4 -4
- package/build/shakaBuildHelpers.py +7 -8
- package/build/test.py +21 -9
- package/build/types/core +1 -0
- package/build/types/ui +6 -1
- package/demo/asset_card.js +129 -41
- package/demo/cast_receiver/receiver_app.css +27 -13
- package/demo/close_button.js +10 -15
- package/demo/common/asset.js +6 -6
- package/demo/common/assets.js +72 -14
- package/demo/config.js +28 -25
- package/demo/custom.js +20 -16
- package/demo/demo.less +107 -16
- package/demo/demo_uncompiled.js +33 -0
- package/demo/demo_utils.js +4 -3
- package/demo/front.js +12 -8
- package/demo/index.html +14 -17
- package/demo/input.js +30 -23
- package/demo/input_container.js +15 -11
- package/demo/load.js +5 -7
- package/demo/main.js +138 -49
- package/demo/search.js +40 -36
- package/demo/service_worker.js +1 -1
- package/demo/tooltip.js +16 -24
- package/dist/.csslintstamp +0 -0
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +165 -152
- package/dist/demo.compiled.debug.map +4 -4
- package/dist/demo.compiled.js +165 -152
- package/dist/demo.compiled.map +4 -4
- package/dist/demo.css +1 -1
- package/dist/demo.css.map +1 -1
- package/dist/deps.js +28 -11
- package/dist/receiver.compiled.debug.js +11 -11
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +11 -11
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.debug.externs.js +232 -102
- package/dist/shaka-player.compiled.debug.js +189 -165
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +232 -102
- package/dist/shaka-player.compiled.js +567 -553
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.debug.externs.js +338 -113
- package/dist/shaka-player.ui.debug.js +296 -276
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +338 -113
- package/dist/shaka-player.ui.js +685 -671
- package/dist/shaka-player.ui.map +4 -4
- package/docs/tutorials/drm-config.md +1 -0
- package/docs/tutorials/fairplay.md +77 -0
- package/docs/tutorials/index.json +1 -0
- package/docs/tutorials/manifest-parser.md +1 -1
- package/docs/tutorials/ui-customization.md +5 -2
- package/docs/tutorials/ui.md +10 -4
- package/docs/tutorials/welcome.md +2 -2
- package/externs/mediasession.js +16 -1
- package/externs/shaka/net.js +14 -4
- package/externs/shaka/player.js +136 -90
- package/externs/tippy.js +30 -0
- package/externs/webkitmediakeys.js +4 -0
- package/karma.conf.js +30 -24
- package/lib/cast/cast_proxy.js +94 -23
- package/lib/cast/cast_receiver.js +8 -1
- package/lib/dash/content_protection.js +33 -1
- package/lib/dash/dash_parser.js +13 -5
- package/lib/hls/hls_parser.js +20 -4
- package/lib/media/drm_engine.js +29 -2
- package/lib/media/media_source_engine.js +9 -6
- package/lib/media/play_rate_controller.js +14 -3
- package/lib/media/playhead.js +8 -3
- package/lib/media/streaming_engine.js +68 -20
- package/lib/media/transmuxer.js +2 -2
- package/lib/media/video_wrapper.js +8 -3
- package/lib/net/data_uri_plugin.js +5 -2
- package/lib/net/http_fetch_plugin.js +3 -3
- package/lib/net/http_plugin_utils.js +2 -4
- package/lib/net/http_xhr_plugin.js +2 -2
- package/lib/net/networking_engine.js +1 -0
- package/lib/offline/offline_scheme.js +7 -2
- package/lib/player.js +18 -8
- package/lib/polyfill/input_event.js +7 -11
- package/lib/polyfill/mediasource.js +1 -1
- package/lib/polyfill/patchedmediakeys_apple.js +2 -72
- package/lib/text/cue.js +1 -1
- package/lib/text/ttml_text_parser.js +1 -1
- package/lib/util/config_utils.js +1 -0
- package/lib/util/error.js +45 -11
- package/lib/util/event_manager.js +211 -100
- package/lib/util/fairplay_utils.js +122 -0
- package/lib/util/i_releasable.js +1 -0
- package/lib/util/player_configuration.js +7 -0
- package/lib/util/pssh.js +41 -0
- package/lib/util/string_utils.js +42 -6
- package/lib/util/timer.js +1 -1
- package/package.json +33 -33
- package/roadmap.md +96 -0
- package/shaka-player.uncompiled.js +5 -1
- package/test/dash/dash_parser_content_protection_unit.js +35 -1
- package/test/dash/dash_parser_manifest_unit.js +60 -0
- package/test/hls/hls_live_unit.js +7 -1
- package/test/hls/hls_parser_unit.js +50 -0
- package/test/media/drm_engine_unit.js +10 -4
- package/test/media/media_source_engine_integration.js +12 -0
- package/test/media/media_source_engine_unit.js +3 -1
- package/test/media/playhead_unit.js +7 -5
- package/test/media/streaming_engine_unit.js +46 -1
- package/test/media/transmuxer_integration.js +13 -0
- package/test/net/data_uri_plugin_unit.js +13 -2
- package/test/net/http_plugin_unit.js +17 -12
- package/test/net/networking_engine_unit.js +17 -8
- package/test/offline/offline_scheme_unit.js +18 -8
- package/test/player_external.js +3 -2
- package/test/player_integration.js +94 -3
- package/test/player_src_equals_integration.js +2 -2
- package/test/player_unit.js +21 -8
- package/test/test/boot.js +20 -5
- package/test/test/externs/jasmine.js +48 -0
- package/test/test/util/expect_async_polyfill.js +145 -0
- package/test/test/util/fake_networking_engine.js +1 -0
- package/test/test/util/manifest_generator.js +2 -1
- package/test/test/util/test_scheme.js +34 -2
- package/test/test/util/ui_utils.js +41 -0
- package/test/test/util/util.js +16 -8
- package/test/ui/ui_unit.js +130 -4
- package/ui/audio_language_selection.js +17 -96
- package/ui/big_play_button.js +61 -0
- package/ui/controls.js +226 -335
- package/ui/controls.less +3 -5
- package/ui/element.js +24 -6
- package/ui/externs/ui.js +62 -9
- package/ui/fullscreen_button.js +2 -52
- package/ui/less/buttons.less +10 -16
- package/ui/less/containers.less +75 -20
- package/ui/less/general.less +18 -2
- package/ui/less/other_elements.less +2 -1
- package/ui/less/overflow_menu.less +11 -10
- package/ui/less/range_elements.less +12 -10
- package/ui/less/spinner.less +2 -0
- package/ui/overflow_menu.js +1 -1
- package/ui/pip_button.js +1 -1
- package/ui/{play_pause_button.js → play_button.js} +17 -47
- package/ui/presentation_time.js +17 -12
- package/ui/range_element.js +176 -0
- package/ui/resolution_selection.js +43 -106
- package/ui/seek_bar.js +204 -0
- package/ui/settings_menu.js +113 -0
- package/ui/small_play_button.js +73 -0
- package/ui/text_displayer.js +17 -14
- package/ui/text_selection.js +42 -107
- package/ui/ui.js +17 -40
- package/ui/volume_bar.js +40 -68
|
@@ -575,9 +575,16 @@ shaka.media.StreamingEngine.prototype.loadNewTextStream = async function(
|
|
|
575
575
|
await this.setupStreams_(streamSet);
|
|
576
576
|
if (this.destroyed_) { return; }
|
|
577
577
|
|
|
578
|
+
const showText = this.playerInterface_
|
|
579
|
+
.mediaSourceEngine
|
|
580
|
+
.getTextDisplayer()
|
|
581
|
+
.isTextVisible();
|
|
582
|
+
|
|
583
|
+
const streamText = showText || this.config_.alwaysStreamText;
|
|
584
|
+
|
|
578
585
|
if ((this.textStreamSequenceId_ == currentSequenceId) &&
|
|
579
586
|
!this.mediaStates_.has(ContentType.TEXT) &&
|
|
580
|
-
!this.unloadingTextStream_) {
|
|
587
|
+
!this.unloadingTextStream_ && streamText) {
|
|
581
588
|
const presentationTime = this.playerInterface_.getPresentationTime();
|
|
582
589
|
const needPeriodIndex = this.findPeriodForTime_(presentationTime);
|
|
583
590
|
|
|
@@ -713,7 +720,12 @@ shaka.media.StreamingEngine.prototype.switchInternal_ = function(
|
|
|
713
720
|
// handle a Period transition. Simply ignore the given stream, assuming that
|
|
714
721
|
// Player will select the same track in onChooseStreams.
|
|
715
722
|
let periodIndex = this.findPeriodContainingStream_(stream);
|
|
716
|
-
|
|
723
|
+
const mediaStates = Array.from(this.mediaStates_.values());
|
|
724
|
+
const needSamePeriod = mediaStates.every((ms) => {
|
|
725
|
+
return ms.needPeriodIndex == mediaState.needPeriodIndex;
|
|
726
|
+
});
|
|
727
|
+
if (clearBuffer && periodIndex != mediaState.needPeriodIndex &&
|
|
728
|
+
needSamePeriod) {
|
|
717
729
|
shaka.log.debug('switch: switching to stream in another Period; clearing ' +
|
|
718
730
|
'buffer and changing Periods');
|
|
719
731
|
// handlePeriodTransition_ will be called on the next update because the
|
|
@@ -796,7 +808,13 @@ shaka.media.StreamingEngine.prototype.switchInternal_ = function(
|
|
|
796
808
|
// Cancel the update timer, if any.
|
|
797
809
|
this.cancelUpdate_(mediaState);
|
|
798
810
|
// Clear right away.
|
|
799
|
-
this.clearBuffer_(mediaState, /* flush */ true, safeMargin)
|
|
811
|
+
this.clearBuffer_(mediaState, /* flush */ true, safeMargin)
|
|
812
|
+
.catch((error) => {
|
|
813
|
+
if (this.playerInterface_) {
|
|
814
|
+
this.playerInterface_.onError(
|
|
815
|
+
/** @type {!shaka.util.Error} */ (error));
|
|
816
|
+
}
|
|
817
|
+
});
|
|
800
818
|
}
|
|
801
819
|
}
|
|
802
820
|
};
|
|
@@ -972,7 +990,11 @@ shaka.media.StreamingEngine.prototype.forceClearBuffer_ = function(
|
|
|
972
990
|
// buffer right away. Note: clearBuffer_() will schedule the next update.
|
|
973
991
|
shaka.log.debug(logPrefix, 'clear: handling right now');
|
|
974
992
|
this.cancelUpdate_(mediaState);
|
|
975
|
-
this.clearBuffer_(mediaState, /* flush */ false, 0)
|
|
993
|
+
this.clearBuffer_(mediaState, /* flush */ false, 0).catch((error) => {
|
|
994
|
+
if (this.playerInterface_) {
|
|
995
|
+
this.playerInterface_.onError(/** @type {!shaka.util.Error} */ (error));
|
|
996
|
+
}
|
|
997
|
+
});
|
|
976
998
|
};
|
|
977
999
|
|
|
978
1000
|
|
|
@@ -1287,8 +1309,11 @@ shaka.media.StreamingEngine.prototype.onUpdate_ = function(mediaState) {
|
|
|
1287
1309
|
// forever at the end. We should only do this if the duration needs to
|
|
1288
1310
|
// shrink. Growing it by less than 1ms can actually cause buffering on
|
|
1289
1311
|
// replay, as in https://github.com/google/shaka-player/issues/979
|
|
1290
|
-
|
|
1291
|
-
|
|
1312
|
+
// On some platforms, this can spuriously be 0, so ignore this case.
|
|
1313
|
+
// https://github.com/google/shaka-player/issues/1967,
|
|
1314
|
+
const duration = this.playerInterface_.mediaSourceEngine.getDuration();
|
|
1315
|
+
if (duration != 0 &&
|
|
1316
|
+
duration < this.manifest_.presentationTimeline.getDuration()) {
|
|
1292
1317
|
this.manifest_.presentationTimeline.setDuration(duration);
|
|
1293
1318
|
}
|
|
1294
1319
|
}.bind(this));
|
|
@@ -1314,11 +1339,7 @@ shaka.media.StreamingEngine.prototype.update_ = function(mediaState) {
|
|
|
1314
1339
|
// If it's a text stream and the original id starts with 'CC', it's CEA
|
|
1315
1340
|
// closed captions. Do not schedule update for closed captions text
|
|
1316
1341
|
// mediastate, since closed captions are embedded in video streams.
|
|
1317
|
-
|
|
1318
|
-
return state.type == ContentType.TEXT &&
|
|
1319
|
-
state.stream.mimeType == shaka.util.MimeUtils.CLOSED_CAPTION_MIMETYPE;
|
|
1320
|
-
};
|
|
1321
|
-
if (isCaptionState(mediaState)) {
|
|
1342
|
+
if (shaka.media.StreamingEngine.isEmbeddedText_(mediaState)) {
|
|
1322
1343
|
this.playerInterface_.mediaSourceEngine.setSelectedClosedCaptionId(
|
|
1323
1344
|
mediaState.stream.originalId || '');
|
|
1324
1345
|
return null;
|
|
@@ -1418,7 +1439,9 @@ shaka.media.StreamingEngine.prototype.update_ = function(mediaState) {
|
|
|
1418
1439
|
mediaStates.forEach((otherState) => {
|
|
1419
1440
|
// Do not consider embedded captions in this calculation. It could lead
|
|
1420
1441
|
// to hangs in streaming.
|
|
1421
|
-
|
|
1442
|
+
if (shaka.media.StreamingEngine.isEmbeddedText_(otherState)) {
|
|
1443
|
+
return;
|
|
1444
|
+
}
|
|
1422
1445
|
|
|
1423
1446
|
const timeNeeded = this.getTimeNeeded_(otherState, presentationTime);
|
|
1424
1447
|
minTimeNeeded = Math.min(minTimeNeeded, timeNeeded);
|
|
@@ -1436,10 +1459,11 @@ shaka.media.StreamingEngine.prototype.update_ = function(mediaState) {
|
|
|
1436
1459
|
}
|
|
1437
1460
|
|
|
1438
1461
|
mediaState.resumeAt = 0;
|
|
1439
|
-
this.fetchAndAppend_(
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1462
|
+
this.fetchAndAppend_(
|
|
1463
|
+
mediaState,
|
|
1464
|
+
presentationTime,
|
|
1465
|
+
currentPeriodIndex,
|
|
1466
|
+
reference);
|
|
1443
1467
|
return null;
|
|
1444
1468
|
};
|
|
1445
1469
|
|
|
@@ -2173,13 +2197,15 @@ shaka.media.StreamingEngine.prototype.handlePeriodTransition_ = function(
|
|
|
2173
2197
|
goog.asserts.assert(
|
|
2174
2198
|
mediaStates.every(function(ms) {
|
|
2175
2199
|
return ms.needPeriodIndex == needPeriodIndex || ms.hasError ||
|
|
2176
|
-
!shaka.media.StreamingEngine.isIdle_(ms)
|
|
2200
|
+
!shaka.media.StreamingEngine.isIdle_(ms) ||
|
|
2201
|
+
shaka.media.StreamingEngine.isEmbeddedText_(ms);
|
|
2177
2202
|
}),
|
|
2178
2203
|
'All MediaStates should need the same Period or be performing updates.');
|
|
2179
2204
|
|
|
2180
2205
|
// Only call onChooseStreams() when all MediaStates need the same Period.
|
|
2181
2206
|
let needSamePeriod = mediaStates.every(function(ms) {
|
|
2182
|
-
return ms.needPeriodIndex == needPeriodIndex
|
|
2207
|
+
return ms.needPeriodIndex == needPeriodIndex ||
|
|
2208
|
+
shaka.media.StreamingEngine.isEmbeddedText_(ms);
|
|
2183
2209
|
});
|
|
2184
2210
|
if (!needSamePeriod) {
|
|
2185
2211
|
shaka.log.debug(
|
|
@@ -2213,6 +2239,10 @@ shaka.media.StreamingEngine.prototype.handlePeriodTransition_ = function(
|
|
|
2213
2239
|
let allReady = mediaStates.every(function(ms) {
|
|
2214
2240
|
let isIdle = shaka.media.StreamingEngine.isIdle_(ms);
|
|
2215
2241
|
let currentPeriodIndex = this.findPeriodContainingStream_(ms.stream);
|
|
2242
|
+
if (shaka.media.StreamingEngine.isEmbeddedText_(ms)) {
|
|
2243
|
+
// Embedded text tracks don't do Period transitions.
|
|
2244
|
+
return true;
|
|
2245
|
+
}
|
|
2216
2246
|
return isIdle && ms.needPeriodIndex == needPeriodIndex &&
|
|
2217
2247
|
currentPeriodIndex != needPeriodIndex;
|
|
2218
2248
|
}.bind(this));
|
|
@@ -2299,6 +2329,18 @@ shaka.media.StreamingEngine.prototype.handlePeriodTransition_ = function(
|
|
|
2299
2329
|
};
|
|
2300
2330
|
|
|
2301
2331
|
|
|
2332
|
+
/**
|
|
2333
|
+
* @param {shaka.media.StreamingEngine.MediaState_} mediaState
|
|
2334
|
+
* @return {boolean}
|
|
2335
|
+
* @private
|
|
2336
|
+
*/
|
|
2337
|
+
shaka.media.StreamingEngine.isEmbeddedText_ = function(mediaState) {
|
|
2338
|
+
const MimeUtils = shaka.util.MimeUtils;
|
|
2339
|
+
return mediaState.type == shaka.util.ManifestParserUtils.ContentType.TEXT &&
|
|
2340
|
+
mediaState.stream.mimeType == MimeUtils.CLOSED_CAPTION_MIMETYPE;
|
|
2341
|
+
};
|
|
2342
|
+
|
|
2343
|
+
|
|
2302
2344
|
/**
|
|
2303
2345
|
* @param {shaka.media.StreamingEngine.MediaState_} mediaState
|
|
2304
2346
|
* @return {boolean} True if the given MediaState is idle; otherwise, return
|
|
@@ -2481,8 +2523,14 @@ shaka.media.StreamingEngine.prototype.scheduleUpdate_ = function(
|
|
|
2481
2523
|
goog.asserts.assert(mediaState.updateTimer == null,
|
|
2482
2524
|
logPrefix + ' did not expect update to be scheduled');
|
|
2483
2525
|
|
|
2484
|
-
mediaState.updateTimer = new shaka.util.DelayedTick(() => {
|
|
2485
|
-
|
|
2526
|
+
mediaState.updateTimer = new shaka.util.DelayedTick(async () => {
|
|
2527
|
+
try {
|
|
2528
|
+
await this.onUpdate_(mediaState);
|
|
2529
|
+
} catch (error) {
|
|
2530
|
+
if (this.playerInterface_) {
|
|
2531
|
+
this.playerInterface_.onError(error);
|
|
2532
|
+
}
|
|
2533
|
+
}
|
|
2486
2534
|
}).tickAfter(delay);
|
|
2487
2535
|
};
|
|
2488
2536
|
|
package/lib/media/transmuxer.js
CHANGED
|
@@ -94,7 +94,7 @@ shaka.media.Transmuxer.isSupported = function(mimeType, contentType) {
|
|
|
94
94
|
* @return {boolean}
|
|
95
95
|
*/
|
|
96
96
|
shaka.media.Transmuxer.isTsContainer = function(mimeType) {
|
|
97
|
-
return mimeType.split(';')[0].split('/')[1] == 'mp2t';
|
|
97
|
+
return mimeType.toLowerCase().split(';')[0].split('/')[1] == 'mp2t';
|
|
98
98
|
};
|
|
99
99
|
|
|
100
100
|
|
|
@@ -106,7 +106,7 @@ shaka.media.Transmuxer.isTsContainer = function(mimeType) {
|
|
|
106
106
|
*/
|
|
107
107
|
shaka.media.Transmuxer.convertTsCodecs = function(contentType, tsMimeType) {
|
|
108
108
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
109
|
-
let mp4MimeType = tsMimeType.replace(
|
|
109
|
+
let mp4MimeType = tsMimeType.replace(/mp2t/i, 'mp4');
|
|
110
110
|
if (contentType == ContentType.AUDIO) {
|
|
111
111
|
mp4MimeType = mp4MimeType.replace('video', 'audio');
|
|
112
112
|
}
|
|
@@ -49,6 +49,9 @@ shaka.media.VideoWrapper = function(video, onSeek, startTime) {
|
|
|
49
49
|
/** @private {number} */
|
|
50
50
|
this.startTime_ = startTime;
|
|
51
51
|
|
|
52
|
+
/** @private {boolean} */
|
|
53
|
+
this.started_ = false;
|
|
54
|
+
|
|
52
55
|
/** @private {shaka.util.EventManager} */
|
|
53
56
|
this.eventManager_ = new shaka.util.EventManager();
|
|
54
57
|
|
|
@@ -92,9 +95,7 @@ shaka.media.VideoWrapper.prototype.release = function() {
|
|
|
92
95
|
* @return {number}
|
|
93
96
|
*/
|
|
94
97
|
shaka.media.VideoWrapper.prototype.getTime = function() {
|
|
95
|
-
return this.video_.
|
|
96
|
-
this.video_.currentTime :
|
|
97
|
-
this.startTime_;
|
|
98
|
+
return this.started_ ? this.video_.currentTime : this.startTime_;
|
|
98
99
|
};
|
|
99
100
|
|
|
100
101
|
|
|
@@ -186,6 +187,10 @@ shaka.media.VideoWrapper.prototype.startListeningToSeeks_ = function() {
|
|
|
186
187
|
this.video_.readyState > 0,
|
|
187
188
|
'The media element should be ready before we listen for seeking.');
|
|
188
189
|
|
|
190
|
+
// Now that any startup seeking is complete, we can trust the video element
|
|
191
|
+
// for currentTime.
|
|
192
|
+
this.started_ = true;
|
|
193
|
+
|
|
189
194
|
this.eventManager_.listen(this.video_, 'seeking', () => this.onSeek_());
|
|
190
195
|
};
|
|
191
196
|
|
|
@@ -31,17 +31,20 @@ goog.require('shaka.util.Uint8ArrayUtils');
|
|
|
31
31
|
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/data_URIs
|
|
32
32
|
* @param {string} uri
|
|
33
33
|
* @param {shaka.extern.Request} request
|
|
34
|
-
* @param {shaka.net.NetworkingEngine.RequestType
|
|
34
|
+
* @param {shaka.net.NetworkingEngine.RequestType} requestType
|
|
35
|
+
* @param {shaka.extern.ProgressUpdated} progressUpdated Called when a
|
|
36
|
+
* progress event happened.
|
|
35
37
|
* @return {!shaka.extern.IAbortableOperation.<shaka.extern.Response>}
|
|
36
38
|
* @export
|
|
37
39
|
*/
|
|
38
|
-
shaka.net.DataUriPlugin = function(uri, request, requestType) {
|
|
40
|
+
shaka.net.DataUriPlugin = function(uri, request, requestType, progressUpdated) {
|
|
39
41
|
try {
|
|
40
42
|
let parsed = shaka.net.DataUriPlugin.parse(uri);
|
|
41
43
|
|
|
42
44
|
/** @type {shaka.extern.Response} */
|
|
43
45
|
let response = {
|
|
44
46
|
uri: uri,
|
|
47
|
+
originalUri: uri,
|
|
45
48
|
data: parsed.data,
|
|
46
49
|
headers: {
|
|
47
50
|
'content-type': parsed.contentType,
|
|
@@ -32,8 +32,8 @@ goog.require('shaka.util.Timer');
|
|
|
32
32
|
* @param {string} uri
|
|
33
33
|
* @param {shaka.extern.Request} request
|
|
34
34
|
* @param {shaka.net.NetworkingEngine.RequestType} requestType
|
|
35
|
-
* @param {shaka.extern.ProgressUpdated
|
|
36
|
-
*
|
|
35
|
+
* @param {shaka.extern.ProgressUpdated} progressUpdated Called when a progress
|
|
36
|
+
* event happened.
|
|
37
37
|
* @return {!shaka.extern.IAbortableOperation.<shaka.extern.Response>}
|
|
38
38
|
* @export
|
|
39
39
|
*/
|
|
@@ -98,7 +98,7 @@ shaka.net.HttpFetchPlugin = function(
|
|
|
98
98
|
* @param {shaka.net.NetworkingEngine.RequestType} requestType
|
|
99
99
|
* @param {!RequestInit} init
|
|
100
100
|
* @param {shaka.net.HttpFetchPlugin.AbortStatus} abortStatus
|
|
101
|
-
* @param {shaka.extern.ProgressUpdated
|
|
101
|
+
* @param {shaka.extern.ProgressUpdated} progressUpdated
|
|
102
102
|
* @return {!Promise<!shaka.extern.Response>}
|
|
103
103
|
* @private
|
|
104
104
|
*/
|
|
@@ -42,12 +42,10 @@ shaka.net.HttpPluginUtils.makeResponse =
|
|
|
42
42
|
function(headers, data, status, uri, responseURL, requestType) {
|
|
43
43
|
if (status >= 200 && status <= 299 && status != 202) {
|
|
44
44
|
// Most 2xx HTTP codes are success cases.
|
|
45
|
-
if (responseURL) {
|
|
46
|
-
uri = responseURL;
|
|
47
|
-
}
|
|
48
45
|
/** @type {shaka.extern.Response} */
|
|
49
46
|
let response = {
|
|
50
|
-
uri: uri,
|
|
47
|
+
uri: responseURL || uri,
|
|
48
|
+
originalUri: uri,
|
|
51
49
|
data: data,
|
|
52
50
|
headers: headers,
|
|
53
51
|
fromCache: !!headers['x-shaka-from-cache'],
|
|
@@ -30,8 +30,8 @@ goog.require('shaka.util.Error');
|
|
|
30
30
|
* @param {string} uri
|
|
31
31
|
* @param {shaka.extern.Request} request
|
|
32
32
|
* @param {shaka.net.NetworkingEngine.RequestType} requestType
|
|
33
|
-
* @param {shaka.extern.ProgressUpdated
|
|
34
|
-
*
|
|
33
|
+
* @param {shaka.extern.ProgressUpdated} progressUpdated Called when a
|
|
34
|
+
* progress event happened.
|
|
35
35
|
* @return {!shaka.extern.IAbortableOperation.<shaka.extern.Response>}
|
|
36
36
|
* @export
|
|
37
37
|
*/
|
|
@@ -30,11 +30,14 @@ goog.require('shaka.util.Error');
|
|
|
30
30
|
* @summary A plugin that handles requests for offline content.
|
|
31
31
|
* @param {string} uri
|
|
32
32
|
* @param {shaka.extern.Request} request
|
|
33
|
-
* @param {shaka.net.NetworkingEngine.RequestType
|
|
33
|
+
* @param {shaka.net.NetworkingEngine.RequestType} requestType
|
|
34
|
+
* @param {shaka.extern.ProgressUpdated} progressUpdated Called when a
|
|
35
|
+
* progress event happened.
|
|
34
36
|
* @return {!shaka.extern.IAbortableOperation.<shaka.extern.Response>}
|
|
35
37
|
* @export
|
|
36
38
|
*/
|
|
37
|
-
shaka.offline.OfflineScheme = function(
|
|
39
|
+
shaka.offline.OfflineScheme = function(
|
|
40
|
+
uri, request, requestType, progressUpdated) {
|
|
38
41
|
let offlineUri = shaka.offline.OfflineUri.parse(uri);
|
|
39
42
|
|
|
40
43
|
if (offlineUri && offlineUri.isManifest()) {
|
|
@@ -64,6 +67,7 @@ shaka.offline.OfflineScheme.getManifest_ = function(uri) {
|
|
|
64
67
|
/** @type {shaka.extern.Response} */
|
|
65
68
|
let response = {
|
|
66
69
|
uri: uri,
|
|
70
|
+
originalUri: uri,
|
|
67
71
|
data: new ArrayBuffer(0),
|
|
68
72
|
headers: {'content-type': 'application/x-offline-manifest'},
|
|
69
73
|
};
|
|
@@ -95,6 +99,7 @@ shaka.offline.OfflineScheme.getSegment_ = function(id, uri) {
|
|
|
95
99
|
|
|
96
100
|
return {
|
|
97
101
|
uri: uri,
|
|
102
|
+
originalUri: uri,
|
|
98
103
|
data: segment.data,
|
|
99
104
|
headers: {},
|
|
100
105
|
};
|
package/lib/player.js
CHANGED
|
@@ -429,7 +429,7 @@ shaka.Player.prototype.destroy = async function() {
|
|
|
429
429
|
* @define {string} A version number taken from git at compile time.
|
|
430
430
|
* @export
|
|
431
431
|
*/
|
|
432
|
-
shaka.Player.version = 'v2.5.
|
|
432
|
+
shaka.Player.version = 'v2.5.5-uncompiled';
|
|
433
433
|
|
|
434
434
|
// Initialize the deprecation system using the version string we just set
|
|
435
435
|
// on the player.
|
|
@@ -1213,7 +1213,6 @@ shaka.Player.prototype.onUnload_ = async function(has, wants) {
|
|
|
1213
1213
|
|
|
1214
1214
|
// Remove everything that has to do with loading content from our payload
|
|
1215
1215
|
// since we are releasing everything that depended on it.
|
|
1216
|
-
has.currentTime = null;
|
|
1217
1216
|
has.factory = null;
|
|
1218
1217
|
has.mimeType = null;
|
|
1219
1218
|
has.startTime = null;
|
|
@@ -1729,7 +1728,8 @@ shaka.Player.prototype.onLoad_ = async function(has, wants) {
|
|
|
1729
1728
|
// active one, update abr manager with filtered variants for the current
|
|
1730
1729
|
// period.
|
|
1731
1730
|
/** @type {shaka.extern.Period} */
|
|
1732
|
-
const currentPeriod =
|
|
1731
|
+
const currentPeriod =
|
|
1732
|
+
this.getPresentationPeriod_() || this.manifest_.periods[0];
|
|
1733
1733
|
const hasPrimary = currentPeriod.variants.some((v) => v.primary);
|
|
1734
1734
|
|
|
1735
1735
|
if (!this.config_.preferredAudioLanguage && !hasPrimary) {
|
|
@@ -2738,12 +2738,15 @@ shaka.Player.prototype.trickPlay = function(rate) {
|
|
|
2738
2738
|
return;
|
|
2739
2739
|
}
|
|
2740
2740
|
|
|
2741
|
-
if (this.
|
|
2742
|
-
|
|
2741
|
+
if (this.video_.paused) {
|
|
2742
|
+
// Our fast forward is implemented with playbackRate and needs the video to
|
|
2743
|
+
// be playing (to not be paused) to take immediate effect.
|
|
2744
|
+
// If the video is paused, "unpause" it.
|
|
2745
|
+
this.video_.play();
|
|
2743
2746
|
}
|
|
2747
|
+
this.playRateController_.set(rate);
|
|
2744
2748
|
|
|
2745
2749
|
if (this.loadMode_ == shaka.Player.LoadMode.MEDIA_SOURCE) {
|
|
2746
|
-
this.playRateController_.set(rate);
|
|
2747
2750
|
this.streamingEngine_.setTrickPlay(Math.abs(rate) > 1);
|
|
2748
2751
|
}
|
|
2749
2752
|
};
|
|
@@ -3120,8 +3123,15 @@ shaka.Player.prototype.selectTextLanguage = function(language, role) {
|
|
|
3120
3123
|
|
|
3121
3124
|
this.currentTextLanguage_ = language;
|
|
3122
3125
|
this.currentTextRole_ = role || '';
|
|
3123
|
-
|
|
3124
|
-
this.
|
|
3126
|
+
|
|
3127
|
+
const chosenText = this.chooseTextStream_(period.textStreams);
|
|
3128
|
+
if (chosenText) {
|
|
3129
|
+
this.addTextStreamToSwitchHistory_(
|
|
3130
|
+
period, chosenText, /* fromAdaptation= */ false);
|
|
3131
|
+
if (this.shouldStreamText_()) {
|
|
3132
|
+
this.switchTextStream_(chosenText);
|
|
3133
|
+
}
|
|
3134
|
+
}
|
|
3125
3135
|
} else {
|
|
3126
3136
|
const track = this.getTextTracks().filter((t) => t.language == language)[0];
|
|
3127
3137
|
if (track) {
|
|
@@ -42,15 +42,18 @@ shaka.polyfill.InputEvent.install = function() {
|
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
// In our tests, we can end up with multiple independent "shaka" namespaces.
|
|
46
|
+
// So we can't compare addEventListener with the polyfill directly.
|
|
47
|
+
// Instead, store the original in a globally accessible place and check if
|
|
48
|
+
// that has been used yet.
|
|
49
|
+
if (HTMLInputElement.prototype['originalAddEventListener']) {
|
|
47
50
|
// The polyfill was already installed.
|
|
48
51
|
return;
|
|
49
52
|
}
|
|
50
53
|
|
|
51
54
|
shaka.log.info('Patching input event support on IE.');
|
|
52
55
|
|
|
53
|
-
|
|
56
|
+
HTMLInputElement.prototype['originalAddEventListener'] =
|
|
54
57
|
HTMLInputElement.prototype.addEventListener;
|
|
55
58
|
|
|
56
59
|
HTMLInputElement.prototype['addEventListener'] =
|
|
@@ -58,13 +61,6 @@ shaka.polyfill.InputEvent.install = function() {
|
|
|
58
61
|
};
|
|
59
62
|
|
|
60
63
|
|
|
61
|
-
/**
|
|
62
|
-
* The original addEventListener from HTMLInputElement.
|
|
63
|
-
* @private Function
|
|
64
|
-
*/
|
|
65
|
-
shaka.polyfill.InputEvent.originalAddEventListener_;
|
|
66
|
-
|
|
67
|
-
|
|
68
64
|
/**
|
|
69
65
|
* Add an event listener to this object and translate the event types to those
|
|
70
66
|
* that work on IE11.
|
|
@@ -89,7 +85,7 @@ shaka.polyfill.InputEvent.addEventListener_ =
|
|
|
89
85
|
}
|
|
90
86
|
}
|
|
91
87
|
|
|
92
|
-
|
|
88
|
+
HTMLInputElement.prototype['originalAddEventListener'].call(
|
|
93
89
|
this, type, listener, options);
|
|
94
90
|
};
|
|
95
91
|
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
|
|
18
18
|
goog.provide('shaka.polyfill.PatchedMediaKeysApple');
|
|
19
19
|
|
|
20
|
-
goog.require('goog.Uri');
|
|
21
20
|
goog.require('goog.asserts');
|
|
22
21
|
goog.require('shaka.log');
|
|
23
22
|
goog.require('shaka.polyfill.register');
|
|
@@ -25,7 +24,6 @@ goog.require('shaka.util.EventManager');
|
|
|
25
24
|
goog.require('shaka.util.FakeEvent');
|
|
26
25
|
goog.require('shaka.util.FakeEventTarget');
|
|
27
26
|
goog.require('shaka.util.PublicPromise');
|
|
28
|
-
goog.require('shaka.util.StringUtils');
|
|
29
27
|
goog.require('shaka.util.Uint8ArrayUtils');
|
|
30
28
|
|
|
31
29
|
|
|
@@ -455,6 +453,7 @@ shaka.polyfill.PatchedMediaKeysApple.MediaKeySession.prototype.
|
|
|
455
453
|
// initData into a Uint8Array.
|
|
456
454
|
this.nativeMediaKeySession_ = this.nativeMediaKeys_.createSession(
|
|
457
455
|
'video/mp4', new Uint8Array(initData));
|
|
456
|
+
this.sessionId = this.nativeMediaKeySession_.sessionId || '';
|
|
458
457
|
|
|
459
458
|
// Attach session event handlers here.
|
|
460
459
|
this.eventManager_.listen(this.nativeMediaKeySession_, 'webkitkeymessage',
|
|
@@ -533,71 +532,6 @@ shaka.polyfill.PatchedMediaKeysApple.MediaKeySession.prototype.
|
|
|
533
532
|
};
|
|
534
533
|
|
|
535
534
|
|
|
536
|
-
/**
|
|
537
|
-
* Rebuild FairPlay init data according to Apple's docs. It's unclear why this
|
|
538
|
-
* is not done by the browser, or if the unprefixed version will do it for us.
|
|
539
|
-
*
|
|
540
|
-
* @param {BufferSource} initData
|
|
541
|
-
* @param {BufferSource} certificate
|
|
542
|
-
* @return {BufferSource}
|
|
543
|
-
*/
|
|
544
|
-
shaka.polyfill.PatchedMediaKeysApple.rebuildInitData_ =
|
|
545
|
-
function(initData, certificate) {
|
|
546
|
-
// TODO: Move this into DrmEngine if it is still needed with unprefixed EME.
|
|
547
|
-
// FairPlay init data is in two parts and must be processed a bit.
|
|
548
|
-
// The first part is a 4 byte little-endian int, which is the length of the
|
|
549
|
-
// second part.
|
|
550
|
-
const initDataArray = new Uint8Array(initData);
|
|
551
|
-
const dataview = new DataView(initDataArray.buffer);
|
|
552
|
-
const length = dataview.getUint32(
|
|
553
|
-
/* position= */ 0, /* littleEndian= */ true);
|
|
554
|
-
if (length + 4 != initDataArray.byteLength) {
|
|
555
|
-
throw new Error('Malformed init data!');
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
// The second part is a UTF-16 LE URI from the manifest.
|
|
559
|
-
const uriString = shaka.util.StringUtils.fromUTF16(
|
|
560
|
-
initDataArray.slice(4), /* littleEndian= */ true);
|
|
561
|
-
|
|
562
|
-
// The domain of that URI is the content ID according to Apple's FPS sample.
|
|
563
|
-
const uri = new goog.Uri(uriString);
|
|
564
|
-
const contentId = uri.getDomain();
|
|
565
|
-
|
|
566
|
-
// From that, we build a new init data to use in the session. This is
|
|
567
|
-
// composed of several parts. First, the raw init data we already got.
|
|
568
|
-
// Second, a 4-byte LE length followed by the content ID in UTF-16-LE.
|
|
569
|
-
// Third, a 4-byte LE length followed by the certificate.
|
|
570
|
-
const contentIdArray = new Uint8Array(
|
|
571
|
-
shaka.util.StringUtils.toUTF16(contentId, /* littleEndian= */ true));
|
|
572
|
-
|
|
573
|
-
const rebuiltInitData = new Uint8Array(
|
|
574
|
-
initDataArray.byteLength +
|
|
575
|
-
4 + contentIdArray.byteLength +
|
|
576
|
-
4 + certificate.byteLength);
|
|
577
|
-
|
|
578
|
-
let offset = 0;
|
|
579
|
-
/** @param {!Uint8Array} array */
|
|
580
|
-
const append = (array) => {
|
|
581
|
-
rebuiltInitData.set(array, offset);
|
|
582
|
-
offset += array.byteLength;
|
|
583
|
-
};
|
|
584
|
-
/** @param {!Uint8Array} array */
|
|
585
|
-
const appendWithLength = (array) => {
|
|
586
|
-
const view = new DataView(rebuiltInitData.buffer);
|
|
587
|
-
const value = array.byteLength;
|
|
588
|
-
view.setUint32(offset, value, /* littleEndian= */ true);
|
|
589
|
-
offset += 4;
|
|
590
|
-
append(array);
|
|
591
|
-
};
|
|
592
|
-
|
|
593
|
-
append(initDataArray);
|
|
594
|
-
appendWithLength(contentIdArray);
|
|
595
|
-
appendWithLength(new Uint8Array(certificate));
|
|
596
|
-
|
|
597
|
-
return rebuiltInitData;
|
|
598
|
-
};
|
|
599
|
-
|
|
600
|
-
|
|
601
535
|
/**
|
|
602
536
|
* Handler for the native media elements webkitneedkey event.
|
|
603
537
|
*
|
|
@@ -617,16 +551,12 @@ shaka.polyfill.PatchedMediaKeysApple.onWebkitNeedKey_ = function(event) {
|
|
|
617
551
|
|
|
618
552
|
goog.asserts.assert(event.initData != null, 'missing init data!');
|
|
619
553
|
|
|
620
|
-
const certificate = mediaKeys.certificate;
|
|
621
|
-
goog.asserts.assert(certificate != null, 'missing certificate!');
|
|
622
|
-
|
|
623
554
|
// NOTE: Because "this" is a real EventTarget, the event we dispatch here must
|
|
624
555
|
// also be a real Event.
|
|
625
556
|
const event2 = new Event('encrypted');
|
|
626
557
|
// TODO: validate this initDataType against the unprefixed version
|
|
627
558
|
event2.initDataType = 'cenc';
|
|
628
|
-
event2.initData =
|
|
629
|
-
event.initData, certificate);
|
|
559
|
+
event2.initData = event.initData;
|
|
630
560
|
|
|
631
561
|
this.dispatchEvent(event2);
|
|
632
562
|
};
|
package/lib/text/cue.js
CHANGED
|
@@ -594,7 +594,7 @@ shaka.text.TtmlTextParser.addStyle_ = function(
|
|
|
594
594
|
if (imageElement) {
|
|
595
595
|
const backgroundImageType = imageElement.getAttribute('imagetype');
|
|
596
596
|
const backgroundImageEncoding = imageElement.getAttribute('encoding');
|
|
597
|
-
const backgroundImageData = imageElement.textContent;
|
|
597
|
+
const backgroundImageData = imageElement.textContent.trim();
|
|
598
598
|
if (backgroundImageType == 'PNG' &&
|
|
599
599
|
backgroundImageEncoding == 'Base64' &&
|
|
600
600
|
backgroundImageData) {
|
package/lib/util/config_utils.js
CHANGED