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
@@ -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
  });
@@ -260,6 +260,20 @@ the {@link shaka.extern.ManifestConfiguration|`.manifest.disableVideo`} or
260
260
  configurations to signal that your content does not have a video or audio
261
261
  stream.
262
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
+
263
277
  [386]: https://github.com/google/shaka-player/issues/386#issuecomment-227898001
264
278
  [489]: https://github.com/google/shaka-player/issues/489#issuecomment-240466224
265
279
  [743]: https://github.com/google/shaka-player/issues/743
@@ -30,7 +30,7 @@ Set up controls with HTML data attributes:
30
30
  The data-shaka-player-cast-receiver-id tag allows you to provide a Cast Application ID that
31
31
  the cast button will cast to; the value provided here is the sample cast receiver. -->
32
32
  <div data-shaka-player-container style="max-width:40em"
33
- data-shaka-player-cast-receiver-id="1BA79154">
33
+ data-shaka-player-cast-receiver-id="E7271BEC">
34
34
  <!-- The data-shaka-player tag will make the UI library use this video element.
35
35
  If no video is provided, the UI will automatically make one inside the container div. -->
36
36
  <video autoplay data-shaka-player id="video" style="width:100%;height:100%"></video>
@@ -111,7 +111,7 @@ set up a listener for the 'caststatuschanged' events.
111
111
  <!-- Add a data-shaka-player-cast-receiver-id tag to provide a Cast Application ID that
112
112
  the cast button will cast to; the value provided here is the sample cast receiver. -->
113
113
  <div data-shaka-player-container style="max-width:40em"
114
- data-shaka-player-cast-receiver-id="1BA79154">
114
+ data-shaka-player-cast-receiver-id="E7271BEC">
115
115
  </div>
116
116
  ```
117
117
 
@@ -137,7 +137,7 @@ or a `<source>` tag inside it to enable auto loading of the specified content.
137
137
 
138
138
  ```html
139
139
  <div data-shaka-player-container style="max-width:40em"
140
- data-shaka-player-cast-receiver-id="1BA79154">
140
+ data-shaka-player-cast-receiver-id="E7271BEC">
141
141
  <!-- The manifest url in the src attribute will be automatically loaded -->
142
142
  <video autoplay data-shaka-player id="video" style="width:100%;height:100%"
143
143
  src="https://storage.googleapis.com/shaka-demo-assets/angel-one/dash.mpd"></video>
@@ -148,7 +148,7 @@ or
148
148
 
149
149
  ```html
150
150
  <div data-shaka-player-container style="max-width:40em"
151
- data-shaka-player-cast-receiver-id="1BA79154">
151
+ data-shaka-player-cast-receiver-id="E7271BEC">
152
152
  <video autoplay data-shaka-player id="video" style="width:100%;height:100%">
153
153
  <!-- The manifest url in the src attribute will be auto loaded -->
154
154
  <source src="https://storage.googleapis.com/shaka-demo-assets/angel-one/dash.mpd"/>
@@ -161,7 +161,7 @@ call to the first one fails.
161
161
 
162
162
  ```html
163
163
  <div data-shaka-player-container style="max-width:40em"
164
- data-shaka-player-cast-receiver-id="1BA79154">
164
+ data-shaka-player-cast-receiver-id="E7271BEC">
165
165
  <video autoplay data-shaka-player id="video" style="width:100%;height:100%">
166
166
  <!-- Try this first -->
167
167
  <source src="https://storage.googleapis.com/shaka-demo-assets/angel-one/dash.mpd"/>
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
  */
@@ -33,6 +33,24 @@
33
33
  shaka.extern.AdsStats;
34
34
 
35
35
 
36
+ /**
37
+ * @typedef {{
38
+ * start: number,
39
+ * end: ?number
40
+ * }}
41
+ *
42
+ * @description
43
+ * Contains the times of a range of an Ad.
44
+ *
45
+ * @property {number} start
46
+ * The start time of the range, in milliseconds.
47
+ * @property {number} end
48
+ * The end time of the range, in milliseconds.
49
+ * @exportDoc
50
+ */
51
+ shaka.extern.AdCuePoint;
52
+
53
+
36
54
  /**
37
55
  * An object that's responsible for all the ad-related logic
38
56
  * in the player.
@@ -46,6 +64,8 @@ shaka.extern.IAdManager = class extends EventTarget {
46
64
  */
47
65
  setLocale(locale) {}
48
66
 
67
+ release() {}
68
+
49
69
  onAssetUnload() {}
50
70
 
51
71
  /**
@@ -77,6 +97,11 @@ shaka.extern.IAdManager = class extends EventTarget {
77
97
  */
78
98
  replaceServerSideAdTagParameters(adTagParameters) {}
79
99
 
