shaka-player 4.3.4 → 4.3.6

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 (111) hide show
  1. package/.github/workflows/build-and-test.yaml +4 -4
  2. package/.github/workflows/demo-version-index.yaml +6 -0
  3. package/.github/workflows/selenium-lab-tests.yaml +78 -17
  4. package/.github/workflows/update-screenshots.yaml +142 -0
  5. package/AUTHORS +2 -1
  6. package/CHANGELOG.md +56 -0
  7. package/CONTRIBUTORS +4 -1
  8. package/demo/common/asset.js +15 -0
  9. package/demo/common/assets.js +4 -2
  10. package/demo/common/message_ids.js +1 -0
  11. package/demo/custom.js +19 -0
  12. package/demo/locales/en.json +1 -0
  13. package/demo/locales/source.json +4 -0
  14. package/demo/main.js +14 -0
  15. package/dist/controls.css +2 -2
  16. package/dist/controls.css.map +1 -1
  17. package/dist/demo.compiled.debug.js +184 -311
  18. package/dist/demo.compiled.debug.map +4 -4
  19. package/dist/demo.compiled.js +184 -311
  20. package/dist/demo.compiled.map +4 -4
  21. package/dist/deps.js +2 -2
  22. package/dist/locales.js +29 -29
  23. package/dist/receiver.compiled.debug.js +51 -80
  24. package/dist/receiver.compiled.debug.map +4 -4
  25. package/dist/receiver.compiled.js +51 -80
  26. package/dist/receiver.compiled.map +4 -4
  27. package/dist/shaka-player.compiled.d.ts +19 -3
  28. package/dist/shaka-player.compiled.debug.d.ts +19 -3
  29. package/dist/shaka-player.compiled.debug.externs.js +20 -14
  30. package/dist/shaka-player.compiled.debug.js +291 -283
  31. package/dist/shaka-player.compiled.debug.map +4 -4
  32. package/dist/shaka-player.compiled.externs.js +20 -14
  33. package/dist/shaka-player.compiled.js +830 -825
  34. package/dist/shaka-player.compiled.map +3 -3
  35. package/dist/shaka-player.ui.d.ts +19 -3
  36. package/dist/shaka-player.ui.debug.d.ts +19 -3
  37. package/dist/shaka-player.ui.debug.externs.js +8 -2
  38. package/dist/shaka-player.ui.debug.js +301 -292
  39. package/dist/shaka-player.ui.debug.map +3 -3
  40. package/dist/shaka-player.ui.externs.js +8 -2
  41. package/dist/shaka-player.ui.js +927 -922
  42. package/dist/shaka-player.ui.map +3 -3
  43. package/docs/tutorials/a11y.md +0 -4
  44. package/docs/tutorials/ad_monetization.md +0 -4
  45. package/docs/tutorials/basic-usage.md +0 -5
  46. package/docs/tutorials/config.md +0 -5
  47. package/docs/tutorials/debugging.md +0 -5
  48. package/docs/tutorials/drm-config.md +0 -5
  49. package/docs/tutorials/errors.md +94 -0
  50. package/docs/tutorials/fairplay.md +4 -4
  51. package/docs/tutorials/index.json +2 -0
  52. package/docs/tutorials/license-server-auth.md +0 -5
  53. package/docs/tutorials/license-wrapping.md +0 -5
  54. package/docs/tutorials/network-and-buffering-config.md +0 -5
  55. package/docs/tutorials/ui-customization.md +0 -5
  56. package/docs/tutorials/ui.md +0 -7
  57. package/docs/tutorials/welcome.md +0 -5
  58. package/docs/tutorials/widevine-service-certs.md +45 -0
  59. package/externs/ima.js +9 -0
  60. package/externs/network_information.js +7 -2
  61. package/externs/shaka/abr_manager.js +6 -0
  62. package/externs/shaka/net.js +1 -0
  63. package/externs/shaka/player.js +13 -7
  64. package/lib/abr/simple_abr_manager.js +27 -3
  65. package/lib/ads/client_side_ad_manager.js +11 -5
  66. package/lib/dash/dash_parser.js +49 -48
  67. package/lib/debug/log.js +9 -13
  68. package/lib/hls/hls_parser.js +23 -6
  69. package/lib/media/drm_engine.js +4 -2
  70. package/lib/media/media_source_engine.js +27 -9
  71. package/lib/media/presentation_timeline.js +9 -2
  72. package/lib/media/segment_index.js +2 -0
  73. package/lib/media/segment_reference.js +3 -2
  74. package/lib/media/streaming_engine.js +31 -7
  75. package/lib/media/transmuxer.js +13 -7
  76. package/lib/media/video_wrapper.js +3 -3
  77. package/lib/net/http_fetch_plugin.js +79 -57
  78. package/lib/net/networking_engine.js +1 -0
  79. package/lib/offline/indexeddb/storage_mechanism.js +1 -1
  80. package/lib/player.js +24 -3
  81. package/lib/polyfill/media_capabilities.js +15 -8
  82. package/lib/polyfill/mediasource.js +24 -2
  83. package/lib/text/mp4_vtt_parser.js +4 -0
  84. package/lib/text/text_engine.js +1 -0
  85. package/lib/text/ui_text_displayer.js +1 -0
  86. package/lib/text/vtt_text_parser.js +4 -5
  87. package/lib/util/manifest_parser_utils.js +1 -2
  88. package/lib/util/mime_utils.js +12 -1
  89. package/lib/util/periods.js +5 -5
  90. package/lib/util/stream_utils.js +28 -16
  91. package/maintained-branches.md +2 -3
  92. package/package.json +1 -1
  93. package/test/dash/dash_parser_live_unit.js +3 -2
  94. package/test/hls/hls_parser_unit.js +156 -0
  95. package/test/media/content_workarounds_unit.js +43 -0
  96. package/test/media/drm_engine_integration.js +4 -17
  97. package/test/media/streaming_engine_unit.js +6 -1
  98. package/test/net/networking_engine_unit.js +6 -1
  99. package/test/player_integration.js +39 -0
  100. package/test/player_unit.js +57 -0
  101. package/test/polyfill/media_capabilities_unit.js +22 -22
  102. package/test/test/assets/text-clip-alt.vtt +63 -0
  103. package/test/test/util/fake_drm_engine.js +3 -0
  104. package/test/test/util/fake_media_source_engine.js +4 -0
  105. package/test/test/util/simple_fakes.js +6 -0
  106. package/test/test/util/test_scheme.js +9 -14
  107. package/test/text/mp4_vtt_parser_unit.js +8 -0
  108. package/test/text/vtt_text_parser_unit.js +26 -2
  109. package/test/text/web_vtt_layout_integration.js +0 -3
  110. package/test/util/mime_utils_unit.js +10 -0
  111. package/ui/less/containers.less +4 -0
