shaka-player 3.1.0 → 3.1.4

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 (181) hide show
  1. package/AUTHORS +8 -2
  2. package/CHANGELOG.md +209 -0
  3. package/CONTRIBUTORS +10 -3
  4. package/README.md +3 -0
  5. package/build/apps.py +2 -2
  6. package/build/check.py +2 -2
  7. package/build/conformance.textproto +0 -9
  8. package/build/generateExterns.js +1 -1
  9. package/build/misspellings.txt +1 -0
  10. package/build/shakaBuildHelpers.py +6 -5
  11. package/build/subprocessWindowsPatch.py +103 -0
  12. package/demo/common/asset.js +11 -0
  13. package/demo/common/assets.js +1 -1
  14. package/demo/common/message_ids.js +5 -0
  15. package/demo/config.js +2 -1
  16. package/demo/custom.js +84 -3
  17. package/demo/demo.less +13 -1
  18. package/demo/demo_utils.js +1 -0
  19. package/demo/input.js +31 -12
  20. package/demo/input_container.js +24 -1
  21. package/demo/locales/en.json +6 -1
  22. package/demo/locales/source.json +20 -0
  23. package/demo/main.js +5 -1
  24. package/dist/controls.css +2 -2
  25. package/dist/controls.css.map +1 -1
  26. package/dist/demo.compiled.debug.js +99 -91
  27. package/dist/demo.compiled.debug.map +3 -3
  28. package/dist/demo.compiled.js +99 -91
  29. package/dist/demo.compiled.map +3 -3
  30. package/dist/demo.css +1 -1
  31. package/dist/demo.css.map +1 -1
  32. package/dist/deps.js +9 -9
  33. package/dist/locales.js +36 -34
  34. package/dist/receiver.compiled.debug.js +74 -70
  35. package/dist/receiver.compiled.debug.map +3 -3
  36. package/dist/receiver.compiled.js +74 -70
  37. package/dist/receiver.compiled.map +3 -3
  38. package/dist/shaka-player.compiled.d.ts +165 -9
  39. package/dist/shaka-player.compiled.debug.d.ts +165 -9
  40. package/dist/shaka-player.compiled.debug.externs.js +179 -11
  41. package/dist/shaka-player.compiled.debug.js +367 -339
  42. package/dist/shaka-player.compiled.debug.map +4 -4
  43. package/dist/shaka-player.compiled.externs.js +179 -11
  44. package/dist/shaka-player.compiled.js +818 -807
  45. package/dist/shaka-player.compiled.map +4 -4
  46. package/dist/shaka-player.ui.d.ts +165 -9
  47. package/dist/shaka-player.ui.debug.d.ts +165 -9
  48. package/dist/shaka-player.ui.debug.externs.js +181 -13
  49. package/dist/shaka-player.ui.debug.js +459 -429
  50. package/dist/shaka-player.ui.debug.map +4 -4
  51. package/dist/shaka-player.ui.externs.js +181 -13
  52. package/dist/shaka-player.ui.js +973 -961
  53. package/dist/shaka-player.ui.map +4 -4
  54. package/docs/tutorials/fairplay.md +1 -1
  55. package/docs/tutorials/faq.md +25 -0
  56. package/docs/tutorials/index.json +2 -2
  57. package/docs/tutorials/upgrade-v3.md +38 -0
  58. package/docs/tutorials/upgrade.md +3 -3
  59. package/externs/ima.js +4 -0
  60. package/externs/media_capabilities.js +16 -0
  61. package/externs/shaka/ads.js +2 -0
  62. package/externs/shaka/net.js +2 -2
  63. package/externs/shaka/player.js +6 -0
  64. package/karma.conf.js +1 -0
  65. package/lib/abr/simple_abr_manager.js +1 -1
  66. package/lib/ads/ad_manager.js +29 -11
  67. package/lib/ads/client_side_ad_manager.js +76 -86
  68. package/lib/ads/server_side_ad_manager.js +26 -11
  69. package/lib/cast/cast_proxy.js +3 -2
  70. package/lib/cast/cast_receiver.js +2 -1
  71. package/lib/cast/cast_sender.js +2 -2
  72. package/lib/cea/sei_processor.js +24 -17
  73. package/lib/dash/dash_parser.js +107 -4
  74. package/lib/dash/segment_list.js +1 -1
  75. package/lib/dash/segment_template.js +45 -15
  76. package/lib/dependencies/all.js +15 -15
  77. package/lib/hls/hls_parser.js +46 -18
  78. package/lib/media/closed_caption_parser.js +3 -1
  79. package/lib/media/content_workarounds.js +18 -0
  80. package/lib/media/drm_engine.js +20 -1
  81. package/lib/media/gap_jumping_controller.js +8 -4
  82. package/lib/media/media_source_engine.js +1 -2
  83. package/lib/media/playhead.js +1 -1
  84. package/lib/media/presentation_timeline.js +3 -1
  85. package/lib/media/segment_index.js +38 -12
  86. package/lib/media/segment_reference.js +8 -0
  87. package/lib/media/streaming_engine.js +30 -21
  88. package/lib/net/http_fetch_plugin.js +2 -2
  89. package/lib/net/networking_engine.js +3 -2
  90. package/lib/offline/storage.js +4 -0
  91. package/lib/player.js +113 -56
  92. package/lib/polyfill/encryption_scheme.js +2 -0
  93. package/lib/polyfill/fullscreen.js +2 -0
  94. package/lib/polyfill/mathround.js +2 -0
  95. package/lib/polyfill/media_capabilities.js +62 -23
  96. package/lib/polyfill/mediasource.js +8 -0
  97. package/lib/polyfill/orientation.js +3 -1
  98. package/lib/polyfill/patchedmediakeys_apple.js +6 -4
  99. package/lib/polyfill/patchedmediakeys_ms.js +6 -4
  100. package/lib/polyfill/patchedmediakeys_nop.js +2 -0
  101. package/lib/polyfill/patchedmediakeys_webkit.js +6 -4
  102. package/lib/polyfill/pip_webkit.js +2 -0
  103. package/lib/polyfill/storage_estimate.js +2 -0
  104. package/lib/polyfill/video_play_promise.js +2 -0
  105. package/lib/polyfill/videoplaybackquality.js +2 -0
  106. package/lib/polyfill/vttcue.js +2 -0
  107. package/lib/text/cue.js +11 -0
  108. package/lib/text/mp4_ttml_parser.js +3 -0
  109. package/lib/text/text_engine.js +14 -2
  110. package/lib/text/ttml_text_parser.js +52 -30
  111. package/lib/text/ui_text_displayer.js +255 -82
  112. package/lib/text/vtt_text_parser.js +4 -2
  113. package/lib/util/error.js +1 -4
  114. package/lib/util/fake_event.js +53 -7
  115. package/lib/util/mime_utils.js +33 -0
  116. package/lib/util/mp4_box_parsers.js +1 -1
  117. package/lib/util/mp4_parser.js +14 -0
  118. package/lib/util/networking.js +1 -1
  119. package/lib/util/periods.js +132 -37
  120. package/lib/util/platform.js +13 -1
  121. package/lib/util/stream_utils.js +46 -7
  122. package/package.json +3 -3
  123. package/test/cast/cast_proxy_unit.js +12 -6
  124. package/test/cast/cast_receiver_integration.js +1 -1
  125. package/test/cast/cast_utils_unit.js +1 -1
  126. package/test/cea/mp4_cea_parser_unit.js +26 -0
  127. package/test/dash/dash_parser_live_unit.js +1 -0
  128. package/test/dash/dash_parser_manifest_unit.js +187 -1
  129. package/test/dash/dash_parser_segment_template_unit.js +3 -3
  130. package/test/demo/demo_unit.js +0 -1
  131. package/test/hls/hls_parser_unit.js +45 -1
  132. package/test/media/closed_caption_parser_unit.js +20 -0
  133. package/test/media/drm_engine_unit.js +59 -3
  134. package/test/media/playhead_unit.js +27 -1
  135. package/test/media/presentation_timeline_unit.js +19 -0
  136. package/test/media/segment_index_unit.js +76 -3
  137. package/test/media/streaming_engine_unit.js +3 -3
  138. package/test/player_integration.js +38 -0
  139. package/test/player_unit.js +125 -6
  140. package/test/test/assets/3675/chunk-stream0-00001.m4s +0 -0
  141. package/test/test/assets/3675/chunk-stream0-00002.m4s +0 -0
  142. package/test/test/assets/3675/chunk-stream0-00003.m4s +0 -0
  143. package/test/test/assets/3675/chunk-stream0-00004.m4s +0 -0
  144. package/test/test/assets/3675/chunk-stream0-00005.m4s +0 -0
  145. package/test/test/assets/3675/chunk-stream0-00006.m4s +0 -0
  146. package/test/test/assets/3675/chunk-stream0-00007.m4s +0 -0
  147. package/test/test/assets/3675/dash_0.mpd +30 -0
  148. package/test/test/assets/3675/dash_1.mpd +30 -0
  149. package/test/test/assets/3675/dash_2.mpd +30 -0
  150. package/test/test/assets/3675/dash_3.mpd +30 -0
  151. package/test/test/assets/3675/dash_4.mpd +30 -0
  152. package/test/test/assets/3675/dash_5.mpd +26 -0
  153. package/test/test/assets/3675/init-stream0.m4s +0 -0
  154. package/test/test/assets/empty_caption_video_init.mp4 +0 -0
  155. package/test/test/assets/empty_caption_video_segment.mp4 +0 -0
  156. package/test/test/util/fake_ad_manager.js +4 -1
  157. package/test/test/util/simple_fakes.js +5 -3
  158. package/test/test/util/waiter.js +36 -2
  159. package/test/text/ttml_text_parser_unit.js +55 -0
  160. package/test/text/ui_text_displayer_unit.js +95 -18
  161. package/test/text/vtt_text_parser_unit.js +17 -1
  162. package/test/ui/localization_unit.js +15 -14
  163. package/test/ui/text_displayer_layout_unit.js +52 -1
  164. package/test/ui/ui_unit.js +4 -0
  165. package/test/util/mp4_box_parsers_unit.js +28 -0
  166. package/test/util/periods_unit.js +190 -2
  167. package/test/util/stream_utils_unit.js +56 -5
  168. package/ui/airplay_button.js +5 -0
  169. package/ui/big_play_button.js +10 -0
  170. package/ui/cast_button.js +2 -3
  171. package/ui/controls.js +9 -7
  172. package/ui/less/containers.less +10 -5
  173. package/ui/locales/en.json +1 -0
  174. package/ui/locales/ru.json +6 -6
  175. package/ui/locales/source.json +4 -0
  176. package/ui/localization.js +28 -51
  177. package/ui/pip_button.js +2 -3
  178. package/ui/play_button.js +10 -10
  179. package/ui/small_play_button.js +12 -0
  180. package/ui/ui.js +1 -1
  181. package/docs/tutorials/upgrade-v2-4.md +0 -481
