shaka-player 3.2.14 → 3.2.15
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/CHANGELOG.md +12 -0
- package/dist/deps.js +1 -1
- package/dist/locales.js +27 -27
- package/dist/shaka-player.compiled.d.ts +1 -1
- package/dist/shaka-player.compiled.debug.d.ts +1 -1
- package/dist/shaka-player.compiled.debug.externs.js +2 -1
- package/dist/shaka-player.compiled.debug.js +74 -73
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.externs.js +2 -1
- package/dist/shaka-player.compiled.js +542 -540
- package/dist/shaka-player.compiled.map +3 -3
- package/dist/shaka-player.ui.d.ts +1 -1
- package/dist/shaka-player.ui.debug.d.ts +1 -1
- package/dist/shaka-player.ui.debug.externs.js +2 -1
- package/dist/shaka-player.ui.debug.js +91 -90
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.externs.js +2 -1
- package/dist/shaka-player.ui.js +657 -655
- package/dist/shaka-player.ui.map +3 -3
- package/lib/cast/cast_proxy.js +2 -1
- package/lib/cast/cast_receiver.js +19 -5
- package/lib/cast/cast_sender.js +2 -1
- package/lib/cast/cast_utils.js +16 -6
- package/lib/hls/hls_parser.js +1 -0
- package/lib/media/playhead.js +23 -1
- package/lib/media/streaming_engine.js +3 -12
- package/lib/player.js +24 -11
- package/lib/util/manifest_parser_utils.js +4 -0
- package/package.json +1 -1
- package/test/cast/cast_receiver_integration.js +97 -16
- package/test/cast/cast_receiver_unit.js +17 -12
- package/test/cast/cast_utils_unit.js +1 -0
- package/test/media/playhead_unit.js +41 -0
- package/test/media/streaming_engine_integration.js +13 -0
- package/test/media/streaming_engine_unit.js +23 -8
- package/test/player_unit.js +87 -0
- package/test/test/util/simple_fakes.js +3 -0
- package/ui/controls.js +4 -1
|
@@ -171,6 +171,8 @@ describe('Playhead', () => {
|
|
|
171
171
|
Util.spyFunc(onSeek),
|
|
172
172
|
Util.spyFunc(onEvent));
|
|
173
173
|
|
|
174
|
+
playhead.ready();
|
|
175
|
+
|
|
174
176
|
expect(video.currentTime).toBe(5);
|
|
175
177
|
expect(playhead.getTime()).toBe(5);
|
|
176
178
|
|
|
@@ -192,6 +194,8 @@ describe('Playhead', () => {
|
|
|
192
194
|
Util.spyFunc(onSeek),
|
|
193
195
|
Util.spyFunc(onEvent));
|
|
194
196
|
|
|
197
|
+
playhead.ready();
|
|
198
|
+
|
|
195
199
|
expect(video.addEventListener).toHaveBeenCalledWith(
|
|
196
200
|
'loadedmetadata', jasmine.any(Function), jasmine.anything());
|
|
197
201
|
expect(video.addEventListener).not.toHaveBeenCalledWith(
|
|
@@ -233,6 +237,8 @@ describe('Playhead', () => {
|
|
|
233
237
|
Util.spyFunc(onSeek),
|
|
234
238
|
Util.spyFunc(onEvent));
|
|
235
239
|
|
|
240
|
+
playhead.ready();
|
|
241
|
+
|
|
236
242
|
video.on['seeking']();
|
|
237
243
|
expect(playhead.getTime()).toBe(5);
|
|
238
244
|
expect(video.currentTime).toBe(5);
|
|
@@ -266,6 +272,8 @@ describe('Playhead', () => {
|
|
|
266
272
|
video, manifest, config, /* startTime= */ 60, Util.spyFunc(onSeek),
|
|
267
273
|
Util.spyFunc(onEvent));
|
|
268
274
|
|
|
275
|
+
playhead.ready();
|
|
276
|
+
|
|
269
277
|
expect(playhead.getTime()).toBe(59); // duration - durationBackoff
|
|
270
278
|
expect(video.currentTime).toBe(59); // duration - durationBackoff
|
|
271
279
|
});
|
|
@@ -296,6 +304,8 @@ describe('Playhead', () => {
|
|
|
296
304
|
video, manifest, config, /* startTime= */ -40, Util.spyFunc(onSeek),
|
|
297
305
|
Util.spyFunc(onEvent));
|
|
298
306
|
|
|
307
|
+
playhead.ready();
|
|
308
|
+
|
|
299
309
|
expect(playhead.getTime()).toBe(30);
|
|
300
310
|
});
|
|
301
311
|
|
|
@@ -308,6 +318,8 @@ describe('Playhead', () => {
|
|
|
308
318
|
Util.spyFunc(onSeek),
|
|
309
319
|
Util.spyFunc(onEvent));
|
|
310
320
|
|
|
321
|
+
playhead.ready();
|
|
322
|
+
|
|
311
323
|
expect(video.addEventListener).toHaveBeenCalledWith(
|
|
312
324
|
'loadedmetadata', jasmine.any(Function), jasmine.anything());
|
|
313
325
|
|
|
@@ -341,6 +353,8 @@ describe('Playhead', () => {
|
|
|
341
353
|
Util.spyFunc(onSeek),
|
|
342
354
|
Util.spyFunc(onEvent));
|
|
343
355
|
|
|
356
|
+
playhead.ready();
|
|
357
|
+
|
|
344
358
|
expect(video.addEventListener).toHaveBeenCalledWith(
|
|
345
359
|
'loadedmetadata', jasmine.any(Function), jasmine.anything());
|
|
346
360
|
|
|
@@ -374,6 +388,8 @@ describe('Playhead', () => {
|
|
|
374
388
|
Util.spyFunc(onSeek),
|
|
375
389
|
Util.spyFunc(onEvent));
|
|
376
390
|
|
|
391
|
+
playhead.ready();
|
|
392
|
+
|
|
377
393
|
// This has to periodically increment the mock date to allow the onSeeking_
|
|
378
394
|
// handler to seek, if appropriate.
|
|
379
395
|
|
|
@@ -646,6 +662,8 @@ describe('Playhead', () => {
|
|
|
646
662
|
expect(currentTime).toBe(1000);
|
|
647
663
|
seekCount = 0;
|
|
648
664
|
|
|
665
|
+
playhead.ready();
|
|
666
|
+
|
|
649
667
|
// The availability window slips ahead.
|
|
650
668
|
timeline.getSeekRangeStart.and.returnValue(1030);
|
|
651
669
|
timeline.getSeekRangeEnd.and.returnValue(1030);
|
|
@@ -690,6 +708,8 @@ describe('Playhead', () => {
|
|
|
690
708
|
Util.spyFunc(onSeek),
|
|
691
709
|
Util.spyFunc(onEvent));
|
|
692
710
|
|
|
711
|
+
playhead.ready();
|
|
712
|
+
|
|
693
713
|
video.on['seeking']();
|
|
694
714
|
expect(video.currentTime).toBe(5);
|
|
695
715
|
expect(playhead.getTime()).toBe(5);
|
|
@@ -722,6 +742,8 @@ describe('Playhead', () => {
|
|
|
722
742
|
Util.spyFunc(onSeek),
|
|
723
743
|
Util.spyFunc(onEvent));
|
|
724
744
|
|
|
745
|
+
playhead.ready();
|
|
746
|
+
|
|
725
747
|
video.on['seeking']();
|
|
726
748
|
expect(video.currentTime).toBe(5);
|
|
727
749
|
expect(playhead.getTime()).toBe(5);
|
|
@@ -759,6 +781,9 @@ describe('Playhead', () => {
|
|
|
759
781
|
|
|
760
782
|
video.currentTime = 0;
|
|
761
783
|
video.seeking = true;
|
|
784
|
+
|
|
785
|
+
playhead.ready();
|
|
786
|
+
|
|
762
787
|
// "video.seeking" stays true until the buffered range intersects with
|
|
763
788
|
// "video.currentTime". Playhead should correct anyway.
|
|
764
789
|
video.on['seeking']();
|
|
@@ -803,6 +828,8 @@ describe('Playhead', () => {
|
|
|
803
828
|
Util.spyFunc(onSeek),
|
|
804
829
|
Util.spyFunc(onEvent));
|
|
805
830
|
|
|
831
|
+
playhead.ready();
|
|
832
|
+
|
|
806
833
|
/**
|
|
807
834
|
* Prevent retries on the initial start time seek. This will ensure that
|
|
808
835
|
* only one call is made for the initial seek, and that any additional calls
|
|
@@ -955,6 +982,8 @@ describe('Playhead', () => {
|
|
|
955
982
|
Util.spyFunc(onSeek),
|
|
956
983
|
Util.spyFunc(onEvent));
|
|
957
984
|
|
|
985
|
+
playhead.ready();
|
|
986
|
+
|
|
958
987
|
jasmine.clock().tick(500);
|
|
959
988
|
for (let time = data.start; time < data.waitingAt; time++) {
|
|
960
989
|
// We don't want to run tick() for 1 second because it will trigger
|
|
@@ -1208,6 +1237,8 @@ describe('Playhead', () => {
|
|
|
1208
1237
|
Util.spyFunc(onSeek),
|
|
1209
1238
|
Util.spyFunc(onEvent));
|
|
1210
1239
|
|
|
1240
|
+
playhead.ready();
|
|
1241
|
+
|
|
1211
1242
|
jasmine.clock().tick(500);
|
|
1212
1243
|
expect(onEvent).not.toHaveBeenCalled();
|
|
1213
1244
|
|
|
@@ -1257,6 +1288,8 @@ describe('Playhead', () => {
|
|
|
1257
1288
|
Util.spyFunc(onSeek),
|
|
1258
1289
|
Util.spyFunc(onEvent));
|
|
1259
1290
|
|
|
1291
|
+
playhead.ready();
|
|
1292
|
+
|
|
1260
1293
|
playhead.notifyOfBufferingChange();
|
|
1261
1294
|
jasmine.clock().tick(500);
|
|
1262
1295
|
|
|
@@ -1280,6 +1313,8 @@ describe('Playhead', () => {
|
|
|
1280
1313
|
Util.spyFunc(onSeek),
|
|
1281
1314
|
Util.spyFunc(onEvent));
|
|
1282
1315
|
|
|
1316
|
+
playhead.ready();
|
|
1317
|
+
|
|
1283
1318
|
playhead.notifyOfBufferingChange();
|
|
1284
1319
|
jasmine.clock().tick(500);
|
|
1285
1320
|
|
|
@@ -1305,6 +1340,8 @@ describe('Playhead', () => {
|
|
|
1305
1340
|
Util.spyFunc(onSeek),
|
|
1306
1341
|
Util.spyFunc(onEvent));
|
|
1307
1342
|
|
|
1343
|
+
playhead.ready();
|
|
1344
|
+
|
|
1308
1345
|
playhead.notifyOfBufferingChange();
|
|
1309
1346
|
jasmine.clock().tick(500);
|
|
1310
1347
|
|
|
@@ -1330,6 +1367,8 @@ describe('Playhead', () => {
|
|
|
1330
1367
|
Util.spyFunc(onSeek),
|
|
1331
1368
|
Util.spyFunc(onEvent));
|
|
1332
1369
|
|
|
1370
|
+
playhead.ready();
|
|
1371
|
+
|
|
1333
1372
|
playhead.notifyOfBufferingChange();
|
|
1334
1373
|
jasmine.clock().tick(500);
|
|
1335
1374
|
|
|
@@ -1362,6 +1401,8 @@ describe('Playhead', () => {
|
|
|
1362
1401
|
Util.spyFunc(onSeek),
|
|
1363
1402
|
Util.spyFunc(onEvent));
|
|
1364
1403
|
|
|
1404
|
+
playhead.ready();
|
|
1405
|
+
|
|
1365
1406
|
jasmine.clock().tick(500);
|
|
1366
1407
|
expect(onEvent).not.toHaveBeenCalled();
|
|
1367
1408
|
|
|
@@ -155,6 +155,19 @@ describe('StreamingEngine', () => {
|
|
|
155
155
|
/* presentationDuration= */ Infinity);
|
|
156
156
|
setupPlayhead();
|
|
157
157
|
|
|
158
|
+
// Retry on failure for live streams.
|
|
159
|
+
config.failureCallback = () => streamingEngine.retry(0.1);
|
|
160
|
+
|
|
161
|
+
// Ignore 404 errors in live stream tests.
|
|
162
|
+
onError.and.callFake((error) => {
|
|
163
|
+
if (error.code == shaka.util.Error.Code.BAD_HTTP_STATUS &&
|
|
164
|
+
error.data[1] == 404) {
|
|
165
|
+
// 404 error
|
|
166
|
+
} else {
|
|
167
|
+
fail(error);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
158
171
|
createStreamingEngine();
|
|
159
172
|
}
|
|
160
173
|
|
|
@@ -855,7 +855,7 @@ describe('StreamingEngine', () => {
|
|
|
855
855
|
|
|
856
856
|
const config = shaka.util.PlayerConfiguration.createDefault().streaming;
|
|
857
857
|
config.bufferingGoal = 60;
|
|
858
|
-
config.failureCallback = () => streamingEngine.retry();
|
|
858
|
+
config.failureCallback = () => streamingEngine.retry(0.1);
|
|
859
859
|
createStreamingEngine(config);
|
|
860
860
|
|
|
861
861
|
// Make requests for different types take different amounts of time.
|
|
@@ -1714,8 +1714,23 @@ describe('StreamingEngine', () => {
|
|
|
1714
1714
|
beforeEach(() => {
|
|
1715
1715
|
setupLive();
|
|
1716
1716
|
mediaSourceEngine = new shaka.test.FakeMediaSourceEngine(segmentData, 0);
|
|
1717
|
-
|
|
1717
|
+
|
|
1718
|
+
// Retry on failure for live streams.
|
|
1719
|
+
const config = shaka.util.PlayerConfiguration.createDefault().streaming;
|
|
1720
|
+
config.failureCallback = () => streamingEngine.retry(0.1);
|
|
1721
|
+
|
|
1722
|
+
createStreamingEngine(config);
|
|
1718
1723
|
presentationTimeInSeconds = 100;
|
|
1724
|
+
|
|
1725
|
+
// Ignore 404 errors in live stream tests.
|
|
1726
|
+
onError.and.callFake((error) => {
|
|
1727
|
+
if (error.code == shaka.util.Error.Code.BAD_HTTP_STATUS &&
|
|
1728
|
+
error.data[1] == 404) {
|
|
1729
|
+
// 404 error
|
|
1730
|
+
} else {
|
|
1731
|
+
fail(error);
|
|
1732
|
+
}
|
|
1733
|
+
});
|
|
1719
1734
|
});
|
|
1720
1735
|
|
|
1721
1736
|
it('outside segment availability window', async () => {
|
|
@@ -1751,9 +1766,9 @@ describe('StreamingEngine', () => {
|
|
|
1751
1766
|
if (startTime >= 100) {
|
|
1752
1767
|
// Ignore a possible call for the first Period.
|
|
1753
1768
|
expect(Util.invokeSpy(timeline.getSegmentAvailabilityStart))
|
|
1754
|
-
.
|
|
1769
|
+
.not.toBeLessThan(100);
|
|
1755
1770
|
expect(Util.invokeSpy(timeline.getSegmentAvailabilityEnd))
|
|
1756
|
-
.
|
|
1771
|
+
.not.toBeLessThan(120);
|
|
1757
1772
|
playing = true;
|
|
1758
1773
|
mediaSourceEngine.appendBuffer.and.callFake(
|
|
1759
1774
|
originalAppendBuffer);
|
|
@@ -1978,7 +1993,7 @@ describe('StreamingEngine', () => {
|
|
|
1978
1993
|
mediaSourceEngine = new shaka.test.FakeMediaSourceEngine(segmentData);
|
|
1979
1994
|
|
|
1980
1995
|
const config = shaka.util.PlayerConfiguration.createDefault().streaming;
|
|
1981
|
-
config.failureCallback = () => streamingEngine.retry();
|
|
1996
|
+
config.failureCallback = () => streamingEngine.retry(0.1);
|
|
1982
1997
|
createStreamingEngine(config);
|
|
1983
1998
|
|
|
1984
1999
|
presentationTimeInSeconds = 100;
|
|
@@ -2139,7 +2154,7 @@ describe('StreamingEngine', () => {
|
|
|
2139
2154
|
netEngine.request.calls.reset();
|
|
2140
2155
|
|
|
2141
2156
|
// Retry streaming.
|
|
2142
|
-
expect(streamingEngine.retry()).toBe(true);
|
|
2157
|
+
expect(streamingEngine.retry(0.1)).toBe(true);
|
|
2143
2158
|
});
|
|
2144
2159
|
|
|
2145
2160
|
// Here we go!
|
|
@@ -2169,7 +2184,7 @@ describe('StreamingEngine', () => {
|
|
|
2169
2184
|
|
|
2170
2185
|
// Retry streaming, which should fail and return false.
|
|
2171
2186
|
netEngine.request.calls.reset();
|
|
2172
|
-
expect(streamingEngine.retry()).toBe(false);
|
|
2187
|
+
expect(streamingEngine.retry(0.1)).toBe(false);
|
|
2173
2188
|
});
|
|
2174
2189
|
|
|
2175
2190
|
// Here we go!
|
|
@@ -2221,7 +2236,7 @@ describe('StreamingEngine', () => {
|
|
|
2221
2236
|
|
|
2222
2237
|
// Retry streaming, which should fail and return false.
|
|
2223
2238
|
netEngine.request.calls.reset();
|
|
2224
|
-
expect(streamingEngine.retry()).toBe(false);
|
|
2239
|
+
expect(streamingEngine.retry(0.1)).toBe(false);
|
|
2225
2240
|
}
|
|
2226
2241
|
});
|
|
2227
2242
|
|
package/test/player_unit.js
CHANGED
|
@@ -3735,6 +3735,93 @@ describe('Player', () => {
|
|
|
3735
3735
|
});
|
|
3736
3736
|
});
|
|
3737
3737
|
|
|
3738
|
+
describe('config streaming.failureCallback default', () => {
|
|
3739
|
+
/** @type {jasmine.Spy} */
|
|
3740
|
+
let retryStreaming;
|
|
3741
|
+
/** @type {jasmine.Spy} */
|
|
3742
|
+
let isLive;
|
|
3743
|
+
|
|
3744
|
+
/**
|
|
3745
|
+
* @suppress {accessControls}
|
|
3746
|
+
* @param {!shaka.util.Error} error
|
|
3747
|
+
*/
|
|
3748
|
+
function defaultStreamingFailureCallback(error) {
|
|
3749
|
+
player.defaultStreamingFailureCallback_(error);
|
|
3750
|
+
}
|
|
3751
|
+
|
|
3752
|
+
beforeEach(() => {
|
|
3753
|
+
retryStreaming = jasmine.createSpy('retryStreaming');
|
|
3754
|
+
isLive = jasmine.createSpy('isLive');
|
|
3755
|
+
|
|
3756
|
+
player.retryStreaming = Util.spyFunc(retryStreaming);
|
|
3757
|
+
player.isLive = Util.spyFunc(isLive);
|
|
3758
|
+
});
|
|
3759
|
+
|
|
3760
|
+
it('ignores VOD failures', () => {
|
|
3761
|
+
isLive.and.returnValue(false);
|
|
3762
|
+
|
|
3763
|
+
const error = new shaka.util.Error(
|
|
3764
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
3765
|
+
shaka.util.Error.Category.NETWORK,
|
|
3766
|
+
shaka.util.Error.Code.BAD_HTTP_STATUS,
|
|
3767
|
+
/* url= */ '',
|
|
3768
|
+
/* http_status= */ 404);
|
|
3769
|
+
|
|
3770
|
+
defaultStreamingFailureCallback(error);
|
|
3771
|
+
expect(retryStreaming).not.toHaveBeenCalled();
|
|
3772
|
+
});
|
|
3773
|
+
|
|
3774
|
+
it('retries live on HTTP 404', () => {
|
|
3775
|
+
isLive.and.returnValue(true);
|
|
3776
|
+
|
|
3777
|
+
const error = new shaka.util.Error(
|
|
3778
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
3779
|
+
shaka.util.Error.Category.NETWORK,
|
|
3780
|
+
shaka.util.Error.Code.BAD_HTTP_STATUS,
|
|
3781
|
+
/* url= */ '',
|
|
3782
|
+
/* http_status= */ 404);
|
|
3783
|
+
|
|
3784
|
+
defaultStreamingFailureCallback(error);
|
|
3785
|
+
expect(retryStreaming).toHaveBeenCalled();
|
|
3786
|
+
});
|
|
3787
|
+
|
|
3788
|
+
it('retries live on generic HTTP error', () => {
|
|
3789
|
+
isLive.and.returnValue(true);
|
|
3790
|
+
|
|
3791
|
+
const error = new shaka.util.Error(
|
|
3792
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
3793
|
+
shaka.util.Error.Category.NETWORK,
|
|
3794
|
+
shaka.util.Error.Code.HTTP_ERROR);
|
|
3795
|
+
|
|
3796
|
+
defaultStreamingFailureCallback(error);
|
|
3797
|
+
expect(retryStreaming).toHaveBeenCalled();
|
|
3798
|
+
});
|
|
3799
|
+
|
|
3800
|
+
it('retries live on HTTP timeout', () => {
|
|
3801
|
+
isLive.and.returnValue(true);
|
|
3802
|
+
|
|
3803
|
+
const error = new shaka.util.Error(
|
|
3804
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
3805
|
+
shaka.util.Error.Category.NETWORK,
|
|
3806
|
+
shaka.util.Error.Code.TIMEOUT);
|
|
3807
|
+
|
|
3808
|
+
defaultStreamingFailureCallback(error);
|
|
3809
|
+
expect(retryStreaming).toHaveBeenCalled();
|
|
3810
|
+
});
|
|
3811
|
+
|
|
3812
|
+
it('ignores other live failures', () => {
|
|
3813
|
+
isLive.and.returnValue(true);
|
|
3814
|
+
|
|
3815
|
+
const error = new shaka.util.Error(
|
|
3816
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
3817
|
+
shaka.util.Error.Category.MEDIA,
|
|
3818
|
+
shaka.util.Error.Code.VIDEO_ERROR);
|
|
3819
|
+
|
|
3820
|
+
defaultStreamingFailureCallback(error);
|
|
3821
|
+
expect(retryStreaming).not.toHaveBeenCalled();
|
|
3822
|
+
});
|
|
3823
|
+
});
|
|
3824
|
+
|
|
3738
3825
|
/**
|
|
3739
3826
|
* Gets the currently active variant track.
|
|
3740
3827
|
* @return {shaka.extern.Track}
|
|
@@ -333,6 +333,9 @@ shaka.test.FakePlayhead = class {
|
|
|
333
333
|
/** @private {number} */
|
|
334
334
|
this.startTime_ = 0;
|
|
335
335
|
|
|
336
|
+
/** @type {!jasmine.Spy} */
|
|
337
|
+
this.ready = jasmine.createSpy('ready');
|
|
338
|
+
|
|
336
339
|
/** @type {!jasmine.Spy} */
|
|
337
340
|
this.setStartTime = jasmine.createSpy('setStartTime')
|
|
338
341
|
.and.callFake((value) => {
|
package/ui/controls.js
CHANGED
|
@@ -970,7 +970,10 @@ shaka.ui.Controls = class extends shaka.util.FakeEventTarget {
|
|
|
970
970
|
if (!this.video_ ||
|
|
971
971
|
this.video_.readyState == 0 ||
|
|
972
972
|
this.castProxy_.isCasting() ||
|
|
973
|
-
!this.config_.enableFullscreenOnRotation
|
|
973
|
+
!this.config_.enableFullscreenOnRotation ||
|
|
974
|
+
!document.fullscreenEnabled) {
|
|
975
|
+
return;
|
|
976
|
+
}
|
|
974
977
|
|
|
975
978
|
if (screen.orientation.type.includes('landscape') &&
|
|
976
979
|
!document.fullscreenElement) {
|