shaka-player 4.5.0 → 4.6.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/AUTHORS +2 -0
  3. package/CHANGELOG.md +98 -0
  4. package/CODE_OF_CONDUCT.md +1 -1
  5. package/CONTRIBUTORS +2 -0
  6. package/README.md +38 -32
  7. package/demo/common/asset.js +11 -17
  8. package/demo/common/assets.js +117 -11
  9. package/demo/config.js +28 -1
  10. package/demo/custom.js +52 -38
  11. package/demo/main.js +11 -3
  12. package/demo/search.js +7 -0
  13. package/dist/controls.css +1 -1
  14. package/dist/controls.css.map +1 -1
  15. package/dist/demo.compiled.debug.js +133 -124
  16. package/dist/demo.compiled.debug.map +3 -3
  17. package/dist/demo.compiled.js +133 -124
  18. package/dist/demo.compiled.map +3 -3
  19. package/dist/deps.js +20 -18
  20. package/dist/locales.js +35 -31
  21. package/dist/receiver.compiled.debug.js +58 -50
  22. package/dist/receiver.compiled.debug.map +3 -3
  23. package/dist/receiver.compiled.js +58 -50
  24. package/dist/receiver.compiled.map +3 -3
  25. package/dist/shaka-player.compiled.d.ts +440 -390
  26. package/dist/shaka-player.compiled.debug.d.ts +440 -390
  27. package/dist/shaka-player.compiled.debug.externs.js +162 -77
  28. package/dist/shaka-player.compiled.debug.js +786 -736
  29. package/dist/shaka-player.compiled.debug.map +4 -4
  30. package/dist/shaka-player.compiled.externs.js +162 -77
  31. package/dist/shaka-player.compiled.js +1154 -1121
  32. package/dist/shaka-player.compiled.map +4 -4
  33. package/dist/shaka-player.ui.d.ts +491 -437
  34. package/dist/shaka-player.ui.debug.d.ts +491 -437
  35. package/dist/shaka-player.ui.debug.externs.js +167 -77
  36. package/dist/shaka-player.ui.debug.js +877 -811
  37. package/dist/shaka-player.ui.debug.map +4 -4
  38. package/dist/shaka-player.ui.externs.js +167 -77
  39. package/dist/shaka-player.ui.js +1362 -1318
  40. package/dist/shaka-player.ui.map +4 -4
  41. package/docs/tutorials/ad_monetization.md +54 -0
  42. package/docs/tutorials/basic-usage.md +2 -1
  43. package/docs/tutorials/errors.md +2 -1
  44. package/docs/tutorials/offline.md +10 -8
  45. package/docs/tutorials/plugins.md +5 -0
  46. package/docs/tutorials/ui-customization.md +13 -0
  47. package/docs/tutorials/ui.md +2 -1
  48. package/docs/tutorials/upgrade.md +3 -0
  49. package/externs/managedmediasource.js +24 -0
  50. package/externs/shaka/abr_manager.js +6 -2
  51. package/externs/shaka/cea.js +7 -0
  52. package/externs/shaka/codecs.js +5 -3
  53. package/externs/shaka/manifest.js +21 -5
  54. package/externs/shaka/manifest_parser.js +17 -0
  55. package/externs/shaka/net.js +2 -2
  56. package/externs/shaka/offline.js +9 -2
  57. package/externs/shaka/player.js +53 -7
  58. package/externs/shaka/text.js +3 -1
  59. package/externs/shaka/transmuxer.js +1 -1
  60. package/lib/abr/simple_abr_manager.js +25 -8
  61. package/lib/ads/media_tailor_ad_manager.js +14 -3
  62. package/lib/cast/cast_receiver.js +1 -1
  63. package/lib/cea/cea_decoder.js +28 -0
  64. package/lib/cea/dummy_caption_decoder.js +5 -0
  65. package/lib/dash/dash_parser.js +249 -83
  66. package/lib/dash/mpd_utils.js +52 -31
  67. package/lib/dash/segment_base.js +4 -5
  68. package/lib/dash/segment_list.js +5 -4
  69. package/lib/dash/segment_template.js +83 -26
  70. package/lib/hls/hls_classes.js +28 -43
  71. package/lib/hls/hls_parser.js +761 -649
  72. package/lib/hls/hls_utils.js +64 -5
  73. package/lib/hls/manifest_text_parser.js +7 -11
  74. package/lib/media/adaptation_set.js +20 -13
  75. package/lib/media/adaptation_set_criteria.js +70 -18
  76. package/lib/media/closed_caption_parser.js +13 -0
  77. package/lib/media/content_workarounds.js +6 -0
  78. package/lib/media/drm_engine.js +8 -13
  79. package/lib/media/manifest_parser.js +8 -113
  80. package/lib/media/media_source_capabilities.js +10 -3
  81. package/lib/media/media_source_engine.js +75 -21
  82. package/lib/media/play_rate_controller.js +8 -38
  83. package/lib/media/presentation_timeline.js +7 -1
  84. package/lib/media/quality_observer.js +1 -1
  85. package/lib/media/segment_index.js +5 -5
  86. package/lib/media/segment_prefetch.js +92 -24
  87. package/lib/media/segment_reference.js +67 -1
  88. package/lib/media/segment_utils.js +343 -0
  89. package/lib/media/stall_detector.js +0 -3
  90. package/lib/media/streaming_engine.js +41 -21
  91. package/lib/mss/mss_parser.js +18 -2
  92. package/lib/net/networking_engine.js +66 -12
  93. package/lib/net/networking_utils.js +95 -0
  94. package/lib/offline/indexeddb/v1_storage_cell.js +2 -0
  95. package/lib/offline/indexeddb/v2_storage_cell.js +2 -0
  96. package/lib/offline/manifest_converter.js +2 -0
  97. package/lib/offline/offline_manifest_parser.js +10 -0
  98. package/lib/offline/storage.js +11 -7
  99. package/lib/player.js +993 -1502
  100. package/lib/polyfill/mediasource.js +22 -1
  101. package/lib/text/mp4_ttml_parser.js +2 -2
  102. package/lib/text/srt_text_parser.js +2 -2
  103. package/lib/text/stub_text_displayer.js +51 -0
  104. package/lib/text/text_engine.js +3 -2
  105. package/lib/text/ttml_text_parser.js +28 -5
  106. package/lib/text/ui_text_displayer.js +4 -0
  107. package/lib/text/vtt_text_parser.js +7 -2
  108. package/lib/transmuxer/aac_transmuxer.js +1 -1
  109. package/lib/transmuxer/ac3_transmuxer.js +1 -1
  110. package/lib/transmuxer/ec3_transmuxer.js +1 -1
  111. package/lib/transmuxer/h264.js +5 -4
  112. package/lib/transmuxer/h265.js +5 -4
  113. package/lib/transmuxer/mp3_transmuxer.js +1 -1
  114. package/lib/transmuxer/mpeg_ts_transmuxer.js +1 -1
  115. package/lib/transmuxer/mss_transmuxer.js +1 -1
  116. package/lib/transmuxer/ts_transmuxer.js +33 -13
  117. package/lib/util/buffer_utils.js +26 -4
  118. package/lib/util/content_steering_manager.js +358 -0
  119. package/lib/util/error.js +2 -6
  120. package/lib/util/fairplay_utils.js +1 -1
  121. package/lib/util/fake_event.js +5 -1
  122. package/lib/util/id3_utils.js +50 -1
  123. package/lib/util/manifest_parser_utils.js +12 -8
  124. package/lib/util/mp4_generator.js +2 -4
  125. package/lib/util/mutex.js +59 -0
  126. package/lib/util/object_utils.js +1 -1
  127. package/lib/util/periods.js +154 -179
  128. package/lib/util/platform.js +4 -3
  129. package/lib/util/player_configuration.js +35 -6
  130. package/lib/util/stream_utils.js +105 -98
  131. package/lib/util/ts_parser.js +124 -73
  132. package/lib/util/uint8array_utils.js +5 -1
  133. package/lib/util/xml_utils.js +5 -0
  134. package/maintained-branches.md +2 -2
  135. package/package.json +1 -1
  136. package/roadmap.md +15 -5
  137. package/shaka-player.uncompiled.js +0 -1
  138. package/test/abr/simple_abr_manager_unit.js +33 -33
  139. package/test/ads/ad_manager_unit.js +3 -2
  140. package/test/cast/cast_receiver_integration.js +3 -4
  141. package/test/cast/cast_utils_unit.js +2 -0
  142. package/test/cea/cea_decoder_unit.js +7 -0
  143. package/test/codec_switching/codec_switching_integration.js +2 -1
  144. package/test/dash/dash_parser_integration.js +2 -1
  145. package/test/dash/dash_parser_live_unit.js +0 -19
  146. package/test/dash/dash_parser_manifest_unit.js +494 -2
  147. package/test/dash/mpd_utils_unit.js +61 -30
  148. package/test/hls/hls_live_unit.js +12 -3
  149. package/test/hls/hls_parser_unit.js +377 -27
  150. package/test/hls/manifest_text_parser_unit.js +32 -99
  151. package/test/media/adaptation_set_criteria_unit.js +172 -21
  152. package/test/media/adaptation_set_unit.js +1 -0
  153. package/test/media/content_workarounds_unit.js +1 -1
  154. package/test/media/drm_engine_unit.js +3 -3
  155. package/test/media/media_source_engine_unit.js +1 -1
  156. package/test/media/play_rate_controller_unit.js +0 -48
  157. package/test/media/segment_index_unit.js +2 -1
  158. package/test/mss/mss_player_integration.js +3 -2
  159. package/test/net/networking_engine_unit.js +3 -3
  160. package/test/{media/manifest_parser_unit.js → net/networking_utils_unit.js} +2 -2
  161. package/test/offline/manifest_convert_unit.js +9 -0
  162. package/test/offline/offline_integration.js +2 -1
  163. package/test/offline/storage_integration.js +21 -9
  164. package/test/player_external.js +4 -2
  165. package/test/player_integration.js +15 -4
  166. package/test/player_load_graph_integration.js +47 -151
  167. package/test/player_src_equals_external.js +1 -0
  168. package/test/player_src_equals_integration.js +71 -4
  169. package/test/player_unit.js +80 -27
  170. package/test/test/util/fake_media_source_engine.js +5 -0
  171. package/test/test/util/fake_networking_engine.js +9 -1
  172. package/test/test/util/fake_segment_prefetch.js +3 -0
  173. package/test/test/util/manifest_generator.js +4 -0
  174. package/test/test/util/manifest_parser_util.js +14 -2
  175. package/test/test/util/offline_utils.js +1 -0
  176. package/test/test/util/simple_fakes.js +2 -2
  177. package/test/test/util/streaming_engine_util.js +3 -0
  178. package/test/test/util/test_scheme.js +6 -0
  179. package/test/test/util/ui_utils.js +4 -3
  180. package/test/text/mp4_ttml_parser_unit.js +4 -4
  181. package/test/text/srt_text_parser_unit.js +1 -1
  182. package/test/text/text_displayer_layout_unit.js +1 -1
  183. package/test/text/text_engine_unit.js +6 -0
  184. package/test/text/ttml_text_parser_unit.js +33 -2
  185. package/test/transmuxer/transmuxer_engine_integration.js +9 -0
  186. package/test/transmuxer/transmuxer_integration.js +33 -3
  187. package/test/ui/ad_ui_unit.js +2 -2
  188. package/test/ui/ui_customization_unit.js +17 -16
  189. package/test/ui/ui_integration.js +30 -20
  190. package/test/ui/ui_unit.js +25 -19
  191. package/test/util/buffer_utils_unit.js +1 -1
  192. package/test/util/content_steering_manager_unit.js +427 -0
  193. package/test/util/id3_utils_unit.js +52 -0
  194. package/test/util/stream_utils_unit.js +17 -113
  195. package/test/util/ts_parser_unit.js +3 -3
  196. package/third_party/closure-uri/uri.js +13 -1
  197. package/ui/audio_language_selection.js +9 -2
  198. package/ui/externs/ui.js +17 -2
  199. package/ui/language_utils.js +43 -8
  200. package/ui/less/range_elements.less +33 -0
  201. package/ui/locales/en.json +1 -0
  202. package/ui/locales/es-419.json +1 -0
  203. package/ui/locales/es.json +1 -0
  204. package/ui/locales/source.json +4 -0
  205. package/ui/localization.js +10 -0
  206. package/ui/remote_button.js +3 -1
  207. package/ui/resolution_selection.js +47 -10
  208. package/ui/seek_bar.js +296 -3
  209. package/ui/text_selection.js +2 -1
  210. package/ui/ui.js +6 -2
  211. package/lib/routing/node.js +0 -23
  212. package/lib/routing/payload.js +0 -47
  213. package/lib/routing/walker.js +0 -587
  214. package/test/routing/walker_unit.js +0 -505