@@ -56,10 +56,6 @@ this.eventManager.listen(this.button_, 'click', () => {
56
56
  });
57
57
  ```
58
58
 
59
- #### Continue the Tutorials
60
-
61
- Next, check out {@tutorial ad_monetization}.
62
-
63
59
 
64
60
 
65
61
  [Web Accessibility Standards]: https://www.w3.org/WAI/standards-guidelines/wcag/
@@ -222,7 +222,3 @@ before instantiating the player.
222
222
  // myapp.CustomAdManager is a placeholder name for your ad manager implementation.
223
223
  shaka.Player.setAdManagerFactory(() => new myapp.CustomAdManager());
224
224
  ```
225
-
226
- #### Continue the Tutorials
227
-
228
- Next, check out {@tutorial plugins}.
@@ -86,8 +86,3 @@ document.addEventListener('DOMContentLoaded', initApp);
86
86
  ```
87
87
 
88
88
  That's it!
89
-
90
-
91
- #### Continue the Tutorials
92
-
93
- Next, check out {@tutorial debugging}.
@@ -142,8 +142,3 @@ player.configure({
142
142
 
143
143
  For more detail on individual configuration options, please see the API docs for
144
144
  {@link shaka.extern.PlayerConfiguration} and {@link shaka.Player#configure}.
145
-
146
-
147
- #### Continue the Tutorials
148
-
149
- Next, check out {@tutorial network-and-buffering-config}.
@@ -187,8 +187,3 @@ To sum up, remember these points when debugging your application:
187
187
  - Use the debug version of Shaka Player for debugging and integration work
188
188
  - Refer to the docs for error codes
189
189
  - Increase the log level when you need more detail
190
-
191
-
192
- #### Continue the Tutorials
193
-
194
- Next, check out {@tutorial config}.
@@ -208,8 +208,3 @@ you should provide an empty string as robustness
208
208
  ##### Other key-systems
209
209
 
210
210
  Values for other key systems are not known to us at this time.
211
-
212
- #### Continue the Tutorials
213
-
214
- Next, check out {@tutorial license-server-auth}.
215
- Or check out {@tutorial fairplay}.
@@ -0,0 +1,94 @@
1
+ # Error Handling
2
+
3
+ The basics for handling native Error and {@link shaka.util.Error} thrown by Shaka.
4
+
5
+ ## Listening To and Handling Errors
6
+
7
+ ```javascript
8
+ const handleError = (error) => {
9
+ if (error instanceof Error) {
10
+ // shaka crashed with an unhandled native error
11
+ }
12
+
13
+ if (error.severity === shaka.util.Error.Severity.CRITICAL) {
14
+ // handle fatal error, playback can not continue
15
+ } else {
16
+ // handle non-fatal error, playback can continue
17
+ }
18
+ };
19
+
20
+ const player = new shaka.Player(video);
21
+
22
+ // handle errors that occur after load
23
+ player.addEventListener('error', handleError);
24
+
25
+ // there are two options for catching errors that occur during load
26
+
27
+ // it's possible to listen directly on the promise
28
+ player.load(url).catch(handleError);
29
+
30
+ // or to use async/await with a try/catch
31
+ try {
32
+ await player.load(url);
33
+ } catch (e) {
34
+ handleError(e);
35
+ }
36
+ ```
37
+
38
+ ## Custom Handling of Streaming Errors
39
+
40
+ The `streaming.failureCallback` property of {@link shaka.extern.PlayerConfiguration} can be used to add custom handling or error conversion of errors that occur during streaming.
41
+
42
+ ```javascript
43
+ player.configure('streaming.failureCallback', (error) => {
44
+ if (error.severity === shaka.util.Error.Severity.CRITICAL) {
45
+ // custom handling of critical error
46
+ // e.g. player.retryStreaming();
47
+ } else {
48
+ // custom handling of recoverable error
49
+ }
50
+ });
51
+ ```
52
+
53
+ ## Custom Handling of Retries
54
+
55
+ When configuring retry parameters in Shaka there may be known error codes that should not be retried, or the need to break out of an infinite retry loop in a live context. Retries for failed network requests are not reported as `RECOVERABLE` errors.
56
+
57
+ For example, if a VOD manifest is missing, unlike when a LIVE manifest is missing, it can be expected to not show up and there is no need to retry.
58
+
59
+ This is how to convert a retry into a critical error, see {@link shaka.net.NetworkingEngine.RetryEvent} and {@link shaka.util.Error} to decipher how the event can be parsed:
60
+
61
+ ```javascript
62
+ const nwEngine = player.getNetworkingEngine();
63
+
64
+ const vodManifestNotFoundHandler = (event /* shaka.net.NetworkingEngine.RetryEvent */) => {
65
+ const code = event.error.code;
66
+ const data = event.error.data;
67
+
68
+ if (code === shaka.util.Error.Code.BAD_HTTP_STATUS) {
69
+ if (
70
+ // each type of error has its own data structure (or none at all), tread with care
71
+ Array.isArray(data) &&
72
+ data[1] === 404 &&
73
+ data[4] === shaka.net.NetworkingEngine.RequestType.MANIFEST
74
+ ) {
75
+ // Throwing inside a retry callback will immediately stop retries
76
+ throw error;
77
+
78
+ // A proprietary error code can also be thrown
79
+ // throw new shaka.util.Error(
80
+ // shaka.util.Error.Severity.CRITICAL,
81
+ // shaka.util.Error.Category.NETWORK,
82
+ // 'RECOGNIZABLE_ERROR_MESSAGE'
83
+ // );
84
+ }
85
+ }
86
+ };
87
+
88
+ nwEngine.addEventListener('retry', vodManifestNotFoundHandler);
89
+
90
+ player.addEventListener('load'() => {
91
+ nwEngine.removeEventListener('retry', vodManifestNotFoundHandler);
92
+ });
93
+
94
+ ```
@@ -53,12 +53,12 @@ you.
53
53
  const req = await fetch('https://example.com/cert.der');
54
54
  const cert = await req.arrayBuffer();
55
55
 
56
- player.configure('drm.advanced.com\\.apple\\.fps\\.serverCertificate',
56
+ player.configure('drm.advanced.com\\.apple\\.fps.serverCertificate',
57
57
  new Uint8Array(cert));
58
58
  ```
