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
@@ -167,7 +167,7 @@ shaka.util.ManifestParserUtils.VIDEO_CODEC_REGEXPS_ = [
167
167
  /^hev/,
168
168
  /^hvc/,
169
169
  /^vp0?[89]/,
170
- /^av1$/,
170
+ /^av01/,
171
171
  ];
172
172
 
173
173
 
@@ -11,6 +11,7 @@ goog.require('shaka.media.Transmuxer');
11
11
 
12
12
  /**
13
13
  * @summary A set of utility functions for dealing with MIME types.
14
+ * @export
14
15
  */
15
16
  shaka.util.MimeUtils = class {
16
17
  /**
@@ -20,6 +21,7 @@ shaka.util.MimeUtils = class {
20
21
  * @param {string} mimeType
21
22
  * @param {string=} codecs
22
23
  * @return {string}
24
+ * @export
23
25
  */
24
26
  static getFullType(mimeType, codecs) {
25
27
  let fullMimeType = mimeType;
@@ -94,6 +96,53 @@ shaka.util.MimeUtils = class {
94
96
  return codecs.split(',');
95
97
  }
96
98
 
99
+ /**
100
+ * Get the normalized codec from a codec string,
101
+ * independently of their container.
102
+ *
103
+ * @param {string} codecString
104
+ * @return {string}
105
+ */
106
+ static getNormalizedCodec(codecString) {
107
+ const parts =
108
+ shaka.util.MimeUtils.getCodecParts_(codecString);
109
+ const base = parts[0];
110
+ const profile = parts[1].toLowerCase();
111
+ switch (true) {
112
+ case base === 'mp4a' && profile === '69':
113
+ case base === 'mp4a' && profile === '6b':
114
+ return 'mp3';
115
+ case base === 'mp4a' && profile === '66':
116
+ case base === 'mp4a' && profile === '67':
117
+ case base === 'mp4a' && profile === '68':
118
+ case base === 'mp4a' && profile === '40.2':
119
+ case base === 'mp4a' && profile === '40.02':
120
+ case base === 'mp4a' && profile === '40.5':
121
+ case base === 'mp4a' && profile === '40.05':
122
+ case base === 'mp4a' && profile === '40.29':
123
+ case base === 'mp4a' && profile === '40.42': // Extended HE-AAC
124
+ return 'aac';
125
+ case base === 'mp4a' && profile === 'a5':
126
+ return 'ac-3'; // Dolby Digital
127
+ case base === 'mp4a' && profile === 'a6':
128
+ return 'ec-3'; // Dolby Digital Plus
129
+ case base === 'mp4a' && profile === 'b2':
130
+ return 'dtsx'; // DTS:X
131
+ case base === 'mp4a' && profile === 'a9':
132
+ return 'dtsc'; // DTS Digital Surround
133
+ case base === 'avc1':
134
+ case base === 'avc3':
135
+ return 'avc'; // H264
136
+ case base === 'hvc1':
137
+ case base === 'hev1':
138
+ return 'hevc'; // H265
139
+ case base === 'dvh1':
140
+ case base === 'dvhe':
141
+ return 'dovi'; // Dolby Vision
142
+ }
143
+ return base;
144
+ }
145
+
97
146
  /**
98
147
  * Get the base codec from a codec string.
99
148
  *
@@ -150,7 +199,7 @@ shaka.util.MimeUtils = class {
150
199
 
151
200
  const base = parts[0];
152
201
 
153
- parts.pop();
202
+ parts.shift();
154
203
  const profile = parts.join('.');
155
204
 
156
205
  // Make sure that we always return a "base" and "profile".
@@ -573,8 +573,8 @@ shaka.util.PeriodCombiner = class {
573
573
  // TODO(#1528): Consider changing this when we support codec switching.
574
574
  const hasCodec = outputStreams.some((s) => {
575
575
  return s.mimeType == stream.mimeType &&
576
- shaka.util.MimeUtils.getCodecBase(s.codecs) ==
577
- shaka.util.MimeUtils.getCodecBase(stream.codecs);
576
+ shaka.util.MimeUtils.getNormalizedCodec(s.codecs) ==
577
+ shaka.util.MimeUtils.getNormalizedCodec(stream.codecs);
578
578
  });
579
579
  if (!hasCodec) {
580
580
  continue;
@@ -1050,10 +1050,11 @@ shaka.util.PeriodCombiner = class {
1050
1050
  * @private
1051
1051
  */
1052
1052
  static areAVStreamsCompatible_(outputStream, candidate) {
1053
- const getCodecBase = (codecs) => shaka.util.MimeUtils.getCodecBase(codecs);
1053
+ const getCodec = (codecs) =>
1054
+ shaka.util.MimeUtils.getNormalizedCodec(codecs);
1054
1055
  // Check MIME type and codecs, which should always be the same.
1055
1056
  if (candidate.mimeType != outputStream.mimeType ||
1056
- getCodecBase(candidate.codecs) != getCodecBase(outputStream.codecs)) {
1057
+ getCodec(candidate.codecs) != getCodec(outputStream.codecs)) {
1057
1058
  return false;
1058
1059
  }
1059
1060
 
@@ -142,6 +142,18 @@ shaka.util.Platform = class {
142
142
  return shaka.util.Platform.userAgentContains_('Web0S');
143
143
  }
144
144
 
145
+ /**
146
+ * Check if the current platform is a WebOS 3.
147
+ *
148
+ * @return {boolean}
149
+ */
150
+ static isWebOS3() {
151
+ // See: http://webostv.developer.lge.com/discover/specifications/web-engine/
152
+ return shaka.util.Platform.userAgentContains_('Web0S') &&
153
+ shaka.util.Platform.userAgentContains_(
154
+ 'Chrome/38.0.2125.122 Safari/537.36');
155
+ }
156
+
145
157
  /**
146
158
  * Check if the current platform is a Google Chromecast.
147
159
  *
@@ -151,6 +163,16 @@ shaka.util.Platform = class {
151
163
  return shaka.util.Platform.userAgentContains_('CrKey');
152
164
  }
153
165
 
166
+ /**
167
+ * Check if the current platform is a Android-based Cast devices.
168
+ *
169
+ * @return {boolean}
170
+ */
171
+ static isAndroidCastDevice() {
172
+ return shaka.util.Platform.isChromecast() &&
173
+ shaka.util.Platform.userAgentContains_('Android');
174
+ }
175
+
154
176
  /**
155
177
  * Check if the current platform is Google Chrome.
156
178
  *
@@ -228,6 +250,16 @@ shaka.util.Platform = class {
228
250
  return null;
229
251
  }
230
252
 
253
+ /**
254
+ * Check if the current platform is Apple Safari
255
+ * or Safari-based iOS browsers.
256
+ *
257
+ * @return {boolean}
258
+ */
259
+ static isSafari() {
260
+ return !!shaka.util.Platform.safariVersion();
261
+ }
262
+
231
263
  /**
232
264
  * Guesses if the platform is a mobile one (iOS or Android).
233
265
  *
@@ -318,6 +350,19 @@ shaka.util.Platform = class {
318
350
  const Platform = shaka.util.Platform;
319
351
  return Platform.isTizen() || Platform.isXboxOne();
320
352
  }
353
+
354
+ /**
355
+ * Returns true if MediaKeys is polyfilled
356
+ *
357
+ * @return {boolean}
358
+ */
359
+ static isMediaKeysPolyfilled() {
360
+ if (window.shakaMediaKeysPolyfill) {
361
+ return true;
362
+ }
363
+
364
+ return false;
365
+ }
321
366
  };
322
367
 
323
368
  /** @private {shaka.util.Timer} */
@@ -9,7 +9,6 @@ goog.provide('shaka.util.PlayerConfiguration');
9
9
  goog.require('goog.asserts');
10
10
  goog.require('shaka.abr.SimpleAbrManager');
11
11
  goog.require('shaka.log');
12
- goog.require('shaka.media.DrmEngine');
13
12
  goog.require('shaka.net.NetworkingEngine');
14
13
  goog.require('shaka.util.ConfigUtils');
15
14
  goog.require('shaka.util.LanguageUtils');
@@ -17,20 +16,15 @@ goog.require('shaka.util.ManifestParserUtils');
17
16
  goog.require('shaka.util.Platform');
18
17
 
19
18
 
20
- // TODO(vaage): Many times in our configs, we need to create an empty
21
- // implementation of a method, but to avoid closure from removing unused
22
- // parameters (and breaking our merge config code) we need to use each
23
- // parameter. Is there a better solution to this problem than what we are
24
- // doing now?
25
- //
26
- // NOTE: Chrome App Content Security Policy prohibits usage of new Function()
27
-
28
19
  /**
29
20
  * @final
30
21
  * @export
31
22
  */
32
23
  shaka.util.PlayerConfiguration = class {
33
- /** @return {shaka.extern.PlayerConfiguration} */
24
+ /**
25
+ * @return {shaka.extern.PlayerConfiguration}
26
+ * @export
27
+ */
34
28
  static createDefault() {
35
29
  // This is a relatively safe default in the absence of clues from the
36
30
  // browser. For slower connections, the default estimate may be too high.
@@ -72,7 +66,11 @@ shaka.util.PlayerConfiguration = class {
72
66
  clearKeys: {}, // key is arbitrary key system ID, value must be string
73
67
  advanced: {}, // key is arbitrary key system ID, value is a record type
74
68
  delayLicenseRequestUntilPlayed: false,
75
- initDataTransform: shaka.media.DrmEngine.defaultInitDataTransform,
69
+ initDataTransform: (initData, initDataType, drmInfo) => {
70
+ return shaka.util.ConfigUtils.referenceParametersAndReturn(
71
+ [initData, initDataType, drmInfo],
72
+ initData);
73
+ },
76
74
  logLicenseExchange: false,
77
75
  updateExpirationTime: 1,
78
76
  preferredKeySystems: [],
@@ -86,6 +84,7 @@ shaka.util.PlayerConfiguration = class {
86
84
  disableText: false,
87
85
  disableThumbnails: false,
88
86
  defaultPresentationDelay: 0,
87
+ segmentRelativeVttTiming: false,
89
88
  dash: {
90
89
  clockSyncUri: '',
91
90
  ignoreDrmInfo: false,
@@ -100,6 +99,8 @@ shaka.util.PlayerConfiguration = class {
100
99
  keySystemsByURI: {
101
100
  'urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b':
102
101
  'org.w3.clearkey',
102
+ 'urn:uuid:e2719d58-a985-b3c9-781a-b030af78d30e':
103
+ 'org.w3.clearkey',
103
104
  'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed':
104
105
  'com.widevine.alpha',
105
106
  'urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95':
@@ -109,19 +110,20 @@ shaka.util.PlayerConfiguration = class {
109
110
  'urn:uuid:f239e769-efa3-4850-9c16-a903c6932efb':
110
111
  'com.adobe.primetime',
111
112
  },
112
- // Need some operation in the callback or else closure may remove calls
113
- // to the function as it would be a no-op. The operation can't just be
114
- // a log message, because those are stripped in the compiled build.
115
113
  manifestPreprocessor: (element) => {
116
- return element;
114
+ return shaka.util.ConfigUtils.referenceParametersAndReturn(
115
+ [element],
116
+ element);
117
117
  },
118
118
  },
119
119
  hls: {
120
120
  ignoreTextStreamFailures: false,
121
121
  ignoreImageStreamFailures: false,
122
- useFullSegmentsForStartTime: false,
123
122
  defaultAudioCodec: 'mp4a.40.2',
124
123
  defaultVideoCodec: 'avc1.42E01E',
124
+ ignoreManifestProgramDateTime: false,
125
+ mediaPlaylistFullMimeType:
126
+ 'video/mp2t; codecs="avc1.42E01E, mp4a.40.2"',
125
127
  },
126
128
  };
127
129
 
@@ -132,7 +134,9 @@ shaka.util.PlayerConfiguration = class {
132
134
  // log message, because those are stripped in the compiled build.
133
135
  failureCallback: (error) => {
134
136
  shaka.log.error('Unhandled streaming error', error);
135
- return [error];
137
+ return shaka.util.ConfigUtils.referenceParametersAndReturn(
138
+ [error],
139
+ undefined);
136
140
  },
137
141
  // When low latency streaming is enabled, rebufferingGoal will default to
138
142
  // 0.01 if not specified.
@@ -143,8 +147,6 @@ shaka.util.PlayerConfiguration = class {
143
147
  alwaysStreamText: false,
144
148
  startAtSegmentBoundary: false,
145
149
  gapDetectionThreshold: 0.1,
146
- smallGapLimit: 0.5,
147
- jumpLargeGaps: false,
148
150
  durationBackoff: 1,
149
151
  forceTransmuxTS: false,
150
152
  // Offset by 5 seconds since Chromecast takes a few seconds to start
@@ -210,7 +212,9 @@ shaka.util.PlayerConfiguration = class {
210
212
  // to the function as it would be a no-op. The operation can't just be a
211
213
  // log message, because those are stripped in the compiled build.
212
214
  progressCallback: (content, progress) => {
213
- return [content, progress];
215
+ return shaka.util.ConfigUtils.referenceParametersAndReturn(
216
+ [content, progress],
217
+ undefined);
214
218
  },
215
219
 
216
220
  // By default we use persistent licenses as forces errors to surface if
@@ -218,6 +222,8 @@ shaka.util.PlayerConfiguration = class {
218
222
  // unexpected behaviours when someone tries to plays downloaded content
219
223
  // without a persistent license.
220
224
  usePersistentLicense: true,
225
+
226
+ numberOfParallelDownloads: 5,
221
227
  };
222
228
 
223
229
  const abr = {
package/lib/util/pssh.js CHANGED
@@ -90,16 +90,21 @@ shaka.util.Pssh = class {
90
90
  }
91
91
 
92
92
  /**
93
- * Creates a pssh blob from the given system ID and data.
93
+ * Creates a pssh blob from the given system ID, data, keyIds and version.
94
94
  *
95
95
  * @param {!Uint8Array} data
96
96
  * @param {!Uint8Array} systemId
97
+ * @param {!Set.<string>} keyIds
98
+ * @param {number} version
97
99
  * @return {!Uint8Array}
98
100
  */
99
- static createPssh(data, systemId) {
101
+ static createPssh(data, systemId, keyIds, version) {
100
102
  goog.asserts.assert(systemId.byteLength == 16, 'Invalid system ID length');
101
103
  const dataLength = data.length;
102
- const psshSize = 0x4 + 0x4 + 0x4 + systemId.length + 0x4 + dataLength;
104
+ let psshSize = 0x4 + 0x4 + 0x4 + systemId.length + 0x4 + dataLength;
105
+ if (version > 0) {
106
+ psshSize += 0x4 + (16 * keyIds.size);
107
+ }
103
108
 
104
109
  /** @type {!Uint8Array} */
105
110
  const psshBox = new Uint8Array(psshSize);
@@ -111,10 +116,24 @@ shaka.util.Pssh = class {
111
116
  byteCursor += 0x4;
112
117
  psshData.setUint32(byteCursor, 0x70737368); // 'pssh'
113
118
  byteCursor += 0x4;
114
- psshData.setUint32(byteCursor, 0); // flags
119
+ (version < 1) ? psshData.setUint32(byteCursor, 0) :
120
+ psshData.setUint32(byteCursor, 0x01000000); // version + flags
115
121
  byteCursor += 0x4;
116
122
  psshBox.set(systemId, byteCursor);
117
123
  byteCursor += systemId.length;
124
+
125
+ // if version > 0, add KID count and kid values.
126
+ if (version > 0) {
127
+ psshData.setUint32(byteCursor, keyIds.size); // KID_count
128
+ byteCursor += 0x4;
129
+ const Uint8ArrayUtils = shaka.util.Uint8ArrayUtils;
130
+ for (const keyId of keyIds) {
131
+ const KID = Uint8ArrayUtils.fromHex(keyId);
132
+ psshBox.set(KID, byteCursor);
133
+ byteCursor += KID.length;
134
+ }
135
+ }
136
+
118
137
  psshData.setUint32(byteCursor, dataLength);
119
138
  byteCursor += 0x4;
120
139
  psshBox.set(data, byteCursor);
@@ -283,12 +283,14 @@ shaka.util.StreamUtils = class {
283
283
  // both be considered the same codec: avc1.42c01e, avc1.4d401f
284
284
  let baseVideoCodec = '';
285
285
  if (variant.video) {
286
- baseVideoCodec = shaka.util.MimeUtils.getCodecBase(variant.video.codecs);
286
+ baseVideoCodec =
287
+ shaka.util.MimeUtils.getNormalizedCodec(variant.video.codecs);
287
288
  }
288
289
 
289
290
  let baseAudioCodec = '';
290
291
  if (variant.audio) {
291
- baseAudioCodec = shaka.util.MimeUtils.getCodecBase(variant.audio.codecs);
292
+ baseAudioCodec =
293
+ shaka.util.MimeUtils.getNormalizedCodec(variant.audio.codecs);
292
294
  }
293
295
 
294
296
  return baseVideoCodec + '-' + baseAudioCodec;
@@ -406,7 +408,7 @@ shaka.util.StreamUtils = class {
406
408
  shaka.util.StreamUtils.filterManifestByCurrentVariant(
407
409
  currentVariant, manifest);
408
410
  shaka.util.StreamUtils.filterTextStreams_(manifest);
409
- shaka.util.StreamUtils.filterImageStreams_(manifest);
411
+ await shaka.util.StreamUtils.filterImageStreams_(manifest);
410
412
  }
411
413
 
412
414
 
@@ -813,37 +815,57 @@ shaka.util.StreamUtils = class {
813
815
  * @param {shaka.extern.Manifest} manifest
814
816
  * @private
815
817
  */
816
- static filterImageStreams_(manifest) {
817
- // Filter image streams.
818
- manifest.imageStreams = manifest.imageStreams.filter((stream) => {
819
- // TODO: re-examine this and avoid allow-listing the MIME types we can
820
- // accept.
821
- const validMimeTypes = [
822
- 'image/svg+xml',
823
- 'image/png',
824
- 'image/jpeg',
825
- ];
826
- const Platform = shaka.util.Platform;
827
- // Add webp support to popular platforms that support it.
828
- const webpSupport = Platform.isWebOS() ||
829
- Platform.isTizen() ||
830
- Platform.isChromecast();
831
- if (webpSupport) {
832
- validMimeTypes.push('image/webp');
818
+ static async filterImageStreams_(manifest) {
819
+ const imageStreams = [];
820
+ for (const stream of manifest.imageStreams) {
821
+ const mimeType = stream.mimeType;
822
+ if (!shaka.util.StreamUtils.supportedImageMimeTypes_.has(mimeType)) {
823
+ const minImage = shaka.util.StreamUtils.minImage_.get(mimeType);
824
+ if (minImage) {
825
+ // eslint-disable-next-line no-await-in-loop
826
+ const res = await shaka.util.StreamUtils.isImageSupported_(minImage);
827
+ shaka.util.StreamUtils.supportedImageMimeTypes_.set(mimeType, res);
828
+ } else {
829
+ shaka.util.StreamUtils.supportedImageMimeTypes_.set(mimeType, false);
830
+ }
833
831
  }
834
- // TODO: add support to image/webp and image/avif
835
- const keep = validMimeTypes.includes(stream.mimeType);
832
+
833
+ const keep =
834
+ shaka.util.StreamUtils.supportedImageMimeTypes_.get(mimeType);
836
835
 
837
836
  if (!keep) {
838
837
  shaka.log.debug('Dropping image stream. Is not supported by the ' +
839
838
  'platform.', stream);
839
+ } else {
840
+ imageStreams.push(stream);
840
841
  }
842
+ }
843
+ manifest.imageStreams = imageStreams;
844
+ }
841
845
 
842
- return keep;
846
+ /**
847
+ * @param {string} minImage
848
+ * @return {!Promise.<boolean>}
849
+ * @private
850
+ */
851
+ static isImageSupported_(minImage) {
852
+ return new Promise((resolve) => {
853
+ const imageElement = /** @type {HTMLImageElement} */(new Image());
854
+ imageElement.src = minImage;
855
+ if ('decode' in imageElement) {
856
+ imageElement.decode().then(() => {
857
+ resolve(true);
858
+ }).catch(() => {
859
+ resolve(false);
860
+ });
861
+ } else {
862
+ imageElement.onload = imageElement.onerror = () => {
863
+ resolve(imageElement.height === 2);
864
+ };
865
+ }
843
866
  });
844
867
  }
845
868
 
846
-
847
869
  /**
848
870
  * @param {shaka.extern.Stream} s0
849
871
  * @param {shaka.extern.Stream} s1
@@ -878,6 +900,11 @@ shaka.util.StreamUtils = class {
878
900
  /** @type {?shaka.extern.Stream} */
879
901
  const video = variant.video;
880
902
 
903
+ /** @type {?string} */
904
+ const audioMimeType = audio ? audio.mimeType : null;
905
+ /** @type {?string} */
906
+ const videoMimeType = video ? video.mimeType : null;
907
+
881
908
  /** @type {?string} */
882
909
  const audioCodec = audio ? audio.codecs : null;
883
910
  /** @type {?string} */
@@ -942,6 +969,8 @@ shaka.util.StreamUtils = class {
942
969
  pixelAspectRatio: null,
943
970
  hdr: null,
944
971
  mimeType: mimeType,
972
+ audioMimeType: audioMimeType,
973
+ videoMimeType: videoMimeType,
945
974
  codecs: codecs.join(', '),
946
975
  audioCodec: audioCodec,
947
976
  videoCodec: videoCodec,
@@ -1009,6 +1038,8 @@ shaka.util.StreamUtils = class {
1009
1038
  pixelAspectRatio: null,
1010
1039
  hdr: null,
1011
1040
  mimeType: stream.mimeType,
1041
+ audioMimeType: null,
1042
+ videoMimeType: null,
1012
1043
  codecs: stream.codecs || null,
1013
1044
  audioCodec: null,
1014
1045
  videoCodec: null,
@@ -1081,6 +1112,8 @@ shaka.util.StreamUtils = class {
1081
1112
  pixelAspectRatio: null,
1082
1113
  hdr: null,
1083
1114
  mimeType: stream.mimeType,
1115
+ audioMimeType: null,
1116
+ videoMimeType: null,
1084
1117
  codecs: null,
1085
1118
  audioCodec: null,
1086
1119
  videoCodec: null,
@@ -1199,6 +1232,8 @@ shaka.util.StreamUtils = class {
1199
1232
  pixelAspectRatio: null,
1200
1233
  hdr: null,
1201
1234
  mimeType: null,
1235
+ audioMimeType: null,
1236
+ videoMimeType: null,
1202
1237
  codecs: null,
1203
1238
  audioCodec: null,
1204
1239
  videoCodec: null,
@@ -1503,3 +1538,40 @@ shaka.util.StreamUtils.DecodingAttributes = {
1503
1538
  POWER: 'powerEfficient',
1504
1539
  BANDWIDTH: 'bandwidth',
1505
1540
  };
1541
+
1542
+ /**
1543
+ * @private {!Map.<string, boolean>}
1544
+ */
1545
+ shaka.util.StreamUtils.supportedImageMimeTypes_ = new Map()
1546
+ .set('image/svg+xml', true)
1547
+ .set('image/png', true)
1548
+ .set('image/jpeg', true)
1549
+ .set('image/jpg', true);
1550
+
1551
+ /**
1552
+ * @const {string}
1553
+ * @private
1554
+ */
1555
+ shaka.util.StreamUtils.minWebPImage_ = 'data:image/webp;base64,UklGRjoAAABXRU' +
1556
+ 'JQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwY' +
1557
+ 'AAA';
1558
+
1559
+ /**
1560
+ * @const {string}
1561
+ * @private
1562
+ */
1563
+ shaka.util.StreamUtils.minAvifImage_ = 'data:image/avif;base64,AAAAIGZ0eXBhdm' +
1564
+ 'lmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljd' +
1565
+ 'AAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEA' +
1566
+ 'AAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAA' +
1567
+ 'AamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAA' +
1568
+ 'xhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAA' +
1569
+ 'CVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A=';
1570
+
1571
+ /**
1572
+ * @const {!Map.<string, string>}
1573
+ * @private
1574
+ */
1575
+ shaka.util.StreamUtils.minImage_ = new Map()
1576
+ .set('image/webp', shaka.util.StreamUtils.minWebPImage_)
1577
+ .set('image/avif', shaka.util.StreamUtils.minAvifImage_);
@@ -6,7 +6,6 @@
6
6
 
7
7
  goog.provide('shaka.util.Uint8ArrayUtils');
8
8
 
9
- goog.require('shaka.Deprecate');
10
9
  goog.require('shaka.util.BufferUtils');
11
10
  goog.require('shaka.util.StringUtils');
12
11
 
@@ -17,21 +16,6 @@ goog.require('shaka.util.StringUtils');
17
16
  * @export
18
17
  */
19
18
  shaka.util.Uint8ArrayUtils = class {
20
- /**
21
- * Compare two Uint8Arrays for equality.
22
- * @param {Uint8Array} arr1
23
- * @param {Uint8Array} arr2
24
- * @return {boolean}
25
- * @deprecated
26
- * @export
27
- */
28
- static equal(arr1, arr2) {
29
- shaka.Deprecate.deprecateFeature(4,
30
- 'shaka.util.Uint8ArrayUtils.equal',
31
- 'Please use shaka.util.BufferUtils.equal instead.');
32
- return shaka.util.BufferUtils.equal(arr1, arr2);
33
- }
34
-
35
19
  /**
36
20
  * Convert a buffer to a base64 string. The output will be standard
37
21
  * alphabet as opposed to base64url safe alphabet.
@@ -199,7 +199,7 @@ shaka.util.XmlUtils = class {
199
199
  }
200
200
 
201
201
  const result = Date.parse(dateString);
202
- return (!isNaN(result) ? Math.floor(result / 1000.0) : null);
202
+ return isNaN(result) ? null : (result / 1000.0);
203
203
  }
204
204
 
205
205
 
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.3.4",
4
+ "version": "4.0.1",
5
5
  "homepage": "https://github.com/shaka-project/shaka-player",
6
6
  "author": "Google",
7
7
  "maintainers": [
@@ -97,5 +97,8 @@
97
97
  },
98
98
  "dependencies": {
99
99
  "eme-encryption-scheme-polyfill": "^2.0.3"
100
+ },
101
+ "engines": {
102
+ "node": ">=14"
100
103
  }
101
104
  }
package/roadmap.md CHANGED
@@ -9,41 +9,41 @@ 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
11
  Priority features up next:
12
- - Support containerless formats
13
- https://github.com/shaka-project/shaka-player/issues/2337
14
12
  - Preload API
15
13
  https://github.com/shaka-project/shaka-player/issues/880
16
- - Codec-switching and order preference
17
- https://github.com/shaka-project/shaka-player/issues/1528
18
- https://github.com/shaka-project/shaka-player/issues/2179
19
14
 
20
15
  Candidate features for future release cycles:
21
- - HLS interstitial support
22
- https://github.com/shaka-project/shaka-player/issues/3364
23
- - Support ID3 tags in mp4
24
- https://github.com/shaka-project/shaka-player/issues/3351
25
- - MSE support for FairPlay
26
- https://github.com/shaka-project/shaka-player/issues/3346
27
- - Smaller, more modular binary
28
16
  - Official TypeScript defs, generated from source
29
17
  https://github.com/shaka-project/shaka-player/issues/1030
30
- - Shaka Analytics Component and an integration with BigQuery Analytics
31
- https://github.com/shaka-project/shaka-player/issues/3359
32
- - Integration with Google Video ML/Cloud AI
33
-
34
- v3.3 - 2021 Q3 or Q4
18
+ - Codec-switching
19
+ https://github.com/shaka-project/shaka-player/issues/1528
35
20
  - Background fetch for offline storage
36
21
  https://github.com/shaka-project/shaka-player/issues/879
37
- - HLS performance improvements
38
- https://github.com/shaka-project/shaka-player/issues/3363
22
+ - Support ID3 tags in mp4
23
+ https://github.com/shaka-project/shaka-player/issues/3351
24
+ - Smaller, more modular binary
25
+
26
+ v3.4 - 2022 Q1 or Q2
27
+ - MSE support for FairPlay
28
+ https://github.com/shaka-project/shaka-player/issues/3346
29
+ - Support containerless formats
30
+ https://github.com/shaka-project/shaka-player/issues/2337
39
31
 
40
32
  =====
41
33
 
34
+ v3.3 - 2022 Q1
35
+ - Common Media Client Data (CMCD) logging support
36
+ https://github.com/shaka-project/shaka-player/issues/3619
37
+ - Non-linear IMA CS ads
38
+ https://github.com/shaka-project/shaka-player/pull/3639
39
+
42
40
  v3.2 - 2021 Q3
43
41
  - MediaCapabilities to make performance-based decisions
44
42
  https://github.com/shaka-project/shaka-player/issues/1391
45
43
  - Configurable key-system priority
46
44
  https://github.com/shaka-project/shaka-player/issues/3002
45
+ - Codec order preferences
46
+ https://github.com/shaka-project/shaka-player/issues/2179
47
47
 
48
48
  v3.1 - 2021 Q2
49
49
  - Low-latency live (LL-HLS, LL-DASH)