100
+ /**
101
+ * @return {!Array.<!shaka.extern.AdCuePoint>}
102
+ */
103
+ getServerSideCuePoints() {}
104
+
80
105
  /**
81
106
  * Get statistics for the current playback session. If the player is not
82
107
  * playing content, this will return an empty stats object.
@@ -1082,6 +1082,8 @@ shaka.extern.LanguageRole;
1082
1082
 
1083
1083
  /**
1084
1084
  * @typedef {{
1085
+ * imageHeight: number,
1086
+ * imageWidth: number,
1085
1087
  * height: number,
1086
1088
  * positionX: number,
1087
1089
  * positionY: number,
@@ -1091,6 +1093,12 @@ shaka.extern.LanguageRole;
1091
1093
  * width: number
1092
1094
  * }}
1093
1095
  *
1096
+ * @property {number} imageHeight
1097
+ * The image height in px. The image height could be different to height if
1098
+ * the layout is different to 1x1.
1099
+ * @property {number} imageWidth
1100
+ * The image width in px. The image width could be different to width if
1101
+ * the layout is different to 1x1.
1094
1102
  * @property {number} height
1095
1103
  * The thumbnail height in px.
1096
1104
  * @property {number} positionX
@@ -349,6 +349,16 @@ shaka.extern.Cue = class {
349
349
  */
350
350
  this.nestedCues;
351
351
 
352
+ /**
353
+ * If true, this represents a container element that is "above" the main
354
+ * cues. For example, the <body> and <div> tags that contain the <p> tags
355
+ * in a TTML file. This controls the flow of the final cues; any nested cues
356
+ * within an "isContainer" cue will be laid out as separate lines.
357
+ * @type {boolean}
358
+ * @exportDoc
359
+ */
360
+ this.isContainer;
361
+
352
362
  /**
353
363
  * Whether or not the cue only acts as a line break between two nested cues.
354
364
  * Should only appear in nested cues.
package/karma.conf.js CHANGED
@@ -11,6 +11,7 @@ const Jimp = require('jimp');
11
11
  const fs = require('fs');
12
12
  const path = require('path');
13
13
  const rimraf = require('rimraf');
14
+ const {ssim} = require('ssim.js');
14
15
  const util = require('karma/common/util');
15
16
  const which = require('which');
16
17
 
@@ -140,6 +141,7 @@ module.exports = (config) => {
140
141
  included: false,
141
142
  },
142
143
  {pattern: 'test/test/assets/*', included: false},
144
+ {pattern: 'test/test/assets/3675/*', included: false},
143
145
  {pattern: 'dist/shaka-player.ui.js', included: false},
144
146
  {pattern: 'dist/locales.js', included: false},
145
147
  {pattern: 'demo/locales/en.json', included: false},
@@ -335,6 +337,10 @@ module.exports = (config) => {
335
337
 
336
338
  config.set({reporters: reporters});
337
339
 
340
+ if (reporters.includes('spec') && settings.spec_hide_passed) {
341
+ config.set({specReporter: {suppressPassed: true}});
342
+ }
343
+
338
344
  if (settings.random) {
339
345
  // If --seed was specified use that value, else generate a seed so that the
340
346
  // exact order can be reproduced if it catches an issue.
@@ -517,8 +523,7 @@ function WebDriverScreenshotMiddlewareFactory(launcher) {
517
523
  *
518
524
  * @param {karma.Launcher.Browser} browser
519
525
  * @param {!Object.<string, string>} params
520
- * @return {!Promise.<number>} The number of pixels changed between the old
521
- * and new screenshots, after cropping and scaling.
526
+ * @return {!Promise.<number>} A similarity score between 0 and 1.
522
527
  */
523
528
  async function diffScreenshot(browser, params) {
524
529
  const webDriverClient = getWebDriverClient(browser);
@@ -603,22 +608,22 @@ function WebDriverScreenshotMiddlewareFactory(launcher) {
603
608
  // Compare the new screenshot to the old one and produce a diff image.
604
609
  // Initially, the image data will be raw pixels, 4 bytes per pixel.
605
610
  // The threshold parameter affects the sensitivity of individual pixel
606
- // comparisons. Setting it too low means small rendering changes in the
607
- // browser can cause failures even when a human can't see the difference,
608
- // and setting it too high means human-noticeable changes could go
609
- // undetected by a test.
610
- const diff = Jimp.diff(oldScreenshot, newScreenshot, /* threshold= */ 0.07);
611
+ // comparisons. This diff is only used for visual review, not for
612
+ // automated similarity checks, so the threshold setting is not so critical
613
+ // as it used to be.
614
+ const threshold = 0.10;
615
+ const diff = Jimp.diff(oldScreenshot, newScreenshot, threshold);
611
616
 
612
617
  // Write the diff to disk. This is used to review when there are changes.
618
+ const fullSizeDiff =
619
+ diff.image.clone().resize(width, height, Jimp.RESIZE_BICUBIC);
613
620
  fs.writeFileSync(
614
- diffScreenshotPath, await diff.image.getBufferAsync('image/png'));
615
-
616
- // "percent" is, surprisingly, a number between 0 and 1, not between 0 and
617
- // 100. Convert this to a number of pixels changed, which has been found to
618
- // be a more effective and less flaky metric.
619
- const pixelsChanged =
620
- diff.percent * diff.image.bitmap.width * diff.image.bitmap.height;
621
- return pixelsChanged;
621
+ diffScreenshotPath, await fullSizeDiff.getBufferAsync('image/png'));
622
+
623
+ // Compare with a structural similarity algorithm. This produces a
624
+ // similarity score that we will use to pass or fail the test.
625
+ const ssimResult = ssim(oldScreenshot.bitmap, newScreenshot.bitmap);
626
+ return ssimResult.mssim; // A score between 0 and 1.
622
627
  }
