shaka-player 3.3.4 → 4.0.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 (201) hide show
  1. package/.github/config.yml +1 -0
  2. package/.github/workflows/build-and-test.yaml +0 -1
  3. package/.github/workflows/demo-version-index.yaml +8 -0
  4. package/.github/workflows/release-please.yaml +19 -3
  5. package/.github/workflows/selenium-lab-tests.yaml +0 -1
  6. package/.github/workflows/sync-labels.yaml +33 -0
  7. package/.github/workflows/update-issues.yaml +29 -0
  8. package/.github/workflows/validate-pr-title.yaml +35 -0
  9. package/AUTHORS +1 -0
  10. package/CHANGELOG.md +209 -28
  11. package/CONTRIBUTORS +1 -0
  12. package/README.md +10 -7
  13. package/app-engine/demo-version-index/README.md +3 -3
  14. package/app-engine/demo-version-index/app.yaml +27 -1
  15. package/app-engine/demo-version-index/generate.py +164 -0
  16. package/app-engine/demo-version-index/main.py +4 -155
  17. package/app-engine/demo-version-index/requirements.txt +0 -1
  18. package/build/README.md +2 -2
  19. package/build/compiler.py +1 -1
  20. package/build/generateTsDefs.py +0 -2
  21. package/build/misspellings.txt +1 -0
  22. package/build/shaka-lab.yaml +0 -2
  23. package/build/test.py +7 -1
  24. package/build/types/core +0 -1
  25. package/build/types/polyfill +0 -3
  26. package/demo/common/asset.js +17 -1
  27. package/demo/common/assets.js +29 -0
  28. package/demo/common/message_ids.js +6 -3
  29. package/demo/config.js +10 -11
  30. package/demo/custom.js +39 -0
  31. package/demo/demo_utils.js +0 -1
  32. package/demo/locales/en.json +6 -3
  33. package/demo/locales/source.json +22 -10
  34. package/demo/main.js +9 -6
  35. package/demo/search.js +2 -1
  36. package/dist/controls.css +1 -1
  37. package/dist/demo.compiled.debug.js +71 -64
  38. package/dist/demo.compiled.debug.map +3 -3
  39. package/dist/demo.compiled.js +71 -64
  40. package/dist/demo.compiled.map +3 -3
  41. package/dist/demo.css +1 -1
  42. package/dist/demo.css.map +1 -1
  43. package/dist/deps.js +16 -20
  44. package/dist/locales.js +33 -31
  45. package/dist/receiver.compiled.debug.js +32 -28
  46. package/dist/receiver.compiled.debug.map +3 -3
  47. package/dist/receiver.compiled.js +32 -28
  48. package/dist/receiver.compiled.map +3 -3
  49. package/dist/shaka-player.compiled.d.ts +78 -82
  50. package/dist/shaka-player.compiled.debug.d.ts +78 -82
  51. package/dist/shaka-player.compiled.debug.externs.js +127 -126
  52. package/dist/shaka-player.compiled.debug.js +471 -523
  53. package/dist/shaka-player.compiled.debug.map +4 -4
  54. package/dist/shaka-player.compiled.externs.js +127 -126
  55. package/dist/shaka-player.compiled.js +844 -858
  56. package/dist/shaka-player.compiled.map +4 -4
  57. package/dist/shaka-player.ui.d.ts +80 -82
  58. package/dist/shaka-player.ui.debug.d.ts +80 -82
  59. package/dist/shaka-player.ui.debug.externs.js +135 -126
  60. package/dist/shaka-player.ui.debug.js +531 -581
  61. package/dist/shaka-player.ui.debug.map +4 -4
  62. package/dist/shaka-player.ui.externs.js +135 -126
  63. package/dist/shaka-player.ui.js +991 -1001
  64. package/dist/shaka-player.ui.map +4 -4
  65. package/docs/tutorials/config.md +0 -2
  66. package/docs/tutorials/drm-config.md +5 -0
  67. package/docs/tutorials/fairplay.md +7 -22
  68. package/docs/tutorials/faq.md +0 -11
  69. package/docs/tutorials/index.json +2 -8
  70. package/docs/tutorials/plugins.md +1 -3
  71. package/docs/tutorials/upgrade.md +85 -11
  72. package/externs/polyfill.js +15 -0
  73. package/externs/shaka/manifest.js +5 -1
  74. package/externs/shaka/net.js +12 -0
  75. package/externs/shaka/offline.js +5 -1
  76. package/externs/shaka/player.js +39 -21
  77. package/externs/shaka/text.js +12 -12
  78. package/externs/sourcebuffer.js +15 -0
  79. package/karma.conf.js +4 -0
  80. package/lib/ads/client_side_ad.js +13 -2
  81. package/lib/ads/client_side_ad_manager.js +22 -4
  82. package/lib/cast/cast_utils.js +0 -1
  83. package/lib/dash/content_protection.js +85 -5
  84. package/lib/dash/dash_parser.js +3 -3
  85. package/lib/hls/hls_parser.js +391 -747
  86. package/lib/hls/manifest_text_parser.js +2 -3
  87. package/lib/media/drm_engine.js +102 -37
  88. package/lib/media/gap_jumping_controller.js +10 -45
  89. package/lib/media/media_source_engine.js +157 -31
  90. package/lib/media/playhead.js +2 -5
  91. package/lib/media/presentation_timeline.js +1 -2
  92. package/lib/media/segment_index.js +13 -46
  93. package/lib/media/segment_reference.js +47 -1
  94. package/lib/media/streaming_engine.js +28 -11
  95. package/lib/media/time_ranges_utils.js +4 -9
  96. package/lib/net/networking_engine.js +3 -0
  97. package/lib/offline/indexeddb/storage_mechanism.js +4 -2
  98. package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
  99. package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
  100. package/lib/offline/manifest_converter.js +1 -0
  101. package/lib/offline/storage.js +100 -132
  102. package/lib/player.js +181 -307
  103. package/lib/polyfill/media_capabilities.js +12 -6
  104. package/lib/polyfill/mediasource.js +0 -28
  105. package/lib/polyfill/patchedmediakeys_nop.js +2 -0
  106. package/lib/polyfill/patchedmediakeys_webkit.js +2 -0
  107. package/lib/text/cue.js +0 -6
  108. package/lib/text/lrc_text_parser.js +8 -0
  109. package/lib/text/mp4_ttml_parser.js +8 -0
  110. package/lib/text/mp4_vtt_parser.js +8 -0
  111. package/lib/text/sbv_text_parser.js +8 -0
  112. package/lib/text/simple_text_displayer.js +1 -7
  113. package/lib/text/srt_text_parser.js +8 -0
  114. package/lib/text/ssa_text_parser.js +8 -0
  115. package/lib/text/text_engine.js +19 -3
  116. package/lib/text/ttml_text_parser.js +8 -0
  117. package/lib/text/ui_text_displayer.js +1 -7
  118. package/lib/text/vtt_text_parser.js +27 -5
  119. package/lib/text/web_vtt_generator.js +1 -7
  120. package/lib/util/config_utils.js +25 -0
  121. package/lib/util/error.js +16 -13
  122. package/lib/util/fairplay_utils.js +109 -0
  123. package/lib/util/functional.js +0 -42
  124. package/lib/util/manifest_parser_utils.js +1 -1
  125. package/lib/util/mime_utils.js +50 -1
  126. package/lib/util/periods.js +5 -4
  127. package/lib/util/platform.js +45 -0
  128. package/lib/util/player_configuration.js +26 -20
  129. package/lib/util/pssh.js +23 -4
  130. package/lib/util/stream_utils.js +96 -24
  131. package/lib/util/uint8array_utils.js +0 -16
  132. package/lib/util/xml_utils.js +1 -1
  133. package/package.json +4 -1
  134. package/roadmap.md +19 -19
  135. package/shaka-player.uncompiled.js +0 -3
  136. package/test/cast/cast_utils_unit.js +1 -0
  137. package/test/dash/dash_parser_content_protection_unit.js +44 -0
  138. package/test/dash/dash_parser_manifest_unit.js +0 -24
  139. package/test/dash/dash_parser_segment_template_unit.js +3 -4
  140. package/test/demo/demo_unit.js +2 -1
  141. package/test/hls/hls_live_unit.js +121 -220
  142. package/test/hls/hls_parser_unit.js +515 -432
  143. package/test/hls/manifest_text_parser_unit.js +19 -0
  144. package/test/media/drm_engine_unit.js +86 -120
  145. package/test/media/media_source_engine_integration.js +26 -3
  146. package/test/media/media_source_engine_unit.js +7 -6
  147. package/test/media/playhead_unit.js +27 -191
  148. package/test/media/segment_index_unit.js +15 -25
  149. package/test/media/streaming_engine_integration.js +4 -39
  150. package/test/media/streaming_engine_unit.js +3 -2
  151. package/test/media/time_ranges_utils_unit.js +0 -5
  152. package/test/offline/indexeddb_storage_unit.js +1 -1
  153. package/test/offline/manifest_convert_unit.js +34 -4
  154. package/test/offline/offline_manifest_parser_unit.js +1 -0
  155. package/test/offline/storage_compatibility_unit.js +1 -1
  156. package/test/offline/storage_integration.js +5 -4
  157. package/test/player_external.js +7 -7
  158. package/test/player_integration.js +22 -10
  159. package/test/player_src_equals_integration.js +81 -83
  160. package/test/player_unit.js +124 -1
  161. package/test/test/boot.js +9 -0
  162. package/test/test/externs/filters.js +4 -0
  163. package/test/test/util/fake_media_source_engine.js +11 -4
  164. package/test/test/util/manifest_generator.js +3 -1
  165. package/test/test/util/manifest_parser_util.js +4 -1
  166. package/test/test/util/offline_utils.js +1 -0
  167. package/test/test/util/simple_fakes.js +31 -2
  168. package/test/test/util/streaming_engine_util.js +1 -0
  169. package/test/test/util/test_scheme.js +24 -1
  170. package/test/test/util/util.js +4 -4
  171. package/test/text/cue_integration.js +2 -2
  172. package/test/text/lrc_text_parser_unit.js +6 -7
  173. package/test/text/mp4_ttml_parser_unit.js +6 -4
  174. package/test/text/mp4_vtt_parser_unit.js +6 -5
  175. package/test/text/sbv_text_parser_unit.js +5 -6
  176. package/test/text/srt_text_parser_unit.js +5 -6
  177. package/test/text/ssa_text_parser_unit.js +17 -29
  178. package/test/text/text_engine_unit.js +45 -5
  179. package/test/text/ttml_text_parser_unit.js +77 -77
  180. package/test/text/vtt_text_parser_unit.js +116 -59
  181. package/test/ui/ui_integration.js +0 -16
  182. package/test/ui/ui_unit.js +27 -0
  183. package/test/util/cmcd_manager_unit.js +3 -0
  184. package/test/util/mime_utils_unit.js +54 -0
  185. package/test/util/periods_unit.js +79 -0
  186. package/test/util/stream_utils_unit.js +23 -7
  187. package/ui/controls.js +65 -40
  188. package/ui/fullscreen_button.js +26 -6
  189. package/ui/less/containers.less +3 -3
  190. package/ui/locales/en.json +1 -0
  191. package/ui/locales/source.json +5 -0
  192. package/ui/resolution_selection.js +31 -33
  193. package/ui/ui.js +0 -17
  194. package/docs/tutorials/gsoc-ideas-list.md +0 -3
  195. package/docs/tutorials/upgrade-v2-5.md +0 -441
  196. package/docs/tutorials/upgrade-v3.md +0 -38
  197. package/lib/polyfill/mathround.js +0 -49
  198. package/lib/polyfill/patchedmediakeys_apple.js +0 -744
  199. package/lib/polyfill/patchedmediakeys_ms.js +0 -698
  200. package/lib/util/mutex.js +0 -52
  201. package/test/util/functional_unit.js +0 -82