59
59
 
60
60
  ```js
61
- player.configure('drm.advanced.com\\.apple\\.fps\\.serverCertificateUri',
61
+ player.configure('drm.advanced.com\\.apple\\.fps.serverCertificateUri',
62
62
  'https://example.com/cert.der');
63
63
  ```
64
64
 
@@ -72,13 +72,13 @@ is used by the browser to generate the license request. If you don't use the
72
72
  default content ID derivation, you need to specify a custom init data transform:
73
73
 
74
74
  ```js
75
- player.configure('drm.initDataTransform', (initData, initDataType) => {
75
+ player.configure('drm.initDataTransform', (initData, initDataType, drmInfo) => {
76
76
  if (initDataType != 'skd')
77
77
  return initData;
78
78
  // 'initData' is a buffer containing an 'skd://' URL as a UTF-8 string.
79
79
  const skdUri = shaka.util.StringUtils.fromBytesAutoDetect(initData);
80
80
  const contentId = getMyContentId(skdUri);
81
- const cert = player.drmInfo().serverCertificate;
81
+ const cert = drmInfo.serverCertificate;
82
82
  return shaka.util.FairPlayUtils.initDataTransform(initData, contentId, cert);
83
83
  });
84
84
  ```
@@ -9,6 +9,7 @@
9
9
  { "license-wrapping": { "title": "License Wrapping" } },
