shaka-player 3.2.0 → 3.2.4

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 (162) hide show
  1. package/.github/workflows/build_and_test.yaml +73 -0
  2. package/.github/workflows/release.yaml +53 -0
  3. package/AUTHORS +3 -0
  4. package/CHANGELOG.md +182 -1
  5. package/CONTRIBUTORS +3 -0
  6. package/README.md +4 -4
  7. package/build/checkversion.py +1 -1
  8. package/build/generateExterns.js +1 -1
  9. package/build/misspellings.txt +1 -0
  10. package/build/shakaBuildHelpers.py +6 -5
  11. package/build/subprocessWindowsPatch.py +103 -0
  12. package/build/test.py +6 -0
  13. package/demo/common/assets.js +1 -1
  14. package/demo/index.html +1 -1
  15. package/dist/controls.css +2 -2
  16. package/dist/controls.css.map +1 -1
  17. package/dist/demo.compiled.debug.js +1 -1
  18. package/dist/demo.compiled.js +1 -1
  19. package/dist/deps.js +8 -8
  20. package/dist/locales.js +37 -37
  21. package/dist/receiver.compiled.debug.js +1 -1
  22. package/dist/receiver.compiled.js +1 -1
  23. package/dist/shaka-player.compiled.d.ts +195 -5
  24. package/dist/shaka-player.compiled.debug.d.ts +195 -5
  25. package/dist/shaka-player.compiled.debug.externs.js +226 -14
  26. package/dist/shaka-player.compiled.debug.js +424 -399
  27. package/dist/shaka-player.compiled.debug.map +4 -4
  28. package/dist/shaka-player.compiled.externs.js +226 -14
  29. package/dist/shaka-player.compiled.js +826 -812
  30. package/dist/shaka-player.compiled.map +4 -4
  31. package/dist/shaka-player.ui.d.ts +197 -16
  32. package/dist/shaka-player.ui.debug.d.ts +197 -16
  33. package/dist/shaka-player.ui.debug.externs.js +230 -27
  34. package/dist/shaka-player.ui.debug.js +466 -442
  35. package/dist/shaka-player.ui.debug.map +4 -4
  36. package/dist/shaka-player.ui.externs.js +230 -27
  37. package/dist/shaka-player.ui.js +946 -932
  38. package/dist/shaka-player.ui.map +4 -4
  39. package/docs/tutorials/fairplay.md +1 -1
  40. package/docs/tutorials/faq.md +14 -0
  41. package/docs/tutorials/ui.md +5 -5
  42. package/externs/ima.js +4 -0
  43. package/externs/shaka/ads.js +25 -0
  44. package/externs/shaka/player.js +8 -0
  45. package/externs/shaka/text.js +10 -0
  46. package/karma.conf.js +20 -15
  47. package/lib/ads/ad_manager.js +46 -26
  48. package/lib/ads/client_side_ad_manager.js +82 -88
  49. package/lib/ads/server_side_ad_manager.js +45 -13
  50. package/lib/cast/cast_proxy.js +6 -2
  51. package/lib/cast/cast_receiver.js +5 -1
  52. package/lib/cast/cast_sender.js +2 -2
  53. package/lib/cea/sei_processor.js +24 -17
  54. package/lib/dash/dash_parser.js +131 -24
  55. package/lib/dash/segment_list.js +1 -1
  56. package/lib/dash/segment_template.js +1 -1
  57. package/lib/hls/hls_parser.js +74 -17
  58. package/lib/hls/manifest_text_parser.js +1 -0
  59. package/lib/media/closed_caption_parser.js +3 -1
  60. package/lib/media/content_workarounds.js +12 -0
  61. package/lib/media/drm_engine.js +20 -1
  62. package/lib/media/gap_jumping_controller.js +8 -4
  63. package/lib/media/media_source_engine.js +1 -2
  64. package/lib/media/playhead.js +1 -1
  65. package/lib/media/region_observer.js +39 -33
  66. package/lib/media/region_timeline.js +17 -19
  67. package/lib/media/segment_index.js +2 -1
  68. package/lib/media/segment_reference.js +19 -1
  69. package/lib/media/streaming_engine.js +8 -4
  70. package/lib/net/networking_engine.js +6 -1
  71. package/lib/offline/download_manager.js +1 -2
  72. package/lib/offline/storage.js +8 -9
  73. package/lib/player.js +129 -59
  74. package/lib/polyfill/aria.js +12 -2
  75. package/lib/polyfill/encryption_scheme.js +2 -0
  76. package/lib/polyfill/fullscreen.js +2 -0
  77. package/lib/polyfill/mathround.js +2 -0
  78. package/lib/polyfill/media_capabilities.js +73 -21
  79. package/lib/polyfill/mediasource.js +8 -0
  80. package/lib/polyfill/orientation.js +3 -1
  81. package/lib/polyfill/patchedmediakeys_apple.js +6 -4
  82. package/lib/polyfill/patchedmediakeys_ms.js +6 -4
  83. package/lib/polyfill/patchedmediakeys_nop.js +2 -0
  84. package/lib/polyfill/patchedmediakeys_webkit.js +6 -4
  85. package/lib/polyfill/pip_webkit.js +2 -0
  86. package/lib/polyfill/storage_estimate.js +2 -0
  87. package/lib/polyfill/video_play_promise.js +2 -0
  88. package/lib/polyfill/videoplaybackquality.js +2 -0
  89. package/lib/polyfill/vttcue.js +2 -0
  90. package/lib/text/cue.js +6 -0
  91. package/lib/text/mp4_ttml_parser.js +3 -0
  92. package/lib/text/text_engine.js +14 -2
  93. package/lib/text/ttml_text_parser.js +135 -87
  94. package/lib/text/ui_text_displayer.js +213 -80
  95. package/lib/text/vtt_text_parser.js +4 -2
  96. package/lib/text/web_vtt_generator.js +21 -12
  97. package/lib/util/fake_event.js +53 -7
  98. package/lib/util/fake_event_target.js +21 -1
  99. package/lib/util/mp4_box_parsers.js +1 -1
  100. package/lib/util/periods.js +4 -1
  101. package/lib/util/platform.js +13 -1
  102. package/lib/util/stream_utils.js +105 -13
  103. package/lib/util/xml_utils.js +50 -12
  104. package/package.json +3 -6
  105. package/roadmap.md +24 -22
  106. package/test/cast/cast_proxy_unit.js +12 -6
  107. package/test/cast/cast_receiver_integration.js +1 -1
  108. package/test/cast/cast_utils_unit.js +1 -1
  109. package/test/cea/mp4_cea_parser_unit.js +26 -0
  110. package/test/dash/dash_parser_live_unit.js +43 -0
  111. package/test/dash/dash_parser_manifest_unit.js +222 -3
  112. package/test/hls/hls_parser_unit.js +79 -1
  113. package/test/media/closed_caption_parser_unit.js +20 -0
  114. package/test/media/drm_engine_integration.js +86 -2
  115. package/test/media/drm_engine_unit.js +57 -0
  116. package/test/media/playhead_unit.js +27 -1
  117. package/test/media/region_observer_unit.js +40 -5
  118. package/test/media/region_timeline_unit.js +40 -22
  119. package/test/media/streaming_engine_integration.js +2 -1
  120. package/test/media/streaming_engine_unit.js +145 -0
  121. package/test/player_integration.js +79 -8
  122. package/test/player_src_equals_integration.js +41 -8
  123. package/test/player_unit.js +14 -4
  124. package/test/test/assets/3675/chunk-stream0-00001.m4s +0 -0
  125. package/test/test/assets/3675/chunk-stream0-00002.m4s +0 -0
  126. package/test/test/assets/3675/chunk-stream0-00003.m4s +0 -0
  127. package/test/test/assets/3675/chunk-stream0-00004.m4s +0 -0
  128. package/test/test/assets/3675/chunk-stream0-00005.m4s +0 -0
  129. package/test/test/assets/3675/chunk-stream0-00006.m4s +0 -0
  130. package/test/test/assets/3675/chunk-stream0-00007.m4s +0 -0
  131. package/test/test/assets/3675/dash_0.mpd +30 -0
  132. package/test/test/assets/3675/dash_1.mpd +30 -0
  133. package/test/test/assets/3675/dash_2.mpd +30 -0
  134. package/test/test/assets/3675/dash_3.mpd +30 -0
  135. package/test/test/assets/3675/dash_4.mpd +30 -0
  136. package/test/test/assets/3675/dash_5.mpd +26 -0
  137. package/test/test/assets/3675/init-stream0.m4s +0 -0
  138. package/test/test/assets/chapters.vtt +2 -2
  139. package/test/test/assets/chapters2.vtt +10 -0
  140. package/test/test/assets/empty_caption_video_init.mp4 +0 -0
  141. package/test/test/assets/empty_caption_video_segment.mp4 +0 -0
  142. package/test/test/util/fake_ad_manager.js +11 -1
  143. package/test/test/util/ttml_utils.js +81 -0
  144. package/test/test/util/util.js +10 -7
  145. package/test/text/mp4_ttml_parser_unit.js +11 -18
  146. package/test/text/ttml_text_parser_unit.js +542 -220
  147. package/test/text/ui_text_displayer_unit.js +93 -20
  148. package/test/text/vtt_text_parser_unit.js +17 -1
  149. package/test/text/web_vtt_generator_unit.js +58 -3
  150. package/test/ui/localization_unit.js +15 -14
  151. package/test/ui/text_displayer_layout_unit.js +21 -8
  152. package/test/util/mp4_box_parsers_unit.js +28 -0
  153. package/test/util/stream_utils_unit.js +60 -3
  154. package/ui/cast_button.js +2 -3
  155. package/ui/controls.js +11 -6
  156. package/ui/less/buttons.less +0 -4
  157. package/ui/less/containers.less +6 -7
  158. package/ui/locales/ru.json +6 -6
  159. package/ui/localization.js +40 -87
  160. package/ui/pip_button.js +2 -3
  161. package/ui/seek_bar.js +1 -2
  162. package/ui/text_selection.js +1 -0
