shaka-player 3.3.5 → 4.0.2

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 (184) hide show
  1. package/.github/config.yml +1 -0
  2. package/.github/workflows/demo-version-index.yaml +8 -0
  3. package/.github/workflows/release-please.yaml +18 -2
  4. package/.github/workflows/sync-labels.yaml +33 -0
  5. package/.github/workflows/update-issues.yaml +29 -0
  6. package/.github/workflows/validate-pr-title.yaml +35 -0
  7. package/AUTHORS +1 -0
  8. package/CHANGELOG.md +215 -41
  9. package/CONTRIBUTORS +1 -0
  10. package/README.md +14 -11
  11. package/app-engine/demo-version-index/README.md +3 -3
  12. package/app-engine/demo-version-index/app.yaml +27 -1
  13. package/app-engine/demo-version-index/generate.py +164 -0
  14. package/app-engine/demo-version-index/main.py +4 -155
  15. package/app-engine/demo-version-index/requirements.txt +0 -1
  16. package/build/checkversion.py +1 -1
  17. package/build/compiler.py +1 -1
  18. package/build/misspellings.txt +1 -0
  19. package/build/shaka-lab.yaml +0 -2
  20. package/build/types/polyfill +0 -3
  21. package/demo/common/asset.js +17 -1
  22. package/demo/common/assets.js +29 -0
  23. package/demo/common/message_ids.js +6 -3
  24. package/demo/config.js +10 -11
  25. package/demo/custom.js +39 -0
  26. package/demo/demo.less +0 -1
  27. package/demo/demo_utils.js +0 -1
  28. package/demo/locales/en.json +6 -3
  29. package/demo/locales/source.json +22 -10
  30. package/demo/main.js +9 -6
  31. package/demo/search.js +2 -1
  32. package/dist/controls.css +3 -3
  33. package/dist/controls.css.map +1 -1
  34. package/dist/demo.compiled.debug.js +71 -64
  35. package/dist/demo.compiled.debug.map +3 -3
  36. package/dist/demo.compiled.js +71 -64
  37. package/dist/demo.compiled.map +3 -3
  38. package/dist/demo.css +1 -1
  39. package/dist/demo.css.map +1 -1
  40. package/dist/deps.js +17 -20
  41. package/dist/locales.js +33 -31
  42. package/dist/receiver.compiled.debug.js +32 -28
  43. package/dist/receiver.compiled.debug.map +3 -3
  44. package/dist/receiver.compiled.js +32 -28
  45. package/dist/receiver.compiled.map +3 -3
  46. package/dist/shaka-player.compiled.d.ts +311 -314
  47. package/dist/shaka-player.compiled.debug.d.ts +311 -314
  48. package/dist/shaka-player.compiled.debug.externs.js +126 -126
  49. package/dist/shaka-player.compiled.debug.js +430 -484
  50. package/dist/shaka-player.compiled.debug.map +4 -4
  51. package/dist/shaka-player.compiled.externs.js +126 -126
  52. package/dist/shaka-player.compiled.js +829 -845
  53. package/dist/shaka-player.compiled.map +4 -4
  54. package/dist/shaka-player.ui.d.ts +357 -358
  55. package/dist/shaka-player.ui.debug.d.ts +357 -358
  56. package/dist/shaka-player.ui.debug.externs.js +134 -126
  57. package/dist/shaka-player.ui.debug.js +489 -541
  58. package/dist/shaka-player.ui.debug.map +4 -4
  59. package/dist/shaka-player.ui.externs.js +134 -126
  60. package/dist/shaka-player.ui.js +988 -1000
  61. package/dist/shaka-player.ui.map +4 -4
  62. package/docs/tutorials/config.md +0 -2
  63. package/docs/tutorials/drm-config.md +5 -0
  64. package/docs/tutorials/fairplay.md +7 -22
  65. package/docs/tutorials/faq.md +0 -11
  66. package/docs/tutorials/index.json +2 -8
  67. package/docs/tutorials/plugins.md +1 -3
  68. package/docs/tutorials/upgrade.md +85 -11
  69. package/externs/polyfill.js +15 -0
  70. package/externs/shaka/manifest.js +5 -1
  71. package/externs/shaka/net.js +12 -0
  72. package/externs/shaka/offline.js +5 -1
  73. package/externs/shaka/player.js +39 -21
  74. package/externs/shaka/text.js +12 -12
  75. package/externs/sourcebuffer.js +15 -0
  76. package/lib/abr/simple_abr_manager.js +2 -1
  77. package/lib/ads/client_side_ad.js +13 -2
  78. package/lib/ads/client_side_ad_manager.js +22 -4
  79. package/lib/cast/cast_utils.js +0 -1
  80. package/lib/dash/content_protection.js +85 -5
  81. package/lib/dash/dash_parser.js +1 -0
  82. package/lib/hls/hls_parser.js +390 -747
  83. package/lib/hls/manifest_text_parser.js +2 -3
  84. package/lib/media/drm_engine.js +105 -37
  85. package/lib/media/gap_jumping_controller.js +10 -45
  86. package/lib/media/media_source_engine.js +150 -30
  87. package/lib/media/playhead.js +2 -5
  88. package/lib/media/presentation_timeline.js +1 -2
  89. package/lib/media/segment_index.js +13 -46
  90. package/lib/media/segment_reference.js +47 -1
  91. package/lib/media/streaming_engine.js +28 -11
  92. package/lib/media/time_ranges_utils.js +4 -9
  93. package/lib/net/networking_engine.js +3 -0
  94. package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
  95. package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
  96. package/lib/offline/manifest_converter.js +1 -0
  97. package/lib/offline/storage.js +8 -41
  98. package/lib/player.js +17 -201
  99. package/lib/polyfill/media_capabilities.js +12 -6
  100. package/lib/polyfill/mediasource.js +0 -28
  101. package/lib/polyfill/patchedmediakeys_nop.js +2 -0
  102. package/lib/polyfill/patchedmediakeys_webkit.js +2 -0
  103. package/lib/text/cue.js +0 -6
  104. package/lib/text/lrc_text_parser.js +8 -0
  105. package/lib/text/mp4_ttml_parser.js +8 -0
  106. package/lib/text/mp4_vtt_parser.js +8 -0
  107. package/lib/text/sbv_text_parser.js +8 -0
  108. package/lib/text/simple_text_displayer.js +1 -7
  109. package/lib/text/srt_text_parser.js +8 -0
  110. package/lib/text/ssa_text_parser.js +8 -0
  111. package/lib/text/text_engine.js +19 -3
  112. package/lib/text/ttml_text_parser.js +8 -0
  113. package/lib/text/ui_text_displayer.js +1 -7
  114. package/lib/text/vtt_text_parser.js +27 -5
  115. package/lib/text/web_vtt_generator.js +1 -7
  116. package/lib/util/error.js +9 -13
  117. package/lib/util/fairplay_utils.js +109 -0
  118. package/lib/util/functional.js +0 -42
  119. package/lib/util/mime_utils.js +16 -5
  120. package/lib/util/platform.js +45 -0
  121. package/lib/util/player_configuration.js +17 -6
  122. package/lib/util/pssh.js +23 -4
  123. package/lib/util/stream_utils.js +92 -22
  124. package/lib/util/uint8array_utils.js +0 -16
  125. package/lib/util/xml_utils.js +1 -1
  126. package/package.json +5 -2
  127. package/roadmap.md +19 -19
  128. package/shaka-player.uncompiled.js +0 -3
  129. package/test/dash/dash_parser_content_protection_unit.js +44 -0
  130. package/test/dash/dash_parser_segment_template_unit.js +3 -4
  131. package/test/demo/demo_unit.js +2 -1
  132. package/test/hls/hls_live_unit.js +155 -230
  133. package/test/hls/hls_parser_unit.js +515 -432
  134. package/test/media/drm_engine_unit.js +86 -120
  135. package/test/media/media_source_engine_integration.js +25 -3
  136. package/test/media/media_source_engine_unit.js +3 -2
  137. package/test/media/playhead_unit.js +27 -191
  138. package/test/media/segment_index_unit.js +15 -25
  139. package/test/media/streaming_engine_integration.js +2 -39
  140. package/test/media/streaming_engine_unit.js +3 -2
  141. package/test/media/time_ranges_utils_unit.js +0 -5
  142. package/test/offline/manifest_convert_unit.js +34 -4
  143. package/test/offline/offline_manifest_parser_unit.js +1 -0
  144. package/test/offline/storage_integration.js +5 -4
  145. package/test/player_external.js +0 -6
  146. package/test/player_integration.js +16 -0
  147. package/test/player_unit.js +26 -0
  148. package/test/test/util/fake_media_source_engine.js +11 -4
  149. package/test/test/util/manifest_generator.js +3 -1
  150. package/test/test/util/manifest_parser_util.js +4 -1
  151. package/test/test/util/offline_utils.js +1 -0
  152. package/test/test/util/streaming_engine_util.js +1 -0
  153. package/test/test/util/test_scheme.js +24 -1
  154. package/test/test/util/util.js +4 -4
  155. package/test/text/cue_integration.js +2 -2
  156. package/test/text/lrc_text_parser_unit.js +6 -7
  157. package/test/text/mp4_ttml_parser_unit.js +6 -4
  158. package/test/text/mp4_vtt_parser_unit.js +6 -5
  159. package/test/text/sbv_text_parser_unit.js +5 -6
  160. package/test/text/srt_text_parser_unit.js +5 -6
  161. package/test/text/ssa_text_parser_unit.js +17 -29
  162. package/test/text/text_engine_unit.js +45 -5
  163. package/test/text/ttml_text_parser_unit.js +77 -77
  164. package/test/text/vtt_text_parser_unit.js +116 -59
  165. package/test/ui/ui_integration.js +0 -16
  166. package/test/ui/ui_unit.js +27 -0
  167. package/test/util/cmcd_manager_unit.js +3 -0
  168. package/test/util/stream_utils_unit.js +23 -7
  169. package/ui/controls.js +65 -40
  170. package/ui/fullscreen_button.js +26 -6
  171. package/ui/less/containers.less +4 -4
  172. package/ui/less/general.less +1 -1
  173. package/ui/less/range_elements.less +1 -0
  174. package/ui/locales/en.json +1 -0
  175. package/ui/locales/source.json +5 -0
  176. package/ui/resolution_selection.js +31 -33
  177. package/ui/ui.js +0 -17
  178. package/.github/pull_request_template.md +0 -10
  179. package/docs/tutorials/upgrade-v2-5.md +0 -441
  180. package/docs/tutorials/upgrade-v3.md +0 -38
  181. package/lib/polyfill/mathround.js +0 -49
  182. package/lib/polyfill/patchedmediakeys_apple.js +0 -744
  183. package/lib/polyfill/patchedmediakeys_ms.js +0 -698
  184. package/test/util/functional_unit.js +0 -82