10
10
  { "ui": { "title": "UI Library" } },
11
11
  { "ui-customization": { "title": "Configuring the UI" } },
12
+ { "errors": { "title": "Error Handling" } },
12
13
  { "a11y": { "title": "Creating accessible buttons" } },
13
14
  { "ad_monetization": { "title": "Serving ads with our IMA SDK integration" } },
14
15
  { "plugins": { "title": "Plugins and Customizing the Build" } },
@@ -16,6 +17,7 @@
16
17
  { "architecture": { "title": "Architecture Diagrams" } },
17
18
  { "service-worker": { "title": "Service Worker Caching" } },
18
19
  { "offline": { "title": "Offline Storage and Playback" } },
20
+ { "widevine-service-certs": { "title": "Widevine Service Certificates" } },
19
21
  { "fairplay": { "title": "FairPlay support" } },
20
22
  { "application-level-redirects": { "title": "Application-Level Redirects" } },
21
23
  { "blob-url": { "title": "Blob URL" } },
@@ -246,8 +246,3 @@ License request can now continue.
246
246
 
247
247
  If you need them, you can also create asynchronous response filters in the same
248
248
  way.
249
-
250
-
251
- #### Continue the Tutorials
252
-
253
- Next, check out {@tutorial license-wrapping}.
@@ -166,8 +166,3 @@ using a request filter:
166
166
 
167
167
  Load the page again, and the license response will be accepted by the Widevine
168
168
  CDM. Open the JavaScript console to see what the server sent back.
169
-
170
-
171
- #### Continue the Tutorials
172
-
173
- Next, check out {@tutorial ui}.
@@ -117,8 +117,3 @@ URLs in your manifests always use `https:`, or by having it not include the
117
117
  scheme (e.g., `//example.com/file.mp4`).
118
118
 
119
119
  [CORS]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
120
-
121
-
122
- #### Continue the Tutorials
123
-
124
- Next, check out {@tutorial drm-config}.
@@ -265,8 +265,3 @@ PR contributions to [the gallery repo][] are welcome.
265
265
  [@lucksy]: https://github.com/lucksy
266
266
  [pre-packaged Shaka UI themes]: https://lucksy.github.io/shaka-player-themes/
267
267
  [the gallery repo]: https://github.com/lucksy/shaka-player-themes
268
-
269
-
270
- #### Continue the Tutorials
271
-
272
- Next, check out {@tutorial a11y} to make your custom buttons accessible to screen readers.
@@ -227,10 +227,3 @@ ui.configure({
227
227
  'castAndroidReceiverCompatible': true,
228
228
  });
