shaka-player 4.12.8 → 4.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (261) hide show
  1. package/AUTHORS +1 -0
  2. package/CONTRIBUTORS +4 -0
  3. package/README.md +22 -21
  4. package/cspell.config.yaml +18 -0
  5. package/dist/controls.css +1 -1
  6. package/dist/controls.css.map +1 -1
  7. package/dist/deps.js +29 -24
  8. package/dist/locales.js +33 -33
  9. package/dist/shaka-player.compiled.d.ts +138 -36
  10. package/dist/shaka-player.compiled.debug.d.ts +138 -36
  11. package/dist/shaka-player.compiled.debug.externs.js +367 -107
  12. package/dist/shaka-player.compiled.debug.js +828 -765
  13. package/dist/shaka-player.compiled.debug.map +4 -4
  14. package/dist/shaka-player.compiled.externs.js +367 -107
  15. package/dist/shaka-player.compiled.js +1451 -1416
  16. package/dist/shaka-player.compiled.map +4 -4
  17. package/dist/shaka-player.ui.d.ts +172 -38
  18. package/dist/shaka-player.ui.debug.d.ts +172 -38
  19. package/dist/shaka-player.ui.debug.externs.js +406 -113
  20. package/dist/shaka-player.ui.debug.js +842 -766
  21. package/dist/shaka-player.ui.debug.map +4 -4
  22. package/dist/shaka-player.ui.externs.js +406 -113
  23. package/dist/shaka-player.ui.js +1670 -1628
  24. package/dist/shaka-player.ui.map +4 -4
  25. package/eslint.config.mjs +343 -0
  26. package/externs/airplay.js +1 -1
  27. package/externs/audiotrack.js +1 -1
  28. package/externs/awesomplete.js +1 -1
  29. package/externs/cast-sdk-v2.js +2 -2
  30. package/externs/cmcd.js +16 -1
  31. package/externs/device_sensor_event.js +1 -1
  32. package/externs/ima.js +8 -8
  33. package/externs/isoboxer.js +31 -31
  34. package/externs/jwk_set.js +1 -1
  35. package/externs/lcevc.js +8 -8
  36. package/externs/mediakeys.js +1 -1
  37. package/externs/mediasession.js +3 -2
  38. package/externs/mediatailor.js +18 -18
  39. package/externs/pictureinpicture.js +41 -1
  40. package/externs/playstation.js +2 -2
  41. package/externs/prefixed_eme.js +1 -1
  42. package/externs/shaka/abortable.js +4 -4
  43. package/externs/shaka/abr_manager.js +1 -1
  44. package/externs/shaka/ads.js +45 -6
  45. package/externs/shaka/cea.js +2 -2
  46. package/externs/shaka/codecs.js +4 -4
  47. package/externs/shaka/drm_info.js +6 -6
  48. package/externs/shaka/error.js +5 -5
  49. package/externs/shaka/manifest.js +51 -56
  50. package/externs/shaka/manifest_parser.js +3 -9
  51. package/externs/shaka/net.js +23 -20
  52. package/externs/shaka/offline.js +37 -37
  53. package/externs/shaka/offline_compat_v1.js +10 -10
  54. package/externs/shaka/offline_compat_v2.js +10 -10
  55. package/externs/shaka/player.js +139 -109
  56. package/externs/shaka/text.js +10 -3
  57. package/externs/shaka/transmuxer.js +1 -1
  58. package/externs/videotrack.js +1 -1
  59. package/lib/abr/ewma.js +1 -1
  60. package/lib/abr/simple_abr_manager.js +70 -22
  61. package/lib/ads/ad_manager.js +43 -18
  62. package/lib/ads/ad_utils.js +160 -58
  63. package/lib/ads/ads_stats.js +1 -1
  64. package/lib/ads/client_side_ad_manager.js +2 -2
  65. package/lib/ads/interstitial_ad.js +16 -11
  66. package/lib/ads/interstitial_ad_manager.js +419 -72
  67. package/lib/ads/interstitial_static_ad.js +299 -0
  68. package/lib/ads/media_tailor_ad.js +1 -0
  69. package/lib/ads/media_tailor_ad_manager.js +37 -36
  70. package/lib/ads/server_side_ad_manager.js +7 -6
  71. package/lib/cast/cast_receiver.js +5 -3
  72. package/lib/cast/cast_sender.js +2 -2
  73. package/lib/cast/cast_utils.js +20 -13
  74. package/lib/cea/cea608_data_channel.js +53 -53
  75. package/lib/cea/cea708_service.js +42 -40
  76. package/lib/cea/cea708_window.js +5 -2
  77. package/lib/cea/cea_decoder.js +5 -7
  78. package/lib/cea/mp4_cea_parser.js +1 -1
  79. package/lib/cea/sei_processor.js +1 -1
  80. package/lib/dash/content_protection.js +62 -192
  81. package/lib/dash/dash_parser.js +119 -119
  82. package/lib/dash/mpd_utils.js +14 -13
  83. package/lib/dash/segment_base.js +5 -5
  84. package/lib/dash/segment_list.js +10 -10
  85. package/lib/dash/segment_template.js +55 -53
  86. package/lib/debug/log.js +2 -2
  87. package/lib/dependencies/all.js +2 -1
  88. package/lib/{media → drm}/drm_engine.js +274 -143
  89. package/lib/{util → drm}/drm_utils.js +20 -11
  90. package/lib/drm/playready.js +233 -0
  91. package/lib/hls/hls_classes.js +14 -14
  92. package/lib/hls/hls_parser.js +257 -196
  93. package/lib/hls/hls_utils.js +14 -14
  94. package/lib/hls/manifest_text_parser.js +10 -10
  95. package/lib/media/adaptation_set.js +6 -5
  96. package/lib/media/adaptation_set_criteria.js +51 -379
  97. package/lib/media/buffering_observer.js +5 -4
  98. package/lib/media/closed_caption_parser.js +2 -2
  99. package/lib/media/content_workarounds.js +2 -2
  100. package/lib/media/example_based_criteria.js +69 -0
  101. package/lib/media/gap_jumping_controller.js +14 -1
  102. package/lib/media/manifest_filterer.js +8 -8
  103. package/lib/media/manifest_parser.js +2 -2
  104. package/lib/media/media_source_capabilities.js +20 -1
  105. package/lib/media/media_source_engine.js +84 -35
  106. package/lib/media/mp4_segment_index_parser.js +5 -5
  107. package/lib/media/playhead.js +2 -8
  108. package/lib/media/playhead_observer.js +1 -1
  109. package/lib/media/preference_based_criteria.js +333 -0
  110. package/lib/media/preload_manager.js +53 -37
  111. package/lib/media/presentation_timeline.js +2 -2
  112. package/lib/media/quality_observer.js +35 -35
  113. package/lib/media/region_observer.js +2 -2
  114. package/lib/media/region_timeline.js +3 -3
  115. package/lib/media/segment_index.js +14 -14
  116. package/lib/media/segment_prefetch.js +17 -13
  117. package/lib/media/segment_reference.js +7 -7
  118. package/lib/media/segment_utils.js +9 -9
  119. package/lib/media/streaming_engine.js +77 -38
  120. package/lib/media/time_ranges_utils.js +1 -1
  121. package/lib/media/video_wrapper.js +1 -1
  122. package/lib/media/webm_segment_index_parser.js +4 -4
  123. package/lib/mss/content_protection.js +17 -222
  124. package/lib/mss/mss_parser.js +23 -24
  125. package/lib/net/data_uri_plugin.js +1 -0
  126. package/lib/net/http_fetch_plugin.js +8 -7
  127. package/lib/net/http_plugin_utils.js +5 -2
  128. package/lib/net/http_xhr_plugin.js +4 -3
  129. package/lib/net/networking_engine.js +72 -17
  130. package/lib/net/networking_utils.js +5 -2
  131. package/lib/offline/download_info.js +5 -1
  132. package/lib/offline/download_manager.js +15 -4
  133. package/lib/offline/download_progress_estimator.js +1 -1
  134. package/lib/offline/indexeddb/base_storage_cell.js +9 -9
  135. package/lib/offline/indexeddb/db_connection.js +1 -1
  136. package/lib/offline/indexeddb/db_operation.js +2 -2
  137. package/lib/offline/indexeddb/eme_session_storage_cell.js +1 -1
  138. package/lib/offline/indexeddb/storage_mechanism.js +1 -1
  139. package/lib/offline/indexeddb/v1_storage_cell.js +3 -3
  140. package/lib/offline/indexeddb/v2_storage_cell.js +2 -2
  141. package/lib/offline/manifest_converter.js +11 -12
  142. package/lib/offline/offline_scheme.js +8 -4
  143. package/lib/offline/session_deleter.js +11 -11
  144. package/lib/offline/storage.js +137 -88
  145. package/lib/offline/storage_muxer.js +8 -8
  146. package/lib/offline/stored_content_utils.js +3 -3
  147. package/lib/offline/stream_bandwidth_estimator.js +1 -1
  148. package/lib/player.js +291 -207
  149. package/lib/polyfill/all.js +1 -1
  150. package/lib/polyfill/media_capabilities.js +5 -5
  151. package/lib/polyfill/patchedmediakeys_apple.js +6 -6
  152. package/lib/polyfill/patchedmediakeys_webkit.js +8 -8
  153. package/lib/polyfill/video_play_promise.js +0 -1
  154. package/lib/text/cue.js +3 -2
  155. package/lib/text/lrc_text_parser.js +1 -1
  156. package/lib/text/mp4_ttml_parser.js +1 -1
  157. package/lib/text/mp4_vtt_parser.js +3 -3
  158. package/lib/text/sbv_text_parser.js +1 -1
  159. package/lib/text/simple_text_displayer.js +37 -10
  160. package/lib/text/ssa_text_parser.js +3 -1
  161. package/lib/text/stub_text_displayer.js +12 -5
  162. package/lib/text/text_engine.js +5 -4
  163. package/lib/text/text_utils.js +4 -4
  164. package/lib/text/ttml_text_parser.js +21 -20
  165. package/lib/text/ui_text_displayer.js +20 -13
  166. package/lib/text/vtt_text_parser.js +10 -10
  167. package/lib/text/web_vtt_generator.js +2 -2
  168. package/lib/transmuxer/aac_transmuxer.js +2 -2
  169. package/lib/transmuxer/ac3_transmuxer.js +2 -2
  170. package/lib/transmuxer/adts.js +2 -0
  171. package/lib/transmuxer/ec3.js +3 -3
  172. package/lib/transmuxer/ec3_transmuxer.js +2 -2
  173. package/lib/transmuxer/h264.js +5 -5
  174. package/lib/transmuxer/h265.js +3 -3
  175. package/lib/transmuxer/mp3_transmuxer.js +2 -2
  176. package/lib/transmuxer/mpeg_audio.js +6 -6
  177. package/lib/transmuxer/mss_transmuxer.js +2 -0
  178. package/lib/transmuxer/transmuxer_engine.js +1 -1
  179. package/lib/transmuxer/ts_transmuxer.js +10 -10
  180. package/lib/util/abortable_operation.js +10 -10
  181. package/lib/util/array_utils.js +6 -6
  182. package/lib/util/cmcd_manager.js +149 -18
  183. package/lib/util/cmsd_manager.js +11 -11
  184. package/lib/util/config_utils.js +3 -3
  185. package/lib/util/content_steering_manager.js +17 -17
  186. package/lib/util/data_view_reader.js +3 -3
  187. package/lib/util/ebml_parser.js +1 -1
  188. package/lib/util/error.js +11 -6
  189. package/lib/util/event_manager.js +1 -1
  190. package/lib/util/exp_golomb.js +1 -1
  191. package/lib/util/fairplay_utils.js +6 -1
  192. package/lib/util/fake_event.js +3 -2
  193. package/lib/util/fake_event_target.js +1 -1
  194. package/lib/util/functional.js +8 -8
  195. package/lib/util/id3_utils.js +1 -1
  196. package/lib/util/iterables.js +6 -6
  197. package/lib/util/language_utils.js +17 -17
  198. package/lib/util/manifest_parser_utils.js +13 -13
  199. package/lib/util/map_utils.js +6 -6
  200. package/lib/util/media_ready_state_utils.js +1 -1
  201. package/lib/util/mime_utils.js +15 -4
  202. package/lib/util/mp4_box_parsers.js +5 -5
  203. package/lib/util/mp4_generator.js +31 -30
  204. package/lib/util/mp4_parser.js +2 -2
  205. package/lib/util/multi_map.js +5 -5
  206. package/lib/util/mutex.js +1 -1
  207. package/lib/util/networking.js +1 -1
  208. package/lib/util/object_utils.js +5 -1
  209. package/lib/util/operation_manager.js +1 -1
  210. package/lib/util/periods.js +24 -24
  211. package/lib/util/platform.js +8 -4
  212. package/lib/util/player_configuration.js +50 -17
  213. package/lib/util/pssh.js +34 -6
  214. package/lib/util/public_promise.js +2 -2
  215. package/lib/util/state_history.js +2 -2
  216. package/lib/util/stream_utils.js +138 -120
  217. package/lib/util/string_utils.js +4 -3
  218. package/lib/util/switch_history.js +2 -2
  219. package/lib/util/tXml.js +22 -17
  220. package/lib/util/text_parser.js +2 -2
  221. package/lib/util/timer.js +1 -1
  222. package/lib/util/ts_parser.js +22 -22
  223. package/lib/util/xml_utils.js +1 -0
  224. package/package.json +7 -4
  225. package/project-words.txt +485 -0
  226. package/shaka-player.uncompiled.js +1 -1
  227. package/third_party/closure-uri/uri.js +2 -2
  228. package/third_party/closure-uri/utils.js +2 -2
  229. package/third_party/language-mapping-list/language-mapping-list.js +1 -1
  230. package/ui/ad_statistics_button.js +9 -5
  231. package/ui/airplay_button.js +1 -0
  232. package/ui/audio_language_selection.js +2 -1
  233. package/ui/context_menu.js +2 -2
  234. package/ui/controls.js +7 -7
  235. package/ui/externs/ui.js +29 -21
  236. package/ui/externs/watermark.js +64 -0
  237. package/ui/fast_forward_button.js +1 -1
  238. package/ui/gl_matrix/matrix_4x4.js +11 -5
  239. package/ui/hidden_fast_forward_button.js +1 -1
  240. package/ui/hidden_seek_button.js +1 -1
  241. package/ui/language_utils.js +27 -26
  242. package/ui/less/buttons.less +2 -2
  243. package/ui/localization.js +21 -21
  244. package/ui/loop_button.js +2 -2
  245. package/ui/overflow_menu.js +2 -2
  246. package/ui/playback_rate_selection.js +1 -1
  247. package/ui/presentation_time.js +4 -1
  248. package/ui/range_element.js +2 -2
  249. package/ui/resolution_selection.js +42 -6
  250. package/ui/rewind_button.js +1 -1
  251. package/ui/seek_bar.js +5 -5
  252. package/ui/statistics_button.js +8 -4
  253. package/ui/text_selection.js +3 -2
  254. package/ui/ui.js +32 -2
  255. package/ui/vr_manager.js +3 -3
  256. package/ui/vr_utils.js +14 -14
  257. package/ui/vr_webgl.js +5 -5
  258. package/ui/watermark.js +313 -0
  259. package/.eslintignore +0 -4
  260. package/.eslintrc.js +0 -310
  261. package/lib/polyfill/patchedmediakeys_nop.js +0 -148
