shaka-player 3.1.4 → 3.3.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 (214) 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 +6 -5
  5. package/CHANGELOG.md +363 -0
  6. package/CONTRIBUTORS +4 -2
  7. package/README.md +4 -4
  8. package/build/types/core +3 -0
  9. package/build/types/offline +1 -0
  10. package/build/types/polyfill +2 -0
  11. package/build/types/ui +2 -0
  12. package/demo/common/asset.js +9 -7
  13. package/demo/common/assets.js +28 -1
  14. package/demo/common/message_ids.js +15 -2
  15. package/demo/config.js +35 -2
  16. package/demo/index.html +1 -1
  17. package/demo/locales/en.json +14 -1
  18. package/demo/locales/source.json +56 -4
  19. package/demo/main.js +2 -1
  20. package/dist/controls.css +26 -2
  21. package/dist/controls.css.map +1 -1
  22. package/dist/demo.compiled.debug.js +24 -21
  23. package/dist/demo.compiled.debug.map +3 -3
  24. package/dist/demo.compiled.js +24 -21
  25. package/dist/demo.compiled.map +3 -3
  26. package/dist/deps.js +33 -25
  27. package/dist/locales.js +31 -29
  28. package/dist/receiver.compiled.debug.js +14 -12
  29. package/dist/receiver.compiled.debug.map +3 -3
  30. package/dist/receiver.compiled.js +14 -12
  31. package/dist/receiver.compiled.map +3 -3
  32. package/dist/shaka-player.compiled.d.ts +258 -20
  33. package/dist/shaka-player.compiled.debug.d.ts +258 -20
  34. package/dist/shaka-player.compiled.debug.externs.js +1005 -695
  35. package/dist/shaka-player.compiled.debug.js +720 -640
  36. package/dist/shaka-player.compiled.debug.map +4 -4
  37. package/dist/shaka-player.compiled.externs.js +1005 -695
  38. package/dist/shaka-player.compiled.js +850 -817
  39. package/dist/shaka-player.compiled.map +4 -4
  40. package/dist/shaka-player.ui.d.ts +274 -21
  41. package/dist/shaka-player.ui.debug.d.ts +274 -21
  42. package/dist/shaka-player.ui.debug.externs.js +766 -429
  43. package/dist/shaka-player.ui.debug.js +863 -765
  44. package/dist/shaka-player.ui.debug.map +4 -4
  45. package/dist/shaka-player.ui.externs.js +766 -429
  46. package/dist/shaka-player.ui.js +1042 -996
  47. package/dist/shaka-player.ui.map +4 -4
  48. package/docs/design/bg-fetch-after.gv +29 -0
  49. package/docs/design/bg-fetch-after.gv.png +0 -0
  50. package/docs/design/bg-fetch-before.gv +18 -0
  51. package/docs/design/bg-fetch-before.gv.png +0 -0
  52. package/docs/design/bg-fetch.md +134 -0
  53. package/docs/tutorials/blob-url.md +15 -0
  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/aria.js +6 -0
  58. package/externs/ima.js +3 -0
  59. package/externs/shaka/ads.js +29 -1
  60. package/externs/shaka/manifest.js +18 -2
  61. package/externs/shaka/manifest_parser.js +10 -1
  62. package/externs/shaka/net.js +20 -4
  63. package/externs/shaka/offline.js +36 -2
  64. package/externs/shaka/player.js +182 -13
  65. package/externs/shaka/text.js +24 -10
  66. package/externs/texttrack.js +3 -0
  67. package/externs/webcrypto.js +18 -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/ad_manager.js +16 -15
  72. package/lib/ads/client_side_ad.js +8 -0
  73. package/lib/ads/client_side_ad_manager.js +14 -6
  74. package/lib/ads/server_side_ad.js +7 -0
  75. package/lib/ads/server_side_ad_manager.js +19 -2
  76. package/lib/cast/cast_proxy.js +8 -0
  77. package/lib/cast/cast_utils.js +7 -1
  78. package/lib/cea/cea608_data_channel.js +56 -56
  79. package/lib/cea/cea608_memory.js +33 -33
  80. package/lib/cea/cea708_service.js +43 -43
  81. package/lib/cea/cea708_window.js +38 -38
  82. package/lib/cea/cea_decoder.js +13 -14
  83. package/lib/cea/cea_utils.js +23 -23
  84. package/lib/cea/dtvcc_packet_builder.js +7 -7
  85. package/lib/cea/i_caption_decoder.js +2 -3
  86. package/lib/cea/i_cea_parser.js +2 -2
  87. package/lib/cea/mp4_cea_parser.js +6 -6
  88. package/lib/dash/dash_parser.js +53 -14
  89. package/lib/dash/segment_base.js +25 -1
  90. package/lib/dash/segment_list.js +18 -9
  91. package/lib/dash/segment_template.js +23 -10
  92. package/lib/hls/hls_parser.js +210 -30
  93. package/lib/media/closed_caption_parser.js +1 -2
  94. package/lib/media/drm_engine.js +162 -192
  95. package/lib/media/quality_observer.js +291 -0
  96. package/lib/media/segment_index.js +9 -1
  97. package/lib/media/segment_reference.js +37 -5
  98. package/lib/media/streaming_engine.js +48 -10
  99. package/lib/net/http_fetch_plugin.js +31 -11
  100. package/lib/net/http_plugin_utils.js +1 -0
  101. package/lib/net/http_xhr_plugin.js +40 -14
  102. package/lib/net/networking_engine.js +82 -18
  103. package/lib/offline/download_info.js +68 -0
  104. package/lib/offline/download_manager.js +14 -7
  105. package/lib/offline/indexeddb/base_storage_cell.js +35 -0
  106. package/lib/offline/indexeddb/storage_mechanism.js +1 -1
  107. package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
  108. package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
  109. package/lib/offline/indexeddb/v5_storage_cell.js +5 -0
  110. package/lib/offline/manifest_converter.js +3 -1
  111. package/lib/offline/storage.js +404 -297
  112. package/lib/offline/stored_content_utils.js +2 -0
  113. package/lib/player.js +622 -153
  114. package/lib/polyfill/aria.js +82 -0
  115. package/lib/polyfill/random_uuid.js +52 -0
  116. package/lib/routing/walker.js +2 -3
  117. package/lib/text/cue.js +12 -0
  118. package/lib/text/srt_text_parser.js +4 -4
  119. package/lib/text/text_engine.js +2 -2
  120. package/lib/text/ttml_text_parser.js +25 -2
  121. package/lib/text/ui_text_displayer.js +2 -2
  122. package/lib/text/vtt_text_parser.js +2 -2
  123. package/lib/text/web_vtt_generator.js +55 -12
  124. package/lib/util/cmcd_manager.js +826 -0
  125. package/lib/util/error.js +12 -0
  126. package/lib/util/language_utils.js +12 -0
  127. package/lib/util/manifest_parser_utils.js +1 -0
  128. package/lib/util/mp4_box_parsers.js +20 -20
  129. package/lib/util/multi_map.js +8 -0
  130. package/lib/util/mutex.js +52 -0
  131. package/lib/util/periods.js +98 -64
  132. package/lib/util/player_configuration.js +31 -1
  133. package/lib/util/stream_utils.js +140 -85
  134. package/lib/util/xml_utils.js +31 -12
  135. package/package.json +1 -1
  136. package/roadmap.md +24 -22
  137. package/shaka-player.uncompiled.js +4 -0
  138. package/test/cast/cast_utils_unit.js +1 -0
  139. package/test/cea/cea608_memory_unit.js +1 -1
  140. package/test/cea/cea708_service_unit.js +8 -8
  141. package/test/cea/cea708_window_unit.js +6 -6
  142. package/test/cea/cea_decoder_unit.js +1 -1
  143. package/test/cea/dtvcc_packet_builder_unit.js +2 -2
  144. package/test/dash/dash_parser_content_protection_unit.js +2 -0
  145. package/test/dash/dash_parser_live_unit.js +101 -1
  146. package/test/dash/dash_parser_manifest_unit.js +78 -2
  147. package/test/dash/dash_parser_segment_base_unit.js +2 -0
  148. package/test/dash/dash_parser_segment_list_unit.js +2 -1
  149. package/test/dash/dash_parser_segment_template_unit.js +2 -1
  150. package/test/hls/hls_live_unit.js +2 -0
  151. package/test/hls/hls_parser_unit.js +252 -0
  152. package/test/media/drm_engine_integration.js +86 -12
  153. package/test/media/drm_engine_unit.js +310 -450
  154. package/test/media/quality_observer_unit.js +139 -0
  155. package/test/media/segment_reference_unit.js +16 -1
  156. package/test/media/streaming_engine_integration.js +2 -1
  157. package/test/media/streaming_engine_unit.js +2 -0
  158. package/test/net/http_plugin_unit.js +20 -15
  159. package/test/offline/manifest_convert_unit.js +2 -0
  160. package/test/offline/storage_integration.js +117 -23
  161. package/test/player_integration.js +151 -0
  162. package/test/player_src_equals_integration.js +52 -0
  163. package/test/player_unit.js +11 -33
  164. package/test/test/assets/chapters.srt +11 -0
  165. package/test/test/assets/chapters.vtt +10 -0
  166. package/test/test/util/cea_utils.js +12 -12
  167. package/test/test/util/dash_parser_util.js +4 -0
  168. package/test/test/util/fake_ad.js +7 -0
  169. package/test/test/util/fake_ad_manager.js +7 -0
  170. package/test/test/util/fake_drm_engine.js +9 -2
  171. package/test/test/util/manifest_generator.js +5 -2
  172. package/test/test/util/manifest_parser_util.js +3 -1
  173. package/test/test/util/test_scheme.js +14 -1
  174. package/test/text/ttml_text_parser_unit.js +47 -0
  175. package/test/text/web_vtt_generator_unit.js +81 -7
  176. package/test/ui/ui_unit.js +250 -0
  177. package/test/util/cmcd_manager_unit.js +277 -0
  178. package/test/util/stream_utils_unit.js +118 -10
  179. package/ui/airplay_button.js +2 -1
  180. package/ui/audio_language_selection.js +9 -5
  181. package/ui/cast_button.js +5 -6
  182. package/ui/constants.js +0 -3
  183. package/ui/context_menu.js +109 -0
  184. package/ui/controls.js +41 -7
  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 +16 -8
  189. package/ui/fullscreen_button.js +2 -3
  190. package/ui/language_utils.js +1 -1
  191. package/ui/less/buttons.less +0 -4
  192. package/ui/less/containers.less +74 -0
  193. package/ui/less/overflow_menu.less +0 -10
  194. package/ui/less/tooltip.less +97 -0
  195. package/ui/locales/en.json +1 -0
  196. package/ui/locales/source.json +4 -0
  197. package/ui/loop_button.js +6 -3
  198. package/ui/mute_button.js +3 -4
  199. package/ui/overflow_menu.js +7 -28
  200. package/ui/pip_button.js +10 -7
  201. package/ui/play_button.js +2 -2
  202. package/ui/playback_rate_selection.js +11 -15
  203. package/ui/presentation_time.js +1 -3
  204. package/ui/resolution_selection.js +11 -7
  205. package/ui/rewind_button.js +17 -9
  206. package/ui/seek_bar.js +6 -6
  207. package/ui/settings_menu.js +36 -4
  208. package/ui/small_play_button.js +1 -0
  209. package/ui/spacer.js +1 -1
  210. package/ui/statistics_button.js +253 -0
  211. package/ui/text_selection.js +19 -15
  212. package/ui/ui.js +30 -0
  213. package/ui/ui_utils.js +1 -1
  214. package/ui/volume_bar.js +2 -4
