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.
Files changed (38) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/deps.js +1 -1
  3. package/dist/locales.js +27 -27
  4. package/dist/shaka-player.compiled.d.ts +1 -1
  5. package/dist/shaka-player.compiled.debug.d.ts +1 -1
  6. package/dist/shaka-player.compiled.debug.externs.js +2 -1
  7. package/dist/shaka-player.compiled.debug.js +74 -73
  8. package/dist/shaka-player.compiled.debug.map +3 -3
  9. package/dist/shaka-player.compiled.externs.js +2 -1
  10. package/dist/shaka-player.compiled.js +542 -540
  11. package/dist/shaka-player.compiled.map +3 -3
  12. package/dist/shaka-player.ui.d.ts +1 -1
  13. package/dist/shaka-player.ui.debug.d.ts +1 -1
  14. package/dist/shaka-player.ui.debug.externs.js +2 -1
  15. package/dist/shaka-player.ui.debug.js +91 -90
  16. package/dist/shaka-player.ui.debug.map +3 -3
  17. package/dist/shaka-player.ui.externs.js +2 -1
  18. package/dist/shaka-player.ui.js +657 -655
  19. package/dist/shaka-player.ui.map +3 -3
  20. package/lib/cast/cast_proxy.js +2 -1
  21. package/lib/cast/cast_receiver.js +19 -5
  22. package/lib/cast/cast_sender.js +2 -1
  23. package/lib/cast/cast_utils.js +16 -6
  24. package/lib/hls/hls_parser.js +1 -0
  25. package/lib/media/playhead.js +23 -1
  26. package/lib/media/streaming_engine.js +3 -12
  27. package/lib/player.js +24 -11
  28. package/lib/util/manifest_parser_utils.js +4 -0
  29. package/package.json +1 -1
  30. package/test/cast/cast_receiver_integration.js +97 -16
  31. package/test/cast/cast_receiver_unit.js +17 -12
  32. package/test/cast/cast_utils_unit.js +1 -0
  33. package/test/media/playhead_unit.js +41 -0
  34. package/test/media/streaming_engine_integration.js +13 -0
  35. package/test/media/streaming_engine_unit.js +23 -8
  36. package/test/player_unit.js +87 -0
  37. package/test/test/util/simple_fakes.js +3 -0
  38. 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
- createStreamingEngine();
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
- .toBe(100);
1769
+ .not.toBeLessThan(100);
1755
1770
  expect(Util.invokeSpy(timeline.getSegmentAvailabilityEnd))
1756
- .toBe(120);
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
 
@@ -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) { return; }
973
+ !this.config_.enableFullscreenOnRotation ||
974
+ !document.fullscreenEnabled) {
975
+ return;
976
+ }
974
977
 
975
978
  if (screen.orientation.type.includes('landscape') &&
976
979
  !document.fullscreenElement) {