@@ -0,0 +1,358 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ goog.provide('shaka.util.ContentSteeringManager');
8
+
9
+ goog.require('goog.Uri');
10
+ goog.require('shaka.media.ManifestParser');
11
+ goog.require('shaka.net.NetworkingEngine');
12
+ goog.require('shaka.util.Error');
13
+ goog.require('shaka.util.IDestroyable');
14
+ goog.require('shaka.util.ManifestParserUtils');
15
+ goog.require('shaka.util.OperationManager');
16
+ goog.require('shaka.util.StringUtils');
17
+ goog.require('shaka.util.Timer');
18
+
19
+
20
+ /**
21
+ * Create a Content Steering manager.
22
+ *
23
+ * @implements {shaka.util.IDestroyable}
24
+ */
25
+ shaka.util.ContentSteeringManager = class {
26
+ /**
27
+ * @param {shaka.extern.ManifestParser.PlayerInterface} playerInterface
28
+ */
29
+ constructor(playerInterface) {
30
+ /** @private {?shaka.extern.ManifestConfiguration} */
31
+ this.config_ = null;
32
+
33
+ /** @private {?shaka.extern.ManifestParser.PlayerInterface} */
34
+ this.playerInterface_ = playerInterface;
35
+
36
+ /** @private {!shaka.util.OperationManager} */
37
+ this.operationManager_ = new shaka.util.OperationManager();
38
+
39
+ /** @private {!Array.<string>} */
40
+ this.baseUris_ = [];
41
+
42
+ /** @private {?string} */
43
+ this.defaultPathwayId_ = null;
44
+
45
+ /** @private {!Array.<string>} */
46
+ this.pathwayPriority_ = [];
47
+
48
+ /** @private {?string} */
49
+ this.lastPathwayUsed_ = null;
50
+
51
+ /** @private {!Array.<shaka.util.ContentSteeringManager.PathawayClone>} */
52
+ this.pathwayClones_ = [];
53
+
54
+ /**
55
+ * Default to 5 minutes. Value in seconds.
56
+ *
57
+ * @private {number}
58
+ */
59
+ this.lastTTL_ = 300;
60
+
61
+ /** @private {!Map.<(string|number), !Map.<string, string>>} */
62
+ this.locations_ = new Map();
63
+
64
+ /** @private {!Map.<string, number>} */
65
+ this.bannedLocations_ = new Map();
66
+
67
+ /** @private {?shaka.util.Timer} */
68
+ this.updateTimer_ = null;
69
+
70
+ /** @private {string} */
71
+ this.manifestType_ = shaka.media.ManifestParser.UNKNOWN;
72
+ }
73
+
74
+ /**
75
+ * @param {shaka.extern.ManifestConfiguration} config
76
+ */
77
+ configure(config) {
78
+ this.config_ = config;
79
+ }
80
+
81
+
82
+ /** @override */
83
+ destroy() {
84
+ this.config_ = null;
85
+ this.playerInterface_ = null;
86
+ this.baseUris_ = [];
87
+ this.defaultPathwayId_ = null;
88
+ this.pathwayPriority_ = [];
89
+ this.pathwayClones_ = [];
90
+ this.locations_.clear();
91
+
92
+ if (this.updateTimer_ != null) {
93
+ this.updateTimer_.stop();
94
+ this.updateTimer_ = null;
95
+ }
96
+
97
+ return this.operationManager_.destroy();
98
+ }
99
+
100
+ /**
101
+ * @param {string} manifestType
102
+ */
103
+ setManifestType(manifestType) {
104
+ this.manifestType_ = manifestType;
105
+ }
106
+
107
+ /**
108
+ * @param {!Array.<string>} baseUris
109
+ */
110
+ setBaseUris(baseUris) {
111
+ this.baseUris_ = baseUris;
112
+ }
113
+
114
+ /**
115
+ * @param {?string} defaultPathwayId
116
+ */
117
+ setDefaultPathwayId(defaultPathwayId) {
118
+ this.defaultPathwayId_ = defaultPathwayId;
119
+ }
120
+
121
+ /**
122
+ * Request the Content Steering info.
123
+ *
124
+ * @param {string} uri
125
+ * @return {!Promise}
126
+ */
127
+ async requestInfo(uri) {
128
+ const uris = shaka.util.ManifestParserUtils.resolveUris(
129
+ this.baseUris_, [this.addQueryParams_(uri)]);
130
+ const type = shaka.net.NetworkingEngine.RequestType.CONTENT_STEERING;
131
+ const request = shaka.net.NetworkingEngine.makeRequest(
132
+ uris, this.config_.retryParameters);
133
+
134
+ const op = this.playerInterface_.networkingEngine.request(type, request);
135
+ this.operationManager_.manage(op);
136
+ try {
137
+ const response = await op.promise;
138
+ const str = shaka.util.StringUtils.fromUTF8(response.data);
139
+ const steeringManifest =
140
+ /** @type {shaka.util.ContentSteeringManager.SteeringManifest} */
141
+ (JSON.parse(str));
142
+ if (steeringManifest.VERSION == 1) {
143
+ this.processManifest_(steeringManifest, response.uri);
144
+ }
145
+ } catch (e) {
146
+ if (e && e.code == shaka.util.Error.Code.OPERATION_ABORTED) {
147
+ return;
148
+ }
149
+ if (this.updateTimer_ != null) {
150
+ this.updateTimer_.stop();
151
+ this.updateTimer_ = null;
152
+ }
153
+ this.updateTimer_ = new shaka.util.Timer(() => {
154
+ this.requestInfo(uri);
155
+ });
156
+ this.updateTimer_.tickAfter(this.lastTTL_);
157
+ }
158
+ }
159
+
160
+ /** @private */
161
+ addQueryParams_(uri) {
162
+ if (!this.pathwayPriority_.length) {
163
+ return uri;
164
+ }
165
+ const finalUri = new goog.Uri(uri);
166
+ const currentPathwayID = this.lastPathwayUsed_ || this.pathwayPriority_[0];
167
+ const currentBandwidth =
168
+ Math.round(this.playerInterface_.getBandwidthEstimate());
169
+ const queryData = finalUri.getQueryData();
170
+ if (this.manifestType_ == shaka.media.ManifestParser.DASH) {
171
+ queryData.add('_DASH_pathway', currentPathwayID);
172
+ queryData.add('_DASH_throughput', String(currentBandwidth));
173
+ } else if (this.manifestType_ == shaka.media.ManifestParser.HLS) {
174
+ queryData.add('_HLS_pathway', currentPathwayID);
175
+ queryData.add('_HLS_throughput', String(currentBandwidth));
176
+ }
177
+ if (queryData.getCount()) {
178
+ finalUri.setQueryData(queryData);
179
+ }
180
+ return finalUri.toString();
181
+ }
182
+
183
+ /**
184
+ * @param {shaka.util.ContentSteeringManager.SteeringManifest} manifest
185
+ * @param {string} finalManifestUri
186
+ * @private
187
+ */
188
+ processManifest_(manifest, finalManifestUri) {
189
+ if (this.updateTimer_ != null) {
190
+ this.updateTimer_.stop();
191
+ this.updateTimer_ = null;
192
+ }
193
+ const uri = manifest['RELOAD-URI'] || finalManifestUri;
194
+ this.updateTimer_ = new shaka.util.Timer(() => {
195
+ this.requestInfo(uri);
196
+ });
197
+ const newTTL = manifest['TTL'];
198
+ if (newTTL) {
199
+ this.lastTTL_ = newTTL;
200
+ }
201
+ this.updateTimer_.tickAfter(this.lastTTL_);
202
+ this.pathwayPriority_ = manifest['PATHWAY-PRIORITY'] || [];
203
+ this.pathwayClones_ = manifest['PATHWAY-CLONES'] || [];
204
+ }
205
+
206
+ /**
207
+ * Clear the previous locations added.
208
+ */
209
+ clearPreviousLocations() {
210
+ this.locations_.clear();
211
+ }
212
+
213
+ /**
214
+ * @param {string|number} streamId
215
+ * @param {string} pathwayId
216
+ * @param {string} uri
217
+ */
218
+ addLocation(streamId, pathwayId, uri) {
219
+ let streamLocations = this.locations_.get(streamId);
220
+ if (!streamLocations) {
221
+ streamLocations = new Map();
222
+ }
223
+ streamLocations.set(pathwayId, uri);
224
+ this.locations_.set(streamId, streamLocations);
225
+ }
226
+
227
+ /**
228
+ * @param {string} uri
229
+ */
230
+ banLocation(uri) {
231
+ const bannedUntil = Date.now() + 60000;
232
+ this.bannedLocations_.set(uri, bannedUntil);
233
+ }
234
+
235
+ /**
236
+ * Get the base locations ordered according the priority.
237
+ *
238
+ * @param {string|number} streamId
239
+ * @return {!Array.<string>}
240
+ */
241
+ getLocations(streamId) {
242
+ const streamLocations = this.locations_.get(streamId) || new Map();
243
+ /** @type {!Array.<!{pathwayId: string, location: string}>} */
244
+ let locationsPathwayIdMap = [];
245
+ for (const pathwayId of this.pathwayPriority_) {
246
+ const location = streamLocations.get(pathwayId);
247
+ if (location) {
248
+ locationsPathwayIdMap.push({pathwayId, location});
249
+ } else {
250
+ const clone = this.pathwayClones_.find((c) => c.ID == pathwayId);
251
+ if (clone) {
252
+ const cloneLocation = streamLocations.get(clone['BASE-ID']);
253
+ if (cloneLocation) {
254
+ if (clone['URI-REPLACEMENT'].HOST) {
255
+ const uri = new goog.Uri(cloneLocation);
256
+ uri.setDomain(clone['URI-REPLACEMENT'].HOST);
257
+ locationsPathwayIdMap.push({
258
+ pathwayId: pathwayId,
259
+ location: uri.toString(),
260
+ });
261
+ } else {
262
+ locationsPathwayIdMap.push({
263
+ pathwayId: pathwayId,
264
+ location: cloneLocation,
265
+ });
266
+ }
267
+ }
268
+ }
269
+ }
270
+ }
271
+
272
+ const now = Date.now();
273
+ for (const uri of this.bannedLocations_.keys()) {
274
+ const bannedUntil = this.bannedLocations_.get(uri);
275
+ if (now > bannedUntil) {
276
+ this.bannedLocations_.delete(uri);
277
+ }
278
+ }
279
+ locationsPathwayIdMap = locationsPathwayIdMap.filter((l) => {
280
+ for (const uri of this.bannedLocations_.keys()) {
281
+ if (uri.includes(new goog.Uri(l.location).getDomain())) {
282
+ return false;
283
+ }
284
+ }
285
+ return true;
286
+ });
287
+
288
+ if (locationsPathwayIdMap.length) {
289
+ this.lastPathwayUsed_ = locationsPathwayIdMap[0].pathwayId;
290
+ }
291
+
292
+ const locations = locationsPathwayIdMap.map((l) => l.location);
293
+
294
+ if (!locations.length && this.defaultPathwayId_) {
295
+ for (const pathwayId of this.defaultPathwayId_.split(',')) {
296
+ const location = streamLocations.get(pathwayId);
297
+ if (location) {
298
+ this.lastPathwayUsed_ = this.defaultPathwayId_;
299
+ locations.push(location);
300
+ }
301
+ }
302
+ }
303
+ if (!locations.length) {
304
+ for (const location of streamLocations.values()) {
305
+ locations.push(location);
306
+ }
307
+ }
308
+ return shaka.util.ManifestParserUtils.resolveUris(
309
+ this.baseUris_, locations);
310
+ }
311
+ };
312
+
313
+
314
+ /**
315
+ * @typedef {{
316
+ * VERSION: number,
317
+ * TTL: number,
318
+ * RELOAD-URI: string,
319
+ * PATHWAY-PRIORITY: !Array.<string>,
320
+ * PATHWAY-CLONES: !Array.<shaka.util.ContentSteeringManager.PathawayClone>
321
+ * }}
322
+ *
323
+ * @description
324
+ * Contains information about the Steering Manifest
325
+ *
326
+ * @property {string} VERSION
327
+ * @property {number} TTL
328
+ * @property {string RELOAD-URI
329
+ * @property {!Array.<string>} PATHWAY-PRIORITY
330
+ * @property {!Array.<
331
+ * shaka.util.ContentSteeringManager.PathawayClone>} PATHWAY-CLONES
332
+ */
333
+ shaka.util.ContentSteeringManager.SteeringManifest;
334
+
335
+
336
+ /**
337
+ * @typedef {{
338
+ * BASE-ID: string,
339
+ * ID: string,
340
+ * URI-REPLACEMENT: !Array.<shaka.util.ContentSteeringManager.UriReplacement>
341
+ * }}
342
+ *
343
+ * @property {string} BASE-ID
344
+ * @property {string} ID
345
+ * @property {!Array.<
346
+ * shaka.util.ContentSteeringManager.UriReplacement>} URI-REPLACEMENT
347
+ */
348
+ shaka.util.ContentSteeringManager.PathawayClone;
349
+
350
+
351
+ /**
352
+ * @typedef {{
353
+ * HOST: string
354
+ * }}
355
+ *
356
+ * @property {string} HOST
357
+ */
358
+ shaka.util.ContentSteeringManager.UriReplacement;
package/lib/util/error.js CHANGED
@@ -330,7 +330,7 @@ shaka.util.Error.Code = {
330
330
 
331
331
  /**
332
332
  * Unable to guess mime type of the text.
333
- * <br> error.data[0] is the text file's extension.
333
+ * <br> error.data[0] is the text file's uri.
334
334
  */
335
335
  'TEXT_COULD_NOT_GUESS_MIME_TYPE': 2011,
336
336
 
@@ -360,11 +360,7 @@ shaka.util.Error.Code = {
360
360
  */
361
361
  'CHAPTERS_TRACK_FAILED': 2015,
362
362
 
363
- /**
364
- * External thumbnails tracks cannot be added in src= because native platform
365
- * doesn't support it.
366
- */
367
- 'CANNOT_ADD_EXTERNAL_THUMBNAILS_TO_SRC_EQUALS': 2016,
363
+ // RETIRED: 'CANNOT_ADD_EXTERNAL_THUMBNAILS_TO_SRC_EQUALS': 2016,
368
364
 
369
365
  /**
370
366
  * Only external urls of WebVTT type are supported.
@@ -205,7 +205,7 @@ shaka.util.FairPlayUtils = class {
205
205
  const stringToArray = (string) => {
206
206
  // 2 bytes for each char
207
207
  const buffer = new ArrayBuffer(string.length * 2);
208
- const array = new Uint16Array(buffer);
208
+ const array = shaka.util.BufferUtils.toUint16(buffer);
209
209
  for (let i = 0, strLen = string.length; i < strLen; i++) {
210
210
  array[i] = string.charCodeAt(i);
211
211
  }
@@ -156,6 +156,7 @@ shaka.util.FakeEvent.EventName = {
156
156
  AbrStatusChanged: 'abrstatuschanged',
157
157
  Adaptation: 'adaptation',
158
158
  Buffering: 'buffering',
159
+ Complete: 'complete',
159
160
  DownloadFailed: 'downloadfailed',
160
161
  DownloadHeadersReceived: 'downloadheadersreceived',
161
162
  DrmSessionUpdate: 'drmsessionupdate',
@@ -163,6 +164,7 @@ shaka.util.FakeEvent.EventName = {
163
164
  Prft: 'prft',
164
165
  Error: 'error',
165
166
  ExpirationUpdated: 'expirationupdated',
167
+ FirstQuartile: 'firstquartile',
166
168
  GapJumped: 'gapjumped',
167
169
  KeyStatusChanged: 'keystatuschanged',
168
170
  Loaded: 'loaded',
@@ -171,16 +173,18 @@ shaka.util.FakeEvent.EventName = {
171
173
  ManifestUpdated: 'manifestupdated',
172
174
  MediaQualityChanged: 'mediaqualitychanged',
173
175
  Metadata: 'metadata',
176
+ Midpoint: 'midpoint',
174
177
  OnStateChange: 'onstatechange',
175
- OnStateIdle: 'onstateidle',
176
178
  RateChange: 'ratechange',
177
179
  SegmentAppended: 'segmentappended',
178
180
  SessionDataEvent: 'sessiondata',
179
181
  StallDetected: 'stalldetected',
182
+ Started: 'started',
180
183
  StateChanged: 'statechanged',
181
184
  Streaming: 'streaming',
182
185
  TextChanged: 'textchanged',
183
186
  TextTrackVisibility: 'texttrackvisibility',
187
+ ThirdQuartile: 'thirdquartile',
184
188
  TimelineRegionAdded: 'timelineregionadded',
185
189
  TimelineRegionEnter: 'timelineregionenter',
186
190
  TimelineRegionExit: 'timelineregionexit',
@@ -140,9 +140,58 @@ shaka.util.Id3Utils = class {
140
140
  key: frame.type,
141
141
  description: '',
142
142
  data: '',
143
+ mimeType: null,
144
+ pictureType: null,
143
145
  };
144
146
 
145
- if (frame.type === 'TXXX') {
147
+ if (frame.type === 'APIC') {
148
+ /*
149
+ * Format:
150
+ * [0] = {Text Encoding}
151
+ * [1 - X] = {MIME Type}\0
152
+ * [X+1] = {Picture Type}
153
+ * [X+2 - Y] = {Description}\0
154
+ * [Y - ?] = {Picture Data or Picture URL}
155
+ */
156
+ if (frame.size < 2) {
157
+ return null;
158
+ }
159
+ if (frame.data[0] !== shaka.util.Id3Utils.UTF8_encoding) {
160
+ shaka.log.warning('Ignore frame with unrecognized character ' +
161
+ 'encoding');
162
+ return null;
163
+ }
164
+
165
+ const mimeTypeEndIndex = frame.data.subarray(1).indexOf(0);
166
+ if (mimeTypeEndIndex === -1) {
167
+ return null;
168
+ }
169
+ const mimeType = StringUtils.fromUTF8(
170
+ BufferUtils.toUint8(frame.data, 1, mimeTypeEndIndex));
171
+ const pictureType = frame.data[2 + mimeTypeEndIndex];
172
+ const descriptionEndIndex = frame.data.subarray(3 + mimeTypeEndIndex)
173
+ .indexOf(0);
174
+ if (descriptionEndIndex === -1) {
175
+ return null;
176
+ }
177
+ const description = StringUtils.fromUTF8(
178
+ BufferUtils.toUint8(frame.data, 3 + mimeTypeEndIndex,
179
+ descriptionEndIndex));
180
+ let data;
181
+ if (mimeType === '-->') {
182
+ data = StringUtils.fromUTF8(
183
+ BufferUtils.toUint8(
184
+ frame.data, 4 + mimeTypeEndIndex + descriptionEndIndex));
185
+ } else {
186
+ data = BufferUtils.toArrayBuffer(
187
+ frame.data.subarray(4 + mimeTypeEndIndex + descriptionEndIndex));
188
+ }
189
+ metadataFrame.mimeType = mimeType;
190
+ metadataFrame.pictureType = pictureType;
191
+ metadataFrame.description = description;
192
+ metadataFrame.data = data;
193
+ return metadataFrame;
194
+ } else if (frame.type === 'TXXX') {
146
195
  /*
147
196
  * Format:
148
197
  * [0] = {Text Encoding}
@@ -8,7 +8,6 @@ goog.provide('shaka.util.ManifestParserUtils');
8
8
 
9
9
  goog.require('goog.Uri');
10
10
  goog.require('shaka.util.Error');
11
- goog.require('shaka.util.Functional');
12
11
 
13
12
 
14
13
  /**
@@ -27,7 +26,6 @@ shaka.util.ManifestParserUtils = class {
27
26
  * @return {!Array.<string>}
28
27
  */
29
28
  static resolveUris(baseUris, relativeUris) {
30
- const Functional = shaka.util.Functional;
31
29
  if (relativeUris.length == 0) {
32
30
  return baseUris;
33
31
  }
@@ -39,12 +37,18 @@ shaka.util.ManifestParserUtils = class {
39
37
  }
40
38
 
41
39
  const relativeAsGoog = relativeUris.map((uri) => new goog.Uri(uri));
42
- // Resolve each URI relative to each base URI, creating an Array of Arrays.
43
- // Then flatten the Arrays into a single Array.
44
- return baseUris.map((uri) => {
45
- const base = new goog.Uri(uri);
46
- return relativeAsGoog.map((i) => base.resolve(i).toString());
47
- }).reduce(Functional.collapseArrays, []);
40
+
41
+ // For each base URI, this code resolves it with every relative URI.
42
+ // The result is a single array containing all the resolved URIs.
43
+ const resolvedUris = [];
44
+ for (const baseStr of baseUris) {
45
+ const base = new goog.Uri(baseStr);
46
+ for (const relative of relativeAsGoog) {
47
+ resolvedUris.push(base.resolve(relative).toString());
48
+ }
49
+ }
50
+
51
+ return resolvedUris;
48
52
  }
49
53
 
50
54
 
@@ -1037,10 +1037,8 @@ shaka.util.Mp4Generator = class {
1037
1037
  mdat_(streamInfo) {
1038
1038
  const Mp4Generator = shaka.util.Mp4Generator;
1039
1039
  const samples = streamInfo.data ? streamInfo.data.samples : [];
1040
- let bytes = new Uint8Array([]);
1041
- for (const sample of samples) {
1042
- bytes = shaka.util.Uint8ArrayUtils.concat(bytes, sample.data);
1043
- }
1040
+ const allData = samples.map((sample) => sample.data);
1041
+ const bytes = shaka.util.Uint8ArrayUtils.concat(...allData);
1044
1042
  return Mp4Generator.box('mdat', bytes);
1045
1043
  }
1046
1044
 
@@ -0,0 +1,59 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ goog.provide('shaka.util.Mutex');
8
+
9
+ goog.require('shaka.log');
10
+
11
+
12
+ /**
13
+ * @summary A simple mutex.
14
+ */
15
+ shaka.util.Mutex = class {
16
+ /** Constructs the mutex. */
17
+ constructor() {
18
+ /** @private {?string} */
19
+ this.acquiredIdentifier = null;
20
+
21
+ /** @private {!Array.<function()>} */
22
+ this.unlockQueue = [];
23
+ }
24
+
25
+ /**
26
+ * Acquires the mutex, as soon as possible.
27
+ * @param {string} identifier
28
+ * @return {!Promise}
29
+ */
30
+ async acquire(identifier) {
31
+ shaka.log.v2(identifier + ' has requested mutex');
32
+ if (this.acquiredIdentifier) {
33
+ await new Promise((resolve) => this.unlockQueue.push(resolve));
34
+ }
35
+ this.acquiredIdentifier = identifier;
36
+ shaka.log.v2(identifier + ' has acquired mutex');
37
+ }
38
+
39
+ /**
40
+ * Releases your hold on the mutex.
41
+ */
42
+ release() {
43
+ shaka.log.v2(this.acquiredIdentifier + ' has released mutex');
44
+ if (this.unlockQueue.length > 0) {
45
+ this.unlockQueue.shift()();
46
+ } else {
47
+ this.acquiredIdentifier = null;
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Completely releases the mutex. Meant for use by the tests.
53
+ */
54
+ releaseAll() {
55
+ while (this.acquiredIdentifier) {
56
+ this.release();
57
+ }
58
+ }
59
+ };
@@ -19,7 +19,7 @@ shaka.util.ObjectUtils = class {
19
19
  * @return {T}
20
20
  */
21
21
  static cloneObject(arg) {
22
- const seenObjects = new Set();
22
+ const seenObjects = new WeakSet();
23
23
  // This recursively clones the value |val|, using the captured variable
24
24
  // |seenObjects| to track the objects we have already cloned.
25
25
  /** @suppress {strictMissingProperties} */