@@ -8,16 +8,19 @@ goog.provide('shaka.media.RegionObserver');
8
8
 
9
9
  goog.require('shaka.media.IPlayheadObserver');
10
10
  goog.require('shaka.media.RegionTimeline');
11
+ goog.require('shaka.util.EventManager');
12
+ goog.require('shaka.util.FakeEvent');
13
+ goog.require('shaka.util.FakeEventTarget');
11
14
 
12
15
 
13
16
  /**
14
17
  * The region observer watches a region timeline and playhead, and fires events
15
- * (onEnter, onExit, and onSkip) as the playhead moves.
18
+ * ('enter', 'exit', 'skip') as the playhead moves.
16
19
  *
17
20
  * @implements {shaka.media.IPlayheadObserver}
18
21
  * @final
19
22
  */
20
- shaka.media.RegionObserver = class {
23
+ shaka.media.RegionObserver = class extends shaka.util.FakeEventTarget {
21
24
  /**
22
25
  * Create a region observer for the given timeline. The observer does not
23
26
  * own the timeline, only uses it. This means that the observer should NOT
@@ -26,6 +29,8 @@ shaka.media.RegionObserver = class {
26
29
  * @param {!shaka.media.RegionTimeline} timeline
27
30
  */
28
31
  constructor(timeline) {
32
+ super();
33
+
29
34
  /** @private {shaka.media.RegionTimeline} */
30
35
  this.timeline_ = timeline;
31
36
 
@@ -39,13 +44,6 @@ shaka.media.RegionObserver = class {
39
44
  */
40
45
  this.oldPosition_ = new Map();
41
46
 
42
- /** @private {shaka.media.RegionObserver.EventListener} */
43
- this.onEnter_ = (region, seeking) => {};
44
- /** @private {shaka.media.RegionObserver.EventListener} */
45
- this.onExit_ = (region, seeking) => {};
46
- /** @private {shaka.media.RegionObserver.EventListener} */
47
- this.onSkip_ = (region, seeking) => {};
48
-
49
47
  // To make the rules easier to read, alias all the relative positions.
50
48
  const RelativePosition = shaka.media.RegionObserver.RelativePosition_;
51
49
  const BEFORE_THE_REGION = RelativePosition.BEFORE_THE_REGION;
@@ -62,39 +60,48 @@ shaka.media.RegionObserver = class {
62
60
  {
63
61
  weWere: null,
64
62
  weAre: IN_THE_REGION,
65
- invoke: (region, seeking) => this.onEnter_(region, seeking),
63
+ invoke: (region, seeking) => this.onEvent_('enter', region, seeking),
66
64
  },
67
65
  {
68
66
  weWere: BEFORE_THE_REGION,
69
67
  weAre: IN_THE_REGION,
70
- invoke: (region, seeking) => this.onEnter_(region, seeking),
68
+ invoke: (region, seeking) => this.onEvent_('enter', region, seeking),
71
69
  },
72
70
  {
73
71
  weWere: AFTER_THE_REGION,
74
72
  weAre: IN_THE_REGION,
75
- invoke: (region, seeking) => this.onEnter_(region, seeking),
73
+ invoke: (region, seeking) => this.onEvent_('enter', region, seeking),
76
74
  },
77
75
  {
78
76
  weWere: IN_THE_REGION,
79
77
  weAre: BEFORE_THE_REGION,
80
- invoke: (region, seeking) => this.onExit_(region, seeking),
78
+ invoke: (region, seeking) => this.onEvent_('exit', region, seeking),
81
79
  },
82
80
  {
83
81
  weWere: IN_THE_REGION,
84
82
  weAre: AFTER_THE_REGION,
85
- invoke: (region, seeking) => this.onExit_(region, seeking),
83
+ invoke: (region, seeking) => this.onEvent_('exit', region, seeking),
86
84
  },
87
85
  {
88
86
  weWere: BEFORE_THE_REGION,
89
87
  weAre: AFTER_THE_REGION,
90
- invoke: (region, seeking) => this.onSkip_(region, seeking),
88
+ invoke: (region, seeking) => this.onEvent_('skip', region, seeking),
91
89
  },
92
90
  {
93
91
  weWere: AFTER_THE_REGION,
94
92
  weAre: BEFORE_THE_REGION,
95
- invoke: (region, seeking) => this.onSkip_(region, seeking),
93
+ invoke: (region, seeking) => this.onEvent_('skip', region, seeking),
96
94
  },
97
95
  ];
96
+
97
+ /** @private {shaka.util.EventManager} */
98
+ this.eventManager_ = new shaka.util.EventManager();
99
+
100
+ this.eventManager_.listen(this.timeline_, 'regionremove', (event) => {
101
+ /** @type {shaka.extern.TimelineRegionInfo} */
102
+ const region = event['region'];
103
+ this.oldPosition_.delete(region);
104
+ });
98
105
  }
99
106
 
100
107
  /** @override */
@@ -105,11 +112,10 @@ shaka.media.RegionObserver = class {
105
112
  // needed.
106
113
  this.oldPosition_.clear();
107
114
 
108
- // Clear the callbacks so that we don't hold onto any references external
109
- // to this class.
110
- this.onEnter_ = (region, seeking) => {};
111
- this.onExit_ = (region, seeking) => {};
112
- this.onSkip_ = (region, seeking) => {};
115
+ this.eventManager_.release();
116
+ this.eventManager_ = null;
117
+
118
+ super.release();
113
119
  }
114
120
 
115
121
  /** @override */
@@ -134,20 +140,20 @@ shaka.media.RegionObserver = class {
134
140
  }
135
141
 
136
142
  /**
137
- * Set all the listeners. This overrides any previous calls to |setListeners|.
143
+ * Dispatch events of the given type. All event types in this class have the
144
+ * same parameters: region and seeking.
138
145
  *
139
- * @param {shaka.media.RegionObserver.EventListener} onEnter
140
- * The callback for when we move from outside a region to inside a region.
141
- * @param {shaka.media.RegionObserver.EventListener} onExit
142
- * The callback for when we move from inside a region to outside a region.
143
- * @param {shaka.media.RegionObserver.EventListener} onSkip
144
- * The callback for when we move from before to after a region or from
145
- * after to before a region.
146
+ * @param {string} eventType
147
+ * @param {shaka.extern.TimelineRegionInfo} region
148
+ * @param {boolean} seeking
149
+ * @private
146
150
  */
147
- setListeners(onEnter, onExit, onSkip) {
148
- this.onEnter_ = onEnter;
149
- this.onExit_ = onExit;
150
- this.onSkip_ = onSkip;
151
+ onEvent_(eventType, region, seeking) {
152
+ const event = new shaka.util.FakeEvent(eventType, new Map([
153
+ ['region', region],
154
+ ['seeking', seeking],
155
+ ]));
156
+ this.dispatchEvent(event);
151
157
  }
152
158
 
153
159
  /**
@@ -6,26 +6,30 @@
6
6
 
7
7
  goog.provide('shaka.media.RegionTimeline');
8
8
 
9
+ goog.require('shaka.util.FakeEvent');
10
+ goog.require('shaka.util.FakeEventTarget');
9
11
  goog.require('shaka.util.IReleasable');
10
12
  goog.require('shaka.util.Timer');
11
13
 
12
14
 
13
15
  /**
14
16
  * The region timeline is a set of unique timeline region info entries. When
15
- * a new entry is added, the |onAddRegion| callback will be called.
17
+ * a new entry is added, the 'regionadd' event will be fired. When an entry is
18
+ * deleted, the 'regionremove' event will be fired.
16
19
  *
17
20
  * @implements {shaka.util.IReleasable}
18
21
  * @final
19
22
  */
20
- shaka.media.RegionTimeline = class {
23
+ shaka.media.RegionTimeline = class extends shaka.util.FakeEventTarget {
21
24
  /**
22
25
  * @param {!function():{start: number, end: number}} getSeekRange
23
26
  */
24
27
  constructor(getSeekRange) {
25
- /** @private {function(shaka.extern.TimelineRegionInfo)} */
26
- this.onAddRegion_ = (region) => {};
28
+ super();
29
+
27
30
  /** @private {!Set.<shaka.extern.TimelineRegionInfo>} */
28
31
  this.regions_ = new Set();
32
+
29
33
  /** @private {!function():{start: number, end: number}} */
30
34
  this.getSeekRange_ = getSeekRange;
31
35
 
@@ -44,22 +48,9 @@ shaka.media.RegionTimeline = class {
44
48
 
45
49
  /** @override */
46
50
  release() {
47
- // Prevent us from holding onto any external references via the callback.
48
- this.onAddRegion_ = (region) => {};
49
51
  this.regions_.clear();
50
52
  this.filterTimer_.stop();
51
- }
52
-
53
- /**
54
- * Set the callbacks for events. This will override any previous calls to
55
- * |setListeners|.
56
- *
57
- * @param {function(shaka.extern.TimelineRegionInfo)} onAddRegion
58
- * Set the callback for when we add a new region. This callback will only
59
- * be called when a region is unique (we reject duplicate regions).
60
- */
61
- setListeners(onAddRegion) {
62
- this.onAddRegion_ = onAddRegion;
53
+ super.release();
63
54
  }
64
55
 
65
56
  /**
@@ -72,7 +63,10 @@ shaka.media.RegionTimeline = class {
72
63
  // instead of making the parser track it.
73
64
  if (similarRegion == null) {
74
65
  this.regions_.add(region);
75
- this.onAddRegion_(region);
66
+ const event = new shaka.util.FakeEvent('regionadd', new Map([
67
+ ['region', region],
68
+ ]));
69
+ this.dispatchEvent(event);
76
70
  }
77
71
  }
78
72
 
@@ -89,6 +83,10 @@ shaka.media.RegionTimeline = class {
89
83
  // reson to store or process them.
90
84
  if (region.endTime < seekRange.start) {
91
85
  this.regions_.delete(region);
86
+ const event = new shaka.util.FakeEvent('regionremove', new Map([
87
+ ['region', region],
88
+ ]));
89
+ this.dispatchEvent(event);
92
90
  }
93
91
  }
94
92
  }
@@ -347,7 +347,8 @@ shaka.media.SegmentIndex = class {
347
347
  lastReference.appendWindowStart,
348
348
  lastReference.appendWindowEnd,
349
349
  lastReference.partialReferences,
350
- lastReference.tilesLayout);
350
+ lastReference.tilesLayout,
351
+ lastReference.tileDuration);
351
352
  }
352
353
 
353
354
 
@@ -140,11 +140,15 @@ shaka.media.SegmentReference = class {
140
140
  * The value is a grid-item-dimension consisting of two positive decimal
141
141
  * integers in the format: column-x-row ('4x3'). It describes the
142
142
  * arrangement of Images in a Grid. The minimum valid LAYOUT is '1x1'.
143
+ * @param {?number=} tileDuration
144
+ * The explicit duration of an individual tile within the tiles grid.
145
+ * If not provided, the duration should be automatically calculated based on
146
+ * the duration of the reference.
143
147
  */
144
148
  constructor(
145
149
  startTime, endTime, uris, startByte, endByte, initSegmentReference,
146
150
  timestampOffset, appendWindowStart, appendWindowEnd,
147
- partialReferences = [], tilesLayout = '') {
151
+ partialReferences = [], tilesLayout = '', tileDuration = null) {
148
152
  // A preload hinted Partial Segment has the same startTime and endTime.
149
153
  goog.asserts.assert(startTime <= endTime,
150
154
  'startTime must be less than or equal to endTime');
@@ -191,6 +195,9 @@ shaka.media.SegmentReference = class {
191
195
 
192
196
  /** @type {?string} */
193
197
  this.tilesLayout = tilesLayout;
198
+
199
+ /** @type {?number} */
200
+ this.tileDuration = tileDuration;
194
201
  }
195
202
 
196
203
  /**
@@ -275,6 +282,17 @@ shaka.media.SegmentReference = class {
275
282
  getTilesLayout() {
276
283
  return this.tilesLayout;
277
284
  }
285
+
286
+ /**
287
+ * Returns the segment's explicit tile duration.
288
+ * Only defined in image segments.
289
+ *
290
+ * @return {?number}
291
+ * @export
292
+ */
293
+ getTileDuration() {
294
+ return this.tileDuration;
295
+ }
278
296
  };
279
297
 
280
298
 
@@ -623,7 +623,7 @@ shaka.media.StreamingEngine = class {
623
623
 
624
624
  // Don't clear the buffer unless something is buffered. This extra
625
625
  // check prevents extra, useless calls to clear the buffer.
626
- if (somethingBuffered) {
626
+ if (somethingBuffered || mediaState.performingUpdate) {
627
627
  this.forceClearBuffer_(mediaState);
628
628
  streamCleared = true;
629
629
  }
@@ -977,7 +977,10 @@ shaka.media.StreamingEngine = class {
977
977
  unscaledBufferingGoal * this.bufferingGoalScale_;
978
978
 
979
979
  // Check if we've buffered to the end of the presentation.
980
- if (timeNeeded >= this.manifest_.presentationTimeline.getDuration()) {
980
+ const timeUntilEnd =
981
+ this.manifest_.presentationTimeline.getDuration() - timeNeeded;
982
+ const oneMicrosecond = 1e-6;
983
+ if (timeUntilEnd < oneMicrosecond) {
981
984
  // We shouldn't rebuffer if the playhead is close to the end of the
982
985
  // presentation.
983
986
  shaka.log.debug(logPrefix, 'buffered to end of presentation');
@@ -1641,7 +1644,7 @@ shaka.media.StreamingEngine = class {
1641
1644
  // See DASH sec. 5.10.3.3.1
1642
1645
  // If a DASH client detects an event message box with a scheme that is not
1643
1646
  // defined in MPD, the client is expected to ignore it.
1644
- if (emsgSchemeIdUris.includes(schemeId)) {
1647
+ if (emsgSchemeIdUris && emsgSchemeIdUris.includes(schemeId)) {
1645
1648
  // See DASH sec. 5.10.4.1
1646
1649
  // A special scheme in DASH used to signal manifest updates.
1647
1650
  if (schemeId == 'urn:mpeg:dash:event:2012') {
@@ -1662,7 +1665,8 @@ shaka.media.StreamingEngine = class {
1662
1665
 
1663
1666
  // Dispatch an event to notify the application about the emsg box.
1664
1667
  const eventName = shaka.Player.EventName.Emsg;
1665
- const event = new shaka.util.FakeEvent(eventName, {'detail': emsg});
1668
+ const data = (new Map()).set('detail', emsg);
1669
+ const event = new shaka.util.FakeEvent(eventName, data);
1666
1670
  this.playerInterface_.onEvent(event);
1667
1671
  }
1668
1672
  }
@@ -222,6 +222,10 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
222
222
  this.destroyed_ = true;
223
223
  this.requestFilters_.clear();
224
224
  this.responseFilters_.clear();
225
+
226
+ // FakeEventTarget implements IReleasable
227
+ super.release();
228
+
225
229
  return this.operationManager_.destroy();
226
230
  }
227
231
 
@@ -544,7 +548,8 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
544
548
  }
545
549
 
546
550
  if (error.severity == shaka.util.Error.Severity.RECOVERABLE) {
547
- const event = new shaka.util.FakeEvent('retry', {'error': error});
551
+ const data = (new Map()).set('error', error);
552
+ const event = new shaka.util.FakeEvent('retry', data);
548
553
  this.dispatchEvent(event);
549
554
 
550
555
  // Move to the next URI.
@@ -44,9 +44,8 @@ shaka.offline.DownloadManager = class {
44
44
 
45
45
  /** @private {!shaka.util.Destroyer} */
46
46
  this.destroyer_ = new shaka.util.Destroyer(() => {
47
- const promises = Array.from(this.groups_.values());
48
47
  // Add a "catch" block to stop errors from being returned.
49
- return Promise.all(promises.map((p) => p.catch(() => {})));
48
+ return this.abortAll().catch(() => {});
50
49
  });
51
50
 
52
51
  /**
@@ -477,16 +477,15 @@ shaka.offline.Storage = class {
477
477
  * @private
478
478
  */
479
479
  async filterManifest_(manifest, drmEngine, config) {
480
- const StreamUtils = shaka.util.StreamUtils;
481
-
482
480
  // Filter the manifest based on the restrictions given in the player
483
481
  // configuration.
484
482
  const maxHwRes = {width: Infinity, height: Infinity};
485
- StreamUtils.filterByRestrictions(manifest, config.restrictions, maxHwRes);
483
+ shaka.util.StreamUtils.filterByRestrictions(
484
+ manifest, config.restrictions, maxHwRes);
486
485
 
487
486
  // Filter the manifest based on what we know MediaCapabilities will be able
488
487
  // to play later (no point storing something we can't play).
489
- StreamUtils.filterManifestByMediaCapabilities(
488
+ await shaka.util.StreamUtils.filterManifestByMediaCapabilities(
490
489
  manifest, config.offline.usePersistentLicense);
491
490
 
492
491
  // Gather all tracks.
@@ -498,24 +497,24 @@ shaka.offline.Storage = class {
498
497
  const preferredVideoCodecs = config.preferredVideoCodecs;
499
498
  const preferredAudioCodecs = config.preferredAudioCodecs;
500
499
 
501
- StreamUtils.chooseCodecsAndFilterManifest(
500
+ shaka.util.StreamUtils.chooseCodecsAndFilterManifest(
502
501
  manifest, preferredVideoCodecs, preferredAudioCodecs,
503
502
  preferredAudioChannelCount, preferredDecodingAttributes);
504
503
 
505
504
  for (const variant of manifest.variants) {
506
505
  goog.asserts.assert(
507
- StreamUtils.isPlayable(variant),
506
+ shaka.util.StreamUtils.isPlayable(variant),
508
507
  'We should have already filtered by "is playable"');
509
508
 
510
- allTracks.push(StreamUtils.variantToTrack(variant));
509
+ allTracks.push(shaka.util.StreamUtils.variantToTrack(variant));
511
510
  }
512
511
 
513
512
  for (const text of manifest.textStreams) {
514
- allTracks.push(StreamUtils.textStreamToTrack(text));
513
+ allTracks.push(shaka.util.StreamUtils.textStreamToTrack(text));
515
514
  }
516
515
 
517
516
  for (const image of manifest.imageStreams) {
518
- allTracks.push(StreamUtils.imageStreamToTrack(image));
517
+ allTracks.push(shaka.util.StreamUtils.imageStreamToTrack(image));
519
518
  }
520
519
 
521
520
  // Let the application choose which tracks to store.