shaka-player 3.1.0 → 3.1.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 (181) hide show
  1. package/AUTHORS +8 -2
  2. package/CHANGELOG.md +209 -0
  3. package/CONTRIBUTORS +10 -3
  4. package/README.md +3 -0
  5. package/build/apps.py +2 -2
  6. package/build/check.py +2 -2
  7. package/build/conformance.textproto +0 -9
  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/demo/common/asset.js +11 -0
  13. package/demo/common/assets.js +1 -1
  14. package/demo/common/message_ids.js +5 -0
  15. package/demo/config.js +2 -1
  16. package/demo/custom.js +84 -3
  17. package/demo/demo.less +13 -1
  18. package/demo/demo_utils.js +1 -0
  19. package/demo/input.js +31 -12
  20. package/demo/input_container.js +24 -1
  21. package/demo/locales/en.json +6 -1
  22. package/demo/locales/source.json +20 -0
  23. package/demo/main.js +5 -1
  24. package/dist/controls.css +2 -2
  25. package/dist/controls.css.map +1 -1
  26. package/dist/demo.compiled.debug.js +99 -91
  27. package/dist/demo.compiled.debug.map +3 -3
  28. package/dist/demo.compiled.js +99 -91
  29. package/dist/demo.compiled.map +3 -3
  30. package/dist/demo.css +1 -1
  31. package/dist/demo.css.map +1 -1
  32. package/dist/deps.js +9 -9
  33. package/dist/locales.js +36 -34
  34. package/dist/receiver.compiled.debug.js +74 -70
  35. package/dist/receiver.compiled.debug.map +3 -3
  36. package/dist/receiver.compiled.js +74 -70
  37. package/dist/receiver.compiled.map +3 -3
  38. package/dist/shaka-player.compiled.d.ts +165 -9
  39. package/dist/shaka-player.compiled.debug.d.ts +165 -9
  40. package/dist/shaka-player.compiled.debug.externs.js +179 -11
  41. package/dist/shaka-player.compiled.debug.js +367 -339
  42. package/dist/shaka-player.compiled.debug.map +4 -4
  43. package/dist/shaka-player.compiled.externs.js +179 -11
  44. package/dist/shaka-player.compiled.js +818 -807
  45. package/dist/shaka-player.compiled.map +4 -4
  46. package/dist/shaka-player.ui.d.ts +165 -9
  47. package/dist/shaka-player.ui.debug.d.ts +165 -9
  48. package/dist/shaka-player.ui.debug.externs.js +181 -13
  49. package/dist/shaka-player.ui.debug.js +459 -429
  50. package/dist/shaka-player.ui.debug.map +4 -4
  51. package/dist/shaka-player.ui.externs.js +181 -13
  52. package/dist/shaka-player.ui.js +973 -961
  53. package/dist/shaka-player.ui.map +4 -4
  54. package/docs/tutorials/fairplay.md +1 -1
  55. package/docs/tutorials/faq.md +25 -0
  56. package/docs/tutorials/index.json +2 -2
  57. package/docs/tutorials/upgrade-v3.md +38 -0
  58. package/docs/tutorials/upgrade.md +3 -3
  59. package/externs/ima.js +4 -0
  60. package/externs/media_capabilities.js +16 -0
  61. package/externs/shaka/ads.js +2 -0
  62. package/externs/shaka/net.js +2 -2
  63. package/externs/shaka/player.js +6 -0
  64. package/karma.conf.js +1 -0
  65. package/lib/abr/simple_abr_manager.js +1 -1
  66. package/lib/ads/ad_manager.js +29 -11
  67. package/lib/ads/client_side_ad_manager.js +76 -86
  68. package/lib/ads/server_side_ad_manager.js +26 -11
  69. package/lib/cast/cast_proxy.js +3 -2
  70. package/lib/cast/cast_receiver.js +2 -1
  71. package/lib/cast/cast_sender.js +2 -2
  72. package/lib/cea/sei_processor.js +24 -17
  73. package/lib/dash/dash_parser.js +107 -4
  74. package/lib/dash/segment_list.js +1 -1
  75. package/lib/dash/segment_template.js +45 -15
  76. package/lib/dependencies/all.js +15 -15
  77. package/lib/hls/hls_parser.js +46 -18
  78. package/lib/media/closed_caption_parser.js +3 -1
  79. package/lib/media/content_workarounds.js +18 -0
  80. package/lib/media/drm_engine.js +20 -1
  81. package/lib/media/gap_jumping_controller.js +8 -4
  82. package/lib/media/media_source_engine.js +1 -2
  83. package/lib/media/playhead.js +1 -1
  84. package/lib/media/presentation_timeline.js +3 -1
  85. package/lib/media/segment_index.js +38 -12
  86. package/lib/media/segment_reference.js +8 -0
  87. package/lib/media/streaming_engine.js +30 -21
  88. package/lib/net/http_fetch_plugin.js +2 -2
  89. package/lib/net/networking_engine.js +3 -2
  90. package/lib/offline/storage.js +4 -0
  91. package/lib/player.js +113 -56
  92. package/lib/polyfill/encryption_scheme.js +2 -0
  93. package/lib/polyfill/fullscreen.js +2 -0
  94. package/lib/polyfill/mathround.js +2 -0
  95. package/lib/polyfill/media_capabilities.js +62 -23
  96. package/lib/polyfill/mediasource.js +8 -0
  97. package/lib/polyfill/orientation.js +3 -1
  98. package/lib/polyfill/patchedmediakeys_apple.js +6 -4
  99. package/lib/polyfill/patchedmediakeys_ms.js +6 -4
  100. package/lib/polyfill/patchedmediakeys_nop.js +2 -0
  101. package/lib/polyfill/patchedmediakeys_webkit.js +6 -4
  102. package/lib/polyfill/pip_webkit.js +2 -0
  103. package/lib/polyfill/storage_estimate.js +2 -0
  104. package/lib/polyfill/video_play_promise.js +2 -0
  105. package/lib/polyfill/videoplaybackquality.js +2 -0
  106. package/lib/polyfill/vttcue.js +2 -0
  107. package/lib/text/cue.js +11 -0
  108. package/lib/text/mp4_ttml_parser.js +3 -0
  109. package/lib/text/text_engine.js +14 -2
  110. package/lib/text/ttml_text_parser.js +52 -30
  111. package/lib/text/ui_text_displayer.js +255 -82
  112. package/lib/text/vtt_text_parser.js +4 -2
  113. package/lib/util/error.js +1 -4
  114. package/lib/util/fake_event.js +53 -7
  115. package/lib/util/mime_utils.js +33 -0
  116. package/lib/util/mp4_box_parsers.js +1 -1
  117. package/lib/util/mp4_parser.js +14 -0
  118. package/lib/util/networking.js +1 -1
  119. package/lib/util/periods.js +132 -37
  120. package/lib/util/platform.js +13 -1
  121. package/lib/util/stream_utils.js +46 -7
  122. package/package.json +3 -3
  123. package/test/cast/cast_proxy_unit.js +12 -6
  124. package/test/cast/cast_receiver_integration.js +1 -1
  125. package/test/cast/cast_utils_unit.js +1 -1
  126. package/test/cea/mp4_cea_parser_unit.js +26 -0
  127. package/test/dash/dash_parser_live_unit.js +1 -0
  128. package/test/dash/dash_parser_manifest_unit.js +187 -1
  129. package/test/dash/dash_parser_segment_template_unit.js +3 -3
  130. package/test/demo/demo_unit.js +0 -1
  131. package/test/hls/hls_parser_unit.js +45 -1
  132. package/test/media/closed_caption_parser_unit.js +20 -0
  133. package/test/media/drm_engine_unit.js +59 -3
  134. package/test/media/playhead_unit.js +27 -1
  135. package/test/media/presentation_timeline_unit.js +19 -0
  136. package/test/media/segment_index_unit.js +76 -3
  137. package/test/media/streaming_engine_unit.js +3 -3
  138. package/test/player_integration.js +38 -0
  139. package/test/player_unit.js +125 -6
  140. package/test/test/assets/3675/chunk-stream0-00001.m4s +0 -0
  141. package/test/test/assets/3675/chunk-stream0-00002.m4s +0 -0
  142. package/test/test/assets/3675/chunk-stream0-00003.m4s +0 -0
  143. package/test/test/assets/3675/chunk-stream0-00004.m4s +0 -0
  144. package/test/test/assets/3675/chunk-stream0-00005.m4s +0 -0
  145. package/test/test/assets/3675/chunk-stream0-00006.m4s +0 -0
  146. package/test/test/assets/3675/chunk-stream0-00007.m4s +0 -0
  147. package/test/test/assets/3675/dash_0.mpd +30 -0
  148. package/test/test/assets/3675/dash_1.mpd +30 -0
  149. package/test/test/assets/3675/dash_2.mpd +30 -0
  150. package/test/test/assets/3675/dash_3.mpd +30 -0
  151. package/test/test/assets/3675/dash_4.mpd +30 -0
  152. package/test/test/assets/3675/dash_5.mpd +26 -0
  153. package/test/test/assets/3675/init-stream0.m4s +0 -0
  154. package/test/test/assets/empty_caption_video_init.mp4 +0 -0
  155. package/test/test/assets/empty_caption_video_segment.mp4 +0 -0
  156. package/test/test/util/fake_ad_manager.js +4 -1
  157. package/test/test/util/simple_fakes.js +5 -3
  158. package/test/test/util/waiter.js +36 -2
  159. package/test/text/ttml_text_parser_unit.js +55 -0
  160. package/test/text/ui_text_displayer_unit.js +95 -18
  161. package/test/text/vtt_text_parser_unit.js +17 -1
  162. package/test/ui/localization_unit.js +15 -14
  163. package/test/ui/text_displayer_layout_unit.js +52 -1
  164. package/test/ui/ui_unit.js +4 -0
  165. package/test/util/mp4_box_parsers_unit.js +28 -0
  166. package/test/util/periods_unit.js +190 -2
  167. package/test/util/stream_utils_unit.js +56 -5
  168. package/ui/airplay_button.js +5 -0
  169. package/ui/big_play_button.js +10 -0
  170. package/ui/cast_button.js +2 -3
  171. package/ui/controls.js +9 -7
  172. package/ui/less/containers.less +10 -5
  173. package/ui/locales/en.json +1 -0
  174. package/ui/locales/ru.json +6 -6
  175. package/ui/locales/source.json +4 -0
  176. package/ui/localization.js +28 -51
  177. package/ui/pip_button.js +2 -3
  178. package/ui/play_button.js +10 -10
  179. package/ui/small_play_button.js +12 -0
  180. package/ui/ui.js +1 -1
  181. package/docs/tutorials/upgrade-v2-4.md +0 -481