@@ -693,22 +693,6 @@ describe('SegmentIndex', /** @suppress {accessControls} */ () => {
693
693
  expect(iterator.current()).toBe(null);
694
694
  });
695
695
 
696
- describe('seek', () => {
697
- it('returns the matching segment', () => {
698
- const index = new shaka.media.SegmentIndex(inputRefs);
699
- const iterator = index[Symbol.iterator]();
700
- expect(iterator.seek(10)).toBe(inputRefs[1]);
701
- expect(iterator.current()).toBe(inputRefs[1]);
702
- });
703
-
704
- it('returns the matching segment with partial segments', () => {
705
- const index = new shaka.media.SegmentIndex(inputRefsWithPartial);
706
- const iterator = index[Symbol.iterator]();
707
- expect(iterator.seek(8)).toBe(inputRefsWithPartial[0]);
708
- expect(iterator.seek(10)).toBe(partialRefs1[0]);
709
- });
710
- });
711
-
712
696
  describe('next', () => {
713
697
  it('starts with the first segment', () => {
714
698
  const index = new shaka.media.SegmentIndex(inputRefs);
@@ -725,20 +709,20 @@ describe('SegmentIndex', /** @suppress {accessControls} */ () => {
725
709
  expect(iterator.next().value).toBe(null);
726
710
  });
727
711
 
728
- it('iterates forward after a seek', () => {
712
+ it('iterates from getIteratorForTime', () => {
729
713
  const index = new shaka.media.SegmentIndex(inputRefs);
730
- const iterator = index[Symbol.iterator]();
731
- expect(iterator.seek(10)).toBe(inputRefs[1]);
714
+ const iterator = index.getIteratorForTime(10);
715
+ expect(iterator.next().value).toBe(inputRefs[1]);
732
716
  expect(iterator.current()).toBe(inputRefs[1]);
733
717
  expect(iterator.next().value).toBe(inputRefs[2]);
734
718
  expect(iterator.current()).toBe(inputRefs[2]);
735
719
  expect(iterator.next().value).toBe(null);
736
720
  });
737
721
 
738
- it('iterates forward after a seek with partial segments', () => {
722
+ it('iterates from getIteratorForTime with partial segments', () => {
739
723
  const index = new shaka.media.SegmentIndex(inputRefsWithPartial);
740
- const iterator = index[Symbol.iterator]();
741
- expect(iterator.seek(10)).toBe(partialRefs1[0]);
724
+ const iterator = index.getIteratorForTime(10);
725
+ expect(iterator.next().value).toBe(partialRefs1[0]);
742
726
  expect(iterator.current()).toBe(partialRefs1[0]);
743
727
  expect(iterator.next().value).toBe(partialRefs1[1]);
744
728
  expect(iterator.current()).toBe(partialRefs1[1]);
@@ -935,11 +919,17 @@ describe('SegmentIndex', /** @suppress {accessControls} */ () => {
935
919
  expect(Array.from(metaIndex)).toEqual(oldRefs);
936
920
 
937
921
  // Every 0.1 seconds, return the next new ref.
938
- index1.updateEvery(0.1, () => {
939
- return [newRefs.shift()];
922
+ const done = new Promise((resolve, reject) => {
923
+ index1.updateEvery(0.1, () => {
924
+ if (newRefs.length == 0) {
925
+ resolve();
926
+ }
927
+ return [newRefs.shift()];
928
+ });
940
929
  });
941
930
  // Wait long enough for all three new refs to be appended.
942
- await shaka.test.Util.delay(0.5);
931
+ // Or for all of the new refs to be passed out.
932
+ await Promise.race([shaka.test.Util.delay(1), done]);
943
933
 
944
934
  expect(Array.from(metaIndex)).toEqual(oldRefs.concat(inputRefs2));
945
935
  });
@@ -214,8 +214,7 @@ describe('StreamingEngine', () => {
214
214
  manifest,
215
215
  config,
216
216
  /* startTime= */ null,
217
- onSeek,
218
- shaka.test.Util.spyFunc(onEvent));
217
+ onSeek);
219
218
  }
220
219
 
221
220
  function setupManifest(
@@ -403,7 +402,6 @@ describe('StreamingEngine', () => {
403
402
  // TODO: Consider also adding tests for missing frames.
404
403
  describe('gap jumping', () => {
405
404
  it('jumps small gaps at the beginning', async () => {
406
- config.smallGapLimit = 5;
407
405
  await setupGappyContent(/* gapAtStart= */ 1, /* dropSegment= */ false);
408
406
 
409
407
  // Let's go!
@@ -419,8 +417,6 @@ describe('StreamingEngine', () => {
419
417
  });
420
418
 
421
419
  it('jumps large gaps at the beginning', async () => {
422
- config.smallGapLimit = 1;
423
- config.jumpLargeGaps = true;
424
420
  await setupGappyContent(/* gapAtStart= */ 5, /* dropSegment= */ false);
425
421
 
426
422
  // Let's go!
@@ -436,7 +432,6 @@ describe('StreamingEngine', () => {
436
432
  });
437
433
 
438
434
  it('jumps small gaps in the middle', async () => {
439
- config.smallGapLimit = 20;
440
435
  await setupGappyContent(/* gapAtStart= */ 0, /* dropSegment= */ true);
441
436
 
442
437
  // Let's go!
@@ -451,11 +446,9 @@ describe('StreamingEngine', () => {
451
446
  await waiter.timeoutAfter(60).waitUntilPlayheadReaches(video, 23);
452
447
  // Should be close enough to still have the gap buffered.
453
448
  expect(video.buffered.length).toBe(2);
454
- expect(onEvent).not.toHaveBeenCalled();
455
449
  });
456
450
 
457
451
  it('jumps large gaps in the middle', async () => {
458
- config.jumpLargeGaps = true;
459
452
  await setupGappyContent(/* gapAtStart= */ 0, /* dropSegment= */ true);
460
453
 
461
454
  // Let's go!
@@ -470,37 +463,6 @@ describe('StreamingEngine', () => {
470
463
  await waiter.timeoutAfter(60).waitUntilPlayheadReaches(video, 23);
471
464
  // Should be close enough to still have the gap buffered.
472
465
  expect(video.buffered.length).toBe(2);
473
- expect(onEvent).toHaveBeenCalled();
474
- });
475
-
476
- it('won\'t jump large gaps with preventDefault()', async () => {
477
- config.jumpLargeGaps = true;
478
- await setupGappyContent(/* gapAtStart= */ 0, /* dropSegment= */ true);
479
-
480
- onEvent.and.callFake((event) => {
481
- event.preventDefault();
482
- });
483
-
484
- // Let's go!
485
- streamingEngine.switchVariant(variant);
486
- await streamingEngine.start();
487
-
488
- await waiter.timeoutAfter(5).waitForEvent(video, 'loadeddata');
489
-
490
- let seekCount = 0;
491
- eventManager.listen(video, 'seeking', () => {
492
- seekCount++;
493
- });
494
-
495
- video.currentTime = 8;
496
- video.play();
497
-
498
- await shaka.test.Util.delay(5);
499
-
500
- // Edge somehow plays _into_ the gap, and Xbox One plays _through_ the
501
- // gap. Just make sure _we_ don't jump the gap by seeking. One seek is
502
- // required to start playback at time 8.
503
- expect(seekCount).toBe(1);
504
466
  });
505
467
 
506
468
  /**
@@ -610,6 +572,7 @@ describe('StreamingEngine', () => {
610
572
  minBufferTime: 2,
611
573
  textStreams: [],
612
574
  imageStreams: [],
575
+ sequenceMode: false,
613
576
  variants: [{
614
577
  id: 1,
615
578
  video: {
@@ -496,7 +496,8 @@ describe('StreamingEngine', () => {
496
496
  expectedMseInit.set(ContentType.VIDEO, videoStream);
497
497
  expectedMseInit.set(ContentType.TEXT, textStream);
498
498
 
499
- expect(mediaSourceEngine.init).toHaveBeenCalledWith(expectedMseInit, false);
499
+ expect(mediaSourceEngine.init).toHaveBeenCalledWith(expectedMseInit,
500
+ /** forceTransmuxTS= */ false, /** sequenceMode= */ false);
500
501
  expect(mediaSourceEngine.init).toHaveBeenCalledTimes(1);
501
502
 
502
503
  expect(mediaSourceEngine.setDuration).toHaveBeenCalledTimes(1);
@@ -801,7 +802,7 @@ describe('StreamingEngine', () => {
801
802
  asymmetricMatch: (val) => val > 40 && val <= 40.1,
802
803
  };
803
804
  expect(mediaSourceEngine.setStreamProperties)
804
- .toHaveBeenCalledWith('video', 0, lt20, gt40);
805
+ .toHaveBeenCalledWith('video', 0, lt20, gt40, false);
805
806
  });
806
807
 
807
808
  // Regression test for https://github.com/shaka-project/shaka-player/issues/3717
@@ -22,11 +22,6 @@ describe('TimeRangesUtils', () => {
22
22
  expect(TimeRangesUtils.isBuffered(b, 13)).toBe(true);
23
23
  });
24
24
 
25
- it('returns buffered when having a small gap', () => {
26
- const b = createFakeBuffered([{start: 10, end: 20}]);
27
- expect(TimeRangesUtils.isBuffered(b, 9, 1)).toBe(true);
28
- });
29
-
30
25
  // Ranges: [10-20], [30-40], [50-60]
31
26
  defineTest('returns false when before range', {time: 3, expected: false});
32
27
  defineTest('returns true inside first range', {time: 12, expected: true});
@@ -107,6 +107,7 @@ describe('ManifestConverter', () => {
107
107
  },
108
108
  appMetadata: null,
109
109
  creationTime: 0,
110
+ sequenceMode: false,
110
111
  };
111
112
 
112
113
  const manifest = createConverter().fromManifestDB(manifestDb);
@@ -143,6 +144,7 @@ describe('ManifestConverter', () => {
143
144
  createVideoStreamDB(1, [0]),
144
145
  createVideoStreamDB(2, [1]),
145
146
  ],
147
+ sequenceMode: false,
146
148
  };
147
149
 
148
150
  const manifest = createConverter().fromManifestDB(manifestDb);
@@ -170,6 +172,7 @@ describe('ManifestConverter', () => {
170
172
  createAudioStreamDB(1, [0]),
171
173
  createAudioStreamDB(2, [1]),
172
174
  ],
175
+ sequenceMode: false,
173
176
  };
174
177
 
175
178
  const manifest = createConverter().fromManifestDB(manifestDb);
@@ -182,6 +185,29 @@ describe('ManifestConverter', () => {
182
185
  expect(manifest.variants[1].video).toBe(null);
183
186
  });
184
187
 
188
+ it('supports containerless content', () => {
189
+ /** @type {shaka.extern.ManifestDB} */
190
+ const manifestDb = {
191
+ originalManifestUri: 'http://example.com/foo',
192
+ duration: 60,
193
+ size: 1234,
194
+ expiration: Infinity,
195
+ sessionIds: [],
196
+ drmInfo: null,
197
+ appMetadata: null,
198
+ creationTime: 0,
199
+ streams: [
200
+ createVideoStreamDB(1, [0]),
201
+ createAudioStreamDB(2, [0]),
202
+ ],
203
+ sequenceMode: true,
204
+ };
205
+
206
+ const manifest = createConverter().fromManifestDB(manifestDb);
207
+ expect(manifest.sequenceMode).toBe(true);
208
+ expect(manifest.variants.length).toBe(1);
209
+ });
210
+
185
211
  it('supports text streams', () => {
186
212
  /** @type {shaka.extern.ManifestDB} */
187
213
  const manifestDb = {
@@ -197,6 +223,7 @@ describe('ManifestConverter', () => {
197
223
  createVideoStreamDB(1, [0]),
198
224
  createTextStreamDB(2),
199
225
  ],
226
+ sequenceMode: false,
200
227
  };
201
228
 
202
229
  const manifest = createConverter().fromManifestDB(manifestDb);
@@ -235,6 +262,7 @@ describe('ManifestConverter', () => {
235
262
  createVideoStreamDB(video1, [variant1]),
236
263
  createVideoStreamDB(video2, [variant2, variant3]),
237
264
  ],
265
+ sequenceMode: false,
238
266
  };
239
267
 
240
268
  const manifest = createConverter().fromManifestDB(manifestDb);
@@ -509,8 +537,6 @@ describe('ManifestConverter', () => {
509
537
 
510
538
  // Assume that we don't have to call createSegmentIndex.
511
539
 
512
- const iterator = stream.segmentIndex[Symbol.iterator]();
513
-
514
540
  streamDb.segments.forEach((segmentDb, i) => {
515
541
  const uri = shaka.offline.OfflineUri.segment(
516
542
  'mechanism', 'cell', segmentDb.dataKey);
@@ -520,10 +546,14 @@ describe('ManifestConverter', () => {
520
546
  null;
521
547
 
522
548
  /** @type {shaka.media.SegmentReference} */
523
- const segment = iterator.seek(segmentDb.startTime);
549
+ const segment =
550
+ stream.segmentIndex
551
+ .getIteratorForTime(segmentDb.startTime).next().value;
524
552
 
525
553
  /** @type {shaka.media.SegmentReference} */
526
- const sameSegment = iterator.seek(segmentDb.endTime - 0.1);
554
+ const sameSegment =
555
+ stream.segmentIndex
556
+ .getIteratorForTime(segmentDb.endTime - 0.1).next().value;
527
557
 
528
558
  expect(segment).toBe(sameSegment);
529
559
  expect(segment.startTime).toBe(segmentDb.startTime);
@@ -210,6 +210,7 @@ filterDescribe('OfflineManifestParser', offlineManifestParserSupport, () => {
210
210
  sessionIds: [sessionId],
211
211
  drmInfo: null,
212
212
  appMetadata: {},
213
+ sequenceMode: false,
213
214
  };
214
215
 
215
216
  return manifest;
@@ -1110,10 +1110,7 @@ filterDescribe('Storage', storageSupport, () => {
1110
1110
  aRequestIsStarted.resolve();
1111
1111
  await promise;
1112
1112
 
1113
- // All downloads for a given stream are in the same "download group",
1114
- // and will be downloaded sequentially. Thus, we expect only the first
1115
- // download to be aborted.
1116
- expect(abortCheck()).toBe(i == 0 ? true : false);
1113
+ expect(abortCheck()).toBe(true);
1117
1114
 
1118
1115
  return new ArrayBuffer(16);
1119
1116
  });
@@ -1355,6 +1352,8 @@ filterDescribe('Storage', storageSupport, () => {
1355
1352
  pixelAspectRatio: '59:54',
1356
1353
  hdr: null,
1357
1354
  mimeType: 'video/mp4,audio/mp4',
1355
+ audioMimeType: 'audio/mp4',
1356
+ videoMimeType: 'video/mp4',
1358
1357
  codecs: 'mp4,mp4',
1359
1358
  audioCodec: 'mp4',
1360
1359
  videoCodec: 'mp4',
@@ -1397,6 +1396,8 @@ filterDescribe('Storage', storageSupport, () => {
1397
1396
  pixelAspectRatio: null,
1398
1397
  hdr: null,
1399
1398
  mimeType: 'text/vtt',
1399
+ audioMimeType: null,
1400
+ videoMimeType: null,
1400
1401
  codecs: 'vtt',
1401
1402
  audioCodec: null,
1402
1403
  videoCodec: null,
@@ -107,12 +107,6 @@ describe('Player', () => {
107
107
  player.configure('manifest.dash.clockSyncUri',
108
108
  'https://shaka-player-demo.appspot.com/time.txt');
109
109
 
110
- // Make sure we don't get stuck on gaps that only appear in some
111
- // browsers (Safari, Firefox).
112
- // TODO(https://github.com/shaka-project/shaka-player/issues/1702):
113
- // Is this necessary because of a bug in Shaka Player?
114
- player.configure('streaming.jumpLargeGaps', true);
115
-
116
110
  // Add asset-specific configuration.
117
111
  player.configure(asset.getConfiguration());
118
112
 
@@ -418,6 +418,22 @@ describe('Player', () => {
418
418
  expect(video.playbackRate).toBe(1);
419
419
  });
420
420
 
421
+ it('in sequence mode', async () => {
422
+ const testSchemeMimeType = 'application/x-test-manifest';
423
+ player = new compiledShaka.Player(video);
424
+ await player.load('test:sintel_sequence_compiled', 0, testSchemeMimeType);
425
+ expect(player.getManifest().sequenceMode).toBe(true);
426
+
427
+ // Ensure the video plays.
428
+ video.play();
429
+ await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 5, 10);
430
+
431
+ // Seek the video, and see if it can continue playing from that point.
432
+ video.currentTime = 20;
433
+ // Expect that we can then reach the end of the video.
434
+ await waiter.timeoutAfter(20).waitForEnd(video);
435
+ });
436
+
421
437
  // Regression test for #2326.
422
438
  //
423
439
  // 1. Construct an instance with a video element.
@@ -116,6 +116,8 @@ describe('Player', () => {
116
116
  jasmine.createSpy('destroy').and.returnValue(Promise.resolve()),
117
117
  setUseEmbeddedText: jasmine.createSpy('setUseEmbeddedText'),
118
118
  getUseEmbeddedText: jasmine.createSpy('getUseEmbeddedText'),
119
+ setSegmentRelativeVttTiming:
120
+ jasmine.createSpy('setSegmentRelativeVttTiming'),
119
121
  getTextDisplayer: () => textDisplayer,
120
122
  ended: jasmine.createSpy('ended').and.returnValue(false),
121
123
  };
@@ -1137,6 +1139,8 @@ describe('Player', () => {
1137
1139
  pixelAspectRatio: '59:54',
1138
1140
  hdr: null,
1139
1141
  mimeType: 'video/mp4',
1142
+ audioMimeType: 'audio/mp4',
1143
+ videoMimeType: 'video/mp4',
1140
1144
  codecs: 'avc1.4d401f, mp4a.40.2',
1141
1145
  audioCodec: 'mp4a.40.2',
1142
1146
  videoCodec: 'avc1.4d401f',
@@ -1171,6 +1175,8 @@ describe('Player', () => {
1171
1175
  pixelAspectRatio: '59:54',
1172
1176
  hdr: null,
1173
1177
  mimeType: 'video/mp4',
1178
+ audioMimeType: 'audio/mp4',
1179
+ videoMimeType: 'video/mp4',
1174
1180
  codecs: 'avc1.4d401f, mp4a.40.2',
1175
1181
  audioCodec: 'mp4a.40.2',
1176
1182
  videoCodec: 'avc1.4d401f',
@@ -1205,6 +1211,8 @@ describe('Player', () => {
1205
1211
  pixelAspectRatio: '59:54',
1206
1212
  hdr: null,
1207
1213
  mimeType: 'video/mp4',
1214
+ audioMimeType: 'audio/mp4',
1215
+ videoMimeType: 'video/mp4',
1208
1216
  codecs: 'avc1.4d401f, mp4a.40.2',
1209
1217
  audioCodec: 'mp4a.40.2',
1210
1218
  videoCodec: 'avc1.4d401f',
@@ -1239,6 +1247,8 @@ describe('Player', () => {
1239
1247
  pixelAspectRatio: '59:54',
1240
1248
  hdr: null,
1241
1249
  mimeType: 'video/mp4',
1250
+ audioMimeType: 'audio/mp4',
1251
+ videoMimeType: 'video/mp4',
1242
1252
  codecs: 'avc1.4d401f, mp4a.40.2',
1243
1253
  audioCodec: 'mp4a.40.2',
1244
1254
  videoCodec: 'avc1.4d401f',
@@ -1273,6 +1283,8 @@ describe('Player', () => {
1273
1283
  pixelAspectRatio: '59:54',
1274
1284
  hdr: null,
1275
1285
  mimeType: 'video/mp4',
1286
+ audioMimeType: 'audio/mp4',
1287
+ videoMimeType: 'video/mp4',
1276
1288
  codecs: 'avc1.4d401f, mp4a.40.2',
1277
1289
  audioCodec: 'mp4a.40.2',
1278
1290
  videoCodec: 'avc1.4d401f',
@@ -1307,6 +1319,8 @@ describe('Player', () => {
1307
1319
  pixelAspectRatio: '59:54',
1308
1320
  hdr: null,
1309
1321
  mimeType: 'video/mp4',
1322
+ audioMimeType: 'audio/mp4',
1323
+ videoMimeType: 'video/mp4',
1310
1324
  codecs: 'avc1.4d401f, mp4a.40.2',
1311
1325
  audioCodec: 'mp4a.40.2',
1312
1326
  videoCodec: 'avc1.4d401f',
@@ -1341,6 +1355,8 @@ describe('Player', () => {
1341
1355
  pixelAspectRatio: '59:54',
1342
1356
  hdr: null,
1343
1357
  mimeType: 'video/mp4',
1358
+ audioMimeType: 'audio/mp4',
1359
+ videoMimeType: 'video/mp4',
1344
1360
  codecs: 'avc1.4d401f, mp4a.40.2',
1345
1361
  audioCodec: 'mp4a.40.2',
1346
1362
  videoCodec: 'avc1.4d401f',
@@ -1375,6 +1391,8 @@ describe('Player', () => {
1375
1391
  pixelAspectRatio: '59:54',
1376
1392
  hdr: null,
1377
1393
  mimeType: 'video/mp4',
1394
+ audioMimeType: 'audio/mp4',
1395
+ videoMimeType: 'video/mp4',
1378
1396
  codecs: 'avc1.4d401f, mp4a.40.2',
1379
1397
  audioCodec: 'mp4a.40.2',
1380
1398
  videoCodec: 'avc1.4d401f',
@@ -1406,6 +1424,8 @@ describe('Player', () => {
1406
1424
  label: 'Spanish',
1407
1425
  kind: 'caption',
1408
1426
  mimeType: 'text/vtt',
1427
+ audioMimeType: null,
1428
+ videoMimeType: null,
1409
1429
  codecs: null,
1410
1430
  audioCodec: null,
1411
1431
  videoCodec: null,
@@ -1440,6 +1460,8 @@ describe('Player', () => {
1440
1460
  label: 'English',
1441
1461
  kind: 'caption',
1442
1462
  mimeType: 'application/ttml+xml',
1463
+ audioMimeType: null,
1464
+ videoMimeType: null,
1443
1465
  codecs: null,
1444
1466
  audioCodec: null,
1445
1467
  videoCodec: null,
@@ -1474,6 +1496,8 @@ describe('Player', () => {
1474
1496
  label: 'English',
1475
1497
  kind: 'caption',
1476
1498
  mimeType: 'application/ttml+xml',
1499
+ audioMimeType: null,
1500
+ videoMimeType: null,
1477
1501
  codecs: null,
1478
1502
  audioCodec: null,
1479
1503
  videoCodec: null,
@@ -1511,6 +1535,8 @@ describe('Player', () => {
1511
1535
  label: null,
1512
1536
  kind: null,
1513
1537
  mimeType: 'image/jpeg',
1538
+ audioMimeType: null,
1539
+ videoMimeType: null,
1514
1540
  codecs: null,
1515
1541
  audioCodec: null,
1516
1542
  videoCodec: null,
@@ -107,8 +107,8 @@ shaka.test.FakeMediaSourceEngine = class {
107
107
 
108
108
  /** @type {!jasmine.Spy} */
109
109
  this.setStreamProperties = jasmine.createSpy('setStreamProperties')
110
- .and.callFake((type, offset, end) =>
111
- this.setStreamPropertiesImpl_(type, offset, end));
110
+ .and.callFake((type, offset, end, sequenceMode) =>
111
+ this.setStreamPropertiesImpl_(type, offset, end, sequenceMode));
112
112
 
113
113
  /** @type {!jasmine.Spy} */
114
114
  this.remove = jasmine.createSpy('remove')
@@ -125,6 +125,10 @@ shaka.test.FakeMediaSourceEngine = class {
125
125
  this.getTextDisplayer =
126
126
  jasmine.createSpy('getTextDisplayer')
127
127
  .and.returnValue(new shaka.test.FakeTextDisplayer());
128
+
129
+ /** @type {!jasmine.Spy} */
130
+ this.setSegmentRelativeVttTiming =
131
+ jasmine.createSpy('setSegmentRelativeVttTiming').and.stub();
128
132
  }
129
133
 
130
134
  /** @override */
@@ -355,14 +359,17 @@ shaka.test.FakeMediaSourceEngine = class {
355
359
  * @param {string} type
356
360
  * @param {number} offset
357
361
  * @param {number} appendWindowEnd
362
+ * @param {boolean} sequenceMode
358
363
  * @return {!Promise}
359
364
  * @private
360
365
  */
361
- setStreamPropertiesImpl_(type, offset, appendWindowEnd) {
366
+ setStreamPropertiesImpl_(type, offset, appendWindowEnd, sequenceMode) {
362
367
  if (!this.segments[type]) {
363
368
  throw new Error('unexpected type');
364
369
  }
365
- this.timestampOffsets_[type] = offset;
370
+ if (!sequenceMode) {
371
+ this.timestampOffsets_[type] = offset;
372
+ }
366
373
  // Don't use |appendWindowEnd|.
367
374
  return Promise.resolve();
368
375
  }
@@ -95,6 +95,8 @@ shaka.test.ManifestGenerator.Manifest = class {
95
95
  this.offlineSessionIds = [];
96
96
  /** @type {number} */
97
97
  this.minBufferTime = 0;
98
+ /** @type {boolean} */
99
+ this.sequenceMode = false;
98
100
 
99
101
  /** @type {shaka.extern.Manifest} */
100
102
  const foo = this;
@@ -421,7 +423,7 @@ shaka.test.ManifestGenerator.DrmInfo = class {
421
423
  if (!this.initData) {
422
424
  this.initData = [];
423
425
  }
424
- this.initData.push({initData: buffer, initDataType: type, keyId: null});
426
+ this.initData.push({initData: buffer, initDataType: type});
425
427
  }
426
428
 
427
429
  /**
@@ -51,11 +51,12 @@ shaka.test.ManifestParser = class {
51
51
  * @param {number=} timestampOffset
52
52
  * @param {!Array.<!shaka.media.SegmentReference>=} partialReferences
53
53
  * @param {?string=} tilesLayout
54
+ * @param {?number=} syncTime
54
55
  * @return {!shaka.media.SegmentReference}
55
56
  */
56
57
  static makeReference(uri, start, end, baseUri = '',
57
58
  startByte = 0, endByte = null, timestampOffset = 0,
58
- partialReferences = [], tilesLayout = '') {
59
+ partialReferences = [], tilesLayout = '', syncTime = null) {
59
60
  const getUris = () => uri.length ? [baseUri + uri] : [];
60
61
 
61
62
  // If a test wants to verify these, they can be set explicitly after
@@ -80,6 +81,8 @@ shaka.test.ManifestParser = class {
80
81
  appendWindowEnd,
81
82
  partialReferences,
82
83
  tilesLayout,
84
+ /* tileDuration= */ undefined,
85
+ syncTime,
83
86
  );
84
87
  }
85
88
  };
@@ -20,6 +20,7 @@ shaka.test.OfflineUtils = class {
20
20
  streams: [],
21
21
  sessionIds: [],
22
22
  size: 1024,
23
+ sequenceMode: false,
23
24
  };
24
25
  }
25
26
 
@@ -275,6 +275,7 @@ shaka.test.StreamingEngineUtil = class {
275
275
  variants: [],
276
276
  textStreams: [],
277
277
  imageStreams: [],
278
+ sequenceMode: false,
278
279
  };
279
280
 
280
281
  /** @type {shaka.extern.Variant} */