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
@@ -8,7 +8,6 @@ goog.provide('shaka.util.StreamUtils');
8
8
 
9
9
  goog.require('goog.asserts');
10
10
  goog.require('shaka.log');
11
- goog.require('shaka.media.MediaSourceEngine');
12
11
  goog.require('shaka.text.TextEngine');
13
12
  goog.require('shaka.util.Functional');
14
13
  goog.require('shaka.util.LanguageUtils');
@@ -28,30 +27,43 @@ shaka.util.StreamUtils = class {
28
27
  * bandwidth and filter out the rest.
29
28
  * Also filters out variants that have too many audio channels.
30
29
  * @param {!shaka.extern.Manifest} manifest
30
+ * @param {!Array.<string>} preferredVideoCodecs
31
+ * @param {!Array.<string>} preferredAudioCodecs
31
32
  * @param {number} preferredAudioChannelCount
33
+ * @param {!Array.<string>} preferredDecodingAttributes
32
34
  */
33
- static chooseCodecsAndFilterManifest(manifest, preferredAudioChannelCount) {
35
+ static chooseCodecsAndFilterManifest(manifest, preferredVideoCodecs,
36
+ preferredAudioCodecs, preferredAudioChannelCount,
37
+ preferredDecodingAttributes) {
34
38
  const StreamUtils = shaka.util.StreamUtils;
35
39
 
36
- // To start, consider a subset of variants based on audio channel
40
+ let variants = manifest.variants;
41
+ // To start, choose the codecs based on configured preferences if available.
42
+ if (preferredVideoCodecs.length || preferredAudioCodecs.length) {
43
+ variants = StreamUtils.choosePreferredCodecs(variants,
44
+ preferredVideoCodecs, preferredAudioCodecs);
45
+ }
46
+
47
+ // Consider a subset of variants based on audio channel
37
48
  // preferences.
38
49
  // For some content (#1013), surround-sound variants will use a different
39
50
  // codec than stereo variants, so it is important to choose codecs **after**
40
51
  // considering the audio channel config.
41
- const variants = StreamUtils.filterVariantsByAudioChannelCount(
42
- manifest.variants, preferredAudioChannelCount);
52
+ variants = StreamUtils.filterVariantsByAudioChannelCount(
53
+ variants, preferredAudioChannelCount);
43
54
 
44
55
  // Now organize variants into buckets by codecs.
45
56
  /** @type {!shaka.util.MultiMap.<shaka.extern.Variant>} */
46
57
  let variantsByCodecs = StreamUtils.getVariantsByCodecs_(variants);
47
58
  variantsByCodecs = StreamUtils.filterVariantsByDensity_(variantsByCodecs);
48
59
 
49
- const bestCodecs = StreamUtils.findBestCodecs_(variantsByCodecs);
60
+ const bestCodecs = StreamUtils.chooseCodecsByDecodingAttributes_(
61
+ variantsByCodecs, preferredDecodingAttributes);
50
62
 
51
63
  // Filter out any variants that don't match, forcing AbrManager to choose
52
- // from the most efficient variants possible.
64
+ // from a single video codec and a single audio codec possible.
53
65
  manifest.variants = manifest.variants.filter((variant) => {
54
- const codecs = StreamUtils.getGroupVariantCodecs_(variant);
66
+ const codecs = StreamUtils.getVariantCodecs_(variant);
55
67
  if (codecs == bestCodecs) {
56
68
  return true;
57
69
  }
@@ -71,8 +83,8 @@ shaka.util.StreamUtils = class {
71
83
  static getVariantsByCodecs_(variants) {
72
84
  const variantsByCodecs = new shaka.util.MultiMap();
73
85
  for (const variant of variants) {
74
- const group = shaka.util.StreamUtils.getGroupVariantCodecs_(variant);
75
- variantsByCodecs.push(group, variant);
86
+ const variantCodecs = shaka.util.StreamUtils.getVariantCodecs_(variant);
87
+ variantsByCodecs.push(variantCodecs, variant);
76
88
  }
77
89
 
78
90
  return variantsByCodecs;
@@ -80,6 +92,8 @@ shaka.util.StreamUtils = class {
80
92
 
81
93
  /**
82
94
  * Filters variants by density.
95
+ * Get variants by codecs map with the max density where all codecs are
96
+ * present.
83
97
  *
84
98
  * @param {!shaka.util.MultiMap.<shaka.extern.Variant>} variantsByCodecs
85
99
  * @return {!shaka.util.MultiMap.<shaka.extern.Variant>}
@@ -120,6 +134,107 @@ shaka.util.StreamUtils = class {
120
134
  return maxDensity ? codecGroupsByDensity.get(maxDensity) : variantsByCodecs;
121
135
  }
122
136
 
137
+ /**
138
+ * Choose the codecs by configured preferred audio and video codecs.
139
+ *
140
+ * @param {!Array<shaka.extern.Variant>} variants
141
+ * @param {!Array.<string>} preferredVideoCodecs
142
+ * @param {!Array.<string>} preferredAudioCodecs
143
+ * @return {!Array<shaka.extern.Variant>}
144
+ */
145
+ static choosePreferredCodecs(variants, preferredVideoCodecs,
146
+ preferredAudioCodecs) {
147
+ let subset = variants;
148
+ for (const videoCodec of preferredVideoCodecs) {
149
+ const filtered = subset.filter((variant) => {
150
+ return variant.video && variant.video.codecs.startsWith(videoCodec);
151
+ });
152
+ if (filtered.length) {
153
+ subset = filtered;
154
+ break;
155
+ }
156
+ }
157
+
158
+ for (const audioCodec of preferredAudioCodecs) {
159
+ const filtered = subset.filter((variant) => {
160
+ return variant.audio && variant.audio.codecs.startsWith(audioCodec);
161
+ });
162
+ if (filtered.length) {
163
+ subset = filtered;
164
+ break;
165
+ }
166
+ }
167
+ return subset;
168
+ }
169
+
170
+ /**
171
+ * Choose the codecs by configured preferred decoding attributes.
172
+ *
173
+ * @param {!shaka.util.MultiMap.<shaka.extern.Variant>} variantsByCodecs
174
+ * @param {!Array.<string>} attributes
175
+ * @return {string}
176
+ * @private
177
+ */
178
+ static chooseCodecsByDecodingAttributes_(variantsByCodecs, attributes) {
179
+ const StreamUtils = shaka.util.StreamUtils;
180
+
181
+ for (const attribute of attributes) {
182
+ if (attribute == StreamUtils.DecodingAttributes.SMOOTH ||
183
+ attribute == StreamUtils.DecodingAttributes.POWER) {
184
+ variantsByCodecs = StreamUtils.chooseCodecsByMediaCapabilitiesInfo_(
185
+ variantsByCodecs, attribute);
186
+ // If we only have one smooth or powerEfficient codecs, choose it as the
187
+ // best codecs.
188
+ if (variantsByCodecs.size() == 1) {
189
+ return variantsByCodecs.keys()[0];
190
+ }
191
+ } else if (attribute == StreamUtils.DecodingAttributes.BANDWIDTH) {
192
+ return StreamUtils.findCodecsByLowestBandwidth_(variantsByCodecs);
193
+ }
194
+ }
195
+ // If there's no configured decoding preferences, or we have multiple codecs
196
+ // that meets the configured decoding preferences, choose the one with
197
+ // the lowest bandwidth.
198
+ return StreamUtils.findCodecsByLowestBandwidth_(variantsByCodecs);
199
+ }
200
+
201
+ /**
202
+ * Choose the best codecs by configured preferred MediaCapabilitiesInfo
203
+ * attributes.
204
+ *
205
+ * @param {!shaka.util.MultiMap.<shaka.extern.Variant>} variantsByCodecs
206
+ * @param {string} attribute
207
+ * @return {!shaka.util.MultiMap.<shaka.extern.Variant>}
208
+ * @private
209
+ */
210
+ static chooseCodecsByMediaCapabilitiesInfo_(variantsByCodecs, attribute) {
211
+ let highestScore = 0;
212
+ const bestVariantsByCodecs = new shaka.util.MultiMap();
213
+ variantsByCodecs.forEach((codecs, variants) => {
214
+ let sum = 0;
215
+ let num = 0;
216
+
217
+ for (const variant of variants) {
218
+ if (variant.decodingInfos.length) {
219
+ sum += variant.decodingInfos[0][attribute] ? 1 : 0;
220
+ num++;
221
+ }
222
+ }
223
+
224
+ const averageScore = sum / num;
225
+ shaka.log.debug('codecs', codecs, 'avg', attribute, averageScore);
226
+
227
+ if (averageScore > highestScore) {
228
+ bestVariantsByCodecs.clear();
229
+ bestVariantsByCodecs.push(codecs, variants);
230
+ highestScore = averageScore;
231
+ } else if (averageScore == highestScore) {
232
+ bestVariantsByCodecs.push(codecs, variants);
233
+ }
234
+ });
235
+ return bestVariantsByCodecs;
236
+ }
237
+
123
238
  /**
124
239
  * Find the lowest-bandwidth (best) codecs.
125
240
  * Compute the average bandwidth for each group of variants.
@@ -128,7 +243,7 @@ shaka.util.StreamUtils = class {
128
243
  * @return {string}
129
244
  * @private
130
245
  */
131
- static findBestCodecs_(variantsByCodecs) {
246
+ static findCodecsByLowestBandwidth_(variantsByCodecs) {
132
247
  let bestCodecs = '';
133
248
  let lowestAverageBandwidth = Infinity;
134
249
 
@@ -163,7 +278,7 @@ shaka.util.StreamUtils = class {
163
278
  * @return {string}
164
279
  * @private
165
280
  */
166
- static getGroupVariantCodecs_(variant) {
281
+ static getVariantCodecs_(variant) {
167
282
  // Only consider the base of the codec string. For example, these should
168
283
  // both be considered the same codec: avc1.42c01e, avc1.4d401f
169
284
  let baseVideoCodec = '';
@@ -183,7 +298,7 @@ shaka.util.StreamUtils = class {
183
298
  * Filter the variants in |manifest| to only include the variants that meet
184
299
  * the given restrictions.
185
300
  *
186
- * @param {shaka.extern.Manifest} manifest
301
+ * @param {!shaka.extern.Manifest} manifest
187
302
  * @param {shaka.extern.Restrictions} restrictions
188
303
  * @param {{width: number, height:number}} maxHwResolution
189
304
  */
@@ -283,17 +398,11 @@ shaka.util.StreamUtils = class {
283
398
  * @param {shaka.media.DrmEngine} drmEngine
284
399
  * @param {?shaka.extern.Variant} currentVariant
285
400
  * @param {shaka.extern.Manifest} manifest
286
- * @param {boolean=} useMediaCapabilities
287
401
  */
288
402
  static async filterManifest(
289
- drmEngine, currentVariant, manifest, useMediaCapabilities) {
290
- if (useMediaCapabilities) {
291
- await shaka.util.StreamUtils.filterManifestByMediaCapabilities(manifest,
292
- manifest.offlineSessionIds.length > 0);
293
- } else {
294
- shaka.util.StreamUtils.filterManifestByDrm(manifest, drmEngine);
295
- shaka.util.StreamUtils.filterManifestByMediaSource(manifest);
296
- }
403
+ drmEngine, currentVariant, manifest) {
404
+ await shaka.util.StreamUtils.filterManifestByMediaCapabilities(manifest,
405
+ manifest.offlineSessionIds.length > 0);
297
406
  shaka.util.StreamUtils.filterManifestByCurrentVariant(
298
407
  currentVariant, manifest);
299
408
  shaka.util.StreamUtils.filterTextStreams_(manifest);
@@ -301,29 +410,6 @@ shaka.util.StreamUtils = class {
301
410
  }
302
411
 
303
412
 
304
- /**
305
- * Filter the variants in |manifest| to only include those that are supported
306
- * by |drm|.
307
- * @param {shaka.extern.Manifest} manifest
308
- * @param {shaka.media.DrmEngine} drmEngine
309
- */
310
- static filterManifestByDrm(manifest, drmEngine) {
311
- manifest.variants = manifest.variants.filter((variant) => {
312
- if (drmEngine && drmEngine.initialized()) {
313
- if (!drmEngine.supportsVariant(variant)) {
314
- shaka.log.debug('Dropping variant - not compatible with key system',
315
- variant);
316
- return false;
317
- }
318
- return true;
319
- }
320
-
321
- shaka.log.debug('DrmEngine is not initialized yet.');
322
- return true;
323
- });
324
- }
325
-
326
-
327
413
  /**
328
414
  * Alters the given Manifest to filter out any streams unsupported by the
329
415
  * platform via MediaCapabilities.decodingInfo() API.
@@ -363,46 +449,6 @@ shaka.util.StreamUtils = class {
363
449
  }
364
450
 
365
451
 
366
- /**
367
- * Filter the variants in the |manifest| to only include those that are
368
- * supported by media source.
369
- * TODO: remove once MediaCap implementations are done.
370
- * @param {shaka.extern.Manifest} manifest
371
- */
372
- static filterManifestByMediaSource(manifest) {
373
- const StreamUtils = shaka.util.StreamUtils;
374
-
375
- manifest.variants = manifest.variants.filter((variant) => {
376
- const audio = variant.audio;
377
- const video = variant.video;
378
-
379
- if (audio && !shaka.media.MediaSourceEngine.isStreamSupported(audio)) {
380
- shaka.log.debug('Dropping variant - audio not compatible with platform',
381
- StreamUtils.getStreamSummaryString_(audio));
382
- return false;
383
- }
384
-
385
- if (video && !shaka.media.MediaSourceEngine.isStreamSupported(video)) {
386
- shaka.log.debug('Dropping variant - video not compatible with platform',
387
- StreamUtils.getStreamSummaryString_(video));
388
- return false;
389
- }
390
-
391
- // See: https://github.com/google/shaka-player/issues/3380
392
- if (shaka.util.Platform.isXboxOne() && video &&
393
- ((video.width && video.width > 1920) ||
394
- (video.height && video.height > 1080)) &&
395
- video.codecs.includes('avc1.')) {
396
- shaka.log.debug('Dropping variant - video not compatible with platform',
397
- StreamUtils.getStreamSummaryString_(video));
398
- return false;
399
- }
400
-
401
- return true;
402
- });
403
- }
404
-
405
-
406
452
  /**
407
453
  * Get the decodingInfo results of the variants via MediaCapabilities.
408
454
  * This should be called after the DrmEngine is created and configured, and
@@ -1371,3 +1417,12 @@ shaka.util.StreamUtils = class {
1371
1417
 
1372
1418
  /** @private {number} */
1373
1419
  shaka.util.StreamUtils.nextTrackId_ = 0;
1420
+
1421
+ /**
1422
+ * @enum {string}
1423
+ */
1424
+ shaka.util.StreamUtils.DecodingAttributes = {
1425
+ SMOOTH: 'smooth',
1426
+ POWER: 'powerEfficient',
1427
+ BANDWIDTH: 'bandwidth',
1428
+ };
@@ -6,6 +6,7 @@
6
6
 
7
7
  goog.provide('shaka.util.XmlUtils');
8
8
 
9
+ goog.require('goog.asserts');
9
10
  goog.require('shaka.log');
10
11
  goog.require('shaka.util.StringUtils');
11
12
 
@@ -312,29 +313,46 @@ shaka.util.XmlUtils = class {
312
313
 
313
314
 
314
315
  /**
315
- * Parse a string and return the resulting root element if
316
- * it was valid XML.
316
+ * Parse a string and return the resulting root element if it was valid XML.
317
+ *
317
318
  * @param {string} xmlString
318
319
  * @param {string} expectedRootElemName
319
320
  * @return {Element}
320
321
  */
321
322
  static parseXmlString(xmlString, expectedRootElemName) {
322
323
  const parser = new DOMParser();
323
- let rootElem = null;
324
324
  let xml = null;
325
325
  try {
326
326
  xml = parser.parseFromString(xmlString, 'text/xml');
327
- } catch (exception) {}
328
- if (xml) {
329
- // The top-level element in the loaded xml should have the
330
- // same type as the element linking.
331
- if (xml.documentElement.tagName == expectedRootElemName) {
332
- rootElem = xml.documentElement;
333
- }
327
+ } catch (exception) {
328
+ shaka.log.error('XML parsing exception:', exception);
329
+ return null;
330
+ }
331
+
332
+ // According to MDN, parseFromString never returns null.
333
+ goog.asserts.assert(xml, 'Parsed XML document cannot be null!');
334
+
335
+ // Check for empty documents.
336
+ const rootElem = xml.documentElement;
337
+ if (!rootElem) {
338
+ shaka.log.error('XML document was empty!');
339
+ return null;
340
+ }
341
+
342
+ // Check for parser errors.
343
+ const parserErrorElements = rootElem.getElementsByTagName('parsererror');
344
+ if (parserErrorElements.length) {
345
+ shaka.log.error('XML parser error found:', parserErrorElements[0]);
346
+ return null;
334
347
  }
335
- if (rootElem && rootElem.getElementsByTagName('parsererror').length > 0) {
348
+
349
+ // The top-level element in the loaded XML should have the name we expect.
350
+ if (xml.documentElement.tagName != expectedRootElemName) {
351
+ shaka.log.error(
352
+ `XML tag name does not match expected "${expectedRootElemName}":`,
353
+ xml.documentElement.tagName);
336
354
  return null;
337
- } // It had a parser error in it.
355
+ }
338
356
 
339
357
  return rootElem;
340
358
  }
@@ -352,6 +370,7 @@ shaka.util.XmlUtils = class {
352
370
  const string = shaka.util.StringUtils.fromUTF8(data);
353
371
  return shaka.util.XmlUtils.parseXmlString(string, expectedRootElemName);
354
372
  } catch (exception) {
373
+ shaka.log.error('parseXmlString threw!', exception);
355
374
  return null;
356
375
  }
357
376
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "shaka-player",
3
3
  "description": "DASH/EME video player library",
4
- "version": "3.1.4",
4
+ "version": "3.3.0",
5
5
  "homepage": "https://github.com/google/shaka-player",
6
6
  "author": "Google",
7
7
  "maintainers": [
package/roadmap.md CHANGED
@@ -8,49 +8,51 @@ CHANGELOG.md.
8
8
  The goals of future milestones are fluid until we begin that development cycle,
9
9
  so the exact milestone for future features is not pre-determined.
10
10
 
11
- Candidate features for future release cycles
12
- - HLS performance improvements
13
- https://github.com/google/shaka-player/issues/3363
14
- - HLS interstitial support
15
- https://github.com/google/shaka-player/issues/3364
16
- - Integration with Google Video ML/Cloud AI
11
+ Priority features up next:
17
12
  - Support containerless formats
18
13
  https://github.com/google/shaka-player/issues/2337
14
+ - Preload API
15
+ https://github.com/google/shaka-player/issues/880
16
+ - Codec-switching and order preference
17
+ https://github.com/google/shaka-player/issues/1528
18
+ https://github.com/google/shaka-player/issues/2179
19
+
20
+ Candidate features for future release cycles:
21
+ - HLS interstitial support
22
+ https://github.com/google/shaka-player/issues/3364
19
23
  - Support ID3 tags in mp4
20
24
  https://github.com/google/shaka-player/issues/3351
21
25
  - MSE support for FairPlay
22
26
  https://github.com/google/shaka-player/issues/3346
23
- - Codec-switching and order preference
24
- https://github.com/google/shaka-player/issues/1528
25
- https://github.com/google/shaka-player/issues/2179
26
- - Configurable key-system priority
27
- https://github.com/google/shaka-player/issues/3002
28
- - Preload API
29
- https://github.com/google/shaka-player/issues/880
30
- - Thumbnail tracks
31
- DASH: https://github.com/google/shaka-player/issues/559
32
- HLS: https://github.com/google/shaka-player/issues/2429
33
27
  - Smaller, more modular binary
34
28
  - Official TypeScript defs, generated from source
35
29
  https://github.com/google/shaka-player/issues/1030
30
+ - Shaka Analytics Component and an integration with BigQuery Analytics
31
+ https://github.com/google/shaka-player/issues/3359
32
+ - Integration with Google Video ML/Cloud AI
36
33
 
37
- v3.3 - 2021 Q3
34
+ v3.3 - 2021 Q3 or Q4
38
35
  - Background fetch for offline storage
39
36
  https://github.com/google/shaka-player/issues/879
40
- - Shaka Analytics Component and an integration with BigQuery Analytics
41
- https://github.com/google/shaka-player/issues/3359
37
+ - HLS performance improvements
38
+ https://github.com/google/shaka-player/issues/3363
42
39
 
43
- v3.2 - 2021 Q2
40
+ =====
41
+
42
+ v3.2 - 2021 Q3
44
43
  - MediaCapabilities to make performance-based decisions
45
44
  https://github.com/google/shaka-player/issues/1391
45
+ - Configurable key-system priority
46
+ https://github.com/google/shaka-player/issues/3002
46
47
 
47
48
  v3.1 - 2021 Q2
48
49
  - Low-latency live (LL-HLS, LL-DASH)
49
50
  https://github.com/google/shaka-player/issues/1525
50
51
  - Own CEA parser, use mux.js only for TS
51
52
  https://github.com/google/shaka-player/issues/2648
52
-
53
- =====
53
+ - Thumbnail tracks
54
+ DASH: https://github.com/google/shaka-player/issues/559
55
+ HLS: https://github.com/google/shaka-player/issues/2429
54
56
 
55
57
  v3.0 - 2020 Q2
56
58
  - Code health improvements
@@ -32,6 +32,7 @@ goog.require('shaka.offline.OfflineManifestParser');
32
32
  goog.require('shaka.offline.OfflineScheme');
33
33
  goog.require('shaka.offline.Storage');
34
34
  goog.require('shaka.offline.indexeddb.StorageMechanism');
35
+ goog.require('shaka.polyfill.Aria');
35
36
  goog.require('shaka.polyfill.EncryptionScheme');
36
37
  goog.require('shaka.polyfill.Fullscreen');
37
38
  goog.require('shaka.polyfill.MathRound');
@@ -43,6 +44,7 @@ goog.require('shaka.polyfill.PatchedMediaKeysMs');
43
44
  goog.require('shaka.polyfill.PatchedMediaKeysNop');
44
45
  goog.require('shaka.polyfill.PatchedMediaKeysWebkit');
45
46
  goog.require('shaka.polyfill.PiPWebkit');
47
+ goog.require('shaka.polyfill.RandomUUID');
46
48
  goog.require('shaka.polyfill.VTTCue');
47
49
  goog.require('shaka.polyfill.VideoPlayPromise');
48
50
  goog.require('shaka.polyfill.VideoPlaybackQuality');
@@ -69,6 +71,7 @@ goog.require('shaka.ui.AdPosition');
69
71
  goog.require('shaka.ui.AirPlayButton');
70
72
  goog.require('shaka.ui.BigPlayButton');
71
73
  goog.require('shaka.ui.CastButton');
74
+ goog.require('shaka.ui.ContextMenu');
72
75
  goog.require('shaka.ui.Element');
73
76
  goog.require('shaka.ui.FastForwardButton');
74
77
  goog.require('shaka.ui.FullscreenButton');
@@ -84,6 +87,7 @@ goog.require('shaka.ui.RewindButton');
84
87
  goog.require('shaka.ui.SkipAdButton');
85
88
  goog.require('shaka.ui.SmallPlayButton');
86
89
  goog.require('shaka.ui.Spacer');
90
+ goog.require('shaka.ui.StatisticsButton');
87
91
  goog.require('shaka.ui.TextSelection');
88
92
  goog.require('shaka.ui.VolumeBar');
89
93
  goog.require('shaka.util.Dom');
@@ -27,6 +27,7 @@ describe('CastUtils', () => {
27
27
  'getAdManager', // Handled specially
28
28
  'getSharedConfiguration', // Handled specially
29
29
  'getNetworkingEngine', // Handled specially
30
+ 'getDrmEngine', // Handled specially
30
31
  'getMediaElement', // Handled specially
31
32
  'setMaxHardwareResolution',
32
33
  'destroy', // Should use CastProxy.destroy instead
@@ -17,7 +17,7 @@ describe('Cea608Memory', () => {
17
17
  /** @type {!shaka.cea.Cea608Memory} */
18
18
  let memory;
19
19
 
20
- /** @type {!string} */
20
+ /** @type {string} */
21
21
  const stream = 'CC1';
22
22
 
23
23
  beforeEach(() => {
@@ -19,39 +19,39 @@ describe('Cea708Service', () => {
19
19
 
20
20
  /**
21
21
  * Hide window (2 bytes), with a bitmap provided to indicate all windows.
22
- * @type {!Array<!number>}
22
+ * @type {!Array<number>}
23
23
  */
24
24
  const hideWindow = [0x8a, 0xff];
25
25
 
26
26
  /**
27
27
  * Define window (7 bytes), defines window #0 to be a visible window
28
28
  * with 32 rows and 32 columns. (We specify 31 for each since decoder adds 1).
29
- * @type {!Array<!number>}
29
+ * @type {!Array<number>}
30
30
  */
31
31
  const defineWindow = [
32
32
  0x98, 0x38, 0x00, 0x00, 0x1f, 0x1f, 0x00,
33
33
  ];
34
34
 
35
- /** @type {!number} */
35
+ /** @type {number} */
36
36
  const startTime = 1;
37
37
 
38
- /** @type {!number} */
38
+ /** @type {number} */
39
39
  const endTime = 2;
40
40
 
41
41
  /**
42
42
  * We arbitrarily pick service 1 for all of these tests.
43
- * @type {!number}
43
+ * @type {number}
44
44
  */
45
45
  const serviceNumber = 1;
46
46
 
47
- /** @type {!string} */
47
+ /** @type {string} */
48
48
  const stream = `svc${serviceNumber}`;
49
49
 
50
50
  /**
51
51
  * Takes in a array of bytes and a presentation timestamp (in seconds),
52
52
  * and converts it into a CEA-708 DTVCC Packet.
53
- * @param {!Array<!number>} bytes
54
- * @param {!number} pts
53
+ * @param {!Array<number>} bytes
54
+ * @param {number} pts
55
55
  */
56
56
  const createCea708PacketFromBytes = (bytes, pts) => {
57
57
  const cea708Bytes = bytes.map((code, i) => {
@@ -15,22 +15,22 @@ describe('Cea708Window', () => {
15
15
  /** @type {!shaka.cea.Cea708Window} */
16
16
  let window;
17
17
 
18
- /** @type {!number} */
18
+ /** @type {number} */
19
19
  const serviceNumber = 1; // We will arbitrarily pick service 1 for all tests.
20
20
 
21
- /** @type {!string} */
21
+ /** @type {string} */
22
22
  const stream = `svc${serviceNumber}`;
23
23
 
24
- /** @type {!number} */
24
+ /** @type {number} */
25
25
  const rowCount = 10;
26
26
 
27
- /** @type {!number} */
27
+ /** @type {number} */
28
28
  const colCount = 32;
29
29
 
30
- /** @type {!number} */
30
+ /** @type {number} */
31
31
  const startTime = 1;
32
32
 
33
- /** @type {!number} */
33
+ /** @type {number} */
34
34
  const endTime = 2;
35
35
 
36
36
  beforeEach(() => {
@@ -13,7 +13,7 @@ goog.require('shaka.text.Cue');
13
13
  describe('CeaDecoder', () => {
14
14
  const CeaUtils = shaka.test.CeaUtils;
15
15
 
16
- /** @type {!string} */
16
+ /** @type {string} */
17
17
  const DEFAULT_BG_COLOR = shaka.cea.CeaUtils.DEFAULT_BG_COLOR;
18
18
 
19
19
  /**
@@ -11,10 +11,10 @@ describe('DtvccPacketBuilder', () => {
11
11
  /** @type {!shaka.cea.DtvccPacketBuilder} */
12
12
  let dtvccPacketBuilder;
13
13
 
14
- /** @type {!number} */
14
+ /** @type {number} */
15
15
  const DTVCC_PACKET_START = shaka.cea.DtvccPacketBuilder.DTVCC_PACKET_START;
16
16
 
17
- /** @type {!number} */
17
+ /** @type {number} */
18
18
  const DTVCC_PACKET_DATA = shaka.cea.DtvccPacketBuilder.DTVCC_PACKET_DATA;
19
19
 
20
20
  beforeEach(() => {
@@ -42,6 +42,8 @@ describe('DashParser ContentProtection', () => {
42
42
 
43
43
  const playerInterface = {
44
44
  networkingEngine: netEngine,
45
+ modifyManifestRequest: (request, manifestInfo) => {},
46
+ modifySegmentRequest: (request, segmentInfo) => {},
45
47
  filter: (manifest) => Promise.resolve(),
46
48
  makeTextStreamsForClosedCaptions: (manifest) => {},
47
49
  onTimelineRegionAdded: fail, // Should not have any EventStream elements.