@@ -31,7 +31,7 @@ player.configure('drm.initDataTransform', (initData, initDataType) => {
31
31
 
32
32
  // 'initData' is a buffer containing an 'skd://' URL as a UTF-8 string.
33
33
  const skdUri = shaka.util.StringUtils.fromBytesAutoDetect(initData);
34
- const contentId = getMyContentId(sdkUri);
34
+ const contentId = getMyContentId(skdUri);
35
35
  const cert = player.drmInfo().serverCertificate;
36
36
  return shaka.util.FairPlayUtils.initDataTransform(initData, contentId, cert);
37
37
  });
@@ -43,6 +43,17 @@ headers in the response. Additionally, with some manifests, we will send a
43
43
  This can also happen with mixed-content restrictions. If the site is using
44
44
  `https:`, then your manifest and segments must also.
45
45
 
46
+ *Sending `Range` header at the start of HLS playback can be disabled using this config:*
47
+ ```
48
+ player.configure({
49
+ manifest: {
50
+ hls: {
51
+ useFullSegmentsForStartTime: true,
52
+ },
53
+ },
54
+ })
55
+ ```
56
+
46
57
  <hr>
47
58
 
48
59
  **Q:** I am getting `REQUESTED_KEY_SYSTEM_CONFIG_UNAVAILABLE` or error code
