shaka-player 3.2.1 → 3.3.1

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 (213) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +1 -1
  3. package/.github/ISSUE_TEMPLATE/question.md +1 -1
  4. package/AUTHORS +9 -5
  5. package/CHANGELOG.md +358 -0
  6. package/CONTRIBUTORS +7 -2
  7. package/build/conformance.textproto +183 -169
  8. package/build/generateExterns.js +1 -1
  9. package/build/types/core +3 -0
  10. package/build/types/offline +1 -0
  11. package/build/types/polyfill +1 -0
  12. package/build/types/ui +2 -0
  13. package/demo/common/assets.js +19 -1
  14. package/demo/common/message_ids.js +13 -1
  15. package/demo/config.js +31 -1
  16. package/demo/index.html +1 -1
  17. package/demo/locales/en.json +12 -0
  18. package/demo/locales/source.json +48 -0
  19. package/dist/controls.css +26 -2
  20. package/dist/controls.css.map +1 -1
  21. package/dist/demo.compiled.debug.js +20 -17
  22. package/dist/demo.compiled.debug.map +3 -3
  23. package/dist/demo.compiled.js +20 -17
  24. package/dist/demo.compiled.map +3 -3
  25. package/dist/deps.js +19 -12
  26. package/dist/locales.js +39 -37
  27. package/dist/receiver.compiled.debug.js +12 -10
  28. package/dist/receiver.compiled.debug.map +3 -3
  29. package/dist/receiver.compiled.js +12 -10
  30. package/dist/receiver.compiled.map +3 -3
  31. package/dist/shaka-player.compiled.d.ts +231 -18
  32. package/dist/shaka-player.compiled.debug.d.ts +231 -18
  33. package/dist/shaka-player.compiled.debug.externs.js +279 -8
  34. package/dist/shaka-player.compiled.debug.js +512 -449
  35. package/dist/shaka-player.compiled.debug.map +4 -4
  36. package/dist/shaka-player.compiled.externs.js +279 -8
  37. package/dist/shaka-player.compiled.js +854 -821
  38. package/dist/shaka-player.compiled.map +4 -4
  39. package/dist/shaka-player.ui.d.ts +247 -19
  40. package/dist/shaka-player.ui.debug.d.ts +247 -19
  41. package/dist/shaka-player.ui.debug.externs.js +307 -9
  42. package/dist/shaka-player.ui.debug.js +662 -580
  43. package/dist/shaka-player.ui.debug.map +4 -4
  44. package/dist/shaka-player.ui.externs.js +307 -9
  45. package/dist/shaka-player.ui.js +1047 -1000
  46. package/dist/shaka-player.ui.map +4 -4
  47. package/docs/design/bg-fetch-after.gv +29 -0
  48. package/docs/design/bg-fetch-after.gv.png +0 -0
  49. package/docs/design/bg-fetch-before.gv +18 -0
  50. package/docs/design/bg-fetch-before.gv.png +0 -0
  51. package/docs/design/bg-fetch.md +134 -0
  52. package/docs/tutorials/blob-url.md +15 -0
  53. package/docs/tutorials/fairplay.md +1 -1
  54. package/docs/tutorials/index.json +1 -0
  55. package/docs/tutorials/ui-customization.md +66 -0
  56. package/docs/tutorials/ui.md +5 -5
  57. package/externs/cmcd.js +186 -0
  58. package/externs/ima.js +3 -0
  59. package/externs/shaka/ads.js +5 -0
  60. package/externs/shaka/manifest.js +12 -1
  61. package/externs/shaka/manifest_parser.js +10 -1
  62. package/externs/shaka/net.js +20 -4
  63. package/externs/shaka/offline.js +31 -2
  64. package/externs/shaka/player.js +138 -5
  65. package/externs/shaka/text.js +24 -0
  66. package/externs/webcrypto.js +18 -0
  67. package/karma.conf.js +1 -0
  68. package/lib/abr/ewma.js +14 -0
  69. package/lib/abr/ewma_bandwidth_estimator.js +16 -2
  70. package/lib/abr/simple_abr_manager.js +6 -0
  71. package/lib/ads/client_side_ad.js +8 -0
  72. package/lib/ads/client_side_ad_manager.js +54 -90
  73. package/lib/ads/server_side_ad.js +7 -0
  74. package/lib/ads/server_side_ad_manager.js +7 -10
  75. package/lib/cast/cast_proxy.js +3 -2
  76. package/lib/cast/cast_receiver.js +2 -1
  77. package/lib/cast/cast_sender.js +2 -2
  78. package/lib/cast/cast_utils.js +1 -0
  79. package/lib/dash/dash_parser.js +141 -16
  80. package/lib/dash/segment_base.js +25 -1
  81. package/lib/dash/segment_list.js +19 -10
  82. package/lib/dash/segment_template.js +24 -11
  83. package/lib/hls/hls_parser.js +146 -40
  84. package/lib/media/drm_engine.js +7 -0
  85. package/lib/media/gap_jumping_controller.js +4 -2
  86. package/lib/media/media_source_engine.js +1 -2
  87. package/lib/media/quality_observer.js +291 -0
  88. package/lib/media/segment_index.js +8 -1
  89. package/lib/media/segment_reference.js +37 -4
  90. package/lib/media/streaming_engine.js +49 -7
  91. package/lib/net/http_fetch_plugin.js +31 -11
  92. package/lib/net/http_plugin_utils.js +1 -0
  93. package/lib/net/http_xhr_plugin.js +40 -14
  94. package/lib/net/networking_engine.js +83 -19
  95. package/lib/offline/download_info.js +68 -0
  96. package/lib/offline/download_manager.js +13 -5
  97. package/lib/offline/indexeddb/base_storage_cell.js +35 -0
  98. package/lib/offline/indexeddb/storage_mechanism.js +1 -1
  99. package/lib/offline/indexeddb/v5_storage_cell.js +5 -0
  100. package/lib/offline/storage.js +393 -284
  101. package/lib/offline/stored_content_utils.js +2 -0
  102. package/lib/player.js +249 -43
  103. package/lib/polyfill/media_capabilities.js +36 -15
  104. package/lib/polyfill/mediasource.js +6 -0
  105. package/lib/polyfill/orientation.js +1 -1
  106. package/lib/polyfill/patchedmediakeys_apple.js +4 -4
  107. package/lib/polyfill/patchedmediakeys_ms.js +4 -4
  108. package/lib/polyfill/patchedmediakeys_webkit.js +4 -4
  109. package/lib/polyfill/random_uuid.js +52 -0
  110. package/lib/text/cue.js +18 -0
  111. package/lib/text/mp4_ttml_parser.js +3 -0
  112. package/lib/text/text_engine.js +14 -2
  113. package/lib/text/ttml_text_parser.js +114 -60
  114. package/lib/text/ui_text_displayer.js +95 -41
  115. package/lib/util/cmcd_manager.js +672 -0
  116. package/lib/util/error.js +6 -0
  117. package/lib/util/fake_event.js +53 -7
  118. package/lib/util/language_utils.js +12 -0
  119. package/lib/util/mutex.js +52 -0
  120. package/lib/util/periods.js +102 -65
  121. package/lib/util/platform.js +13 -1
  122. package/lib/util/player_configuration.js +18 -0
  123. package/lib/util/stream_utils.js +99 -10
  124. package/lib/util/xml_utils.js +19 -0
  125. package/package.json +2 -2
  126. package/shaka-player.uncompiled.js +3 -0
  127. package/test/cast/cast_proxy_unit.js +12 -6
  128. package/test/cast/cast_utils_unit.js +1 -1
  129. package/test/dash/dash_parser_content_protection_unit.js +2 -0
  130. package/test/dash/dash_parser_live_unit.js +101 -1
  131. package/test/dash/dash_parser_manifest_unit.js +222 -2
  132. package/test/dash/dash_parser_segment_base_unit.js +2 -0
  133. package/test/dash/dash_parser_segment_list_unit.js +2 -1
  134. package/test/dash/dash_parser_segment_template_unit.js +2 -1
  135. package/test/hls/hls_live_unit.js +2 -0
  136. package/test/hls/hls_parser_unit.js +7 -1
  137. package/test/media/closed_caption_parser_unit.js +6 -1
  138. package/test/media/drm_engine_unit.js +47 -3
  139. package/test/media/quality_observer_unit.js +139 -0
  140. package/test/media/segment_reference_unit.js +16 -1
  141. package/test/media/streaming_engine_integration.js +4 -2
  142. package/test/media/streaming_engine_unit.js +147 -0
  143. package/test/net/http_plugin_unit.js +20 -15
  144. package/test/offline/storage_integration.js +108 -4
  145. package/test/player_integration.js +178 -8
  146. package/test/player_src_equals_integration.js +41 -8
  147. package/test/player_unit.js +19 -9
  148. package/test/test/assets/3675/chunk-stream0-00001.m4s +0 -0
  149. package/test/test/assets/3675/chunk-stream0-00002.m4s +0 -0
  150. package/test/test/assets/3675/chunk-stream0-00003.m4s +0 -0
  151. package/test/test/assets/3675/chunk-stream0-00004.m4s +0 -0
  152. package/test/test/assets/3675/chunk-stream0-00005.m4s +0 -0
  153. package/test/test/assets/3675/chunk-stream0-00006.m4s +0 -0
  154. package/test/test/assets/3675/chunk-stream0-00007.m4s +0 -0
  155. package/test/test/assets/3675/dash_0.mpd +30 -0
  156. package/test/test/assets/3675/dash_1.mpd +30 -0
  157. package/test/test/assets/3675/dash_2.mpd +30 -0
  158. package/test/test/assets/3675/dash_3.mpd +30 -0
  159. package/test/test/assets/3675/dash_4.mpd +30 -0
  160. package/test/test/assets/3675/dash_5.mpd +26 -0
  161. package/test/test/assets/3675/init-stream0.m4s +0 -0
  162. package/test/test/assets/chapters.vtt +2 -2
  163. package/test/test/assets/chapters2.vtt +10 -0
  164. package/test/test/util/dash_parser_util.js +4 -0
  165. package/test/test/util/fake_ad.js +7 -0
  166. package/test/test/util/fake_ad_manager.js +1 -1
  167. package/test/test/util/fake_drm_engine.js +9 -2
  168. package/test/test/util/manifest_generator.js +3 -2
  169. package/test/test/util/test_scheme.js +14 -1
  170. package/test/test/util/ttml_utils.js +81 -0
  171. package/test/text/mp4_ttml_parser_unit.js +11 -18
  172. package/test/text/ttml_text_parser_unit.js +552 -227
  173. package/test/text/ui_text_displayer_unit.js +29 -17
  174. package/test/ui/localization_unit.js +15 -14
  175. package/test/ui/text_displayer_layout_unit.js +13 -1
  176. package/test/ui/ui_unit.js +250 -0
  177. package/test/util/cmcd_manager_unit.js +291 -0
  178. package/test/util/stream_utils_unit.js +45 -4
  179. package/third_party/closure-uri/uri.js +21 -0
  180. package/ui/airplay_button.js +1 -0
  181. package/ui/audio_language_selection.js +7 -0
  182. package/ui/cast_button.js +3 -3
  183. package/ui/context_menu.js +109 -0
  184. package/ui/controls.js +45 -13
  185. package/ui/controls.less +1 -0
  186. package/ui/enums.js +4 -0
  187. package/ui/externs/ui.js +28 -1
  188. package/ui/fast_forward_button.js +14 -5
  189. package/ui/fullscreen_button.js +1 -0
  190. package/ui/less/buttons.less +0 -4
  191. package/ui/less/containers.less +77 -7
  192. package/ui/less/overflow_menu.less +0 -10
  193. package/ui/less/tooltip.less +97 -0
  194. package/ui/locales/en.json +1 -0
  195. package/ui/locales/ru.json +6 -6
  196. package/ui/locales/source.json +4 -0
  197. package/ui/localization.js +28 -51
  198. package/ui/loop_button.js +5 -0
  199. package/ui/mute_button.js +2 -1
  200. package/ui/overflow_menu.js +5 -25
  201. package/ui/pip_button.js +7 -3
  202. package/ui/play_button.js +2 -2
  203. package/ui/playback_rate_selection.js +8 -9
  204. package/ui/resolution_selection.js +7 -0
  205. package/ui/rewind_button.js +15 -6
  206. package/ui/seek_bar.js +4 -2
  207. package/ui/settings_menu.js +36 -4
  208. package/ui/small_play_button.js +1 -0
  209. package/ui/statistics_button.js +253 -0
  210. package/ui/text_selection.js +12 -4
  211. package/ui/ui.js +30 -0
  212. package/ui/volume_bar.js +1 -1
  213. package/externs/media_capabilities.js +0 -16