@@ -10,6 +10,8 @@ goog.require('shaka.log');
10
10
  goog.require('shaka.media.BufferingObserver');
11
11
  goog.require('shaka.media.ManifestParser');
12
12
  goog.require('shaka.media.PresentationTimeline');
13
+ goog.require('shaka.media.SegmentReference');
14
+ goog.require('shaka.media.SegmentIndex');
13
15
  goog.require('shaka.test.FakeAbrManager');
14
16
  goog.require('shaka.test.FakeDrmEngine');
15
17
  goog.require('shaka.test.FakeManifestParser');
@@ -34,7 +36,7 @@ describe('Player', () => {
34
36
  const originalLogWarn = shaka.log.warning;
35
37
  const originalLogAlwaysWarn = shaka.log.alwaysWarn;
36
38
  const originalIsTypeSupported = window.MediaSource.isTypeSupported;
37
- const originalDecodingInfo = navigator.mediaCapabilities.decodingInfo;
39
+ const originalDecodingInfo = window.shakaMediaCapabilities.decodingInfo;
38
40
 
39
41
  const fakeManifestUri = 'fake-manifest-uri';
40
42
  const fakeMimeType = 'application/test';
@@ -91,7 +93,7 @@ describe('Player', () => {
91
93
  // Since this is not an integration test, we don't want MediaCapabilities to
92
94
  // fail assertions based on browser support for types. Pretend that all
93
95
  // video and audio types are supported.
94
- navigator.mediaCapabilities.decodingInfo = async (config) => {
96
+ window.shakaMediaCapabilities.decodingInfo = async (config) => {
95
97
  await Promise.resolve();
96
98
  const videoType = config['video'] ?
97
99
  config['video'].contentType.split('/')[0] : null;
@@ -175,7 +177,7 @@ describe('Player', () => {
175
177
  shaka.log.alwaysWarn = originalLogAlwaysWarn;
176
178
  window.MediaSource.isTypeSupported = originalIsTypeSupported;
177
179
  shaka.media.ManifestParser.unregisterParserByMime(fakeMimeType);
178
- navigator.mediaCapabilities.decodingInfo = originalDecodingInfo;
180
+ window.shakaMediaCapabilities.decodingInfo = originalDecodingInfo;
179
181
  }
180
182
  });
181
183
 
@@ -1986,6 +1988,24 @@ describe('Player', () => {
1986
1988
  expect(variantChanged).not.toHaveBeenCalled();
1987
1989
  });
1988
1990
  });
1991
+
1992
+ it('chooses the configured text language and role at start', async () => {
1993
+ player.configure({
1994
+ preferredTextLanguage: 'en',
1995
+ preferredTextRole: 'commentary',
1996
+ });
1997
+
1998
+ await player.load(fakeManifestUri, 0, fakeMimeType);
1999
+
2000
+ // Text was turned on during startup.
2001
+ expect(player.isTextTrackVisible()).toBe(true);
2002
+
2003
+ expect(getActiveTextTrack()).toEqual(jasmine.objectContaining({
2004
+ id: 52,
2005
+ language: 'en',
2006
+ roles: ['commentary'],
2007
+ }));
2008
+ });
1989
2009
  }); // describe('tracks')
1990
2010
 
1991
2011
  describe('languages', () => {
@@ -2443,7 +2463,7 @@ describe('Player', () => {
2443
2463
  it('throws CONTENT_UNSUPPORTED_BY_BROWSER', async () => {
2444
2464
  window.MediaSource.isTypeSupported = (mimeType) => false;
2445
2465
 
2446
- navigator.mediaCapabilities.decodingInfo = async (config) => {
2466
+ window.shakaMediaCapabilities.decodingInfo = async (config) => {
2447
2467
  await Promise.resolve();
2448
2468
  return {supported: false};
2449
2469
  };
@@ -2817,7 +2837,7 @@ describe('Player', () => {
2817
2837
  });
2818
2838
 
2819
2839
  if (useMediaCapabilities) {
2820
- navigator.mediaCapabilities.decodingInfo = async (config) => {
2840
+ window.shakaMediaCapabilities.decodingInfo = async (config) => {
2821
2841
  await Promise.resolve();
2822
2842
  const videoType = config['video'] ? config['video'].contentType : '';
2823
2843
  if (videoType.includes('video') &&
@@ -2940,7 +2960,7 @@ describe('Player', () => {
2940
2960
 
2941
2961
  manifest.addVariant(1, (variant) => {
2942
2962
  variant.addVideo(2, (stream) => {
2943
- stream.size(200, 1500);
2963
+ stream.size(200, 1024);
2944
2964
  });
2945
2965
  });
2946
2966
 
@@ -3514,6 +3534,105 @@ describe('Player', () => {
3514
3534
  ]);
3515
3535
  });
3516
3536
  });
3537
+
3538
+ describe('getThumbnails', () => {
3539
+ it('returns correct thumbnail position for supplied time', async () => {
3540
+ const uris = () => ['thumbnail'];
3541
+ const ref = new shaka.media.SegmentReference(
3542
+ 0, 60, uris, 0, null, null, 0, 0, Infinity, [],
3543
+ );
3544
+ const index = new shaka.media.SegmentIndex([ref]);
3545
+
3546
+ manifest = shaka.test.ManifestGenerator.generate((manifest) => {
3547
+ manifest.addVariant(0, (variant) => {
3548
+ variant.addVideo(1);
3549
+ });
3550
+ manifest.addImageStream(5, (stream) => {
3551
+ stream.originalId = 'thumbnail';
3552
+ stream.width = 200;
3553
+ stream.height = 150;
3554
+ stream.mimeType = 'image/jpeg';
3555
+ stream.tilesLayout = '2x3';
3556
+ stream.segmentIndex = index;
3557
+ });
3558
+ });
3559
+
3560
+ await player.load(fakeManifestUri, 0, fakeMimeType);
3561
+
3562
+ const thumbnail0 = await player.getThumbnails(5, 0);
3563
+ const thumbnail1 = await player.getThumbnails(5, 11);
3564
+ const thumbnail2 = await player.getThumbnails(5, 21);
3565
+ const thumbnail5 = await player.getThumbnails(5, 51);
3566
+ expect(thumbnail0).toEqual(jasmine.objectContaining({
3567
+ positionX: 0,
3568
+ positionY: 0,
3569
+ width: 100,
3570
+ height: 50,
3571
+ }));
3572
+ expect(thumbnail1).toEqual(jasmine.objectContaining({
3573
+ positionX: 100,
3574
+ positionY: 0,
3575
+ width: 100,
3576
+ height: 50,
3577
+ }));
3578
+ expect(thumbnail2).toEqual(jasmine.objectContaining({
3579
+ positionX: 0,
3580
+ positionY: 50,
3581
+ width: 100,
3582
+ height: 50,
3583
+ }));
3584
+ expect(thumbnail5).toEqual(jasmine.objectContaining({
3585
+ positionX: 100,
3586
+ positionY: 100,
3587
+ width: 100,
3588
+ height: 50,
3589
+ }));
3590
+ });
3591
+
3592
+ it('returns correct duration for a partially-used segment', async () => {
3593
+ const uris = () => ['thumbnail'];
3594
+
3595
+ const ref1 = new shaka.media.SegmentReference(
3596
+ 0, 60, uris, 0, null, null, 0, 0, Infinity);
3597
+ const ref2 = new shaka.media.SegmentReference(
3598
+ 60, 90, uris, 0, null, null, 0, 0, Infinity);
3599
+ ref2.trueEndTime = 120;
3600
+
3601
+ const index = new shaka.media.SegmentIndex([ref1, ref2]);
3602
+
3603
+ manifest = shaka.test.ManifestGenerator.generate((manifest) => {
3604
+ manifest.addVariant(0, (variant) => {
3605
+ variant.addVideo(1);
3606
+ });
3607
+ manifest.addImageStream(5, (stream) => {
3608
+ stream.originalId = 'thumbnail';
3609
+ stream.width = 200;
3610
+ stream.height = 150;
3611
+ stream.mimeType = 'image/jpeg';
3612
+ stream.tilesLayout = '2x3';
3613
+ stream.segmentIndex = index;
3614
+ });
3615
+ });
3616
+
3617
+ await player.load(fakeManifestUri, 0, fakeMimeType);
3618
+
3619
+ const thumbnail0 = await player.getThumbnails(5, 0);
3620
+ expect(thumbnail0.startTime).toBe(0);
3621
+ expect(thumbnail0.duration).toBe(10);
3622
+
3623
+ const thumbnail1 = await player.getThumbnails(5, 10);
3624
+ expect(thumbnail1.startTime).toBe(10);
3625
+ expect(thumbnail1.duration).toBe(10);
3626
+
3627
+ const thumbnail6 = await player.getThumbnails(5, 60);
3628
+ expect(thumbnail6.startTime).toBe(60);
3629
+ expect(thumbnail6.duration).toBe(10);
3630
+
3631
+ const thumbnail8 = await player.getThumbnails(5, 80);
3632
+ expect(thumbnail8.startTime).toBe(80);
3633
+ expect(thumbnail8.duration).toBe(10);
3634
+ });
3635
+ });
3517
3636
  });
3518
3637
 
3519
3638
  /**
@@ -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>
@@ -25,6 +25,9 @@ shaka.test.FakeAdManager = class extends shaka.util.FakeEventTarget {
25
25
  this.stats_ = new shaka.ads.AdsStats();
26
26
  }
27
27
 
28
+ /** @override */
29
+ release() {}
30
+
28
31
  /** @override */
29
32
  setLocale(locale) {}
30
33
 
@@ -75,7 +78,7 @@ shaka.test.FakeAdManager = class extends shaka.util.FakeEventTarget {
75
78
  */
76
79
  startAd(ad) {
77
80
  const event = new shaka.util.FakeEvent(shaka.ads.AdManager.AD_STARTED,
78
- {'ad': ad});
81
+ (new Map()).set('ad', ad));
79
82
 
80
83
  this.dispatchEvent(event);
81
84
  }
@@ -90,13 +90,15 @@ shaka.test.FakeAbrManager = class {
90
90
  /** @extends {shaka.media.StreamingEngine} */
91
91
  shaka.test.FakeStreamingEngine = class {
92
92
  constructor() {
93
- const resolve = () => Promise.resolve();
94
-
95
93
  let activeVariant = null;
96
94
  let activeText = null;
97
95
 
98
96
  /** @type {!jasmine.Spy} */
99
- this.destroy = jasmine.createSpy('destroy').and.callFake(resolve);
97
+ this.destroy = jasmine.createSpy('destroy').and.callFake(() => {
98
+ activeVariant = null;
99
+ activeText = null;
100
+ return Promise.resolve();
101
+ });
100
102
 
101
103
  /** @type {!jasmine.Spy} */
102
104
  this.configure = jasmine.createSpy('configure');
@@ -132,10 +132,43 @@ shaka.test.Waiter = class {
132
132
  * @return {!Promise}
133
133
  */
134
134
  waitForEnd(mediaElement) {
135
- if (mediaElement.ended) {
135
+ // Sometimes, the ended flag is not set, or the event does not fire,
136
+ // (I'm looking at **you**, Safari), so also check if we've reached the
137
+ // duration.
138
+ if (mediaElement.ended ||
139
+ mediaElement.currentTime >= mediaElement.duration) {
136
140
  return Promise.resolve();
137
141
  }
138
- return this.waitForEvent(mediaElement, 'ended');
142
+
143
+ // The name of what we're waiting for.
144
+ const goalName = 'end of media';
145
+
146
+ // Cleanup on timeout.
147
+ const cleanup = () => {
148
+ this.eventManager_.unlisten(mediaElement, 'timeupdate');
149
+ this.eventManager_.unlisten(mediaElement, 'ended');
150
+ };
151
+
152
+ // The conditions for success. Don't rely on either time, or the ended
153
+ // flag, or the ended event, specifically. Any of these is sufficient.
154
+ // This flexibility cuts down on test flake on Safari (currently 14) in
155
+ // particular, where the flag might be set, but the ended event did not
156
+ // fire.
157
+ const p = new Promise((resolve) => {
158
+ this.eventManager_.listen(mediaElement, 'timeupdate', () => {
159
+ if (mediaElement.currentTime >= mediaElement.duration ||
160
+ mediaElement.ended) {
161
+ cleanup();
162
+ resolve();
163
+ }
164
+ });
165
+ this.eventManager_.listen(mediaElement, 'ended', () => {
166
+ cleanup();
167
+ resolve();
168
+ });
169
+ });
170
+
171
+ return this.waitUntilGeneric_(goalName, p, cleanup, mediaElement);
139
172
  }
140
173
 
141
174
  /**
@@ -256,6 +289,7 @@ shaka.test.Waiter = class {
256
289
  'ready state', mediaElement.readyState,
257
290
  'playback rate', mediaElement.playbackRate,
258
291
  'paused', mediaElement.paused,
292
+ 'ended', mediaElement.ended,
259
293
  'buffered', buffered);
260
294
  }
261
295
  };
@@ -295,6 +295,52 @@ describe('TtmlTextParser', () => {
295
295
  {periodStart: 0, segmentStart: 0, segmentEnd: 0});
296
296
  });
297
297
 
298
+ it('inherits timing information of nested cues if unprovided', () => {
299
+ verifyHelper(
300
+ [
301
+ {
302
+ startTime: 62.05,
303
+ endTime: 3723.2,
304
+ nestedCues: [
305
+ {startTime: 62.05, endTime: 3723.2, payload: 'Test'},
306
+ ],
307
+ },
308
+ ],
309
+ '<tt><body>' +
310
+ '<div><div begin="01:02.05" end="01:02:03.200">Test</div></div>' +
311
+ '</body></tt>',
312
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0});
313
+ });
314
+
315
+ it('does not discard cues with image subcues', () => {
316
+ verifyHelper(
317
+ [
318
+ {
319
+ startTime: 62.05,
320
+ endTime: 3723.2,
321
+ nestedCues: [
322
+ {
323
+ startTime: 62.05,
324
+ endTime: 3723.2,
325
+ payload: '',
326
+ backgroundImage: 'data:image/png;base64,base64EncodedImage',
327
+ },
328
+ ],
329
+ },
330
+ ],
331
+ '<tt ' +
332
+ 'xmlns:ttm="http://www.w3.org/ns/ttml#metadata" ' +
333
+ 'xmlns:smpte="http://www.smpte-ra.org/schemas/2052-1/2010/smpte-tt">' +
334
+ '<metadata>' +
335
+ '<smpte:image imageType="PNG" encoding="Base64" xml:id="img_0">' +
336
+ 'base64EncodedImage</smpte:image>' +
337
+ '</metadata><body>' +
338
+ '<div><div begin="01:02.05" end="01:02:03.200" ' +
339
+ 'smpte:backgroundImage="#img_0"></div></div>' +
340
+ '</body></tt>',
341
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0});
342
+ });
343
+
298
344
  it('supports colon formatted time', () => {
299
345
  verifyHelper(
300
346
  [
@@ -430,6 +476,15 @@ describe('TtmlTextParser', () => {
430
476
  {periodStart: 0, segmentStart: 0, segmentEnd: 0});
431
477
  });
432
478
 
479
+ it('supports comments in the body', () => {
480
+ verifyHelper(
481
+ [],
482
+ '<tt><body><div>' +
483
+ '<!-- text-based TTML -->' +
484
+ '</div></body></tt>',
485
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0});
486
+ });
487
+
433
488
  it('parses alignment from textAlign attribute of a region', () => {
434
489
  verifyHelper(
435
490
  [