@@ -249,6 +260,20 @@ the {@link shaka.extern.ManifestConfiguration|`.manifest.disableVideo`} or
249
260
  configurations to signal that your content does not have a video or audio
250
261
  stream.
251
262
 
263
+ <hr>
264
+
265
+ **Q:** How can I make Shaka Player work with Vue?
266
+
267
+ **A:** Currently, Shaka Player does not support being made into a Vue reactive
268
+ object. When Vue wraps an object in a reactive Proxy, it
269
+ {@link https://v3.vuejs.org/guide/reactivity.html#proxied-objects|also wraps
270
+ nested objects}. This results in Vue converting some of our internal values into
271
+ Proxy objects, which causes failures at load-time.
272
+ If you want to use Shaka Player in Vue, avoid making it into a reactive object;
273
+ so don't declare it using a ref(), and if you put your player instance into a
274
+ data() object, you can prefix the property name with "$" or "_" to make Vue not
275
+ proxy them.
276
+
252
277
  [386]: https://github.com/google/shaka-player/issues/386#issuecomment-227898001
253
278
  [489]: https://github.com/google/shaka-player/issues/489#issuecomment-240466224
254
279
  [743]: https://github.com/google/shaka-player/issues/743
@@ -22,8 +22,8 @@
22
22
  { "upgrade": {
23
23
  "title": "Upgrade Guide",
24
24
  "children": {
25
- "upgrade-v2-4": { "title": "Upgrade Guide, v2.4 => v3.0" },
26
- "upgrade-v2-5": { "title": "Upgrade Guide, v2.5 => v3.0" },
25
+ "upgrade-v2-5": { "title": "Upgrade Guide, v2.5 => v3" },
26
+ "upgrade-v3": { "title": "Upgrade Guide, v3" },
27
27
  "upgrade-manifest": { "title": "Shaka Player Manifest Upgrade Guide" }
28
28
  }
29
29
  } }