@@ -0,0 +1,313 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ goog.provide('shaka.ui.Watermark');
8
+
9
+ goog.requireType('shaka.ui.Controls');
10
+
11
+ goog.require('shaka.ui.Element');
12
+ goog.require('shaka.log');
13
+
14
+ /**
15
+ * A UI component that adds watermark functionality to the Shaka Player.
16
+ * Allows adding text watermarks with various customization options.
17
+ * @extends {shaka.ui.Element}
18
+ * @final
19
+ * @export
20
+ */
21
+ shaka.ui.Watermark = class extends shaka.ui.Element {
22
+ /**
23
+ * Creates a new Watermark instance.
24
+ * @param {!HTMLElement} parent The parent element for the watermark canvas
25
+ * @param {!shaka.ui.Controls} controls The controls instance
26
+ */
27
+ constructor(parent, controls) {
28
+ super(parent, controls);
29
+
30
+ /** @private {!HTMLCanvasElement} */
31
+ this.canvas_ = /** @type {!HTMLCanvasElement} */ (
32
+ document.createElement('canvas')
33
+ );
34
+ this.canvas_.style.position = 'absolute';
35
+ this.canvas_.style.top = '0';
36
+ this.canvas_.style.left = '0';
37
+ this.canvas_.style.pointerEvents = 'none';
38
+
39
+ this.parent.appendChild(this.canvas_);
40
+ this.resizeCanvas_();
41
+
42
+ /** @private {number|null} */
43
+ this.animationId_ = null;
44
+
45
+ /** @private {ResizeObserver|null} */
46
+ this.resizeObserver_ = null;
47
+
48
+ // Use ResizeObserver if available, fallback to window resize event
49
+ if (window.ResizeObserver) {
50
+ this.resizeObserver_ = new ResizeObserver(() => this.resizeCanvas_());
51
+ this.resizeObserver_.observe(this.parent);
52
+ } else {
53
+ // Fallback for older browsers
54
+ window.addEventListener('resize', () => this.resizeCanvas_());
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Gets the 2D rendering context safely
60
+ * @return {?CanvasRenderingContext2D}
61
+ * @private
62
+ */
63
+ getContext2D_() {
64
+ const ctx = this.canvas_.getContext('2d');
65
+ if (!ctx) {
66
+ shaka.log.error('2D context is not available');
67
+ return null;
68
+ }
69
+ return /** @type {!CanvasRenderingContext2D} */ (ctx);
70
+ }
71
+
72
+ /**
73
+ * Resize canvas to match video container
74
+ * @private
75
+ */
76
+ resizeCanvas_() {
77
+ this.canvas_.width = this.parent.offsetWidth;
78
+ this.canvas_.height = this.parent.offsetHeight;
79
+ }
80
+
81
+ /**
82
+ * Sets a text watermark on the video with customizable options.
83
+ * The watermark can be either static (fixed position) or dynamic (moving).
84
+ * @param {string} text The text to display as watermark
85
+ * @param {?shaka.ui.Watermark.Options=} options configuration options
86
+ * @export
87
+ */
88
+ setTextWatermark(text, options) {
89
+ /** @type {!shaka.ui.Watermark.Options} */
90
+ const defaultOptions = {
91
+ type: 'static',
92
+ text: text,
93
+ position: 'top-right',
94
+ color: 'rgba(255, 255, 255, 0.7)',
95
+ size: 20,
96
+ alpha: 0.7,
97
+ interval: 2 * 1000,
98
+ skip: 0.5 * 1000,
99
+ displayDuration: 2 * 1000,
100
+ transitionDuration: 0.5,
101
+ };
102
+
103
+ /** @type {!shaka.ui.Watermark.Options} */
104
+ const config = /** @type {!shaka.ui.Watermark.Options} */ (
105
+ Object.assign({}, defaultOptions, options || defaultOptions)
106
+ );
107
+
108
+ if (config.type === 'static') {
109
+ this.drawStaticWatermark_(config);
110
+ } else if (config.type === 'dynamic') {
111
+ this.startDynamicWatermark_(config);
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Draws a static watermark on the canvas.
117
+ * @param {!shaka.ui.Watermark.Options} config configuration options
118
+ * @private
119
+ */
120
+ drawStaticWatermark_(config) {
121
+ const ctx = this.getContext2D_();
122
+ if (!ctx) {
123
+ return;
124
+ }
125
+
126
+ ctx.clearRect(0, 0, this.canvas_.width, this.canvas_.height);
127
+
128
+ ctx.globalAlpha = config.alpha;
129
+ ctx.fillStyle = config.color;
130
+ ctx.font = `${config.size}px Arial`;
131
+
132
+ const metrics = ctx.measureText(config.text);
133
+ const padding = 20;
134
+ let x;
135
+ let y;
136
+
137
+ switch (config.position) {
138
+ case 'top-left':
139
+ x = padding;
140
+ y = config.size + padding;
141
+ break;
142
+ case 'top-right':
143
+ x = this.canvas_.width - metrics.width - padding;
144
+ y = config.size + padding;
145
+ break;
146
+ case 'bottom-left':
147
+ x = padding;
148
+ y = this.canvas_.height - padding;
149
+ break;
150
+ case 'bottom-right':
151
+ x = this.canvas_.width - metrics.width - padding;
152
+ y = this.canvas_.height - padding;
153
+ break;
154
+ default:
155
+ x = (this.canvas_.width - metrics.width) / 2;
156
+ y = (this.canvas_.height + config.size) / 2;
157
+ }
158
+
159
+ ctx.fillText(config.text, x, y);
160
+ }
161
+
162
+ /**
163
+ * Starts a dynamic watermark animation on the canvas.
164
+ * @param {!shaka.ui.Watermark.Options} config configuration options
165
+ * @private
166
+ */
167
+ startDynamicWatermark_(config) {
168
+ const ctx = /** @type {!CanvasRenderingContext2D} */ (
169
+ this.canvas_.getContext('2d')
170
+ );
171
+ let currentPosition = {left: 0, top: 0};
172
+ let currentAlpha = 0;
173
+ let phase = 'fadeIn'; // States: fadeIn, display, fadeOut, transition
174
+
175
+ let displayFrames = Math.round(config.displayDuration * 60); // 60fps
176
+ const transitionFrames = Math.round(config.transitionDuration * 60);
177
+ const fadeSpeed = 1 / (transitionFrames / 2); // Smoother fade speed
178
+
179
+ /** @private {number} */
180
+ let positionIndex = 0;
181
+
182
+ const getNextPosition = () => {
183
+ ctx.font = `${config.size}px Arial`;
184
+ const textMetrics = ctx.measureText(config.text);
185
+ const textWidth = textMetrics.width;
186
+ const textHeight = config.size;
187
+ const padding = 20;
188
+
189
+ // Define fixed positions
190
+ const positions = [
191
+ // Top-left
192
+ {
193
+ left: padding,
194
+ top: textHeight + padding,
195
+ },
196
+ // Top-right
197
+ {
198
+ left: this.canvas_.width - textWidth - padding,
199
+ top: textHeight + padding,
200
+ },
201
+ // Bottom-left
202
+ {
203
+ left: padding,
204
+ top: this.canvas_.height - padding,
205
+ },
206
+ // Bottom-right
207
+ {
208
+ left: this.canvas_.width - textWidth - padding,
209
+ top: this.canvas_.height - padding,
210
+ },
211
+ // Center
212
+ {
213
+ left: (this.canvas_.width - textWidth) / 2,
214
+ top: (this.canvas_.height + textHeight) / 2,
215
+ },
216
+ ];
217
+
218
+ // Cycle through positions
219
+ const position = positions[positionIndex];
220
+ positionIndex = (positionIndex + 1) % positions.length;
221
+ return position;
222
+ };
223
+
224
+ currentPosition = getNextPosition();
225
+
226
+ const updateWatermark = () => {
227
+ if (!this.animationId_) {
228
+ return;
229
+ }
230
+
231
+ const width = this.canvas_.width;
232
+ const height = this.canvas_.height;
233
+ ctx.clearRect(0, 0, width, height);
234
+
235
+ // State machine for watermark phases
236
+ switch (phase) {
237
+ case 'fadeIn':
238
+ currentAlpha = Math.min(config.alpha, currentAlpha + fadeSpeed);
239
+ if (currentAlpha >= config.alpha) {
240
+ phase = 'display';
241
+ }
242
+ break;
243
+ case 'display':
244
+ if (--displayFrames <= 0) {
245
+ phase = 'fadeOut';
246
+ }
247
+ break;
248
+ case 'fadeOut':
249
+ currentAlpha = Math.max(0, currentAlpha - fadeSpeed);
250
+ if (currentAlpha <= 0) {
251
+ phase = 'transition';
252
+ currentPosition = getNextPosition();
253
+ displayFrames = Math.round(config.displayDuration * 60);
254
+ phase = 'fadeIn';
255
+ }
256
+ break;
257
+ }
258
+
259
+ // Draw watermark if visible
260
+ if (currentAlpha > 0) {
261
+ ctx.globalAlpha = currentAlpha;
262
+ ctx.fillStyle = config.color;
263
+ ctx.font = `${config.size}px Arial`;
264
+ ctx.fillText(config.text, currentPosition.left, currentPosition.top);
265
+ }
266
+
267
+ // Request next frame if animation is still active
268
+ if (this.animationId_) {
269
+ this.animationId_ = requestAnimationFrame(updateWatermark);
270
+ }
271
+ };
272
+
273
+ // Start the animation loop
274
+ this.animationId_ = requestAnimationFrame(updateWatermark);
275
+ }
276
+
277
+ /**
278
+ * Removes the current watermark from the video and stops any animations.
279
+ * @export
280
+ */
281
+ removeWatermark() {
282
+ if (this.animationId_) {
283
+ cancelAnimationFrame(this.animationId_);
284
+ this.animationId_ = null;
285
+ }
286
+ const ctx = this.getContext2D_();
287
+ if (!ctx) {
288
+ return;
289
+ }
290
+ ctx.clearRect(0, 0, this.canvas_.width, this.canvas_.height);
291
+ }
292
+
293
+ /**
294
+ * Releases the watermark instance and cleans up the canvas element.
295
+ * @override
296
+ */
297
+ release() {
298
+ if (this.canvas_ && this.canvas_.parentNode) {
299
+ this.canvas_.parentNode.removeChild(this.canvas_);
300
+ }
301
+
302
+ // Clean up resize observer if it exists
303
+ if (this.resizeObserver_) {
304
+ this.resizeObserver_.disconnect();
305
+ this.resizeObserver_ = null;
306
+ } else {
307
+ // Remove window resize listener if we were using that
308
+ window.removeEventListener('resize', () => this.resizeCanvas_());
309
+ }
310
+
311
+ super.release();
312
+ }
313
+ };
package/.eslintignore DELETED
@@ -1,4 +0,0 @@
1
- # Similar to .gitignore, this lists files ignored by eslint.
2
-
3
- # This is default ignored, but we want to still lint it.
4
- !.eslintrc.js
package/.eslintrc.js DELETED
@@ -1,310 +0,0 @@
1
- // vim: foldmethod=marker:foldmarker={{{,}}}
2
- /*! @license
3
- * Shaka Player
4
- * Copyright 2016 Google LLC
5
- * SPDX-License-Identifier: Apache-2.0
6
- */
7
-
8
- // ESlint config
9
-
10
- // This is a matcher (usable in no-restricted-syntax) that matches either a
11
- // test or a before/after block.
12
- const testNameRegex =
13
- '/^([fx]?it|(drm|quarantined)It|(before|after)(Each|All))$/';
14
- const testCall = `CallExpression[callee.name=${testNameRegex}]`;
15
-
16
- const commonNoRestrictedSyntax = [
17
- {
18
- 'selector':
19
- 'MemberExpression[object.name="goog"][property.name="inherits"]',
20
- 'message': 'Don\'t use goog.inherits.',
21
- },
22
- {
23
- 'selector': ':not(MethodDefinition) > FunctionExpression',
24
- 'message': 'Use arrow functions instead of "function" functions.',
25
- },
26
- {
27
- 'selector': 'CallExpression[callee.property.name="forEach"] >' +
28
- ':function[params.length=1]',
29
- 'message': 'Use for-of instead of forEach',
30
- },
31
- {
32
- // NOTE: prefer-spread rule covers .apply() already.
33
- 'selector': 'CallExpression[callee.property.name=/^(bind|call)$/]',
34
- 'message': 'Don\'t use Function bind/call.',
35
- },
36
- {
37
- 'selector': 'MemberExpression[property.name="prototype"]',
38
- 'message': 'Use ES6 classes not .prototype.',
39
- },
40
- {
41
- 'selector': 'BinaryExpression[operator=/^([<>!=]=?)$/] > ' +
42
- 'CallExpression[callee.property.name=indexOf]',
43
- 'message': 'Use Array.includes instead of indexOf.',
44
- },
45
- ];
46
-
47
- module.exports = {
48
- 'env': {
49
- 'browser': true,
50
- 'es6': true,
51
- },
52
- 'parserOptions': {
53
- 'ecmaVersion': 2017,
54
- },
55
- 'extends': ['eslint:recommended', 'google', 'plugin:shaka-rules/config'],
56
- 'rules': {
57
- // Things the compiler already takes care of, with more precision: {{{
58
- 'no-console': 'off',
59
- 'no-eq-null': 'off',
60
- 'no-eval': 'off',
61
- 'no-undef': 'off',
62
- 'valid-jsdoc': 'off',
63
- // }}}
64
-
65
- // Things we should probably fix, but in stages in multiple commits: {{{
66
-
67
- // These could catch real bugs
68
- 'default-case': 'off',
69
- // TODO: Enable no-loop-func in next eslint release. We can't use it
70
- // now since it doesn't allow capturing "const" variables, which is safe
71
- 'no-loop-func': 'off',
72
- 'no-unused-expressions': 'off', // Conflicts with some Closure declarations
73
- 'prefer-promise-reject-errors': 'off',
74
-
75
- // These could improve readability
76
- 'complexity': 'off',
77
- 'no-negated-condition': 'off',
78
- 'no-shadow': 'off',
79
- // }}}
80
-
81
- // "Possible error" rules: {{{
82
- 'no-async-promise-executor': 'error',
83
- 'no-await-in-loop': 'error',
84
- 'no-empty': ['error', {'allowEmptyCatch': true}],
85
- 'no-misleading-character-class': 'error',
86
- 'no-template-curly-in-string': 'error',
87
- 'no-fallthrough': ['error', {'allowEmptyCase': true}],
88
- // TODO: Try to re-enable this if possible. Right now, it produces way too
89
- // many false-positives with eslint 7. It worked well enough in eslint 5.
90
- // 'require-atomic-updates': 'error',
91
- // }}}
92
-
93
- // "Best practices" rules: {{{
94
- 'accessor-pairs': 'error',
95
- 'array-callback-return': 'error',
96
- // causes issues when implementing an interface
97
- 'class-methods-use-this': 'off',
98
- 'consistent-return': 'error',
99
- 'dot-location': ['error', 'property'],
100
- 'dot-notation': 'off', // We use bracket notation in tests on purpose
101
- 'eqeqeq': 'off', // Compiler handles type checking in advance
102
- 'guard-for-in': 'off',
103
- 'no-alert': 'error',
104
- 'no-caller': 'error',
105
- 'no-div-regex': 'error',
106
- 'no-extend-native': 'error', // May conflict with future polyfills
107
- 'no-extra-label': 'error',
108
- 'no-floating-decimal': 'error',
109
- 'no-implicit-coercion': ['error', {'allow': ['!!']}],
110
- 'no-implied-eval': 'error',
111
- 'no-invalid-this': 'error',
112
- 'no-iterator': 'error',
113
- 'no-labels': 'error',
114
- 'no-lone-blocks': 'error',
115
- 'no-multi-spaces': ['error', {'ignoreEOLComments': true}],
116
- 'no-multi-str': 'error',
117
- 'no-new': 'error',
118
- 'no-new-func': 'error',
119
- 'no-new-wrappers': 'error',
120
- 'no-octal-escape': 'error',
121
- 'no-proto': 'error',
122
- 'no-return-assign': 'error',
123
- 'no-return-await': 'error',
124
- 'no-script-url': 'error',
125
- 'no-self-compare': 'error',
126
- 'no-sequences': 'error',
127
- 'no-throw-literal': 'error',
128
- 'no-unmodified-loop-condition': 'error',
129
- 'no-unused-vars': 'off', // Interface impls may not require all args
130
- 'no-useless-call': 'error',
131
- 'no-useless-catch': 'error',
132
- 'no-useless-concat': 'error',
133
- 'no-useless-return': 'error',
134
- 'no-void': 'error',
135
- 'no-warning-comments': 'off', // TODO and FIXME are fine
136
- 'radix': ['error', 'always'],
137
- 'require-await': 'error',
138
- 'wrap-iife': ['error', 'inside'],
139
- 'yoda': ['error', 'never'],
140
- // }}}
141
-
142
- // "Variables" rules: {{{
143
- 'no-label-var': 'error',
144
- 'no-shadow-restricted-names': 'error',
145
- 'no-undef-init': 'off', // Sometimes necessary with hacky compiler casts
146
- 'no-undefined': 'off', // We use undefined in many places, legitimately
147
- // Does not know when things are executed, false positives
148
- 'no-use-before-define': 'off',
149
- // }}}
150
-
151
- // "Stylistic Issues" rules: {{{
152
- 'array-bracket-newline': ['error', 'consistent'],
153
- 'block-spacing': ['error', 'always'],
154
- 'brace-style': ['error', '1tbs', {'allowSingleLine': true}],
155
- 'id-denylist': ['error', 'async'],
156
- 'lines-between-class-members': 'error',
157
- 'max-statements-per-line': ['error', {'max': 1}],
158
- 'new-parens': 'error',
159
- 'no-mixed-operators': [
160
- 'error', {
161
- 'groups': [['&', '|', '^', '~', '<<', '>>', '>>>', '&&', '||']],
162
- 'allowSamePrecedence': false,
163
- },
164
- ],
165
- 'no-restricted-syntax': [
166
- 'error',
167
- ...commonNoRestrictedSyntax,
168
- ],
169
- 'no-whitespace-before-property': 'error',
170
- 'nonblock-statement-body-position': ['error', 'below'],
171
- 'operator-assignment': 'error',
172
- 'spaced-comment': ['error', 'always', {
173
- // Characters which may be glued to the start of a comment block, but
174
- // which do not violate the rule. The "*" is for jsdoc's "/**" syntax,
175
- // and the "!" is for the "/*!" of license headers which are passed
176
- // verbatim through the compiler.
177
- 'markers': ['*', '!'],
178
- }],
179
- 'require-jsdoc': ['error', {
180
- 'require': {
181
- 'FunctionDeclaration': true,
182
- 'MethodDefinition': true,
183
- 'ClassDeclaration': true,
184
- },
185
- }],
186
- // }}}
187
-
188
- // "ECMAScript 6" rules: {{{
189
- 'arrow-spacing': 'error',
190
- 'no-useless-constructor': 'error',
191
- 'prefer-arrow-callback': 'error',
192
- 'prefer-const': ['error', {'ignoreReadBeforeAssign': true}],
193
- // }}}
194
- },
195
- 'overrides': [
196
- {
197
- 'rules': {
198
- 'no-restricted-syntax': [
199
- 'error',
200
- {
201
- 'selector': 'CallExpression[callee.name="beforeAll"] ' +
202
- ':matches(' +
203
- 'CallExpression[callee.property.name="createSpy"],' +
204
- 'CallExpression[callee.name="spyOn"])',
205
- 'message': 'Create spies in beforeEach, not beforeAll.',
206
- },
207
- {
208
- 'selector': testCall + ' > :function[params.length>0]',
209
- 'message': 'Use async instead of "done" in tests.',
210
- },
211
- {
212
- 'selector': testCall + ' > CallExpression',
213
- 'message': 'Use filterDescribe instead of checkAndRun calls',
214
- },
215
- {
216
- 'selector': 'CatchClause',
217
- 'message': 'Use expect.toThrow or expectAsync.toBeRejected',
218
- },
219
- {
220
- 'selector': 'CallExpression[callee.name=expect] >' +
221
- 'CallExpression[callee.property.name=count]' +
222
- '[callee.object.property.name=calls]',
223
- 'message': 'Use expect.toHaveBeenCalledTimes',
224
- },
225
- {
226
- 'selector':
227
- 'CallExpression[callee.property.name=toHaveBeenCalledTimes] >' +
228
- 'Literal[value=0]',
229
- 'message': 'Use expect.not.toHaveBeenCalled',
230
- },
231
- ...commonNoRestrictedSyntax,
232
- ],
233
- },
234
- 'files': [
235
- 'test/**/*.js',
236
- ],
237
- },
238
- {
239
- 'rules': {
240
- 'no-restricted-syntax': 'off',
241
- },
242
- 'files': [
243
- 'demo/load.js',
244
- 'externs/**/*.js',
245
- 'test/test/externs/*.js',
246
- 'ui/externs/*.js',
247
- ],
248
- },
249
- {
250
- 'rules': {
251
- 'no-var': 'off',
252
- },
253
- 'files': [
254
- // Closure requires using var in externs.
255
- 'ui/externs/*.js',
256
- 'externs/**/*.js',
257
- 'test/test/externs/*.js',
258
- // Use var in load.js so it works in old browsers. We'll use
259
- // compiled mode for the main library and the demo.
260
- 'demo/load.js',
261
- ],
262
- },
263
- {
264
- 'rules': {
265
- 'prefer-rest-params': 'off',
266
- },
267
- 'files': [
268
- // Test code should still use "arguments", since the alternate
269
- // "rest parameter" syntax won't work in uncompiled code on IE.
270
- 'test/**/*.js',
271
- // These two files use "arguments" to patch over functions. It
272
- // is difficult to reason about whether or not these instances
273
- // would always work with rest parameters, so just allow them to
274
- // use "arguments".
275
- 'demo/log_section.js',
276
- 'lib/debug/asserts.js',
277
- ],
278
- },
279
- {
280
- 'rules': {
281
- // Disable rules on useless constructors so we can use ES6 classes in
282
- // externs.
283
- 'no-useless-constructor': 'off',
284
- },
285
- 'files': ['externs/**/*.js'],
286
- },
287
- {
288
- 'rules': {
289
- // JSDoc is not strictly required in externs, tests, and in load.js.
290
- 'require-jsdoc': 'off',
291
- },
292
- 'files': [
293
- 'demo/load.js',
294
- 'externs/**/*.js',
295
- 'test/**/*.js',
296
- ],
297
- },
298
- {
299
- 'rules': {
300
- // Externs naturally redeclare things eslint knows about.
301
- 'no-redeclare': 'off',
302
- },
303
- 'files': [
304
- 'ui/externs/*.js',
305
- 'externs/**/*.js',
306
- 'test/test/externs/*.js',
307
- ],
308
- },
309
- ],
310
- };