623
628
 
624
629
  /**
@@ -6,7 +6,6 @@
6
6
 
7
7
 
8
8
  goog.provide('shaka.ads.AdManager');
9
- goog.provide('shaka.ads.CuePoint');
10
9
 
11
10
  goog.require('shaka.Player');
12
11
  goog.require('shaka.ads.AdsStats');
@@ -16,6 +15,7 @@ goog.require('shaka.log');
16
15
  goog.require('shaka.util.Error');
17
16
  goog.require('shaka.util.FakeEvent');
18
17
  goog.require('shaka.util.FakeEventTarget');
18
+ goog.require('shaka.util.IReleasable');
19
19
 
20
20
 
21
21
  /**
@@ -359,6 +359,7 @@ goog.require('shaka.util.FakeEventTarget');
359
359
  /**
360
360
  * A class responsible for ad-related interactions.
361
361
  * @implements {shaka.extern.IAdManager}
362
+ * @implements {shaka.util.IReleasable}
362
363
  * @export
363
364
  */
364
365
  shaka.ads.AdManager = class extends shaka.util.FakeEventTarget {
@@ -403,6 +404,10 @@ shaka.ads.AdManager = class extends shaka.util.FakeEventTarget {
403
404
  shaka.util.Error.Code.CS_IMA_SDK_MISSING);
404
405
  }
405
406
 
407
+ if (this.csAdManager_) {
408
+ this.csAdManager_.release();
409
+ }
410
+
406
411
  this.csAdManager_ = new shaka.ads.ClientSideAdManager(
407
412
  adContainer, video, this.locale_,
408
413
  (e) => {
@@ -430,6 +435,23 @@ shaka.ads.AdManager = class extends shaka.util.FakeEventTarget {
430
435
  }
431
436
 
432
437
 
438
+ /**
439
+ * @override
440
+ * @export
441
+ */
442
+ release() {
443
+ if (this.csAdManager_) {
444
+ this.csAdManager_.release();
445
+ this.csAdManager_ = null;
446
+ }
447
+ if (this.ssAdManager_) {
448
+ this.ssAdManager_.release();
449
+ this.ssAdManager_ = null;
450
+ }
451
+ super.release();
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) => {
@@ -576,6 +594,22 @@ shaka.ads.AdManager = class extends shaka.util.FakeEventTarget {
576
594
  }
577
595
 
578
596
 
597
+ /**
598
+ * @return {!Array.<!shaka.extern.AdCuePoint>}
599
+ * @override
600
+ * @export
601
+ */
602
+ getServerSideCuePoints() {
603
+ if (!this.ssAdManager_) {
604
+ throw new shaka.util.Error(
605
+ shaka.util.Error.Severity.RECOVERABLE,
606
+ shaka.util.Error.Category.ADS,
607
+ shaka.util.Error.Code.SS_AD_MANAGER_NOT_INITIALIZED);
608
+ }
609
+ return this.ssAdManager_.getCuePoints();
610
+ }
611
+
612
+
579
613
  /**
580
614
  * @return {shaka.extern.AdsStats}
581
615
  * @override
@@ -628,20 +662,6 @@ shaka.ads.AdManager = class extends shaka.util.FakeEventTarget {
628
662
  }
629
663
  };
630
664
 
631
-
632
- shaka.ads.CuePoint = class {
633
- /**
634
- * @param {number} start
635
- * @param {?number=} end
636
- */
637
- constructor(start, end = null) {
638
- /** @public {number} */
639
- this.start = start;
640
- /** @public {?number} */
641
- this.end = end;
642
- }
643
- };
644
-
645
665
  /**
646
666
  * The event name for when a sequence of ads has been loaded.
647
667
  *