@@ -0,0 +1,38 @@
1
+ # Shaka Upgrade Guide, v3
2
+
3
+ This is a detailed guide for upgrading from any older version of Shaka Player v3
4
+ to the current version.
5
+
6
+ Shaka Player has been keeping strictly with semantic versioning since v3.0.0, so
7
+ upgrades from any older v3 to the current v3 release should be backward
8
+ compatible. Any minor exceptions or nuances will be noted here.
9
+
10
+
11
+ #### What's New?
12
+
13
+ v3.1:
14
+ - Ads APIs and UI leveraging Google IMA SDK (included separately by app)
15
+ - Low-latency HLS support
16
+ - Built-in CEA 608/708 decoder (mux.js no longer needed for this)
17
+ - Thumbnail track support
18
+ - UI overflow menu items now available as control panel buttons
19
+ - Network stall detection
20
+ - HDR & spatial audio metadata
21
+ - PlayReady support in HLS
22
+ - WebVTT styling and embedded tag support
23
+ - SubViewer (SBV), SubStation Alpha (SSA), LyRiCs (LRC), and SubRip (SRT)
24
+ subtitle format support
25
+ - Forced subtitles
26
+ - Side-loaded subtitles in src= playback mode
27
+ - Custom seekbar UI plugin
28
+ - AirPlay support in UI
29
+
30
+
31
+ #### New Requirements
32
+
33
+ v3.1:
34
+ - TextDecoder/TextEncoder platform support or polyfill required
35
+ - Affects Xbox One
36
+ - We suggest [https://github.com/anonyco/FastestSmallestTextEncoderDecoder](fastestsmallesttextencoderdecoder/EncoderDecoderTogether.min.js)
37
+ - IE11 support dropped (announced before v3.0)
38
+
@@ -4,7 +4,7 @@ If you are upgrading from **v1 - v2.2**, please see
4
4
  {@link https://v2-4-7-dot-shaka-player-demo.appspot.com/docs/api/tutorial-upgrade.html
5
5
  the upgrade guides from the v2.4 releases}, then return to this guide.
6
6
 
7
- If you are upgrading from **v2.3**, please see
7
+ If you are upgrading from **v2.3 - v2.4**, please see
8
8
  {@link https://v2-5-10-dot-shaka-player-demo.appspot.com/docs/api/tutorial-upgrade.html
9
9
  the upgrade guides from the v2.5 releases}, then return to this guide.
10
10
 
@@ -12,6 +12,6 @@ From these older release branches, you will have to use our upgrade guides in
12
12
  phases. This is necessary to keep our guides maintainable. Thanks for your
13
13
  understanding!
14
14
 
15
- If you are upgrading from **v2.4**, please see {@tutorial upgrade-v2-4}.
16
-
17
15
  If you are upgrading from **v2.5**, please see {@tutorial upgrade-v2-5}.
16
+
17
+ If you are upgrading from another **v3** release, please see {@tutorial upgrade-v3}.
package/externs/ima.js CHANGED
@@ -43,6 +43,8 @@ google.ima.AdsLoader = class {
43
43
 
44
44
  /** @override */
45
45
  dispatchEvent() {}
46
+
47
+ destroy() {}
46
48
  };
47
49
 
48
50
 
@@ -79,6 +81,8 @@ google.ima.AdsManager = class {
79
81
 
80
82
  stop() {}
81
83
 
84
+ destroy() {}
85
+
82
86
  /**
83
87
  * @param {number} volume
84
88
  */
@@ -0,0 +1,16 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ /**
8
+ * @fileoverview Externs for Shaka MediaCapabilities which were missing in the
9
+ * Closure compiler.
10
+ *
11
+ * @externs
12
+ */
13
+
14
+
15
+ /** @type {MediaCapabilities} */
16
+ window.shakaMediaCapabilities;
@@ -46,6 +46,8 @@ shaka.extern.IAdManager = class extends EventTarget {
46
46
  */
47
47
  setLocale(locale) {}
48
48
 
49
+ release() {}
50
+
49
51
  onAssetUnload() {}
50
52
 
51
53
  /**
@@ -60,7 +60,7 @@ shaka.extern.RetryParameters;
60
60
  * retryParameters: !shaka.extern.RetryParameters,
61
61
  * licenseRequestType: ?string,
62
62
  * sessionId: ?string,
63
- * streamDataCallback: ?function(BufferSource)
63
+ * streamDataCallback: ?function(BufferSource):!Promise
64
64
  * }}
65
65
  *
66
66
  * @description
@@ -90,7 +90,7 @@ shaka.extern.RetryParameters;
90
90
  * @property {?string} sessionId
91
91
  * If this is a LICENSE request, this field contains the session ID of the
92
92
  * EME session that made the request.
93
- * @property {?function(BufferSource)} streamDataCallback
93
+ * @property {?function(BufferSource):!Promise} streamDataCallback
94
94
  * A callback function to handle the chunked data of the ReadableStream.
95
95
  * @exportDoc
96
96
  */
@@ -1059,6 +1059,8 @@ shaka.extern.LanguageRole;
1059
1059
  * height: number,
1060
1060
  * positionX: number,
1061
1061
  * positionY: number,
1062
+ * startTime: number,
1063
+ * duration: number,
1062
1064
  * uris: !Array.<string>,
1063
1065
  * width: number
1064
1066
  * }}
@@ -1069,6 +1071,10 @@ shaka.extern.LanguageRole;
1069
1071
  * The thumbnail left position in px.
1070
1072
  * @property {number} positionY
1071
1073
  * The thumbnail top position in px.
1074
+ * @property {number} startTime
1075
+ * The start time of the thumbnail in the presentation timeline, in seconds.
1076
+ * @property {number} duration
1077
+ * The duration of the thumbnail, in seconds.
1072
1078
  * @property {!Array.<string>} uris
1073
1079
  * An array of URIs to attempt. They will be tried in the order they are
1074
1080
  * given.
package/karma.conf.js CHANGED
@@ -140,6 +140,7 @@ module.exports = (config) => {
140
140
  included: false,
141
141
  },
142
142
  {pattern: 'test/test/assets/*', included: false},
143
+ {pattern: 'test/test/assets/3675/*', included: false},
143
144
  {pattern: 'dist/shaka-player.ui.js', included: false},
144
145
  {pattern: 'dist/locales.js', included: false},
145
146
  {pattern: 'demo/locales/en.json', included: false},
@@ -52,7 +52,7 @@ shaka.abr.SimpleAbrManager = class {
52
52
  // of connectivity changes.
53
53
  if (navigator.connection) {
54
54
  navigator.connection.addEventListener('change', () => {
55
- if (this.config_.useNetworkInformation) {
55
+ if (this.config_.useNetworkInformation && this.enabled_) {
56
56
  this.bandwidthEstimator_ = new shaka.abr.EwmaBandwidthEstimator();
57
57
  const chosenVariant = this.chooseVariant();
58
58
  if (chosenVariant) {
@@ -16,6 +16,7 @@ goog.require('shaka.log');
16
16
  goog.require('shaka.util.Error');
17
17
  goog.require('shaka.util.FakeEvent');
18
18
  goog.require('shaka.util.FakeEventTarget');
19
+ goog.require('shaka.util.IReleasable');
19
20
 
20
21
 
21
22
  /**
@@ -359,6 +360,7 @@ goog.require('shaka.util.FakeEventTarget');
359
360
  /**
360
361
  * A class responsible for ad-related interactions.
361
362
  * @implements {shaka.extern.IAdManager}
363
+ * @implements {shaka.util.IReleasable}
362
364
  * @export
363
365
  */
364
366
  shaka.ads.AdManager = class extends shaka.util.FakeEventTarget {
@@ -403,6 +405,10 @@ shaka.ads.AdManager = class extends shaka.util.FakeEventTarget {
403
405
  shaka.util.Error.Code.CS_IMA_SDK_MISSING);
404
406
  }
405
407
 
408
+ if (this.csAdManager_) {
409
+ this.csAdManager_.release();
410
+ }
411
+
406
412
  this.csAdManager_ = new shaka.ads.ClientSideAdManager(
407
413
  adContainer, video, this.locale_,
408
414
  (e) => {
@@ -430,6 +436,22 @@ shaka.ads.AdManager = class extends shaka.util.FakeEventTarget {
430
436
  }
431
437
 
432
438
 
439
+ /**
440
+ * @override
441
+ * @export
442
+ */
443
+ release() {
444
+ if (this.csAdManager_) {
445
+ this.csAdManager_.release();
446
+ this.csAdManager_ = null;
447
+ }
448
+ if (this.ssAdManager_) {
449
+ this.ssAdManager_.release();
450
+ this.ssAdManager_ = null;
451
+ }
452
+ }
453
+
454
+
433
455
  /**
434
456
  * @override
435
457
  * @export
@@ -438,21 +460,13 @@ shaka.ads.AdManager = class extends shaka.util.FakeEventTarget {
438
460
  if (this.csAdManager_) {
439
461
  this.csAdManager_.stop();
440
462
  }
463
+ if (this.ssAdManager_) {
464
+ this.ssAdManager_.stop();
465
+ }
441
466
 
442
467
  this.dispatchEvent(
443
468
  new shaka.util.FakeEvent(shaka.ads.AdManager.AD_STOPPED));
444
469
 
445
- // TODO:
446
- // For SS DAI streams, if a different asset gets unloaded as
447
- // part of the process
448
- // of loading a DAI asset, stream manager state gets reset and we
449
- // don't get any ad events.
450
- // We need to figure out if it makes sense to stop the SS
451
- // manager on unload, and, if it does, find
452
- // a way to do it safely.
453
- // if (this.ssAdManager_) {
454
- // this.ssAdManager_.stop();
455
- // }
456
470
  this.stats_ = new shaka.ads.AdsStats();
457
471
  }
458
472
 
@@ -491,6 +505,10 @@ shaka.ads.AdManager = class extends shaka.util.FakeEventTarget {
491
505
  shaka.util.Error.Code.SS_IMA_SDK_MISSING);
492
506
  }
493
507
 
508
+ if (this.ssAdManager_) {
509
+ this.ssAdManager_.release();
510
+ }
511
+
494
512
  this.ssAdManager_ = new shaka.ads.ServerSideAdManager(
495
513
  adContainer, video, this.locale_,
496
514
  (e) => {
@@ -13,10 +13,12 @@ goog.provide('shaka.ads.ClientSideAdManager');
13
13
 
14
14
  goog.require('goog.asserts');
15
15
  goog.require('shaka.ads.ClientSideAd');
16
+ goog.require('shaka.util.IReleasable');
16
17
 
17
18
 
18
19
  /**
19
20
  * A class responsible for client-side ad interactions.
21
+ * @implements {shaka.util.IReleasable}
20
22
  */
21
23
  shaka.ads.ClientSideAdManager = class {
22
24
  /**
@@ -32,6 +34,9 @@ shaka.ads.ClientSideAdManager = class {
32
34
  /** @private {HTMLMediaElement} */
33
35
  this.video_ = video;
34
36
 
37
+ /** @private {ResizeObserver} */
38
+ this.resizeObserver_ = null;
39
+
35
40
  /** @private {number} */
36
41
  this.requestAdsStartTime_ = NaN;
37
42
 
@@ -106,6 +111,21 @@ shaka.ads.ClientSideAdManager = class {
106
111
  }
107
112
  }
108
113
 
114
+ /** @override */
115
+ release() {
116
+ this.stop();
117
+ if (this.resizeObserver_) {
118
+ this.resizeObserver_.disconnect();
119
+ }
120
+ if (this.eventManager_) {
121
+ this.eventManager_.release();
122
+ }
123
+ if (this.imaAdsManager_) {
124
+ this.imaAdsManager_.destroy();
125
+ }
126
+ this.adsLoader_.destroy();
127
+ }
128
+
109
129
  /**
110
130
  * @param {!google.ima.AdErrorEvent} e
111
131
  * @private
@@ -118,7 +138,7 @@ shaka.ads.ClientSideAdManager = class {
118
138
  // Remove ad breaks from the timeline
119
139
  this.onEvent_(
120
140
  new shaka.util.FakeEvent(shaka.ads.AdManager.CUEPOINTS_CHANGED,
121
- {'cuepoints': []}));
141
+ (new Map()).set('cuepoints', [])));
122
142
  }
123
143
 
124
144
 
@@ -131,17 +151,14 @@ shaka.ads.ClientSideAdManager = class {
131
151
 
132
152
  const now = Date.now() / 1000;
133
153
  const loadTime = now - this.requestAdsStartTime_;
134
- this.onEvent_(
135
- new shaka.util.FakeEvent(shaka.ads.AdManager.ADS_LOADED,
136
- {'loadTime': loadTime}));
154
+ this.onEvent_(new shaka.util.FakeEvent(shaka.ads.AdManager.ADS_LOADED,
155
+ (new Map()).set('loadTime', loadTime)));
137
156
 
138
157
  this.imaAdsManager_ = e.getAdsManager(this.video_);
139
158
 
140
159
  this.onEvent_(new shaka.util.FakeEvent(
141
160
  shaka.ads.AdManager.IMA_AD_MANAGER_LOADED,
142
- {
143
- 'imaAdManager': this.imaAdsManager_,
144
- }));
161
+ (new Map()).set('imaAdManager', this.imaAdsManager_)));
145
162
 
146
163
  const cuePointStarts = this.imaAdsManager_.getCuePoints();
147
164
  if (cuePointStarts.length) {
@@ -152,9 +169,9 @@ shaka.ads.ClientSideAdManager = class {
152
169
  cuePoints.push(shakaCuePoint);
153
170
  }
154
171
 
155
- this.onEvent_(
156
- new shaka.util.FakeEvent(shaka.ads.AdManager.CUEPOINTS_CHANGED,
157
- {'cuepoints': cuePoints}));
172
+ this.onEvent_(new shaka.util.FakeEvent(
173
+ shaka.ads.AdManager.CUEPOINTS_CHANGED,
174
+ (new Map()).set('cuepoints', cuePoints)));
158
175
  }
159
176
 
160
177
  this.addImaEventListeners_();
@@ -176,6 +193,16 @@ shaka.ads.ClientSideAdManager = class {
176
193
  this.video_.offsetHeight, viewMode);
177
194
  });
178
195
 
196
+ if ('ResizeObserver' in window) {
197
+ this.resizeObserver_ = new ResizeObserver(() => {
198
+ const viewMode = document.fullscreenElement ?
199
+ google.ima.ViewMode.FULLSCREEN : google.ima.ViewMode.NORMAL;
200
+ this.imaAdsManager_.resize(this.video_.offsetWidth,
201
+ this.video_.offsetHeight, viewMode);
202
+ });
203
+ this.resizeObserver_.observe(this.video_);
204
+ }
205
+
179
206
  // Single video and overlay ads will start at this time
180
207
  // TODO (ismena): Need a better inderstanding of what this does.
181
208
  // The docs say it's called to 'start playing the ads,' but I haven't
@@ -194,6 +221,15 @@ shaka.ads.ClientSideAdManager = class {
194
221
  * @private
195
222
  */
196
223
  addImaEventListeners_() {
224
+ /**
225
+ * @param {!Event} e
226
+ * @param {string} type
227
+ */
228
+ const convertEventAndSend = (e, type) => {
229
+ const data = (new Map()).set('originalEvent', e);
230
+ this.onEvent_(new shaka.util.FakeEvent(type, data));
231
+ };
232
+
197
233
  this.eventManager_.listen(this.imaAdsManager_,
198
234
  google.ima.AdErrorEvent.Type.AD_ERROR, (error) => {
199
235
  this.onAdError_(/** @type {!google.ima.AdErrorEvent} */ (error));
@@ -211,30 +247,22 @@ shaka.ads.ClientSideAdManager = class {
211
247
 
212
248
  this.eventManager_.listen(this.imaAdsManager_,
213
249
  google.ima.AdEvent.Type.FIRST_QUARTILE, (e) => {
214
- this.onEvent_(
215
- new shaka.util.FakeEvent(shaka.ads.AdManager.AD_FIRST_QUARTILE,
216
- {'originalEvent': e}));
250
+ convertEventAndSend(e, shaka.ads.AdManager.AD_FIRST_QUARTILE);
217
251
  });
218
252
 
219
253
  this.eventManager_.listen(this.imaAdsManager_,
220
254
  google.ima.AdEvent.Type.MIDPOINT, (e) => {
221
- this.onEvent_(
222
- new shaka.util.FakeEvent(shaka.ads.AdManager.AD_MIDPOINT,
223
- {'originalEvent': e}));
255
+ convertEventAndSend(e, shaka.ads.AdManager.AD_MIDPOINT);
224
256
  });
225
257
 
226
258
  this.eventManager_.listen(this.imaAdsManager_,
227
259
  google.ima.AdEvent.Type.THIRD_QUARTILE, (e) => {
228
- this.onEvent_(
229
- new shaka.util.FakeEvent(shaka.ads.AdManager.AD_THIRD_QUARTILE,
230
- {'originalEvent': e}));
260
+ convertEventAndSend(e, shaka.ads.AdManager.AD_THIRD_QUARTILE);
231
261
  });
232
262
 
233
263
  this.eventManager_.listen(this.imaAdsManager_,
234
264
  google.ima.AdEvent.Type.COMPLETE, (e) => {
235
- this.onEvent_(
236
- new shaka.util.FakeEvent(shaka.ads.AdManager.AD_COMPLETE,
237
- {'originalEvent': e}));
265
+ convertEventAndSend(e, shaka.ads.AdManager.AD_COMPLETE);
238
266
  });
239
267
 
240
268
  this.eventManager_.listen(this.imaAdsManager_,
@@ -249,140 +277,102 @@ shaka.ads.ClientSideAdManager = class {
249
277
 
250
278
  this.eventManager_.listen(this.imaAdsManager_,
251
279
  google.ima.AdEvent.Type.SKIPPED, (e) => {
252
- this.onEvent_(
253
- new shaka.util.FakeEvent(shaka.ads.AdManager.AD_SKIPPED,
254
- {'originalEvent': e}));
280
+ convertEventAndSend(e, shaka.ads.AdManager.AD_SKIPPED);
255
281
  });
256
282
 
257
283
  this.eventManager_.listen(this.imaAdsManager_,
258
284
  google.ima.AdEvent.Type.VOLUME_CHANGED, (e) => {
259
- this.onEvent_(
260
- new shaka.util.FakeEvent(shaka.ads.AdManager.AD_VOLUME_CHANGED,
261
- {'originalEvent': e}));
285
+ convertEventAndSend(e, shaka.ads.AdManager.AD_VOLUME_CHANGED);
262
286
  });
263
287
 
264
288
  this.eventManager_.listen(this.imaAdsManager_,
265
289
  google.ima.AdEvent.Type.VOLUME_MUTED, (e) => {
266
- this.onEvent_(
267
- new shaka.util.FakeEvent(shaka.ads.AdManager.AD_MUTED,
268
- {'originalEvent': e}));
290
+ convertEventAndSend(e, shaka.ads.AdManager.AD_MUTED);
269
291
  });
270
292
 
271
293
  this.eventManager_.listen(this.imaAdsManager_,
272
294
  google.ima.AdEvent.Type.PAUSED, (e) => {
273
295
  goog.asserts.assert(this.ad_ != null, 'Ad should not be null!');
274
296
  this.ad_.setPaused(true);
275
- this.onEvent_(
276
- new shaka.util.FakeEvent(shaka.ads.AdManager.AD_PAUSED,
277
- {'originalEvent': e}));
297
+ convertEventAndSend(e, shaka.ads.AdManager.AD_PAUSED);
278
298
  });
279
299
 
280
300
  this.eventManager_.listen(this.imaAdsManager_,
281
301
  google.ima.AdEvent.Type.RESUMED, (e) => {
282
302
  goog.asserts.assert(this.ad_ != null, 'Ad should not be null!');
283
303
  this.ad_.setPaused(false);
284
- this.onEvent_(
285
- new shaka.util.FakeEvent(shaka.ads.AdManager.AD_RESUMED,
286
- {'originalEvent': e}));
304
+ convertEventAndSend(e, shaka.ads.AdManager.AD_RESUMED);
287
305
  });
288
306
 
289
307
  this.eventManager_.listen(this.imaAdsManager_,
290
308
  google.ima.AdEvent.Type.SKIPPABLE_STATE_CHANGED, (e) => {
291
309
  goog.asserts.assert(this.ad_ != null, 'Ad should not be null!');
292
- this.onEvent_(new shaka.util.FakeEvent(
293
- shaka.ads.AdManager.AD_SKIP_STATE_CHANGED,
294
- {'originalEvent': e}));
310
+ convertEventAndSend(e, shaka.ads.AdManager.AD_SKIP_STATE_CHANGED);
295
311
  });
296
312
 
297
313
  this.eventManager_.listen(this.imaAdsManager_,
298
314
  google.ima.AdEvent.Type.CLICK, (e) => {
299
- this.onEvent_(new shaka.util.FakeEvent(
300
- shaka.ads.AdManager.AD_CLICKED,
301
- {'originalEvent': e}));
315
+ convertEventAndSend(e, shaka.ads.AdManager.AD_CLICKED);
302
316
  });
303
317
 
304
318
  this.eventManager_.listen(this.imaAdsManager_,
305
319
  google.ima.AdEvent.Type.AD_PROGRESS, (e) => {
306
- this.onEvent_(new shaka.util.FakeEvent(
307
- shaka.ads.AdManager.AD_PROGRESS,
308
- {'originalEvent': e}));
320
+ convertEventAndSend(e, shaka.ads.AdManager.AD_PROGRESS);
309
321
  });
310
322
 
311
323
  this.eventManager_.listen(this.imaAdsManager_,
312
324
  google.ima.AdEvent.Type.AD_BUFFERING, (e) => {
313
- this.onEvent_(new shaka.util.FakeEvent(
314
- shaka.ads.AdManager.AD_BUFFERING,
315
- {'originalEvent': e}));
325
+ convertEventAndSend(e, shaka.ads.AdManager.AD_BUFFERING);
316
326
  });
317
327
 
318
328
  this.eventManager_.listen(this.imaAdsManager_,
319
329
  google.ima.AdEvent.Type.IMPRESSION, (e) => {
320
- this.onEvent_(new shaka.util.FakeEvent(
321
- shaka.ads.AdManager.AD_IMPRESSION,
322
- {'originalEvent': e}));
330
+ convertEventAndSend(e, shaka.ads.AdManager.AD_IMPRESSION);
323
331
  });
324
332
 
325
333
  this.eventManager_.listen(this.imaAdsManager_,
326
334
  google.ima.AdEvent.Type.DURATION_CHANGE, (e) => {
327
- this.onEvent_(new shaka.util.FakeEvent(
328
- shaka.ads.AdManager.AD_DURATION_CHANGED,
329
- {'originalEvent': e}));
335
+ convertEventAndSend(e, shaka.ads.AdManager.AD_DURATION_CHANGED);
330
336
  });
331
337
 
332
338
  this.eventManager_.listen(this.imaAdsManager_,
333
339
  google.ima.AdEvent.Type.USER_CLOSE, (e) => {
334
- this.onEvent_(new shaka.util.FakeEvent(
335
- shaka.ads.AdManager.AD_CLOSED,
336
- {'originalEvent': e}));
340
+ convertEventAndSend(e, shaka.ads.AdManager.AD_CLOSED);
337
341
  });
338
342
 
339
343
  this.eventManager_.listen(this.imaAdsManager_,
340
344
  google.ima.AdEvent.Type.LOADED, (e) => {
341
- this.onEvent_(new shaka.util.FakeEvent(
342
- shaka.ads.AdManager.AD_LOADED,
343
- {'originalEvent': e}));
345
+ convertEventAndSend(e, shaka.ads.AdManager.AD_LOADED);
344
346
  });
345
347
 
346
348
  this.eventManager_.listen(this.imaAdsManager_,
347
349
  google.ima.AdEvent.Type.ALL_ADS_COMPLETED, (e) => {
348
- this.onEvent_(new shaka.util.FakeEvent(
349
- shaka.ads.AdManager.ALL_ADS_COMPLETED,
350
- {'originalEvent': e}));
350
+ convertEventAndSend(e, shaka.ads.AdManager.ALL_ADS_COMPLETED);
351
351
  });
352
352
 
353
353
  this.eventManager_.listen(this.imaAdsManager_,
354
354
  google.ima.AdEvent.Type.LINEAR_CHANGED, (e) => {
355
- this.onEvent_(new shaka.util.FakeEvent(
356
- shaka.ads.AdManager.AD_LINEAR_CHANGED,
357
- {'originalEvent': e}));
355
+ convertEventAndSend(e, shaka.ads.AdManager.AD_LINEAR_CHANGED);
358
356
  });
359
357
 
360
358
  this.eventManager_.listen(this.imaAdsManager_,
361
359
  google.ima.AdEvent.Type.AD_METADATA, (e) => {
362
- this.onEvent_(new shaka.util.FakeEvent(
363
- shaka.ads.AdManager.AD_METADATA,
364
- {'originalEvent': e}));
360
+ convertEventAndSend(e, shaka.ads.AdManager.AD_METADATA);
365
361
  });
366
362
 
367
363
  this.eventManager_.listen(this.imaAdsManager_,
368
364
  google.ima.AdEvent.Type.LOG, (e) => {
369
- this.onEvent_(new shaka.util.FakeEvent(
370
- shaka.ads.AdManager.AD_RECOVERABLE_ERROR,
371
- {'originalEvent': e}));
365
+ convertEventAndSend(e, shaka.ads.AdManager.AD_RECOVERABLE_ERROR);
372
366
  });
373
367
 
374
368
  this.eventManager_.listen(this.imaAdsManager_,
375
369
  google.ima.AdEvent.Type.AD_BREAK_READY, (e) => {
376
- this.onEvent_(new shaka.util.FakeEvent(
377
- shaka.ads.AdManager.AD_BREAK_READY,
378
- {'originalEvent': e}));
370
+ convertEventAndSend(e, shaka.ads.AdManager.AD_BREAK_READY);
379
371
  });
380
372
 
381
373
  this.eventManager_.listen(this.imaAdsManager_,
382
374
  google.ima.AdEvent.Type.INTERACTION, (e) => {
383
- this.onEvent_(new shaka.util.FakeEvent(
384
- shaka.ads.AdManager.AD_INTERACTION,
385
- {'originalEvent': e}));
375
+ convertEventAndSend(e, shaka.ads.AdManager.AD_INTERACTION);
386
376
  });
387
377
  }
388
378
 
@@ -396,12 +386,12 @@ shaka.ads.ClientSideAdManager = class {
396
386
 
397
387
  const imaAd = e.getAd();
398
388
  this.ad_ = new shaka.ads.ClientSideAd(imaAd, this.imaAdsManager_);
399
- this.onEvent_(new shaka.util.FakeEvent(shaka.ads.AdManager.AD_STARTED,
400
- {
401
- 'ad': this.ad_,
402
- 'sdkAdObject': imaAd,
403
- 'originalEvent': e,
404
- }));
389
+ const data = new Map()
390
+ .set('ad', this.ad_)
391
+ .set('sdkAdObject', imaAd)
392
+ .set('originalEvent', e);
393
+ this.onEvent_(new shaka.util.FakeEvent(
394
+ shaka.ads.AdManager.AD_STARTED, data));
405
395
  this.adContainer_.setAttribute('ad-active', 'true');
406
396
  this.video_.pause();
407
397
  }
@@ -412,7 +402,7 @@ shaka.ads.ClientSideAdManager = class {
412
402
  */
413
403
  onAdComplete_(e) {
414
404
  this.onEvent_(new shaka.util.FakeEvent(shaka.ads.AdManager.AD_STOPPED,
415
- {'originalEvent': e}));
405
+ (new Map()).set('originalEvent', e)));
416
406
  this.adContainer_.removeAttribute('ad-active');
417
407
  this.video_.play();
418
408
  }