@@ -87,6 +87,41 @@ describe('Player', () => {
87
87
  });
88
88
  }); // describe('attach')
89
89
 
90
+ describe('updateStartTime() in manifestparsed event handler', () => {
91
+ it('does not get segments prior to startTime', async () => {
92
+ player.addEventListener('manifestparsed', () => {
93
+ player.updateStartTime(24);
94
+ });
95
+ const results = {
96
+ requestedVideoSegment0: false,
97
+ requestedVideoSegment1: false,
98
+ requestedVideoSegment2: false,
99
+ };
100
+ const expected = {
101
+ requestedVideoSegment0: false,
102
+ requestedVideoSegment1: false,
103
+ requestedVideoSegment2: true,
104
+ };
105
+ player.getNetworkingEngine().registerRequestFilter(
106
+ (type, request) => {
107
+ if (request.uris[0] == 'test:sintel/video/0') {
108
+ results.requestedVideoSegment0 = true;
109
+ }
110
+ if (request.uris[0] == 'test:sintel/video/1') {
111
+ results.requestedVideoSegment1 = true;
112
+ }
113
+ if (request.uris[0] == 'test:sintel/video/2') {
114
+ results.requestedVideoSegment2 = true;
115
+ }
116
+ });
117
+ await player.load('test:sintel_compiled');
118
+ video.play();
119
+ await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 25, 30);
120
+ expect(results).toEqual(expected);
121
+ });
122
+ });
123
+
124
+
90
125
  describe('getStats', () => {
91
126
  it('gives stats about current stream', async () => {
92
127
  // This is tested more in player_unit.js. This is here to test the public
@@ -652,6 +687,70 @@ describe('Player', () => {
652
687
  });
653
688
  });
654
689
 
690
+ describe('mediaQualityChanges', () => {
691
+ /** @type {!jasmine.Spy} */
692
+ let onQualityChange;
693
+ /** @type {!shaka.test.Waiter} */
694
+ let waiter;
695
+
696
+ const qualityChange1 = jasmine.objectContaining({
697
+ mediaQuality: jasmine.objectContaining({
698
+ bandwidth: 1,
699
+ codecs: 'mp4a.40.2',
700
+ contentType: 'audio',
701
+ mimeType: 'audio/mp4',
702
+ }),
703
+ type: 'mediaqualitychanged',
704
+ position: jasmine.any(Number),
705
+ });
706
+ const qualityChange2 = jasmine.objectContaining({
707
+ mediaQuality: jasmine.objectContaining({
708
+ bandwidth: 1,
709
+ codecs: 'avc1.42c01e',
710
+ contentType: 'video',
711
+ mimeType: 'video/mp4',
712
+ }),
713
+ type: 'mediaqualitychanged',
714
+ position: jasmine.any(Number),
715
+ });
716
+
717
+ beforeEach(() => {
718
+ onQualityChange = jasmine.createSpy('onQualityChange');
719
+ // const spyFunc = Util.spyFunc(onQualityChange);
720
+ player.addEventListener('mediaqualitychanged',
721
+ Util.spyFunc(onQualityChange));
722
+ waiter = new shaka.test.Waiter(eventManager)
723
+ .timeoutAfter(10)
724
+ .failOnTimeout(true);
725
+ });
726
+
727
+ it('emits audio/video quality changes at start when enabled', async () => {
728
+ player.configure('streaming.observeQualityChanges', true);
729
+
730
+ await player.load('test:sintel_compiled');
731
+ video.play();
732
+
733
+ // Wait for the video to start playback. If it takes longer than 10
734
+ // seconds, fail the test.
735
+ await waiter.waitForMovementOrFailOnTimeout(video, 10);
736
+ expect(onQualityChange).toHaveBeenCalledTimes(2);
737
+ expect(onQualityChange).toHaveBeenCalledWith(qualityChange1);
738
+ expect(onQualityChange).toHaveBeenCalledWith(qualityChange2);
739
+ });
740
+
741
+ it('does not emit quality changes at start when disabled', async () => {
742
+ player.configure('streaming.observeQualityChanges', false);
743
+
744
+ await player.load('test:sintel_compiled');
745
+ video.play();
746
+
747
+ // Wait for the video to start playback. If it takes longer than 10
748
+ // seconds, fail the test.
749
+ await waiter.waitForMovementOrFailOnTimeout(video, 10);
750
+ expect(onQualityChange).not.toHaveBeenCalled();
751
+ });
752
+ });
753
+
655
754
  describe('seek range', () => {
656
755
  // Regression test for Issue #3675.
657
756
  it('has a reasonable seek range after going from live to VOD', async () => {
@@ -959,4 +1058,56 @@ describe('Player', () => {
959
1058
  }
960
1059
  });
961
1060
  }); // describe('unloading')
1061
+
1062
+ describe('chapters', () => {
1063
+ it('add external chapters in vtt format', async () => {
1064
+ await player.load('test:sintel_no_text_compiled');
1065
+ const locationUri = new goog.Uri(location.href);
1066
+ const partialUri = new goog.Uri('/base/test/test/assets/chapters.vtt');
1067
+ const absoluteUri = locationUri.resolve(partialUri);
1068
+ await player.addChaptersTrack(absoluteUri.toString(), 'en');
1069
+
1070
+ await shaka.test.Util.delay(1.5);
1071
+
1072
+ const chapters = player.getChapters('en');
1073
+ expect(chapters.length).toBe(3);
1074
+ const chapter1 = chapters[0];
1075
+ expect(chapter1.title).toBe('Chapter 1');
1076
+ expect(chapter1.startTime).toBe(0);
1077
+ expect(chapter1.endTime).toBe(5);
1078
+ const chapter2 = chapters[1];
1079
+ expect(chapter2.title).toBe('Chapter 2');
1080
+ expect(chapter2.startTime).toBe(5);
1081
+ expect(chapter2.endTime).toBe(30);
1082
+ const chapter3 = chapters[2];
1083
+ expect(chapter3.title).toBe('Chapter 3');
1084
+ expect(chapter3.startTime).toBe(30);
1085
+ expect(chapter3.endTime).toBe(61.349);
1086
+ });
1087
+
1088
+ it('add external chapters in srt format', async () => {
1089
+ await player.load('test:sintel_no_text_compiled');
1090
+ const locationUri = new goog.Uri(location.href);
1091
+ const partialUri = new goog.Uri('/base/test/test/assets/chapters.srt');
1092
+ const absoluteUri = locationUri.resolve(partialUri);
1093
+ await player.addChaptersTrack(absoluteUri.toString(), 'en');
1094
+
1095
+ await shaka.test.Util.delay(1.5);
1096
+
1097
+ const chapters = player.getChapters('en');
1098
+ expect(chapters.length).toBe(3);
1099
+ const chapter1 = chapters[0];
1100
+ expect(chapter1.title).toBe('Chapter 1');
1101
+ expect(chapter1.startTime).toBe(0);
1102
+ expect(chapter1.endTime).toBe(5);
1103
+ const chapter2 = chapters[1];
1104
+ expect(chapter2.title).toBe('Chapter 2');
1105
+ expect(chapter2.startTime).toBe(5);
1106
+ expect(chapter2.endTime).toBe(30);
1107
+ const chapter3 = chapters[2];
1108
+ expect(chapter3.title).toBe('Chapter 3');
1109
+ expect(chapter3.startTime).toBe(30);
1110
+ expect(chapter3.endTime).toBe(61.349);
1111
+ });
1112
+ }); // describe('chapters')
962
1113
  });
@@ -326,6 +326,58 @@ describe('Player Src Equals', () => {
326
326
  expect(newTrack).toBeTruthy();
327
327
  });
328
328
 
329
+ it('add external chapters in vtt format', async () => {
330
+ await loadWithSrcEquals(SMALL_MP4_CONTENT_URI, /* startTime= */ null);
331
+
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');
336
+
337
+ await shaka.test.Util.delay(1.5);
338
+
339
+ const chapters = player.getChapters('en');
340
+ expect(chapters.length).toBe(3);
341
+ const chapter1 = chapters[0];
342
+ expect(chapter1.title).toBe('Chapter 1');
343
+ expect(chapter1.startTime).toBe(0);
344
+ expect(chapter1.endTime).toBe(5);
345
+ const chapter2 = chapters[1];
346
+ expect(chapter2.title).toBe('Chapter 2');
347
+ expect(chapter2.startTime).toBe(5);
348
+ expect(chapter2.endTime).toBe(30);
349
+ const chapter3 = chapters[2];
350
+ expect(chapter3.title).toBe('Chapter 3');
351
+ expect(chapter3.startTime).toBe(30);
352
+ expect(chapter3.endTime).toBe(61.349);
353
+ });
354
+
355
+ it('add external chapters in srt format', async () => {
356
+ await loadWithSrcEquals(SMALL_MP4_CONTENT_URI, /* startTime= */ null);
357
+
358
+ const locationUri = new goog.Uri(location.href);
359
+ const partialUri = new goog.Uri('/base/test/test/assets/chapters.srt');
360
+ const absoluteUri = locationUri.resolve(partialUri);
361
+ await player.addChaptersTrack(absoluteUri.toString(), 'en');
362
+
363
+ await shaka.test.Util.delay(1.5);
364
+
365
+ const chapters = player.getChapters('en');
366
+ expect(chapters.length).toBe(3);
367
+ const chapter1 = chapters[0];
368
+ expect(chapter1.title).toBe('Chapter 1');
369
+ expect(chapter1.startTime).toBe(0);
370
+ expect(chapter1.endTime).toBe(5);
371
+ const chapter2 = chapters[1];
372
+ expect(chapter2.title).toBe('Chapter 2');
373
+ expect(chapter2.startTime).toBe(5);
374
+ expect(chapter2.endTime).toBe(30);
375
+ const chapter3 = chapters[2];
376
+ expect(chapter3.title).toBe('Chapter 3');
377
+ expect(chapter3.startTime).toBe(30);
378
+ expect(chapter3.endTime).toBe(61.349);
379
+ });
380
+
329
381
  // Since we are not in-charge of streaming, calling |retryStreaming| should
330
382
  // have no effect.
331
383
  it('requesting streaming retry does nothing', async () => {
@@ -2809,16 +2809,7 @@ describe('Player', () => {
2809
2809
  expect(tracks[0].id).toBe(4);
2810
2810
  });
2811
2811
 
2812
-
2813
- for (const useMediaCapabilities of [true, false]) {
2814
- const isEnabled = useMediaCapabilities ? 'enabled' : 'disabled';
2815
- it('removes if key system does not support codec with ' +
2816
- 'MediaCapabilities ' + isEnabled, async () => {
2817
- await testWithUnsupportedCodec(useMediaCapabilities);
2818
- });
2819
- }
2820
-
2821
- async function testWithUnsupportedCodec(useMediaCapabilities) {
2812
+ it('removes if key system does not support codec', async () => {
2822
2813
  manifest = shaka.test.ManifestGenerator.generate((manifest) => {
2823
2814
  manifest.addVariant(0, (variant) => {
2824
2815
  variant.addVideo(1, (stream) => {
@@ -2836,35 +2827,22 @@ describe('Player', () => {
2836
2827
  });
2837
2828
  });
2838
2829
 
2839
- if (useMediaCapabilities) {
2840
- window.shakaMediaCapabilities.decodingInfo = async (config) => {
2841
- await Promise.resolve();
2842
- const videoType = config['video'] ? config['video'].contentType : '';
2843
- if (videoType.includes('video') &&
2830
+ window.shakaMediaCapabilities.decodingInfo = async (config) => {
2831
+ await Promise.resolve();
2832
+ const videoType = config['video'] ? config['video'].contentType : '';
2833
+ if (videoType.includes('video') &&
2844
2834
  videoType.includes('unsupported')) {
2845
- return {supported: false};
2846
- } else {
2847
- return {supported: true};
2848
- }
2849
- };
2850
- } else {
2851
- // We must be careful that our video/unsupported was not filtered out
2852
- // because of MSE support. We are specifically testing EME-based
2853
- // filtering of codecs.
2854
- expect(MediaSource.isTypeSupported('video/unsupported')).toBe(true);
2855
- // Make sure that drm engine will reject the variant with an unsupported
2856
- // video mime type.
2857
- drmEngine.supportsVariant.and.callFake((variant) => {
2858
- return variant.video.codecs != 'unsupported';
2859
- });
2860
- }
2835
+ return {supported: false};
2836
+ } else {
2837
+ return {supported: true};
2838
+ }
2839
+ };
2861
2840
 
2862
- player.configure({useMediaCapabilities: useMediaCapabilities});
2863
2841
  await player.load(fakeManifestUri, 0, fakeMimeType);
2864
2842
  const tracks = player.getVariantTracks();
2865
2843
  expect(tracks.length).toBe(1);
2866
2844
  expect(tracks[0].id).toBe(1);
2867
- }
2845
+ });
2868
2846
 
2869
2847
  it('removes based on bandwidth', async () => {
2870
2848
  manifest = shaka.test.ManifestGenerator.generate((manifest) => {
@@ -0,0 +1,11 @@
1
+ 1
2
+ 00:00,000 --> 00:05,000
3
+ Chapter 1
4
+
5
+ 2
6
+ 00:05,000 --> 00:30,000
7
+ Chapter 2
8
+
9
+ 3
10
+ 00:30,000 --> 01:01,349
11
+ Chapter 3
@@ -0,0 +1,10 @@
1
+ WEBVTT
2
+
3
+ 00:00.000 --> 00:05.000
4
+ Chapter 1
5
+
6
+ 00:05.000 --> 00:30.000
7
+ Chapter 2
8
+
9
+ 00:30.000 --> 01:01.349
10
+ Chapter 3
@@ -16,9 +16,9 @@ goog.require('shaka.text.Cue');
16
16
  shaka.test.CeaUtils = class {
17
17
  /**
18
18
  * Returns a cue with no underline/italics, and default colors
19
- * @param {!number} startTime
20
- * @param {!number} endTime
21
- * @param {!string} payload
19
+ * @param {number} startTime
20
+ * @param {number} endTime
21
+ * @param {string} payload
22
22
  */
23
23
  static createDefaultCue(startTime, endTime, payload) {
24
24
  const cue = new shaka.text.Cue(startTime, endTime, payload);
@@ -29,13 +29,13 @@ shaka.test.CeaUtils = class {
29
29
 
30
30
  /**
31
31
  * Returns a cue with custom underline, italics, color, background color.
32
- * @param {!number} startTime
33
- * @param {!number} endTime
34
- * @param {!string} payload
35
- * @param {!boolean} underline
36
- * @param {!boolean} italics
37
- * @param {!string} textColor
38
- * @param {!string} backgroundColor
32
+ * @param {number} startTime
33
+ * @param {number} endTime
34
+ * @param {string} payload
35
+ * @param {boolean} underline
36
+ * @param {boolean} italics
37
+ * @param {string} textColor
38
+ * @param {string} backgroundColor
39
39
  * @return {!shaka.text.Cue}
40
40
  */
41
41
  static createStyledCue(startTime, endTime, payload, underline,
@@ -54,8 +54,8 @@ shaka.test.CeaUtils = class {
54
54
 
55
55
  /**
56
56
  * Returns a cue that corresponds to a linebreak.
57
- * @param {!number} startTime
58
- * @param {!number} endTime
57
+ * @param {number} startTime
58
+ * @param {number} endTime
59
59
  * @return {!shaka.text.Cue}
60
60
  */
61
61
  static createLineBreakCue(startTime, endTime) {
@@ -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
  */
@@ -53,6 +53,13 @@ shaka.test.FakeAdManager = class extends shaka.util.FakeEventTarget {
53
53
  /** @override */
54
54
  replaceServerSideAdTagParameters(adTagParameters) {}
55
55
 
56
+ /**
57
+ * @override
58
+ */
59
+ getServerSideCuePoints() {
60
+ return [];
61
+ }
62
+
56
63
  /** @override */
57
64
  getStats() {
58
65
  return this.stats_;
@@ -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.
@@ -407,6 +407,8 @@ shaka.test.ManifestGenerator.DrmInfo = class {
407
407
  this.keyIds = new Set();
408
408
  /** @type {string} */
409
409
  this.sessionType = '';
410
+ /** @type {string} */
411
+ this.serverCertificateUri = '';
410
412
 
411
413
  /** @type {shaka.extern.DrmInfo} */
412
414
  const foo = this;
@@ -651,15 +653,16 @@ shaka.test.ManifestGenerator.Stream = class {
651
653
  * @param {!Array.<string>} uris
652
654
  * @param {number} startByte
653
655
  * @param {?number} endByte
656
+ * @param {null|shaka.extern.MediaQualityInfo=} mediaQuality
654
657
  */
655
- setInitSegmentReference(uris, startByte, endByte) {
658
+ setInitSegmentReference(uris, startByte, endByte, mediaQuality) {
656
659
  goog.asserts.assert(this.manifest_,
657
660
  'A top-level generated Manifest is required to use this method!');
658
661
 
659
662
  const getUris = () => uris;
660
663
  this.initSegmentReference_ =
661
664
  new this.manifest_.shaka_.media.InitSegmentReference(
662
- getUris, startByte, endByte);
665
+ getUris, startByte, endByte, mediaQuality);
663
666
  }
664
667
 
665
668
  /**
@@ -56,11 +56,12 @@ shaka.test.ManifestParser = class {
56
56
  * @param {?number=} endByte
57
57
  * @param {number=} timestampOffset
58
58
  * @param {!Array.<!shaka.media.SegmentReference>=} partialReferences
59
+ * @param {?string=} tilesLayout
59
60
  * @return {!shaka.media.SegmentReference}
60
61
  */
61
62
  static makeReference(uri, start, end, baseUri = '',
62
63
  startByte = 0, endByte = null, timestampOffset = 0,
63
- partialReferences = []) {
64
+ partialReferences = [], tilesLayout = '') {
64
65
  const getUris = () => uri.length ? [baseUri + uri] : [];
65
66
 
66
67
  // If a test wants to verify these, they can be set explicitly after
@@ -84,6 +85,7 @@ shaka.test.ManifestParser = class {
84
85
  appendWindowStart,
85
86
  appendWindowEnd,
86
87
  partialReferences,
88
+ tilesLayout,
87
89
  );
88
90
  }
89
91
  };
@@ -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);
@@ -1266,6 +1266,8 @@ describe('TtmlTextParser', () => {
1266
1266
  fontStyle: Cue.fontStyle.ITALIC,
1267
1267
  lineHeight: '20px',
1268
1268
  fontSize: '10em',
1269
+ textStrokeColor: 'blue',
1270
+ textStrokeWidth: '3px',
1269
1271
  },
1270
1272
  {
1271
1273
  startTime: 2,
@@ -1277,6 +1279,7 @@ describe('TtmlTextParser', () => {
1277
1279
  '<tt xmlns:tts="http://www.w3.org/ns/ttml#styling">' +
1278
1280
  '<styling>' +
1279
1281
  '<style xml:id="s1" tts:color="red" ' +
1282
+ 'tts:textOutline="blue 3px" ' +
1280
1283
  'tts:backgroundColor="blue" ' +
1281
1284
  'tts:fontWeight="bold" ' +
1282
1285
  'tts:fontFamily="Times New Roman" ' +
@@ -1295,6 +1298,50 @@ describe('TtmlTextParser', () => {
1295
1298
  {periodStart: 0, segmentStart: 0, segmentEnd: 0});
1296
1299
  });
1297
1300
 
1301
+ it('uses text color if tts:textOutline does not specify color', () => {
1302
+ verifyHelper(
1303
+ [
1304
+ {
1305
+ startTime: 1,
1306
+ endTime: 2,
1307
+ payload: 'Test',
1308
+ color: 'red',
1309
+ textStrokeColor: 'red',
1310
+ textStrokeWidth: '3px',
1311
+ },
1312
+ ],
1313
+ '<tt xmlns:tts="http://www.w3.org/ns/ttml#styling">' +
1314
+ '<styling>' +
1315
+ '<style xml:id="s1" tts:color="red" ' +
1316
+ 'tts:textOutline="3px" />' +
1317
+ '</styling>' +
1318
+ '<body region="subtitleArea"><div>' +
1319
+ '<p begin="00:01.00" end="00:02.00" style="s1">Test</p>' +
1320
+ '</div></body></tt>',
1321
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0});
1322
+ });
1323
+
1324
+ it('does not add an outline if tts:textOutline only contains color', () => {
1325
+ verifyHelper(
1326
+ [
1327
+ {
1328
+ startTime: 1,
1329
+ endTime: 2,
1330
+ payload: 'Test',
1331
+ color: 'red',
1332
+ },
1333
+ ],
1334
+ '<tt xmlns:tts="http://www.w3.org/ns/ttml#styling">' +
1335
+ '<styling>' +
1336
+ '<style xml:id="s1" tts:color="red" ' +
1337
+ 'tts:textOutline="blue" />' +
1338
+ '</styling>' +
1339
+ '<body region="subtitleArea"><div>' +
1340
+ '<p begin="00:01.00" end="00:02.00" style="s1">Test</p>' +
1341
+ '</div></body></tt>',
1342
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0});
1343
+ });
1344
+
1298
1345
  // Regression test for #2623
1299
1346
  it('does not apply background colors to containers', () => {
1300
1347
  verifyHelper(