@@ -330,9 +330,9 @@ describe('Player Src Equals', () => {
330
330
  await loadWithSrcEquals(SMALL_MP4_CONTENT_URI, /* startTime= */ null);
331
331
 
332
332
  const locationUri = new goog.Uri(location.href);
333
- const partialUri = new goog.Uri('/base/test/test/assets/chapters.vtt');
334
- const absoluteUri = locationUri.resolve(partialUri);
335
- await player.addChaptersTrack(absoluteUri.toString(), 'en');
333
+ const partialUri1 = new goog.Uri('/base/test/test/assets/chapters.vtt');
334
+ const absoluteUri1 = locationUri.resolve(partialUri1);
335
+ await player.addChaptersTrack(absoluteUri1.toString(), 'en');
336
336
 
337
337
  await shaka.test.Util.delay(1.5);
338
338
 
@@ -345,11 +345,44 @@ describe('Player Src Equals', () => {
345
345
  const chapter2 = chapters[1];
346
346
  expect(chapter2.title).toBe('Chapter 2');
347
347
  expect(chapter2.startTime).toBe(5);
348
- expect(chapter2.endTime).toBe(30);
348
+ expect(chapter2.endTime).toBe(10);
349
349
  const chapter3 = chapters[2];
350
350
  expect(chapter3.title).toBe('Chapter 3');
351
- expect(chapter3.startTime).toBe(30);
352
- expect(chapter3.endTime).toBe(61.349);
351
+ expect(chapter3.startTime).toBe(10);
352
+ expect(chapter3.endTime).toBe(20);
353
+
354
+ const partialUri2 = new goog.Uri('/base/test/test/assets/chapters2.vtt');
355
+ const absoluteUri2 = locationUri.resolve(partialUri2);
356
+ await player.addChaptersTrack(absoluteUri2.toString(), 'en');
357
+
358
+ await shaka.test.Util.delay(1.5);
359
+
360
+ const chaptersUpdated = player.getChapters('en');
361
+ expect(chaptersUpdated.length).toBe(6);
362
+ const chapterUpdated1 = chaptersUpdated[0];
363
+ expect(chapterUpdated1.title).toBe('Chapter 1');
364
+ expect(chapterUpdated1.startTime).toBe(0);
365
+ expect(chapterUpdated1.endTime).toBe(5);
366
+ const chapterUpdated2 = chaptersUpdated[1];
367
+ expect(chapterUpdated2.title).toBe('Chapter 2');
368
+ expect(chapterUpdated2.startTime).toBe(5);
369
+ expect(chapterUpdated2.endTime).toBe(10);
370
+ const chapterUpdated3 = chaptersUpdated[2];
371
+ expect(chapterUpdated3.title).toBe('Chapter 3');
372
+ expect(chapterUpdated3.startTime).toBe(10);
373
+ expect(chapterUpdated3.endTime).toBe(20);
374
+ const chapterUpdated4 = chaptersUpdated[3];
375
+ expect(chapterUpdated4.title).toBe('Chapter 4');
376
+ expect(chapterUpdated4.startTime).toBe(20);
377
+ expect(chapterUpdated4.endTime).toBe(30);
378
+ const chapterUpdated5 = chaptersUpdated[4];
379
+ expect(chapterUpdated5.title).toBe('Chapter 5');
380
+ expect(chapterUpdated5.startTime).toBe(30);
381
+ expect(chapterUpdated5.endTime).toBe(40);
382
+ const chapterUpdated6 = chaptersUpdated[5];
383
+ expect(chapterUpdated6.title).toBe('Chapter 6');
384
+ expect(chapterUpdated6.startTime).toBe(40);
385
+ expect(chapterUpdated6.endTime).toBe(61.349);
353
386
  });
354
387
 
355
388
  it('add external chapters in srt format', async () => {
@@ -358,11 +391,11 @@ describe('Player Src Equals', () => {
358
391
  const locationUri = new goog.Uri(location.href);
359
392
  const partialUri = new goog.Uri('/base/test/test/assets/chapters.srt');
360
393
  const absoluteUri = locationUri.resolve(partialUri);
361
- await player.addChaptersTrack(absoluteUri.toString(), 'en');
394
+ await player.addChaptersTrack(absoluteUri.toString(), 'es');
362
395
 
363
396
  await shaka.test.Util.delay(1.5);
364
397
 
365
- const chapters = player.getChapters('en');
398
+ const chapters = player.getChapters('es');
366
399
  expect(chapters.length).toBe(3);
367
400
  const chapter1 = chapters[0];
368
401
  expect(chapter1.title).toBe('Chapter 1');
@@ -36,7 +36,7 @@ describe('Player', () => {
36
36
  const originalLogWarn = shaka.log.warning;
37
37
  const originalLogAlwaysWarn = shaka.log.alwaysWarn;
38
38
  const originalIsTypeSupported = window.MediaSource.isTypeSupported;
39
- const originalDecodingInfo = window.shakaMediaCapabilities.decodingInfo;
39
+ const originalDecodingInfo = navigator.mediaCapabilities.decodingInfo;
40
40
 
41
41
  const fakeManifestUri = 'fake-manifest-uri';
42
42
  const fakeMimeType = 'application/test';
@@ -93,7 +93,7 @@ describe('Player', () => {
93
93
  // Since this is not an integration test, we don't want MediaCapabilities to
94
94
  // fail assertions based on browser support for types. Pretend that all
95
95
  // video and audio types are supported.
96
- window.shakaMediaCapabilities.decodingInfo = async (config) => {
96
+ navigator.mediaCapabilities.decodingInfo = async (config) => {
97
97
  await Promise.resolve();
98
98
  const videoType = config['video'] ?
99
99
  config['video'].contentType.split('/')[0] : null;
@@ -177,7 +177,7 @@ describe('Player', () => {
177
177
  shaka.log.alwaysWarn = originalLogAlwaysWarn;
178
178
  window.MediaSource.isTypeSupported = originalIsTypeSupported;
179
179
  shaka.media.ManifestParser.unregisterParserByMime(fakeMimeType);
180
- window.shakaMediaCapabilities.decodingInfo = originalDecodingInfo;
180
+ navigator.mediaCapabilities.decodingInfo = originalDecodingInfo;
181
181
  }
182
182
  });
183
183
 
@@ -1092,8 +1092,8 @@ describe('Player', () => {
1092
1092
  // Image tracks
1093
1093
  manifest.addImageStream(53, (stream) => {
1094
1094
  stream.originalId = 'thumbnail';
1095
- stream.width = 100;
1096
- stream.height = 200;
1095
+ stream.width = 200;
1096
+ stream.height = 400;
1097
1097
  stream.bandwidth = 10;
1098
1098
  stream.mimeType = 'image/jpeg';
1099
1099
  stream.tilesLayout = '1x1';
@@ -1503,8 +1503,8 @@ describe('Player', () => {
1503
1503
  audioBandwidth: null,
1504
1504
  videoBandwidth: null,
1505
1505
  bandwidth: 10,
1506
- width: 100,
1507
- height: 200,
1506
+ width: 200,
1507
+ height: 400,
1508
1508
  frameRate: null,
1509
1509
  pixelAspectRatio: null,
1510
1510
  hdr: null,
@@ -2463,7 +2463,7 @@ describe('Player', () => {
2463
2463
  it('throws CONTENT_UNSUPPORTED_BY_BROWSER', async () => {
2464
2464
  window.MediaSource.isTypeSupported = (mimeType) => false;
2465
2465
 
2466
- window.shakaMediaCapabilities.decodingInfo = async (config) => {
2466
+ navigator.mediaCapabilities.decodingInfo = async (config) => {
2467
2467
  await Promise.resolve();
2468
2468
  return {supported: false};
2469
2469
  };
@@ -2827,7 +2827,7 @@ describe('Player', () => {
2827
2827
  });
2828
2828
  });
2829
2829
 
2830
- window.shakaMediaCapabilities.decodingInfo = async (config) => {
2830
+ navigator.mediaCapabilities.decodingInfo = async (config) => {
2831
2831
  await Promise.resolve();
2832
2832
  const videoType = config['video'] ? config['video'].contentType : '';
2833
2833
  if (videoType.includes('video') &&
@@ -3537,29 +3537,39 @@ describe('Player', () => {
3537
3537
 
3538
3538
  await player.load(fakeManifestUri, 0, fakeMimeType);
3539
3539
 
3540
+ expect(player.getImageTracks()[0].width).toBe(100);
3541
+ expect(player.getImageTracks()[0].height).toBe(50);
3540
3542
  const thumbnail0 = await player.getThumbnails(5, 0);
3541
3543
  const thumbnail1 = await player.getThumbnails(5, 11);
3542
3544
  const thumbnail2 = await player.getThumbnails(5, 21);
3543
3545
  const thumbnail5 = await player.getThumbnails(5, 51);
3544
3546
  expect(thumbnail0).toEqual(jasmine.objectContaining({
3547
+ imageHeight: 150,
3548
+ imageWidth: 200,
3545
3549
  positionX: 0,
3546
3550
  positionY: 0,
3547
3551
  width: 100,
3548
3552
  height: 50,
3549
3553
  }));
3550
3554
  expect(thumbnail1).toEqual(jasmine.objectContaining({
3555
+ imageHeight: 150,
3556
+ imageWidth: 200,
3551
3557
  positionX: 100,
3552
3558
  positionY: 0,
3553
3559
  width: 100,
3554
3560
  height: 50,
3555
3561
  }));
3556
3562
  expect(thumbnail2).toEqual(jasmine.objectContaining({
3563
+ imageHeight: 150,
3564
+ imageWidth: 200,
3557
3565
  positionX: 0,
3558
3566
  positionY: 50,
3559
3567
  width: 100,
3560
3568
  height: 50,
3561
3569
  }));
3562
3570
  expect(thumbnail5).toEqual(jasmine.objectContaining({
3571
+ imageHeight: 150,
3572
+ imageWidth: 200,
3563
3573
  positionX: 100,
3564
3574
  positionY: 100,
3565
3575
  width: 100,
@@ -0,0 +1,30 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3
+ xmlns="urn:mpeg:dash:schema:mpd:2011"
4
+ xmlns:xlink="http://www.w3.org/1999/xlink"
5
+ xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
6
+ profiles="urn:mpeg:dash:profile:isoff-live:2011"
7
+ type="dynamic"
8
+ minimumUpdatePeriod="PT2S"
9
+ suggestedPresentationDelay="PT2S"
10
+ availabilityStartTime="2021-10-28T07:36:27.755Z"
11
+ publishTime="2021-10-28T07:36:29.744Z"
12
+ timeShiftBufferDepth="PT10.0S"
13
+ maxSegmentDuration="PT2.0S"
14
+ minBufferTime="PT4.0S">
15
+ <ProgramInformation>
16
+ </ProgramInformation>
17
+ <ServiceDescription id="0">
18
+ </ServiceDescription>
19
+ <Period id="0" start="PT0.0S">
20
+ <AdaptationSet id="0" contentType="video" startWithSAP="1" segmentAlignment="true" bitstreamSwitching="true" frameRate="30/1" maxWidth="1280" maxHeight="720" par="16:9">
21
+ <Representation id="0" mimeType="video/mp4" codecs="avc1.64001f" bandwidth="122012" width="1280" height="720" sar="1:1">
22
+ <SegmentTemplate timescale="15360" initialization="init-stream$RepresentationID$.m4s" media="chunk-stream$RepresentationID$-$Number%05d$.m4s" startNumber="1">
23
+ <SegmentTimeline>
24
+ <S t="0" d="30720" />
25
+ </SegmentTimeline>
26
+ </SegmentTemplate>
27
+ </Representation>
28
+ </AdaptationSet>
29
+ </Period>
30
+ </MPD>
@@ -0,0 +1,30 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3
+ xmlns="urn:mpeg:dash:schema:mpd:2011"
4
+ xmlns:xlink="http://www.w3.org/1999/xlink"
5
+ xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
6
+ profiles="urn:mpeg:dash:profile:isoff-live:2011"
7
+ type="dynamic"
8
+ minimumUpdatePeriod="PT2S"
9
+ suggestedPresentationDelay="PT2S"
10
+ availabilityStartTime="2021-10-28T07:36:27.755Z"
11
+ publishTime="2021-10-28T07:36:31.750Z"
12
+ timeShiftBufferDepth="PT10.0S"
13
+ maxSegmentDuration="PT2.0S"
14
+ minBufferTime="PT4.0S">
15
+ <ProgramInformation>
16
+ </ProgramInformation>
17
+ <ServiceDescription id="0">
18
+ </ServiceDescription>
19
+ <Period id="0" start="PT0.0S">
20
+ <AdaptationSet id="0" contentType="video" startWithSAP="1" segmentAlignment="true" bitstreamSwitching="true" frameRate="30/1" maxWidth="1280" maxHeight="720" par="16:9">
21
+ <Representation id="0" mimeType="video/mp4" codecs="avc1.64001f" bandwidth="122012" width="1280" height="720" sar="1:1">
22
+ <SegmentTemplate timescale="15360" initialization="init-stream$RepresentationID$.m4s" media="chunk-stream$RepresentationID$-$Number%05d$.m4s" startNumber="1">
23
+ <SegmentTimeline>
24
+ <S t="0" d="30720" r="1" />
25
+ </SegmentTimeline>
26
+ </SegmentTemplate>
27
+ </Representation>
28
+ </AdaptationSet>
29
+ </Period>
30
+ </MPD>
@@ -0,0 +1,30 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3
+ xmlns="urn:mpeg:dash:schema:mpd:2011"
4
+ xmlns:xlink="http://www.w3.org/1999/xlink"
5
+ xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
6
+ profiles="urn:mpeg:dash:profile:isoff-live:2011"
7
+ type="dynamic"
8
+ minimumUpdatePeriod="PT2S"
9
+ suggestedPresentationDelay="PT2S"
10
+ availabilityStartTime="2021-10-28T07:36:27.755Z"
11
+ publishTime="2021-10-28T07:36:35.752Z"
12
+ timeShiftBufferDepth="PT10.0S"
13
+ maxSegmentDuration="PT2.0S"
14
+ minBufferTime="PT4.0S">
15
+ <ProgramInformation>
16
+ </ProgramInformation>
17
+ <ServiceDescription id="0">
18
+ </ServiceDescription>
19
+ <Period id="0" start="PT0.0S">
20
+ <AdaptationSet id="0" contentType="video" startWithSAP="1" segmentAlignment="true" bitstreamSwitching="true" frameRate="30/1" maxWidth="1280" maxHeight="720" par="16:9">
21
+ <Representation id="0" mimeType="video/mp4" codecs="avc1.64001f" bandwidth="122012" width="1280" height="720" sar="1:1">
22
+ <SegmentTemplate timescale="15360" initialization="init-stream$RepresentationID$.m4s" media="chunk-stream$RepresentationID$-$Number%05d$.m4s" startNumber="1">
23
+ <SegmentTimeline>
24
+ <S t="0" d="30720" r="3" />
25
+ </SegmentTimeline>
26
+ </SegmentTemplate>
27
+ </Representation>
28
+ </AdaptationSet>
29
+ </Period>
30
+ </MPD>
@@ -0,0 +1,30 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3
+ xmlns="urn:mpeg:dash:schema:mpd:2011"
4
+ xmlns:xlink="http://www.w3.org/1999/xlink"
5
+ xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
6
+ profiles="urn:mpeg:dash:profile:isoff-live:2011"
7
+ type="dynamic"
8
+ minimumUpdatePeriod="PT2S"
9
+ suggestedPresentationDelay="PT2S"
10
+ availabilityStartTime="2021-10-28T07:36:27.755Z"
11
+ publishTime="2021-10-28T07:36:37.752Z"
12
+ timeShiftBufferDepth="PT10.0S"
13
+ maxSegmentDuration="PT2.0S"
14
+ minBufferTime="PT4.0S">
15
+ <ProgramInformation>
16
+ </ProgramInformation>
17
+ <ServiceDescription id="0">
18
+ </ServiceDescription>
19
+ <Period id="0" start="PT0.0S">
20
+ <AdaptationSet id="0" contentType="video" startWithSAP="1" segmentAlignment="true" bitstreamSwitching="true" frameRate="30/1" maxWidth="1280" maxHeight="720" par="16:9">
21
+ <Representation id="0" mimeType="video/mp4" codecs="avc1.64001f" bandwidth="122012" width="1280" height="720" sar="1:1">
22
+ <SegmentTemplate timescale="15360" initialization="init-stream$RepresentationID$.m4s" media="chunk-stream$RepresentationID$-$Number%05d$.m4s" startNumber="1">
23
+ <SegmentTimeline>
24
+ <S t="0" d="30720" r="4" />
25
+ </SegmentTimeline>
26
+ </SegmentTemplate>
27
+ </Representation>
28
+ </AdaptationSet>
29
+ </Period>
30
+ </MPD>
@@ -0,0 +1,30 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3
+ xmlns="urn:mpeg:dash:schema:mpd:2011"
4
+ xmlns:xlink="http://www.w3.org/1999/xlink"
5
+ xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
6
+ profiles="urn:mpeg:dash:profile:isoff-live:2011"
7
+ type="dynamic"
8
+ minimumUpdatePeriod="PT2S"
9
+ suggestedPresentationDelay="PT2S"
10
+ availabilityStartTime="2021-10-28T07:36:27.755Z"
11
+ publishTime="2021-10-28T07:36:41.751Z"
12
+ timeShiftBufferDepth="PT10.0S"
13
+ maxSegmentDuration="PT2.0S"
14
+ minBufferTime="PT4.0S">
15
+ <ProgramInformation>
16
+ </ProgramInformation>
17
+ <ServiceDescription id="0">
18
+ </ServiceDescription>
19
+ <Period id="0" start="PT0.0S">
20
+ <AdaptationSet id="0" contentType="video" startWithSAP="1" segmentAlignment="true" bitstreamSwitching="true" frameRate="30/1" maxWidth="1280" maxHeight="720" par="16:9">
21
+ <Representation id="0" mimeType="video/mp4" codecs="avc1.64001f" bandwidth="122012" width="1280" height="720" sar="1:1">
22
+ <SegmentTemplate timescale="15360" initialization="init-stream$RepresentationID$.m4s" media="chunk-stream$RepresentationID$-$Number%05d$.m4s" startNumber="3">
23
+ <SegmentTimeline>
24
+ <S t="61440" d="30720" r="4" />
25
+ </SegmentTimeline>
26
+ </SegmentTemplate>
27
+ </Representation>
28
+ </AdaptationSet>
29
+ </Period>
30
+ </MPD>
@@ -0,0 +1,26 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3
+ xmlns="urn:mpeg:dash:schema:mpd:2011"
4
+ xmlns:xlink="http://www.w3.org/1999/xlink"
5
+ xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
6
+ profiles="urn:mpeg:dash:profile:isoff-live:2011"
7
+ type="static"
8
+ mediaPresentationDuration="PT14.0S"
9
+ maxSegmentDuration="PT2.0S"
10
+ minBufferTime="PT4.0S">
11
+ <ProgramInformation>
12
+ </ProgramInformation>
13
+ <ServiceDescription id="0">
14
+ </ServiceDescription>
15
+ <Period id="0" start="PT0.0S">
16
+ <AdaptationSet id="0" contentType="video" startWithSAP="1" segmentAlignment="true" bitstreamSwitching="true" frameRate="30/1" maxWidth="1280" maxHeight="720" par="16:9">
17
+ <Representation id="0" mimeType="video/mp4" codecs="avc1.64001f" bandwidth="122012" width="1280" height="720" sar="1:1">
18
+ <SegmentTemplate timescale="15360" initialization="init-stream$RepresentationID$.m4s" media="chunk-stream$RepresentationID$-$Number%05d$.m4s" startNumber="3">
19
+ <SegmentTimeline>
20
+ <S t="61440" d="30720" r="4" />
21
+ </SegmentTimeline>
22
+ </SegmentTemplate>
23
+ </Representation>
24
+ </AdaptationSet>
25
+ </Period>
26
+ </MPD>
@@ -3,8 +3,8 @@ WEBVTT
3
3
  00:00.000 --> 00:05.000
4
4
  Chapter 1
5
5
 
6
- 00:05.000 --> 00:30.000
6
+ 00:05.000 --> 00:10.000
7
7
  Chapter 2
8
8
 
9
- 00:30.000 --> 01:01.349
9
+ 00:10.000 --> 00:20.000
10
10
  Chapter 3
@@ -0,0 +1,10 @@
1
+ WEBVTT
2
+
3
+ 00:20.000 --> 00:30.000
4
+ Chapter 4
5
+
6
+ 00:30.000 --> 00:40.000
7
+ Chapter 5
8
+
9
+ 00:40.000 --> 01:01.349
10
+ Chapter 6
@@ -46,6 +46,8 @@ shaka.test.Dash = class {
46
46
 
47
47
  const playerInterface = {
48
48
  networkingEngine: networkingEngine,
49
+ modifyManifestRequest: (request, manifestInfo) => {},
50
+ modifySegmentRequest: (request, segmentInfo) => {},
49
51
  filter: () => {},
50
52
  makeTextStreamsForClosedCaptions: (manifest) => {},
51
53
  onTimelineRegionAdded: fail, // Should not have any EventStream elements.
@@ -78,6 +80,8 @@ shaka.test.Dash = class {
78
80
 
79
81
  const playerInterface = {
80
82
  networkingEngine: networkingEngine,
83
+ modifyManifestRequest: (request, manifestInfo) => {},
84
+ modifySegmentRequest: (request, segmentInfo) => {},
81
85
  filter: () => {},
82
86
  makeTextStreamsForClosedCaptions: (manifest) => {},
83
87
  onTimelineRegionAdded: fail, // Should not have any EventStream elements.
@@ -154,6 +154,13 @@ shaka.test.FakeAd = class {
154
154
  }
155
155
 
156
156
 
157
+ /**
158
+ * @override
159
+ */
160
+ isLinear() {
161
+ return true;
162
+ }
163
+
157
164
  /**
158
165
  * @override
159
166
  */
@@ -85,7 +85,7 @@ shaka.test.FakeAdManager = class extends shaka.util.FakeEventTarget {
85
85
  */
86
86
  startAd(ad) {
87
87
  const event = new shaka.util.FakeEvent(shaka.ads.AdManager.AD_STARTED,
88
- {'ad': ad});
88
+ (new Map()).set('ad', ad));
89
89
 
90
90
  this.dispatchEvent(event);
91
91
  }
@@ -17,7 +17,7 @@ goog.require('shaka.test.Util');
17
17
  */
18
18
  shaka.test.FakeDrmEngine = class {
19
19
  constructor() {
20
- /** @private {!Array.<number>} */
20
+ /** @private {!Array.<string>} */
21
21
  this.offlineSessions_ = [];
22
22
  /** @private {?shaka.extern.DrmInfo} */
23
23
  this.drmInfo_ = null;
@@ -45,6 +45,13 @@ shaka.test.FakeDrmEngine = class {
45
45
  // be returned.
46
46
  this.getDrmInfo.and.callFake(() => this.drmInfo_);
47
47
 
48
+ /** @type {!jasmine.Spy} */
49
+ this.newInitData = jasmine.createSpy('newInitData');
50
+ this.newInitData.and.callFake((initDataType, initData) => {
51
+ const num = 1 + this.offlineSessions_.length;
52
+ this.offlineSessions_.push('session-' + num);
53
+ });
54
+
48
55
  /** @type {!jasmine.Spy} */
49
56
  this.getExpiration = jasmine.createSpy('getExpiration');
50
57
  this.getExpiration.and.returnValue(Infinity);
@@ -90,7 +97,7 @@ shaka.test.FakeDrmEngine = class {
90
97
  }
91
98
 
92
99
  /**
93
- * @param {!Array.<number>} sessions
100
+ * @param {!Array.<string>} sessions
94
101
  */
95
102
  setSessionIds(sessions) {
96
103
  // Copy the values to break the reference to the input value.
@@ -653,15 +653,16 @@ shaka.test.ManifestGenerator.Stream = class {
653
653
  * @param {!Array.<string>} uris
654
654
  * @param {number} startByte
655
655
  * @param {?number} endByte
656
+ * @param {null|shaka.extern.MediaQualityInfo=} mediaQuality
656
657
  */
657
- setInitSegmentReference(uris, startByte, endByte) {
658
+ setInitSegmentReference(uris, startByte, endByte, mediaQuality) {
658
659
  goog.asserts.assert(this.manifest_,
659
660
  'A top-level generated Manifest is required to use this method!');
660
661
 
661
662
  const getUris = () => uris;
662
663
  this.initSegmentReference_ =
663
664
  new this.manifest_.shaka_.media.InitSegmentReference(
664
- getUris, startByte, endByte);
665
+ getUris, startByte, endByte, mediaQuality);
665
666
  }
666
667
 
667
668
  /**
@@ -206,10 +206,23 @@ shaka.test.TestScheme = class {
206
206
  * @param {string} name
207
207
  */
208
208
  function addStreamInfo(stream, variant, data, contentType, name) {
209
+ const mediaQualityInfo = {
210
+ bandwidth: 1,
211
+ codecs: data[contentType].codecs || 'unknown',
212
+ contentType: contentType,
213
+ mimeType: data[contentType].mimeType,
214
+ audioSamplingRate: null,
215
+ frameRate: null,
216
+ height: null,
217
+ channelsCount: null,
218
+ pixelAspectRatio: null,
219
+ width: null,
220
+ };
209
221
  stream.mimeType = data[contentType].mimeType;
210
222
  stream.codecs = data[contentType].codecs;
211
223
  stream.setInitSegmentReference(
212
- ['test:' + name + '/' + contentType + '/init'], 0, null);
224
+ ['test:' + name + '/' + contentType + '/init'], 0, null,
225
+ mediaQualityInfo);
213
226
  stream.useSegmentTemplate(
214
227
  'test:' + name + '/' + contentType + '/%d',
215
228
  data[contentType].segmentDuration);
@@ -0,0 +1,81 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ goog.provide('shaka.test.TtmlUtils');
8
+
9
+ shaka.test.TtmlUtils = class {
10
+ /**
11
+ * @param {!Array} expectedCues
12
+ * @param {!Array} actualCues
13
+ * @param {!Object} bodyProperties
14
+ * @param {Object=} divProperties
15
+ */
16
+ static verifyHelper(expectedCues, actualCues, bodyProperties, divProperties) {
17
+ const mapExpected = (cue) => {
18
+ if (cue.region) {
19
+ cue.region = jasmine.objectContaining(cue.region);
20
+ }
21
+
22
+ if (cue.nestedCues && (cue.nestedCues instanceof Array)) {
23
+ cue.nestedCues = cue.nestedCues.map(mapExpected);
24
+ }
25
+
26
+ if (cue.isContainer == undefined) {
27
+ // If not specified to be true, check for isContainer to be false.
28
+ cue.isContainer = false;
29
+ }
30
+
31
+ return jasmine.objectContaining(cue);
32
+ };
33
+
34
+ /**
35
+ * @param {!Object} properties
36
+ * @return {!shaka.extern.Cue}
37
+ */
38
+ const makeContainer = (properties) => {
39
+ const region = {
40
+ id: '',
41
+ viewportAnchorX: 0,
42
+ viewportAnchorY: 0,
43
+ regionAnchorX: 0,
44
+ regionAnchorY: 0,
45
+ width: 100,
46
+ height: 100,
47
+ widthUnits: shaka.text.CueRegion.units.PERCENTAGE,
48
+ heightUnits: shaka.text.CueRegion.units.PERCENTAGE,
49
+ viewportAnchorUnits: shaka.text.CueRegion.units.PERCENTAGE,
50
+ scroll: '',
51
+ };
52
+ const containerCue = /** @type {!shaka.extern.Cue} */ ({
53
+ region,
54
+ nestedCues: jasmine.any(Object),
55
+ payload: '',
56
+ startTime: 0,
57
+ endTime: Infinity,
58
+ isContainer: true,
59
+ });
60
+ Object.assign(containerCue, properties);
61
+ return mapExpected(containerCue);
62
+ };
63
+
64
+ if (expectedCues.length == 0 && !divProperties) {
65
+ expect(actualCues.length).toBe(0);
66
+ } else {
67
+ // Body.
68
+ expect(actualCues.length).toBe(1);
69
+ const body = actualCues[0];
70
+ expect(body).toEqual(makeContainer(bodyProperties));
71
+
72
+ // Div.
73
+ expect(body.nestedCues.length).toBe(1);
74
+ const div = body.nestedCues[0];
75
+ expect(div).toEqual(makeContainer(divProperties || bodyProperties));
76
+
77
+ // Cues.
78
+ expect(div.nestedCues).toEqual(expectedCues.map(mapExpected));
79
+ }
80
+ }
81
+ };
@@ -4,6 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
+ goog.require('shaka.test.TtmlUtils');
7
8
  goog.require('shaka.test.Util');
8
9
  goog.require('shaka.text.Mp4TtmlParser');
9
10
  goog.require('shaka.util.BufferUtils');
@@ -48,7 +49,14 @@ describe('Mp4TtmlParser', () => {
48
49
  parser.parseInit(ttmlInitSegment);
49
50
  const time = {periodStart: 0, segmentStart: 0, segmentEnd: 0};
50
51
  const ret = parser.parseMedia(ttmlSegmentMultipleMDAT, time);
51
- expect(ret.length).toBe(20);
52
+ // Bodies.
53
+ expect(ret.length).toBe(2);
54
+ // Divs.
55
+ expect(ret[0].nestedCues.length).toBe(1);
56
+ expect(ret[1].nestedCues.length).toBe(1);
57
+ // Cues.
58
+ expect(ret[0].nestedCues[0].nestedCues.length).toBe(10);
59
+ expect(ret[1].nestedCues[0].nestedCues.length).toBe(10);
52
60
  });
53
61
 
54
62
  it('accounts for offset', () => {
@@ -159,22 +167,7 @@ describe('Mp4TtmlParser', () => {
159
167
  parser.parseInit(ttmlInitSegment);
160
168
  const time = {periodStart: 0, segmentStart: 0, segmentEnd: 0};
161
169
  const result = parser.parseMedia(ttmlSegment, time);
162
- verifyHelper(cues, result);
170
+ shaka.test.TtmlUtils.verifyHelper(
171
+ cues, result, {startTime: 23, endTime: 53.5});
163
172
  });
164
-
165
- function verifyHelper(/** !Array */ expected, /** !Array */ actual) {
166
- const mapExpected = (cue) => {
167
- if (cue.region) {
168
- cue.region = jasmine.objectContaining(cue.region);
169
- }
170
-
171
- if (cue.nestedCues) {
172
- cue.nestedCues = cue.nestedCues.map(mapExpected);
173
- }
174
-
175
- return jasmine.objectContaining(cue);
176
- };
177
-
178
- expect(actual).toEqual(expected.map(mapExpected));
179
- }
180
173
  });