@@ -25,13 +25,13 @@ describe('VttTextParser', () => {
25
25
  it('supports no cues', () => {
26
26
  verifyHelper([],
27
27
  'WEBVTT',
28
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
28
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
29
29
  });
30
30
 
31
31
  it('supports initial comments', () => {
32
32
  verifyHelper([],
33
33
  'WEBVTT - Comments',
34
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
34
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
35
35
  });
36
36
 
37
37
  it('supports comment blocks', () => {
@@ -39,7 +39,7 @@ describe('VttTextParser', () => {
39
39
  'WEBVTT\n\n' +
40
40
  'NOTE\n' +
41
41
  'This is a comment block',
42
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
42
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
43
43
  });
44
44
 
45
45
  it('supports comment blocks with inital comment', () => {
@@ -47,7 +47,7 @@ describe('VttTextParser', () => {
47
47
  'WEBVTT\n\n' +
48
48
  'NOTE - A header comment\n' +
49
49
  'This is a comment block',
50
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
50
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
51
51
  });
52
52
 
53
53
  it('handles a blank line at the end of the file', () => {
@@ -58,7 +58,7 @@ describe('VttTextParser', () => {
58
58
  'WEBVTT\n\n' +
59
59
  '00:00:20.000 --> 00:00:40.000\n' +
60
60
  'Test\n\n',
61
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
61
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
62
62
  });
63
63
 
64
64
  it('handles no blank line at the end of the file', () => {
@@ -69,8 +69,7 @@ describe('VttTextParser', () => {
69
69
  'WEBVTT\n\n' +
70
70
  '00:00:20.000 --> 00:00:40.000\n' +
71
71
  'Test\n',
72
- {periodStart: 0, segmentStart: 0, segmentEnd: 0,
73
- });
72
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
74
73
  });
75
74
 
76
75
  it('handles no newline after the final text payload', () => {
@@ -81,7 +80,7 @@ describe('VttTextParser', () => {
81
80
  'WEBVTT\n\n' +
82
81
  '00:00:20.000 --> 00:00:40.000\n' +
83
82
  'Test',
84
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
83
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
85
84
  });
86
85
 
87
86
  it('supports cues with no settings', () => {
@@ -97,7 +96,7 @@ describe('VttTextParser', () => {
97
96
  '2\n' +
98
97
  '00:00:40.000 --> 00:00:50.000\n' +
99
98
  'Test2',
100
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
99
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
101
100
  });
102
101
 
103
102
  it('supports cues with no ID', () => {
@@ -111,7 +110,7 @@ describe('VttTextParser', () => {
111
110
  'Test\n\n' +
112
111
  '00:00:40.000 --> 00:00:50.000\n' +
113
112
  'Test2',
114
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
113
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
115
114
  });
116
115
 
117
116
  it('supports comments within cues', () => {
@@ -127,7 +126,7 @@ describe('VttTextParser', () => {
127
126
  'This is a note\n\n' +
128
127
  '00:00:40.000 --> 00:00:50.000\n' +
129
128
  'Test2',
130
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
129
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
131
130
  });
132
131
 
133
132
  it('supports non-integer timecodes', () => {
@@ -138,7 +137,7 @@ describe('VttTextParser', () => {
138
137
  'WEBVTT\n\n' +
139
138
  '00:00:20.100 --> 00:00:40.505\n' +
140
139
  'Test',
141
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
140
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
142
141
  });
143
142
 
144
143
  it('supports large timecodes', () => {
@@ -149,50 +148,50 @@ describe('VttTextParser', () => {
149
148
  'WEBVTT\n\n' +
150
149
  '00:00:20.000 --> 30:00:00.000\n' +
151
150
  'Test',
152
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
151
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
153
152
  });
154
153
 
155
154
  it('requires header', () => {
156
155
  errorHelper(shaka.util.Error.Code.INVALID_TEXT_HEADER,
157
156
  '',
158
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
157
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
159
158
  errorHelper(shaka.util.Error.Code.INVALID_TEXT_HEADER,
160
159
  '00:00:00.000 --> 00:00:00.020\nTest',
161
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
160
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
162
161
  });
163
162
 
164
163
  it('rejects invalid time values', () => {
165
164
  errorHelper(shaka.util.Error.Code.INVALID_TEXT_CUE,
166
165
  'WEBVTT\n\n00.020 --> 0:00.040\nTest',
167
- {periodStart: 0, segmentStart: 0, segmentEnd: 0},
166
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0},
168
167
  anyString);
169
168
  errorHelper(shaka.util.Error.Code.INVALID_TEXT_CUE,
170
169
  'WEBVTT\n\n0:00.020 --> 0:00.040\nTest',
171
- {periodStart: 0, segmentStart: 0, segmentEnd: 0},
170
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0},
172
171
  anyString);
173
172
  errorHelper(shaka.util.Error.Code.INVALID_TEXT_CUE,
174
173
  'WEBVTT\n\n00:00.20 --> 0:00.040\nTest',
175
- {periodStart: 0, segmentStart: 0, segmentEnd: 0},
174
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0},
176
175
  anyString);
177
176
  errorHelper(shaka.util.Error.Code.INVALID_TEXT_CUE,
178
177
  'WEBVTT\n\n00:100.20 --> 0:00.040\nTest',
179
- {periodStart: 0, segmentStart: 0, segmentEnd: 0},
178
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0},
180
179
  anyString);
181
180
  errorHelper(shaka.util.Error.Code.INVALID_TEXT_CUE,
182
181
  'WEBVTT\n\n00:00.020 --> 0:00.040\nTest',
183
- {periodStart: 0, segmentStart: 0, segmentEnd: 0},
182
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0},
184
183
  anyString);
185
184
  errorHelper(shaka.util.Error.Code.INVALID_TEXT_CUE,
186
185
  'WEBVTT\n\n00:00:00:00.020 --> 0:00.040\nTest',
187
- {periodStart: 0, segmentStart: 0, segmentEnd: 0},
186
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0},
188
187
  anyString);
189
188
  errorHelper(shaka.util.Error.Code.INVALID_TEXT_CUE,
190
189
  'WEBVTT\n\n00:61.020 --> 0:00.040\nTest',
191
- {periodStart: 0, segmentStart: 0, segmentEnd: 0},
190
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0},
192
191
  anyString);
193
192
  errorHelper(shaka.util.Error.Code.INVALID_TEXT_CUE,
194
193
  'WEBVTT\n\n61:00.020 --> 0:00.040\nTest',
195
- {periodStart: 0, segmentStart: 0, segmentEnd: 0},
194
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0},
196
195
  anyString);
197
196
  });
198
197
 
@@ -217,7 +216,7 @@ describe('VttTextParser', () => {
217
216
  'Test\n\n' +
218
217
  '00:00:40.000 --> 00:00:50.000 vertical:lr\n' +
219
218
  'Test2',
220
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
219
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
221
220
  });
222
221
 
223
222
  it('supports line setting', () => {
@@ -249,7 +248,7 @@ describe('VttTextParser', () => {
249
248
  'Test3\n\n' +
250
249
  '00:00:55.000 --> 00:01:05.000 line:12.3%\n' +
251
250
  'Test4\n\n',
252
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
251
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
253
252
  });
254
253
 
255
254
  it('supports line setting with optional part', () => {
@@ -271,7 +270,7 @@ describe('VttTextParser', () => {
271
270
  'Test\n\n' +
272
271
  '00:00:40.000 --> 00:00:50.000 line:-1,center\n' +
273
272
  'Test2',
274
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
273
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
275
274
  });
276
275
 
277
276
  it('supports position setting', () => {
@@ -285,7 +284,7 @@ describe('VttTextParser', () => {
285
284
  'Test\n\n' +
286
285
  '00:00:25.000 --> 00:00:45.000 position:12.3%\n' +
287
286
  'Test2\n\n',
288
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
287
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
289
288
  });
290
289
 
291
290
  it('supports position setting with optional part', () => {
@@ -305,7 +304,7 @@ describe('VttTextParser', () => {
305
304
  'Test\n\n' +
306
305
  '00:00:20.000 --> 00:00:40.000 position:45%,start\n' +
307
306
  'Test2',
308
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
307
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
309
308
  });
310
309
 
311
310
  it('supports size setting', () => {
@@ -319,7 +318,7 @@ describe('VttTextParser', () => {
319
318
  'Test\n\n' +
320
319
  '00:00:25.000 --> 00:00:45.000 size:12.3%\n' +
321
320
  'Test2\n\n',
322
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
321
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
323
322
  });
324
323
 
325
324
  it('supports align setting', () => {
@@ -330,7 +329,7 @@ describe('VttTextParser', () => {
330
329
  'WEBVTT\n\n' +
331
330
  '00:00:20.000 --> 00:00:40.000 align:center\n' +
332
331
  'Test',
333
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
332
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
334
333
  });
335
334
 
336
335
  it('supports multiple settings', () => {
@@ -348,7 +347,7 @@ describe('VttTextParser', () => {
348
347
  'WEBVTT\n\n' +
349
348
  '00:00:20.000 --> 00:00:40.000 align:center size:56% vertical:lr\n' +
350
349
  'Test',
351
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
350
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
352
351
  });
353
352
 
354
353
  it('supports timestamps with one-digit hour at start time', () => {
@@ -366,7 +365,7 @@ describe('VttTextParser', () => {
366
365
  'WEBVTT\n\n' +
367
366
  '0:00:20.000 --> 00:00:40.000 align:center size:56% vertical:lr\n' +
368
367
  'Test',
369
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
368
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
370
369
  });
371
370
 
372
371
  it('supports timestamps with one-digit hour at end time', () => {
@@ -384,7 +383,7 @@ describe('VttTextParser', () => {
384
383
  'WEBVTT\n\n' +
385
384
  '00:00:20.000 --> 0:00:40.000 align:center size:56% vertical:lr\n' +
386
385
  'Test',
387
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
386
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
388
387
  });
389
388
 
390
389
  it('supports stamps with one-digit hours at start & end time', () => {
@@ -402,15 +401,15 @@ describe('VttTextParser', () => {
402
401
  'WEBVTT\n\n' +
403
402
  '0:00:20.000 --> 0:00:40.000 align:center size:56% vertical:lr\n' +
404
403
  'Test',
405
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
404
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
406
405
  });
407
406
 
408
- it('uses time offset from periodStart, not segmentStart', () => {
407
+ it('uses time offset from vttOffset, not periodStart or segmentStart', () => {
409
408
  verifyHelper(
410
409
  [
411
410
  {
412
- startTime: 70,
413
- endTime: 80,
411
+ startTime: 50,
412
+ endTime: 60,
414
413
  payload: 'Test',
415
414
  textAlign: 'center',
416
415
  size: 56,
@@ -420,10 +419,9 @@ describe('VttTextParser', () => {
420
419
  'WEBVTT\n\n' +
421
420
  '0:00:10.000 --> 0:00:20.000 align:center size:56% vertical:lr\n' +
422
421
  'Test',
423
- {periodStart: 60, segmentStart: 80, segmentEnd: 100});
422
+ {periodStart: 60, segmentStart: 80, segmentEnd: 100, vttOffset: 40});
424
423
  });
425
424
 
426
-
427
425
  it('parses VTTRegions', () => {
428
426
  verifyHelper(
429
427
  [
@@ -451,7 +449,7 @@ describe('VttTextParser', () => {
451
449
  'viewportanchor=10%,90% scroll=up\n\n' +
452
450
  '0:00:20.000 --> 0:00:40.000 region:reg1\n' +
453
451
  'Test',
454
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
452
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
455
453
  });
456
454
 
457
455
  it('ignores and logs invalid settings', () => {
@@ -464,7 +462,7 @@ describe('VttTextParser', () => {
464
462
  'WEBVTT\n\n' +
465
463
  '00:00:20.000 --> 00:00:40.000 vertical:es\n' +
466
464
  'Test\n\n',
467
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
465
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
468
466
 
469
467
  verifyHelper(
470
468
  [
@@ -473,7 +471,7 @@ describe('VttTextParser', () => {
473
471
  'WEBVTT\n\n' +
474
472
  '00:00:20.000 --> 00:00:40.000 vertical:\n' +
475
473
  'Test\n\n',
476
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
474
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
477
475
 
478
476
  verifyHelper(
479
477
  [
@@ -482,7 +480,7 @@ describe('VttTextParser', () => {
482
480
  'WEBVTT\n\n' +
483
481
  '00:00:20.000 --> 00:00:40.000 vertical\n' +
484
482
  'Test\n\n',
485
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
483
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
486
484
 
487
485
  verifyHelper(
488
486
  [
@@ -491,7 +489,7 @@ describe('VttTextParser', () => {
491
489
  'WEBVTT\n\n' +
492
490
  '00:00:20.000 --> 00:00:40.000 line:-3%\n' +
493
491
  'Test\n\n',
494
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
492
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
495
493
 
496
494
  verifyHelper(
497
495
  [
@@ -500,7 +498,7 @@ describe('VttTextParser', () => {
500
498
  'WEBVTT\n\n' +
501
499
  '00:00:20.000 --> 00:00:40.000 line:45%%\n' +
502
500
  'Test\n\n',
503
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
501
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
504
502
 
505
503
  verifyHelper(
506
504
  [
@@ -509,7 +507,7 @@ describe('VttTextParser', () => {
509
507
  'WEBVTT\n\n' +
510
508
  '00:00:20.000 --> 00:00:40.000 align:10\n' +
511
509
  'Test\n\n',
512
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
510
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
513
511
 
514
512
  verifyHelper(
515
513
  [
@@ -518,7 +516,7 @@ describe('VttTextParser', () => {
518
516
  'WEBVTT\n\n' +
519
517
  '00:00:20.000 --> 00:00:40.000 align:foo\n' +
520
518
  'Test\n\n',
521
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
519
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
522
520
 
523
521
  expect(logWarningSpy).toHaveBeenCalledTimes(7);
524
522
  });
@@ -537,7 +535,61 @@ describe('VttTextParser', () => {
537
535
  'Test\n\n' +
538
536
  '00:00:40.000 --> 00:00:50.000 line:-1\n' +
539
537
  'Test2',
540
- {periodStart: 0, segmentStart: 25, segmentEnd: 65});
538
+ {periodStart: 0, segmentStart: 25, segmentEnd: 65, vttOffset: 0},
539
+ /* sequenceMode= */ true);
540
+ });
541
+
542
+ it('ignores X-TIMESTAMP-MAP header if not in sequence mode', () => {
543
+ verifyHelper(
544
+ [
545
+ {startTime: 20, endTime: 40, payload: 'Test'},
546
+ {startTime: 40, endTime: 50, payload: 'Test2'},
547
+ ],
548
+ 'WEBVTT\n' +
549
+ 'X-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:01:00:00.000\n\n' +
550
+ '00:00:20.000 --> 00:00:40.000 line:0\n' +
551
+ 'Test\n\n' +
552
+ '00:00:40.000 --> 00:00:50.000 line:-1\n' +
553
+ 'Test2',
554
+ {periodStart: 0, segmentStart: 25, segmentEnd: 65, vttOffset: 0},
555
+ /* sequenceMode= */ false);
556
+ });
557
+
558
+ it('parses X-TIMESTAMP-MAP header with non-zero local base', () => {
559
+ verifyHelper(
560
+ [
561
+ {startTime: 1800, endTime: 1810, payload: 'Test'},
562
+ {startTime: 1820, endTime: 1830, payload: 'Test2'},
563
+ ],
564
+ // 162000000 = 30 * 60 * 90k = 30 minutes for the TS part of the map.
565
+ // The local (VTT) part of the map is 1 hour.
566
+ // So text times of 1 hour map to media times of 30 minutes.
567
+ 'WEBVTT\n' +
568
+ 'X-TIMESTAMP-MAP=MPEGTS:162000000,LOCAL:01:00:00.000\n\n' +
569
+ '01:00:00.000 --> 01:00:10.000 line:0\n' +
570
+ 'Test\n\n' +
571
+ '01:00:20.000 --> 01:00:30.000 line:-1\n' +
572
+ 'Test2',
573
+ {periodStart: 0, segmentStart: 25, segmentEnd: 65, vttOffset: 0},
574
+ /* sequenceMode= */ true);
575
+ });
576
+
577
+ it('combines X-TIMESTAMP-MAP header with periodStart', () => {
578
+ verifyHelper(
579
+ [
580
+ {startTime: 130, endTime: 150, payload: 'Test'},
581
+ {startTime: 150, endTime: 160, payload: 'Test2'},
582
+ ],
583
+ // 900000 = 10 sec, so expect every timestamp to be 10
584
+ // seconds ahead of what is specified.
585
+ 'WEBVTT\n' +
586
+ 'X-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000\n\n' +
587
+ '00:00:20.000 --> 00:00:40.000 line:0\n' +
588
+ 'Test\n\n' +
589
+ '00:00:40.000 --> 00:00:50.000 line:-1\n' +
590
+ 'Test2',
591
+ {periodStart: 100, segmentStart: 25, segmentEnd: 65, vttOffset: 0},
592
+ /* sequenceMode= */ true);
541
593
  });
542
594
 
543
595
  it('handles timestamp rollover with X-TIMESTAMP-MAP header', () => {
@@ -553,7 +605,8 @@ describe('VttTextParser', () => {
553
605
  'Test',
554
606
  // Non-null segmentStart takes precedence over X-TIMESTAMP-MAP.
555
607
  // This protects us from rollover in the MPEGTS field.
556
- {periodStart: 0, segmentStart: 95440, segmentEnd: 95550});
608
+ {periodStart: 0, segmentStart: 95440, segmentEnd: 95550, vttOffset: 0},
609
+ /* sequenceMode= */ true);
557
610
 
558
611
  verifyHelper(
559
612
  [
@@ -566,7 +619,8 @@ describe('VttTextParser', () => {
566
619
  'X-TIMESTAMP-MAP=MPEGTS:9745408,LOCAL:00:00:00.000\n\n' +
567
620
  '00:00:00.000 --> 00:00:02.000 line:0\n' +
568
621
  'Test2',
569
- {periodStart: 0, segmentStart: 95550, segmentEnd: 95560});
622
+ {periodStart: 0, segmentStart: 95550, segmentEnd: 95560, vttOffset: 0},
623
+ /* sequenceMode= */ true);
570
624
  });
571
625
 
572
626
  it('supports global style blocks', () => {
@@ -597,7 +651,7 @@ describe('VttTextParser', () => {
597
651
  'Test\n\n' +
598
652
  '00:00:40.000 --> 00:00:50.000\n' +
599
653
  'Test2',
600
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
654
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
601
655
  });
602
656
 
603
657
  it('supports global style blocks without blank lines', () => {
@@ -625,7 +679,7 @@ describe('VttTextParser', () => {
625
679
  'Test\n\n' +
626
680
  '00:00:40.000 --> 00:00:50.000\n' +
627
681
  'Test2',
628
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
682
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
629
683
  });
630
684
 
631
685
  it('supports payload stylized', () => {
@@ -766,7 +820,7 @@ describe('VttTextParser', () => {
766
820
  '<b>Test <i>7</i></b>\n\n' +
767
821
  '00:01:30.000 --> 00:01:40.000\n' +
768
822
  '<b>Test<i>8</b>',
769
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
823
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
770
824
  });
771
825
 
772
826
  it('supports specific style blocks', () => {
@@ -794,7 +848,7 @@ describe('VttTextParser', () => {
794
848
  '<b>Test</b>\n\n' +
795
849
  '00:00:40.000 --> 00:00:50.000\n' +
796
850
  'Test2',
797
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
851
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
798
852
  });
799
853
 
800
854
  it('supports only two digits in the timestamp', () => {
@@ -805,7 +859,7 @@ describe('VttTextParser', () => {
805
859
  'WEBVTT\n\n' +
806
860
  '00:00:20.00 --> 00:00:40.00\n' +
807
861
  'Test',
808
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
862
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
809
863
  });
810
864
 
811
865
  it('supports class with default color', () => {
@@ -947,7 +1001,7 @@ describe('VttTextParser', () => {
947
1001
  '<c.lime>forward slash 1/2 in text</c>\n\n' +
948
1002
  '00:01:50.000 --> 00:02:00.000\n' +
949
1003
  '<c.lime>less or more < > in text</c>',
950
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
1004
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
951
1005
  });
952
1006
 
953
1007
  it('supports default color overriding', () => {
@@ -973,18 +1027,21 @@ describe('VttTextParser', () => {
973
1027
  '::cue(bg_blue) { font-size: 10px; background-color: #FF0 }\n\n' +
974
1028
  '00:00:10.000 --> 00:00:20.000\n' +
975
1029
  '<c.red.bg_blue>Example 1</c>\n\n',
976
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
1030
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
977
1031
  });
978
1032
 
979
1033
  /**
980
1034
  * @param {!Array} cues
981
1035
  * @param {string} text
982
1036
  * @param {shaka.extern.TextParser.TimeContext} time
1037
+ * @param {boolean=} sequenceMode
983
1038
  */
984
- function verifyHelper(cues, text, time) {
1039
+ function verifyHelper(cues, text, time, sequenceMode = false) {
985
1040
  const data =
986
1041
  shaka.util.BufferUtils.toUint8(shaka.util.StringUtils.toUTF8(text));
987
- const result = new shaka.text.VttTextParser().parseMedia(data, time);
1042
+ const parser = new shaka.text.VttTextParser();
1043
+ parser.setSequenceMode(sequenceMode);
1044
+ const result = parser.parseMedia(data, time);
988
1045
 
989
1046
  const expected = cues.map((cue) => {
990
1047
  if (cue.nestedCues) {
@@ -454,22 +454,6 @@ describe('UI', () => {
454
454
  expect(isChosen).not.toBe(null);
455
455
  });
456
456
 
457
- it('restores the resolutions menu after audio-only playback', async () => {
458
- /** @type {HTMLElement} */
459
- const resolutionButton = shaka.util.Dom.getElementByClassName(
460
- 'shaka-resolution-button', videoContainer);
461
-
462
- // Load an audio-only clip. The menu should be hidden.
463
- await player.load('test:sintel_audio_only_compiled');
464
- expect(player.isAudioOnly()).toBe(true);
465
- expect(resolutionButton.classList.contains('shaka-hidden')).toBe(true);
466
-
467
- // Load an audio-video clip. The menu should be visible again.
468
- await player.load('test:sintel_multi_lingual_multi_res_compiled');
469
- expect(player.isAudioOnly()).toBe(false);
470
- expect(resolutionButton.classList.contains('shaka-hidden')).toBe(false);
471
- });
472
-
473
457
  /**
474
458
  * @return {Element}
475
459
  */
@@ -642,6 +642,33 @@ describe('UI', () => {
642
642
  expect(getResolutions()).toEqual(['540p']);
643
643
  });
644
644
 
645
+ it('displays audio quality based on current stream', async () => {
646
+ const manifest =
647
+ shaka.test.ManifestGenerator.generate((manifest) => {
648
+ manifest.addVariant(0, (variant) => {
649
+ variant.addAudio(0);
650
+ variant.bandwidth = 100000;
651
+ });
652
+ manifest.addVariant(1, (variant) => {
653
+ variant.addAudio(1);
654
+ variant.bandwidth = 200000;
655
+ });
656
+ });
657
+
658
+ shaka.media.ManifestParser.registerParserByMime(
659
+ fakeMimeType, () => new shaka.test.FakeManifestParser(manifest));
660
+
661
+ await player.load(
662
+ /* uri= */ 'fake', /* startTime= */ 0, fakeMimeType);
663
+
664
+ const qualityButtons = videoContainer.querySelectorAll(
665
+ 'button.explicit-resolution > span');
666
+ const qualityOptions =
667
+ Array.from(qualityButtons).map((btn) => btn.innerText);
668
+
669
+ expect(qualityOptions).toEqual(['200 kbits/s', '100 kbits/s']);
670
+ });
671
+
645
672
  /**
646
673
  * Use internals to update the resolution menu. Our fake manifest can
647
674
  * cause problems with startup where the Player will get stuck using
@@ -120,6 +120,9 @@ describe('CmcdManager', () => {
120
120
  retryParameters: /** @type {shaka.extern.RetryParameters} */({}),
121
121
  licenseRequestType: null,
122
122
  sessionId: null,
123
+ drmInfo: null,
124
+ initData: null,
125
+ initDataType: null,
123
126
  streamDataCallback: null,
124
127
  };
125
128
 
@@ -0,0 +1,54 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ describe('MimeUtils', () => {
8
+ const getNormalizedCodec = (codecs) =>
9
+ shaka.util.MimeUtils.getNormalizedCodec(codecs);
10
+
11
+ it('normalizes codecs', () => {
12
+ expect(getNormalizedCodec('mp4a.66')).toBe('aac');
13
+ expect(getNormalizedCodec('mp4a.67')).toBe('aac');
14
+ expect(getNormalizedCodec('mp4a.68')).toBe('aac');
15
+
16
+ expect(getNormalizedCodec('mp3')).toBe('mp3');
17
+ expect(getNormalizedCodec('mp4a.69')).toBe('mp3');
18
+ expect(getNormalizedCodec('mp4a.6B')).toBe('mp3');
19
+ expect(getNormalizedCodec('mp4a.6b')).toBe('mp3');
20
+
21
+ expect(getNormalizedCodec('mp4a.40.2')).toBe('aac');
22
+ expect(getNormalizedCodec('mp4a.40.02')).toBe('aac');
23
+ expect(getNormalizedCodec('mp4a.40.5')).toBe('aac');
24
+ expect(getNormalizedCodec('mp4a.40.05')).toBe('aac');
25
+ expect(getNormalizedCodec('mp4a.40.29')).toBe('aac');
26
+ expect(getNormalizedCodec('mp4a.40.42')).toBe('aac');
27
+
28
+ expect(getNormalizedCodec('ac-3')).toBe('ac-3');
29
+ expect(getNormalizedCodec('mp4a.a5')).toBe('ac-3');
30
+ expect(getNormalizedCodec('mp4a.A5')).toBe('ac-3');
31
+
32
+ expect(getNormalizedCodec('ec-3')).toBe('ec-3');
33
+ expect(getNormalizedCodec('mp4a.a6')).toBe('ec-3');
34
+ expect(getNormalizedCodec('mp4a.A6')).toBe('ec-3');
35
+
36
+ expect(getNormalizedCodec('dtsc')).toBe('dtsc');
37
+ expect(getNormalizedCodec('mp4a.a9')).toBe('dtsc');
38
+
39
+ expect(getNormalizedCodec('dtsx')).toBe('dtsx');
40
+ expect(getNormalizedCodec('mp4a.b2')).toBe('dtsx');
41
+
42
+ expect(getNormalizedCodec('vp8')).toBe('vp8');
43
+ expect(getNormalizedCodec('vp8.0')).toBe('vp8');
44
+
45
+ expect(getNormalizedCodec('avc1')).toBe('avc');
46
+ expect(getNormalizedCodec('avc3')).toBe('avc');
47
+
48
+ expect(getNormalizedCodec('hvc1')).toBe('hevc');
49
+ expect(getNormalizedCodec('hev1')).toBe('hevc');
50
+
51
+ expect(getNormalizedCodec('dvh1.05')).toBe('dovi');
52
+ expect(getNormalizedCodec('dvhe.05')).toBe('dovi');
53
+ });
54
+ });