229
229
  ```
230
-
231
-
232
-
233
-
234
- #### Continue the Tutorials
235
-
236
- Next, check out {@tutorial ui-customization}.
@@ -106,8 +106,3 @@ To subscribe to new releases on GitHub, you can follow
106
106
  To receive infrequent announcements and surveys from us, you can join our
107
107
  [mailing list](https://groups.google.com/forum/#!forum/shaka-player-users).
108
108
  The list is very low volume, and can only be written to by us.
109
-
110
-
111
- #### Continue the Tutorials
112
-
113
- Next, check out {@tutorial basic-usage}.
@@ -0,0 +1,45 @@
1
+ # Widevine Service Certificates
2
+
3
+ With Widevine, you can eliminate one round-trip to your license server or proxy
4
+ per session by preloading a Widevine service certificate. You can either provide
5
+ it directly or set a URI and let Shaka fetch it for you. Do this before calling
6
+ `player.load()`. The values will persist across multiple calls to `load()` on
7
+ the same `shaka.Player` instance.
8
+
9
+ ```js
10
+ // This is an example of loading the certificate from your site at runtime.
11
+ // You could also choose to bundle it into your JavaScript as a Uint8Array.
12
+ const req = await fetch('https://example.com/service.cert');
13
+ const cert = new Uint8Array(await req.arrayBuffer());
14
+
15
+ // This is the short form for configuration of a certificate:
16
+ player.configure('drm.advanced.com\\.widevine\\.alpha.serverCertificate',
17
+ cert);
18
+
19
+ // This is the long form:
20
+ player.configure({
21
+ drm: {
22
+ advanced: {
23
+ 'com.widevine.alpha': {
24
+ 'serverCertificate': cert,
25
+ },
26
+ },
27
+ },
28
+ });
29
+
30
+
31
+ // This is the short form for configuration of a certificate URI:
32
+ player.configure('drm.advanced.com\\.widevine\\.alpha.serverCertificateUri',
33
+ 'https://example.com/service.cert');
34
+
35
+ // This is the long form:
36
+ player.configure({
37
+ drm: {
38
+ advanced: {
39
+ 'com.widevine.alpha': {
40
+ 'serverCertificateUri': 'https://example.com/service.cert',
41
+ },
42
+ },
43
+ },
44
+ });
45
+ ```
package/externs/ima.js CHANGED
@@ -513,6 +513,15 @@ google.ima.dai.api.StreamRequest.prototype.streamActivityMonitorId;
513
513
  google.ima.dai.api.StreamRequest.prototype.format;
514
514
 
515
515
 
516
+ /**
517
+ * @enum {string}
518
+ */
519
+ google.ima.dai.api.StreamRequest.StreamFormat = {
520
+ DASH: 'dash',
521
+ HLS: 'hls',
522
+ };
523
+
524
+
516
525
  /** @const */
517
526
  google.ima.dai.api.VODStreamRequest =
518
527
  class extends google.ima.dai.api.StreamRequest {};
@@ -19,5 +19,10 @@ NetworkInformation.prototype.saveData;
19
19
  * @param {string} type
20
20
  * @param {Function} listener
21
21
  */
22
- NetworkInformation.prototype.addEventListener =
23
- function(type, listener) {};
22
+ NetworkInformation.prototype.addEventListener = function(type, listener) {};
23
+
24
+ /**
25
+ * @param {string} type
26
+ * @param {Function} listener
27
+ */
28
+ NetworkInformation.prototype.removeEventListener = function(type, listener) {};
@@ -44,6 +44,12 @@ shaka.extern.AbrManager = class {
44
44
  */
45
45
  stop() {}
46
46
 
47
+ /**
48
+ * Request that this object release all internal references.
49
+ * @exportDoc
50
+ */
51
+ release() {}
52
+
47
53
  /**
48
54
  * Updates manager's variants collection.
49
55
  *
@@ -112,6 +112,7 @@ shaka.extern.Request;
112
112
  /**
113
113
  * @typedef {{
114
114
  * uri: string,
115
+ * originalUri: string,
115
116
  * data: BufferSource,
116
117
  * status: (number|undefined),
117
118
  * headers: !Object.<string, string>,
@@ -688,9 +688,7 @@ shaka.extern.AdvancedDrmConfiguration;
688
688
  * clearKeys: !Object.<string, string>,
689
689
  * delayLicenseRequestUntilPlayed: boolean,
690
690
  * advanced: Object.<string, shaka.extern.AdvancedDrmConfiguration>,
691
- * initDataTransform:
692
- * ((function(!Uint8Array, string, ?shaka.extern.DrmInfo):!Uint8Array)|
693
- * undefined),
691
+ * initDataTransform:(shaka.extern.InitDataTransform|undefined),
694
692
  * logLicenseExchange: boolean,
695
693
  * updateExpirationTime: number,
696
694
  * preferredKeySystems: !Array.<string>,
@@ -716,10 +714,7 @@ shaka.extern.AdvancedDrmConfiguration;
716
714
  * <i>Optional.</i> <br>
717
715
  * A dictionary which maps key system IDs to advanced DRM configuration for
718
716
  * those key systems.
719
- * @property
720
- * {((function(!Uint8Array, string, ?shaka.extern.DrmInfo):!Uint8Array)|
721
- * undefined)}
722
- * initDataTransform
717
+ * @property {shaka.extern.InitDataTransform|undefined} initDataTransform
723
718
  * <i>Optional.</i><br>
724
719
  * If given, this function is called with the init data from the
725
720
  * manifest/media and should return the (possibly transformed) init data to
@@ -748,6 +743,17 @@ shaka.extern.AdvancedDrmConfiguration;
748
743
  */
749
744
  shaka.extern.DrmConfiguration;
750
745
 
746
+ /**
747
+ * @typedef {function(!Uint8Array, string, ?shaka.extern.DrmInfo):!Uint8Array}
748
+ *
749
+ * @description
750
+ * A callback function to handle custom content ID signaling for FairPlay
751
+ * content.
752
+ *
753
+ * @exportDoc
754
+ */
755
+ shaka.extern.InitDataTransform;
756
+
751
757
 
752
758
  /**
753
759
  * @typedef {{
@@ -6,6 +6,7 @@
6
6
 
7
7
  goog.provide('shaka.abr.SimpleAbrManager');
8
8
 
9
+ goog.require('shaka.util.IReleasable');
9
10
  goog.require('goog.asserts');
10
11
  goog.require('shaka.abr.EwmaBandwidthEstimator');
11
12
  goog.require('shaka.log');
@@ -32,6 +33,7 @@ goog.require('shaka.util.Timer');
32
33
  * </p>
33
34
  *
34
35
  * @implements {shaka.extern.AbrManager}
36
+ * @implements {shaka.util.IReleasable}
35
37
  * @export
36
38
  */
37
39
  shaka.abr.SimpleAbrManager = class {
@@ -50,8 +52,8 @@ shaka.abr.SimpleAbrManager = class {
50
52
  // retrieving information about a user's network connection. We listen
51
53
  // to the change event to be able to make quick changes in case the type
52
54
  // of connectivity changes.
53
- if (navigator.connection) {
54
- navigator.connection.addEventListener('change', () => {
55
+ if (navigator.connection && navigator.connection.addEventListener) {
56
+ this.onNetworkInformationChange_ = () => {
55
57
  if (this.config_.useNetworkInformation && this.enabled_) {
56
58
  this.bandwidthEstimator_ = new shaka.abr.EwmaBandwidthEstimator();
57
59
  if (this.config_) {
@@ -62,7 +64,10 @@ shaka.abr.SimpleAbrManager = class {
62
64
  this.switch_(chosenVariant);
63
65
  }
64
66
  }
65
- });
67
+ };
68
+
69
+ navigator.connection.addEventListener(
70
+ 'change', this.onNetworkInformationChange_);
66
71
  }
67
72
 
68
73
  /**
@@ -93,6 +98,9 @@ shaka.abr.SimpleAbrManager = class {
93
98
  /** @private {ResizeObserver} */
94
99
  this.resizeObserver_ = null;
95
100
 
101
+ /** @private {?function():void} */
102
+ this.onNetworkInformationChange_ = null;
103
+
96
104
  /** @private {shaka.util.Timer} */
97
105
  this.resizeObserverTimer_ = new shaka.util.Timer(() => {
98
106
  if (this.config_.restrictToElementSize) {
@@ -128,6 +136,22 @@ shaka.abr.SimpleAbrManager = class {
128
136
  // can start using bandwidth estimates right away after init() is called.
129
137
  }
130
138
 
139
+ /**
140
+ * @override
141
+ * @export
142
+ */
143
+ release() {
144
+ // stop() should already have been called for unload
145
+
146
+ if (navigator.connection && navigator.connection.removeEventListener) {
147
+ navigator.connection.removeEventListener(
148
+ 'change', this.onNetworkInformationChange_);
149
+ this.onNetworkInformationChange_ = null;
150
+ }
151
+
152
+ this.resizeObserverTimer_ = null;
153
+ }
154
+
131
155
 
132
156
  /**
133
157
  * @override
@@ -79,9 +79,9 @@ shaka.ads.ClientSideAdManager = class {
79
79
  });
80
80
 
81
81
  // Notify the SDK when the video has ended, so it can play post-roll ads.
82
- this.video_.onended = () => {
82
+ this.eventManager_.listen(this.video_, 'ended', () => {
83
83
  this.adsLoader_.contentComplete();
84
- };
84
+ });
85
85
  }
86
86
 
87
87
  /**
@@ -219,9 +219,9 @@ shaka.ads.ClientSideAdManager = class {
219
219
  // seen the ads actually play until requestAds() is called.
220
220
  // Note: We listen for a play event to avoid autoplay issues that might
221
221
  // crash IMA.
222
- this.video_.addEventListener('play', () => {
222
+ this.eventManager_.listenOnce(this.video_, 'play', () => {
223
223
  this.imaAdsManager_.start();
224
- }, {once: true});
224
+ });
225
225
  } catch (adError) {
226
226
  // If there was a problem with the VAST response,
227
227
  // we we won't be getting an ad. Hide ad UI if we showed it already
@@ -440,6 +440,10 @@ shaka.ads.ClientSideAdManager = class {
440
440
  if (this.ad_.isLinear()) {
441
441
  this.adContainer_.setAttribute('ad-active', 'true');
442
442
  this.video_.pause();
443
+ this.ad_.setVolume(this.video_.volume);
444
+ if (this.video_.muted) {
445
+ this.ad_.setMuted(true);
446
+ }
443
447
  }
444
448
  }
445
449
 
@@ -452,7 +456,9 @@ shaka.ads.ClientSideAdManager = class {
452
456
  (new Map()).set('originalEvent', e)));
453
457
  if (this.ad_ && this.ad_.isLinear()) {
454
458
  this.adContainer_.removeAttribute('ad-active');
455
- this.video_.play();
459
+ if (!this.video_.ended) {
460
+ this.video_.play();
461
+ }
456
462
  }
457
463
  }
458
464
  };
@@ -1279,55 +1279,56 @@ shaka.dash.DashParser = class {
1279
1279
  context.period.id + ',' + context.representation.id : '';
1280
1280
 
1281
1281
  /** @type {shaka.extern.Stream} */
1282
- const stream = {
1283
- id: this.globalId_++,
1284
- originalId: context.representation.id,
1285
- createSegmentIndex: async () => {
1286
- // If we have a stream with the same context id stored in the map
1287
- // that has no segmentIndex, we should set the segmentIndex for it.
1288
- const storedInMap = contextId && context.dynamic &&
1289
- this.streamMap_[contextId];
1290
-
1291
- const currentStream = storedInMap ? this.streamMap_[contextId] : stream;
1292
- if (!currentStream.segmentIndex) {
1293
- currentStream.segmentIndex = await streamInfo.generateSegmentIndex();
1294
- }
1295
- },
1282
+ let stream;
1296
1283
 
1297
- closeSegmentIndex: () => {
1298
- if (stream.segmentIndex) {
1299
- stream.segmentIndex.release();
1300
- stream.segmentIndex = null;
1301
- }
1302
- },
1303
- segmentIndex: null,
1304
- mimeType: context.representation.mimeType,
1305
- codecs: context.representation.codecs,
1306
- frameRate: context.representation.frameRate,
1307
- pixelAspectRatio: context.representation.pixelAspectRatio,
1308
- bandwidth: context.bandwidth,
1309
- width: context.representation.width,
1310
- height: context.representation.height,
1311
- kind,
1312
- encrypted: contentProtection.drmInfos.length > 0,
1313
- drmInfos: contentProtection.drmInfos,
1314
- keyIds,
1315
- language,
1316
- label,
1317
- type: context.adaptationSet.contentType,
1318
- primary: isPrimary,
1319
- trickModeVideo: null,
1320
- emsgSchemeIdUris:
1321
- context.representation.emsgSchemeIdUris,
1322
- roles,
1323
- forced: forced,
1324
- channelsCount: context.representation.numChannels,
1325
- audioSamplingRate: context.representation.audioSamplingRate,
1326
- spatialAudio: spatialAudio,
1327
- closedCaptions,
1328
- hdr,
1329
- tilesLayout,
1330
- matchedStreams: [],
1284
+ if (contextId && this.streamMap_[contextId]) {
1285
+ stream = this.streamMap_[contextId];
1286
+ } else {
1287
+ stream = {
1288
+ id: this.globalId_++,
1289
+ originalId: context.representation.id,
1290
+ createSegmentIndex: () => Promise.resolve(),
1291
+ closeSegmentIndex: () => {
1292
+ if (stream.segmentIndex) {
1293
+ stream.segmentIndex.release();
1294
+ stream.segmentIndex = null;
1295
+ }
1296
+ },
1297
+ segmentIndex: null,
1298
+ mimeType: context.representation.mimeType,
1299
+ codecs: context.representation.codecs,
1300
+ frameRate: context.representation.frameRate,
1301
+ pixelAspectRatio: context.representation.pixelAspectRatio,
1302
+ bandwidth: context.bandwidth,
1303
+ width: context.representation.width,
1304
+ height: context.representation.height,
1305
+ kind,
1306
+ encrypted: contentProtection.drmInfos.length > 0,
1307
+ drmInfos: contentProtection.drmInfos,
1308
+ keyIds,
1309
+ language,
1310
+ label,
1311
+ type: context.adaptationSet.contentType,
1312
+ primary: isPrimary,
1313
+ trickModeVideo: null,
1314
+ emsgSchemeIdUris:
1315
+ context.representation.emsgSchemeIdUris,
1316
+ roles,
1317
+ forced,
1318
+ channelsCount: context.representation.numChannels,
1319
+ audioSamplingRate: context.representation.audioSamplingRate,
1320
+ spatialAudio,
1321
+ closedCaptions,
1322
+ hdr,
1323
+ tilesLayout,
1324
+ matchedStreams: [],
1325
+ };
1326
+ }
1327
+
1328
+ stream.createSegmentIndex = async () => {
1329
+ if (!stream.segmentIndex) {
1330
+ stream.segmentIndex = await streamInfo.generateSegmentIndex();
1331
+ }
1331
1332
  };
1332
1333
 
1333
1334
  if (contextId && context.dynamic && !this.streamMap_[contextId]) {
package/lib/debug/log.js CHANGED
@@ -134,23 +134,19 @@ shaka.log.MAX_LOG_LEVEL = 3;
134
134
  shaka.log.oneTimeWarningIssued_ = new Set();
135
135
 
136
136
 
137
- // IE8 has no console unless it is opened in advance.
138
- // IE9 console methods are not Functions and have no bind.
139
- if (window.console && window.console.log.bind) {
137
+ if (window.console) {
140
138
  /** @private {!Object.<shaka.log.Level, function(...*)>} */
141
139
  shaka.log.logMap_ = {
142
- /* eslint-disable no-restricted-syntax */
143
- [shaka.log.Level.ERROR]: console.error.bind(console),
144
- [shaka.log.Level.WARNING]: console.warn.bind(console),
145
- [shaka.log.Level.INFO]: console.info.bind(console),
146
- [shaka.log.Level.DEBUG]: console.log.bind(console),
147
- [shaka.log.Level.V1]: console.debug.bind(console),
148
- [shaka.log.Level.V2]: console.debug.bind(console),
149
- /* eslint-enable no-restricted-syntax */
140
+ [shaka.log.Level.ERROR]: (...args) => console.error(...args),
141
+ [shaka.log.Level.WARNING]: (...args) => console.warn(...args),
142
+ [shaka.log.Level.INFO]: (...args) => console.info(...args),
143
+ [shaka.log.Level.DEBUG]: (...args) => console.log(...args),
144
+ [shaka.log.Level.V1]: (...args) => console.debug(...args),
145
+ [shaka.log.Level.V2]: (...args) => console.debug(...args),
150
146
  };
151
147
 
152
- shaka.log.alwaysWarn = shaka.log.logMap_[shaka.log.Level.WARNING];
153
- shaka.log.alwaysError = shaka.log.logMap_[shaka.log.Level.ERROR];
148
+ shaka.log.alwaysWarn = (...args) => console.warn(...args);
149
+ shaka.log.alwaysError = (...args) => console.error(...args);
154
150
 
155
151
  if (goog.DEBUG) {
156
152
  // Since we don't want to export shaka.log in production builds, we don't