shaka-player 3.3.4 → 4.0.0

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/workflows/build-and-test.yaml +0 -1
  2. package/.github/workflows/demo-version-index.yaml +8 -0
  3. package/.github/workflows/release-please.yaml +23 -2
  4. package/.github/workflows/selenium-lab-tests.yaml +0 -1
  5. package/.github/workflows/sync-labels.yaml +33 -0
  6. package/.github/workflows/update-issues.yaml +29 -0
  7. package/.github/workflows/validate-pr-title.yaml +35 -0
  8. package/AUTHORS +1 -0
  9. package/CHANGELOG.md +198 -32
  10. package/CONTRIBUTORS +1 -0
  11. package/README.md +10 -7
  12. package/app-engine/demo-version-index/README.md +3 -3
  13. package/app-engine/demo-version-index/app.yaml +27 -1
  14. package/app-engine/demo-version-index/generate.py +164 -0
  15. package/app-engine/demo-version-index/main.py +4 -155
  16. package/app-engine/demo-version-index/requirements.txt +0 -1
  17. package/build/README.md +2 -2
  18. package/build/compiler.py +1 -1
  19. package/build/generateTsDefs.py +0 -2
  20. package/build/shaka-lab.yaml +0 -2
  21. package/build/test.py +7 -1
  22. package/build/types/core +0 -1
  23. package/build/types/polyfill +0 -3
  24. package/demo/common/asset.js +17 -1
  25. package/demo/common/assets.js +29 -0
  26. package/demo/common/message_ids.js +6 -3
  27. package/demo/config.js +10 -11
  28. package/demo/custom.js +39 -0
  29. package/demo/demo_utils.js +0 -1
  30. package/demo/locales/en.json +6 -3
  31. package/demo/locales/source.json +22 -10
  32. package/demo/main.js +9 -6
  33. package/demo/search.js +2 -1
  34. package/dist/controls.css +1 -1
  35. package/dist/demo.compiled.debug.js +71 -64
  36. package/dist/demo.compiled.debug.map +3 -3
  37. package/dist/demo.compiled.js +71 -64
  38. package/dist/demo.compiled.map +3 -3
  39. package/dist/demo.css +1 -1
  40. package/dist/demo.css.map +1 -1
  41. package/dist/deps.js +16 -20
  42. package/dist/locales.js +31 -29
  43. package/dist/receiver.compiled.debug.js +32 -28
  44. package/dist/receiver.compiled.debug.map +3 -3
  45. package/dist/receiver.compiled.js +32 -28
  46. package/dist/receiver.compiled.map +3 -3
  47. package/dist/shaka-player.compiled.d.ts +78 -83
  48. package/dist/shaka-player.compiled.debug.d.ts +78 -83
  49. package/dist/shaka-player.compiled.debug.externs.js +126 -126
  50. package/dist/shaka-player.compiled.debug.js +426 -483
  51. package/dist/shaka-player.compiled.debug.map +4 -4
  52. package/dist/shaka-player.compiled.externs.js +126 -126
  53. package/dist/shaka-player.compiled.js +838 -856
  54. package/dist/shaka-player.compiled.map +4 -4
  55. package/dist/shaka-player.ui.d.ts +80 -83
  56. package/dist/shaka-player.ui.debug.d.ts +80 -83
  57. package/dist/shaka-player.ui.debug.externs.js +134 -126
  58. package/dist/shaka-player.ui.debug.js +488 -543
  59. package/dist/shaka-player.ui.debug.map +4 -4
  60. package/dist/shaka-player.ui.externs.js +134 -126
  61. package/dist/shaka-player.ui.js +980 -994
  62. package/dist/shaka-player.ui.map +4 -4
  63. package/docs/tutorials/config.md +0 -2
  64. package/docs/tutorials/drm-config.md +5 -0
  65. package/docs/tutorials/fairplay.md +7 -22
  66. package/docs/tutorials/faq.md +0 -11
  67. package/docs/tutorials/index.json +2 -8
  68. package/docs/tutorials/plugins.md +1 -3
  69. package/docs/tutorials/upgrade.md +83 -11
  70. package/externs/polyfill.js +15 -0
  71. package/externs/shaka/manifest.js +5 -1
  72. package/externs/shaka/net.js +12 -0
  73. package/externs/shaka/offline.js +5 -1
  74. package/externs/shaka/player.js +39 -32
  75. package/externs/shaka/text.js +12 -12
  76. package/externs/sourcebuffer.js +15 -0
  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 -1
  82. package/lib/hls/hls_parser.js +378 -743
  83. package/lib/hls/manifest_text_parser.js +2 -3
  84. package/lib/media/drm_engine.js +102 -53
  85. package/lib/media/gap_jumping_controller.js +10 -45
  86. package/lib/media/media_source_engine.js +87 -15
  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 +29 -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 +100 -132
  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 +24 -2
  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 +2 -0
  120. package/lib/util/platform.js +45 -0
  121. package/lib/util/player_configuration.js +12 -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 +1 -1
  127. package/roadmap.md +19 -19
  128. package/shaka-player.uncompiled.js +0 -3
  129. package/test/cast/cast_utils_unit.js +1 -0
  130. package/test/dash/dash_parser_content_protection_unit.js +44 -0
  131. package/test/dash/dash_parser_manifest_unit.js +0 -24
  132. package/test/dash/dash_parser_segment_template_unit.js +3 -4
  133. package/test/demo/demo_unit.js +2 -1
  134. package/test/hls/hls_live_unit.js +99 -220
  135. package/test/hls/hls_parser_unit.js +515 -432
  136. package/test/media/drm_engine_unit.js +86 -120
  137. package/test/media/media_source_engine_integration.js +26 -3
  138. package/test/media/media_source_engine_unit.js +7 -6
  139. package/test/media/playhead_unit.js +27 -191
  140. package/test/media/segment_index_unit.js +15 -25
  141. package/test/media/streaming_engine_integration.js +4 -39
  142. package/test/media/streaming_engine_unit.js +3 -2
  143. package/test/media/time_ranges_utils_unit.js +0 -5
  144. package/test/offline/manifest_convert_unit.js +34 -4
  145. package/test/offline/offline_manifest_parser_unit.js +1 -0
  146. package/test/offline/storage_integration.js +5 -4
  147. package/test/player_external.js +0 -6
  148. package/test/player_integration.js +16 -0
  149. package/test/player_unit.js +26 -0
  150. package/test/test/util/fake_media_source_engine.js +11 -4
  151. package/test/test/util/manifest_generator.js +3 -1
  152. package/test/test/util/manifest_parser_util.js +4 -1
  153. package/test/test/util/offline_utils.js +1 -0
  154. package/test/test/util/streaming_engine_util.js +1 -0
  155. package/test/test/util/test_scheme.js +24 -1
  156. package/test/test/util/util.js +4 -4
  157. package/test/text/cue_integration.js +2 -2
  158. package/test/text/lrc_text_parser_unit.js +6 -7
  159. package/test/text/mp4_ttml_parser_unit.js +6 -4
  160. package/test/text/mp4_vtt_parser_unit.js +6 -5
  161. package/test/text/sbv_text_parser_unit.js +5 -6
  162. package/test/text/srt_text_parser_unit.js +5 -6
  163. package/test/text/ssa_text_parser_unit.js +17 -29
  164. package/test/text/text_engine_unit.js +45 -5
  165. package/test/text/ttml_text_parser_unit.js +77 -77
  166. package/test/text/vtt_text_parser_unit.js +55 -57
  167. package/test/ui/ui_integration.js +0 -16
  168. package/test/ui/ui_unit.js +27 -0
  169. package/test/util/cmcd_manager_unit.js +3 -0
  170. package/test/util/stream_utils_unit.js +23 -7
  171. package/ui/controls.js +65 -40
  172. package/ui/fullscreen_button.js +26 -6
  173. package/ui/less/containers.less +3 -3
  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/docs/tutorials/upgrade-v2-5.md +0 -441
  179. package/docs/tutorials/upgrade-v3.md +0 -38
  180. package/lib/polyfill/mathround.js +0 -49
  181. package/lib/polyfill/patchedmediakeys_apple.js +0 -744
  182. package/lib/polyfill/patchedmediakeys_ms.js +0 -698
  183. package/lib/util/mutex.js +0 -52
  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: {
@@ -622,6 +585,7 @@ describe('StreamingEngine', () => {
622
585
  width: 600,
623
586
  height: 400,
624
587
  type: shaka.util.ManifestParserUtils.ContentType.VIDEO,
588
+ drmInfos: [],
625
589
  },
626
590
  audio: {
627
591
  id: 3,
@@ -631,6 +595,7 @@ describe('StreamingEngine', () => {
631
595
  codecs: 'mp4a.40.2',
632
596
  bandwidth: 192000,
633
597
  type: shaka.util.ManifestParserUtils.ContentType.AUDIO,
598
+ drmInfos: [],
634
599
  },
635
600
  }],
636
601
  };
@@ -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
  };
@@ -1130,6 +1132,8 @@ describe('Player', () => {
1130
1132
  pixelAspectRatio: '59:54',
1131
1133
  hdr: null,
1132
1134
  mimeType: 'video/mp4',
1135
+ audioMimeType: 'audio/mp4',
1136
+ videoMimeType: 'video/mp4',
1133
1137
  codecs: 'avc1.4d401f, mp4a.40.2',
1134
1138
  audioCodec: 'mp4a.40.2',
1135
1139
  videoCodec: 'avc1.4d401f',
@@ -1164,6 +1168,8 @@ describe('Player', () => {
1164
1168
  pixelAspectRatio: '59:54',
1165
1169
  hdr: null,
1166
1170
  mimeType: 'video/mp4',
1171
+ audioMimeType: 'audio/mp4',
1172
+ videoMimeType: 'video/mp4',
1167
1173
  codecs: 'avc1.4d401f, mp4a.40.2',
1168
1174
  audioCodec: 'mp4a.40.2',
1169
1175
  videoCodec: 'avc1.4d401f',
@@ -1198,6 +1204,8 @@ describe('Player', () => {
1198
1204
  pixelAspectRatio: '59:54',
1199
1205
  hdr: null,
1200
1206
  mimeType: 'video/mp4',
1207
+ audioMimeType: 'audio/mp4',
1208
+ videoMimeType: 'video/mp4',
1201
1209
  codecs: 'avc1.4d401f, mp4a.40.2',
1202
1210
  audioCodec: 'mp4a.40.2',
1203
1211
  videoCodec: 'avc1.4d401f',
@@ -1232,6 +1240,8 @@ describe('Player', () => {
1232
1240
  pixelAspectRatio: '59:54',
1233
1241
  hdr: null,
1234
1242
  mimeType: 'video/mp4',
1243
+ audioMimeType: 'audio/mp4',
1244
+ videoMimeType: 'video/mp4',
1235
1245
  codecs: 'avc1.4d401f, mp4a.40.2',
1236
1246
  audioCodec: 'mp4a.40.2',
1237
1247
  videoCodec: 'avc1.4d401f',
@@ -1266,6 +1276,8 @@ describe('Player', () => {
1266
1276
  pixelAspectRatio: '59:54',
1267
1277
  hdr: null,
1268
1278
  mimeType: 'video/mp4',
1279
+ audioMimeType: 'audio/mp4',
1280
+ videoMimeType: 'video/mp4',
1269
1281
  codecs: 'avc1.4d401f, mp4a.40.2',
1270
1282
  audioCodec: 'mp4a.40.2',
1271
1283
  videoCodec: 'avc1.4d401f',
@@ -1300,6 +1312,8 @@ describe('Player', () => {
1300
1312
  pixelAspectRatio: '59:54',
1301
1313
  hdr: null,
1302
1314
  mimeType: 'video/mp4',
1315
+ audioMimeType: 'audio/mp4',
1316
+ videoMimeType: 'video/mp4',
1303
1317
  codecs: 'avc1.4d401f, mp4a.40.2',
1304
1318
  audioCodec: 'mp4a.40.2',
1305
1319
  videoCodec: 'avc1.4d401f',
@@ -1334,6 +1348,8 @@ describe('Player', () => {
1334
1348
  pixelAspectRatio: '59:54',
1335
1349
  hdr: null,
1336
1350
  mimeType: 'video/mp4',
1351
+ audioMimeType: 'audio/mp4',
1352
+ videoMimeType: 'video/mp4',
1337
1353
  codecs: 'avc1.4d401f, mp4a.40.2',
1338
1354
  audioCodec: 'mp4a.40.2',
1339
1355
  videoCodec: 'avc1.4d401f',
@@ -1368,6 +1384,8 @@ describe('Player', () => {
1368
1384
  pixelAspectRatio: '59:54',
1369
1385
  hdr: null,
1370
1386
  mimeType: 'video/mp4',
1387
+ audioMimeType: 'audio/mp4',
1388
+ videoMimeType: 'video/mp4',
1371
1389
  codecs: 'avc1.4d401f, mp4a.40.2',
1372
1390
  audioCodec: 'mp4a.40.2',
1373
1391
  videoCodec: 'avc1.4d401f',
@@ -1399,6 +1417,8 @@ describe('Player', () => {
1399
1417
  label: 'Spanish',
1400
1418
  kind: 'caption',
1401
1419
  mimeType: 'text/vtt',
1420
+ audioMimeType: null,
1421
+ videoMimeType: null,
1402
1422
  codecs: null,
1403
1423
  audioCodec: null,
1404
1424
  videoCodec: null,
@@ -1433,6 +1453,8 @@ describe('Player', () => {
1433
1453
  label: 'English',
1434
1454
  kind: 'caption',
1435
1455
  mimeType: 'application/ttml+xml',
1456
+ audioMimeType: null,
1457
+ videoMimeType: null,
1436
1458
  codecs: null,
1437
1459
  audioCodec: null,
1438
1460
  videoCodec: null,
@@ -1467,6 +1489,8 @@ describe('Player', () => {
1467
1489
  label: 'English',
1468
1490
  kind: 'caption',
1469
1491
  mimeType: 'application/ttml+xml',
1492
+ audioMimeType: null,
1493
+ videoMimeType: null,
1470
1494
  codecs: null,
1471
1495
  audioCodec: null,
1472
1496
  videoCodec: null,
@@ -1504,6 +1528,8 @@ describe('Player', () => {
1504
1528
  label: null,
1505
1529
  kind: null,
1506
1530
  mimeType: 'image/jpeg',
1531
+ audioMimeType: null,
1532
+ videoMimeType: null,
1507
1533
  codecs: null,
1508
1534
  audioCodec: null,
1509
1535
  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} */