shaka-player 4.1.1 → 4.2.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 (179) hide show
  1. package/.github/workflows/build-and-test.yaml +67 -15
  2. package/.github/workflows/compute-incremental-coverage.py +251 -0
  3. package/.github/workflows/report-incremental-coverage.yaml +39 -0
  4. package/.github/workflows/selenium-lab-tests.yaml +44 -1
  5. package/AUTHORS +1 -0
  6. package/CHANGELOG.md +36 -8
  7. package/CONTRIBUTORS +3 -0
  8. package/README.md +20 -6
  9. package/demo/common/assets.js +25 -0
  10. package/demo/common/message_ids.js +2 -0
  11. package/demo/config.js +5 -1
  12. package/demo/index.html +1 -3
  13. package/demo/locales/en.json +2 -0
  14. package/demo/locales/source.json +8 -0
  15. package/dist/controls.css +1 -1
  16. package/dist/demo.compiled.debug.js +25 -23
  17. package/dist/demo.compiled.debug.map +3 -3
  18. package/dist/demo.compiled.js +25 -23
  19. package/dist/demo.compiled.map +3 -3
  20. package/dist/deps.js +6 -5
  21. package/dist/locales.js +30 -30
  22. package/dist/receiver.compiled.debug.js +24 -22
  23. package/dist/receiver.compiled.debug.map +3 -3
  24. package/dist/receiver.compiled.js +24 -22
  25. package/dist/receiver.compiled.map +3 -3
  26. package/dist/shaka-player.compiled.d.ts +69 -5
  27. package/dist/shaka-player.compiled.debug.d.ts +69 -5
  28. package/dist/shaka-player.compiled.debug.externs.js +111 -42
  29. package/dist/shaka-player.compiled.debug.js +352 -301
  30. package/dist/shaka-player.compiled.debug.map +4 -4
  31. package/dist/shaka-player.compiled.externs.js +111 -42
  32. package/dist/shaka-player.compiled.js +823 -802
  33. package/dist/shaka-player.compiled.map +4 -4
  34. package/dist/shaka-player.ui.d.ts +69 -5
  35. package/dist/shaka-player.ui.debug.d.ts +69 -5
  36. package/dist/shaka-player.ui.debug.externs.js +111 -42
  37. package/dist/shaka-player.ui.debug.js +360 -310
  38. package/dist/shaka-player.ui.debug.map +4 -4
  39. package/dist/shaka-player.ui.externs.js +111 -42
  40. package/dist/shaka-player.ui.js +980 -957
  41. package/dist/shaka-player.ui.map +4 -4
  42. package/docs/tutorials/fairplay.md +149 -0
  43. package/docs/tutorials/ui.md +6 -6
  44. package/docs/tutorials/upgrade.md +1 -0
  45. package/docs/tutorials/welcome.md +6 -3
  46. package/externs/shaka/abr_manager.js +8 -0
  47. package/externs/shaka/manifest.js +43 -0
  48. package/externs/shaka/player.js +13 -2
  49. package/karma.conf.js +3 -11
  50. package/lib/abr/simple_abr_manager.js +72 -4
  51. package/lib/ads/client_side_ad_manager.js +1 -1
  52. package/lib/dash/dash_parser.js +5 -0
  53. package/lib/hls/hls_parser.js +123 -27
  54. package/lib/media/drm_engine.js +1 -3
  55. package/lib/media/media_source_engine.js +57 -24
  56. package/lib/media/presentation_timeline.js +24 -1
  57. package/lib/media/segment_index.js +8 -0
  58. package/lib/media/segment_reference.js +7 -1
  59. package/lib/media/streaming_engine.js +42 -6
  60. package/lib/media/time_ranges_utils.js +46 -0
  61. package/lib/net/networking_engine.js +1 -0
  62. package/lib/player.js +8 -6
  63. package/lib/polyfill/media_capabilities.js +9 -0
  64. package/lib/polyfill/patchedmediakeys_apple.js +729 -0
  65. package/lib/polyfill/videoplaybackquality.js +3 -1
  66. package/lib/text/cue.js +0 -5
  67. package/lib/text/simple_text_displayer.js +21 -9
  68. package/lib/text/ui_text_displayer.js +83 -19
  69. package/lib/text/vtt_text_parser.js +61 -4
  70. package/lib/util/buffer_utils.js +3 -0
  71. package/lib/util/error.js +21 -1
  72. package/lib/util/fairplay_utils.js +100 -2
  73. package/lib/util/object_utils.js +1 -0
  74. package/lib/util/platform.js +30 -1
  75. package/lib/util/player_configuration.js +3 -10
  76. package/lib/util/stream_utils.js +23 -3
  77. package/lib/util/string_utils.js +102 -13
  78. package/maintained-branches.md +15 -0
  79. package/package.json +3 -5
  80. package/shaka-player.uncompiled.js +1 -0
  81. package/test/hls/hls_parser_unit.js +49 -33
  82. package/test/media/drm_engine_integration.js +24 -8
  83. package/test/media/media_source_engine_integration.js +24 -10
  84. package/test/media/media_source_engine_unit.js +53 -38
  85. package/test/media/streaming_engine_unit.js +107 -32
  86. package/test/test/util/fake_media_source_engine.js +10 -9
  87. package/test/test/util/simple_fakes.js +4 -0
  88. package/test/test/util/streaming_engine_util.js +10 -2
  89. package/test/text/simple_text_displayer_unit.js +27 -0
  90. package/test/text/ui_text_displayer_unit.js +65 -0
  91. package/test/text/vtt_text_parser_unit.js +26 -0
  92. package/test/util/string_utils_unit.js +46 -8
  93. package/ui/text_selection.js +2 -2
  94. package/app-engine/README.md +0 -9
  95. package/app-engine/demo-version-index/README.md +0 -14
  96. package/app-engine/demo-version-index/app.yaml +0 -28
  97. package/app-engine/demo-version-index/generate.py +0 -164
  98. package/app-engine/demo-version-index/main.py +0 -11
  99. package/app-engine/demo-version-index/requirements.txt +0 -5
  100. package/app-engine/demo-version-index/templates/index.html +0 -114
  101. package/app-engine/shaka-player-demo/README.md +0 -18
  102. package/app-engine/shaka-player-demo/app.yaml +0 -61
  103. package/app-engine/shaka-player-demo/main.py +0 -95
  104. package/app-engine/shaka-player-demo/posters/10yo.png +0 -0
  105. package/app-engine/shaka-player-demo/posters/10yo.xcf +0 -0
  106. package/app-engine/shaka-player-demo/posters/1yo.jpg +0 -0
  107. package/app-engine/shaka-player-demo/posters/2yo.png +0 -0
  108. package/app-engine/shaka-player-demo/posters/2yo.xcf +0 -0
  109. package/app-engine/shaka-player-demo/posters/3yo.png +0 -0
  110. package/app-engine/shaka-player-demo/posters/3yo.xcf +0 -0
  111. package/app-engine/shaka-player-demo/posters/4yo.png +0 -0
  112. package/app-engine/shaka-player-demo/posters/4yo.xcf +0 -0
  113. package/app-engine/shaka-player-demo/posters/5yo.png +0 -0
  114. package/app-engine/shaka-player-demo/posters/5yo.xcf +0 -0
  115. package/app-engine/shaka-player-demo/posters/6yo.png +0 -0
  116. package/app-engine/shaka-player-demo/posters/6yo.xcf +0 -0
  117. package/app-engine/shaka-player-demo/posters/7yo.png +0 -0
  118. package/app-engine/shaka-player-demo/posters/7yo.xcf +0 -0
  119. package/app-engine/shaka-player-demo/posters/8yo.png +0 -0
  120. package/app-engine/shaka-player-demo/posters/8yo.xcf +0 -0
  121. package/app-engine/shaka-player-demo/posters/9yo.png +0 -0
  122. package/app-engine/shaka-player-demo/posters/9yo.xcf +0 -0
  123. package/app-engine/shaka-player-demo/posters/audioOnly.gif +0 -0
  124. package/app-engine/shaka-player-demo/posters/audioRickRoll.gif +0 -0
  125. package/app-engine/shaka-player-demo/posters/colorbars.gif +0 -0
  126. package/app-engine/shaka-player-demo/posters/fireworks.jpg +0 -0
  127. package/app-engine/shaka-player-demo/posters/party-hat.png +0 -0
  128. package/app-engine/shaka-player-demo/posters/sources.txt +0 -46
  129. package/app-engine/shaka-player-demo/posters/standard.png +0 -0
  130. package/app-engine/shaka-player-demo/posters/trek.jpg +0 -0
  131. package/app-engine/shaka-player-demo/posters/valentines.png +0 -0
  132. package/app-engine/shaka-player-demo/posters/zombie.jpg +0 -0
  133. package/app-engine/shaka-player-demo/posters.py +0 -110
  134. package/app-engine/shaka-player-demo/requirements.txt +0 -5
  135. package/app-engine/shaka-player-demo/time.txt +0 -1
  136. package/build/README.md +0 -127
  137. package/build/__init__.py +0 -0
  138. package/build/all.py +0 -150
  139. package/build/apps.py +0 -186
  140. package/build/build.py +0 -392
  141. package/build/check.py +0 -354
  142. package/build/checkversion.py +0 -84
  143. package/build/compiler.py +0 -513
  144. package/build/conformance.textproto +0 -335
  145. package/build/docker/Dockerfile +0 -20
  146. package/build/docker/docker-compose.yml +0 -10
  147. package/build/docs.py +0 -54
  148. package/build/eslint-plugin-shaka-rules/arg-comment-spacing.js +0 -72
  149. package/build/eslint-plugin-shaka-rules/index.js +0 -24
  150. package/build/eslint-plugin-shaka-rules/package.json +0 -7
  151. package/build/eslint-plugin-shaka-rules/private.js +0 -109
  152. package/build/gendeps.py +0 -71
  153. package/build/generateExterns.js +0 -867
  154. package/build/generateLocalizations.py +0 -262
  155. package/build/generateTsDefs.py +0 -137
  156. package/build/install-linux-prereqs.sh +0 -136
  157. package/build/license-header +0 -5
  158. package/build/misspellings.txt +0 -39
  159. package/build/pixelsChanged.js +0 -35
  160. package/build/shaka-lab.yaml +0 -161
  161. package/build/shakaBuildHelpers.py +0 -356
  162. package/build/stats.py +0 -816
  163. package/build/subprocessWindowsPatch.py +0 -103
  164. package/build/test.py +0 -541
  165. package/build/types/ads +0 -8
  166. package/build/types/cast +0 -6
  167. package/build/types/cea +0 -13
  168. package/build/types/complete +0 -9
  169. package/build/types/core +0 -108
  170. package/build/types/dash +0 -8
  171. package/build/types/hls +0 -9
  172. package/build/types/manifests +0 -5
  173. package/build/types/networking +0 -6
  174. package/build/types/offline +0 -22
  175. package/build/types/polyfill +0 -18
  176. package/build/types/text +0 -11
  177. package/build/types/ui +0 -39
  178. package/build/updateScreenshots.py +0 -85
  179. package/build/wrapper.template.js +0 -52
@@ -1,8 +1,41 @@
1
1
  # FairPlay Support
2
2
 
3
3
  We support FairPlay with EME on compatible environments or native `src=`.
4
+
5
+ By default Shaka Player supports Modern EME, if your provider doesn't support
6
+ Modern EME yet, you can use legacy Apple Media Keys with:
7
+ ```js
8
+ shaka.polyfill.PatchedMediaKeysApple.install();
9
+ ```
10
+
11
+ The support in each case would be the following:
12
+
13
+ | |Modern EME |legacy Apple Media Keys|
14
+ |:----------:|:---------:|:---------------------:|
15
+ |src= (CMAF) |**Y** |**Y** |
16
+ |src= (TS) |**Y** |**Y** |
17
+ |MSE (CMAF) |**Y** | - |
18
+ |MSE (TS) | - | - |
19
+
20
+
4
21
  Adding FairPlay support involves a bit more work than other key systems.
5
22
 
23
+
24
+ ## Keysystem used in EME
25
+
26
+ Depending on the EME implementation that is being used, the Fairplay keysystem
27
+ varies.
28
+
29
+ For Modern EME:
30
+ ```
31
+ com.apple.fps
32
+ ```
33
+
34
+ For legacy Apple Media Keys:
35
+ ```
36
+ com.apple.fps.1_0
37
+ ```
38
+
6
39
  ## Server certificate
7
40
 
8
41
  All FairPlay content requires setting a server certificate. You can either
@@ -22,6 +55,27 @@ player.configure('drm.advanced.com\\.apple\\.fps\\.serverCertificateUri',
22
55
  'https://example.com/cert.der');
23
56
  ```
24
57
 
58
+ ## Content ID
59
+
60
+ Note: Normally only applies to legacy Apple Media Keys but some providers also
61
+ need it in Modern EME.
62
+
63
+ Some FairPlay content use custom signaling for the content ID. The content ID
64
+ is used by the browser to generate the license request. If you don't use the
65
+ default content ID derivation, you need to specify a custom init data transform:
66
+
67
+ ```js
68
+ player.configure('drm.initDataTransform', (initData, initDataType) => {
69
+ if (initDataType != 'skd')
70
+ return initData;
71
+ // 'initData' is a buffer containing an 'skd://' URL as a UTF-8 string.
72
+ const skdUri = shaka.util.StringUtils.fromBytesAutoDetect(initData);
73
+ const contentId = getMyContentId(skdUri);
74
+ const cert = player.drmInfo().serverCertificate;
75
+ return shaka.util.FairPlayUtils.initDataTransform(initData, contentId, cert);
76
+ });
77
+ ```
78
+
25
79
  ## License wrapping
26
80
 
27
81
  Some FairPlay servers need to accept the license request in a different format
@@ -61,3 +115,98 @@ player.getNetworkingEngine().registerResponseFilter((type, response) => {
61
115
  response.data = shaka.util.Uint8ArrayUtils.fromBase64(responseText).buffer;
62
116
  });
63
117
  ```
118
+
119
+ ### Integration with some DRMs providers
120
+
121
+ Note: Some providers support both Modern EME and legacy Apple Media Keys.
122
+
123
+ #### EZDRM (Modern EME)
124
+
125
+ For integration with EZDRM the following can be used:
126
+
127
+ ```js
128
+ const FairPlayUtils = shaka.util.FairPlayUtils;
129
+ player.getNetworkingEngine()
130
+ .registerRequestFilter(FairPlayUtils.ezdrmFairPlayRequest);
131
+ player.getNetworkingEngine()
132
+ .registerResponseFilter(FairPlayUtils.commonFairPlayResponse);
133
+ ```
134
+
135
+ Note: If the url of the license server has to undergo any transformation
136
+ (eg: add the contentId), you would have to create your filter manually.
137
+
138
+ ```js
139
+ player.getNetworkingEngine().registerRequestFilter((type, request) => {
140
+ if (type != shaka.net.NetworkingEngine.RequestType.LICENSE) {
141
+ return;
142
+ }
143
+ const uri = request.uris[0];
144
+ const FairPlayUtils = shaka.util.FairPlayUtils;
145
+ const contentId = FairPlayUtils.defaultGetContentId(request.initData);
146
+ const newUri = uri.replace('^assetId^', contentId);
147
+ request.uris = [newUri];
148
+ request.headers['Content-Type'] = 'application/octet-stream'
149
+ });
150
+ ```
151
+
152
+ #### EZDRM (legacy Apple Media Keys)
153
+
154
+ For integration with EZDRM the following can be used:
155
+
156
+ ```js
157
+ shaka.polyfill.PatchedMediaKeysApple.install();
158
+ const FairPlayUtils = shaka.util.FairPlayUtils;
159
+ player.getNetworkingEngine()
160
+ .registerRequestFilter(FairPlayUtils.ezdrmFairPlayRequest);
161
+ player.getNetworkingEngine()
162
+ .registerResponseFilter(FairPlayUtils.commonFairPlayResponse);
163
+ player.configure('drm.initDataTransform',
164
+ FairPlayUtils.ezdrmInitDataTransform);
165
+ ```
166
+
167
+ Note: If the url of the license server has to undergo any transformation
168
+ (eg: add the contentId), you would have to create your filter manually.
169
+
170
+ ```js
171
+ player.getNetworkingEngine().registerRequestFilter((type, request) => {
172
+ if (type != shaka.net.NetworkingEngine.RequestType.LICENSE) {
173
+ return;
174
+ }
175
+ const uri = request.uris[0];
176
+ const FairPlayUtils = shaka.util.FairPlayUtils;
177
+ const contentId = FairPlayUtils.defaultGetContentId(request.initData);
178
+ const newUri = uri.replace('^assetId^', contentId);
179
+ request.uris = [newUri];
180
+ request.headers['Content-Type'] = 'application/octet-stream'
181
+ });
182
+ ```
183
+
184
+ #### Verimatrix (legacy Apple Media Keys)
185
+
186
+ For integration with Verimatrix the following can be used:
187
+
188
+ ```js
189
+ shaka.polyfill.PatchedMediaKeysApple.install();
190
+ const FairPlayUtils = shaka.util.FairPlayUtils;
191
+ player.getNetworkingEngine()
192
+ .registerRequestFilter(FairPlayUtils.verimatrixFairPlayRequest);
193
+ player.getNetworkingEngine()
194
+ .registerResponseFilter(FairPlayUtils.commonFairPlayResponse);
195
+ player.configure('drm.initDataTransform',
196
+ FairPlayUtils.verimatrixInitDataTransform);
197
+ ```
198
+
199
+ #### Conax (legacy Apple Media Keys)
200
+
201
+ For integration with Conax the following can be used:
202
+
203
+ ```js
204
+ shaka.polyfill.PatchedMediaKeysApple.install();
205
+ const FairPlayUtils = shaka.util.FairPlayUtils;
206
+ player.getNetworkingEngine()
207
+ .registerRequestFilter(FairPlayUtils.conaxFairPlayRequest);
208
+ player.getNetworkingEngine()
209
+ .registerResponseFilter(FairPlayUtils.commonFairPlayResponse);
210
+ player.configure('drm.initDataTransform',
211
+ FairPlayUtils.conaxInitDataTransform);
212
+ ```
@@ -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="BBED8D28">
33
+ data-shaka-player-cast-receiver-id="07AEE832">
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="BBED8D28">
114
+ data-shaka-player-cast-receiver-id="07AEE832">
115
115
  </div>
116
116
  ```
117
117
 
@@ -154,7 +154,7 @@ or a `<source>` tag inside it to enable auto loading of the specified content.
154
154
 
155
155
  ```html
156
156
  <div data-shaka-player-container style="max-width:40em"
157
- data-shaka-player-cast-receiver-id="BBED8D28">
157
+ data-shaka-player-cast-receiver-id="07AEE832">
158
158
  <!-- The manifest url in the src attribute will be automatically loaded -->
159
159
  <video autoplay data-shaka-player id="video" style="width:100%;height:100%"
160
160
  src="https://storage.googleapis.com/shaka-demo-assets/angel-one/dash.mpd"></video>
@@ -165,7 +165,7 @@ or
165
165
 
166
166
  ```html
167
167
  <div data-shaka-player-container style="max-width:40em"
168
- data-shaka-player-cast-receiver-id="BBED8D28">
168
+ data-shaka-player-cast-receiver-id="07AEE832">
169
169
  <video autoplay data-shaka-player id="video" style="width:100%;height:100%">
170
170
  <!-- The manifest url in the src attribute will be auto loaded -->
171
171
  <source src="https://storage.googleapis.com/shaka-demo-assets/angel-one/dash.mpd"/>
@@ -178,7 +178,7 @@ call to the first one fails.
178
178
 
179
179
  ```html
180
180
  <div data-shaka-player-container style="max-width:40em"
181
- data-shaka-player-cast-receiver-id="BBED8D28">
181
+ data-shaka-player-cast-receiver-id="07AEE832">
182
182
  <video autoplay data-shaka-player id="video" style="width:100%;height:100%">
183
183
  <!-- Try this first -->
184
184
  <source src="https://storage.googleapis.com/shaka-demo-assets/angel-one/dash.mpd"/>
@@ -222,7 +222,7 @@ const video = controls.getVideo();
222
222
  // Receiver Compatability.
223
223
  ui.configure({
224
224
  // Set the castReceiverAppId
225
- 'castReceiverAppId': 'BBED8D28',
225
+ 'castReceiverAppId': '07AEE832',
226
226
  // Enable casting to native Android Apps (e.g. Android TV Apps)
227
227
  'castAndroidReceiverCompatible': true,
228
228
  });
@@ -25,6 +25,7 @@ application:
25
25
  - TextDecoder/TextEncoder platform support or polyfill required (affects
26
26
  Xbox One, but not evergreen browsers); we suggest the polyfill
27
27
  [https://github.com/anonyco/FastestSmallestTextEncoderDecoder](fastestsmallesttextencoderdecoder/EncoderDecoderTogether.min.js)
28
+ Fallback included by default in v4.2
28
29
 
29
30
  - Support removed:
30
31
  - IE11 support removed
@@ -98,11 +98,14 @@ You can find a full list of available browsers with `--browsers help`, and you
98
98
  can find a complete list of testing options with `--help`.
99
99
 
100
100
 
101
- #### Join the announcement list
101
+ #### Announcements
102
102
 
103
- If you want to receive release or survey announcements, you should join our
103
+ To subscribe to new releases on GitHub, you can follow
104
+ [instructions from this blog](https://www.jessesquires.com/blog/2020/07/30/github-tip-watching-releases/).
105
+
106
+ To receive infrequent announcements and surveys from us, you can join our
104
107
  [mailing list](https://groups.google.com/forum/#!forum/shaka-player-users).
105
- The list is very low volume.
108
+ The list is very low volume, and can only be written to by us.
106
109
 
107
110
 
108
111
  #### Continue the Tutorials
@@ -103,6 +103,14 @@ shaka.extern.AbrManager = class {
103
103
  */
104
104
  playbackRateChanged(rate) {}
105
105
 
106
+ /**
107
+ * Set media element.
108
+ *
109
+ * @param {HTMLMediaElement} mediaElement
110
+ * @exportDoc
111
+ */
112
+ setMediaElement(mediaElement) {}
113
+
106
114
  /**
107
115
  * Sets the ABR configuration.
108
116
  *
@@ -244,6 +244,49 @@ shaka.extern.Variant;
244
244
  shaka.extern.CreateSegmentIndexFunction;
245
245
 
246
246
 
247
+ /**
248
+ * @typedef {{
249
+ * method: string,
250
+ * cryptoKey: (webCrypto.CryptoKey|undefined),
251
+ * fetchKey: (shaka.extern.CreateSegmentIndexFunction|undefined),
252
+ * iv: (!Uint8Array|undefined),
253
+ * firstMediaSequenceNumber: number
254
+ * }}
255
+ *
256
+ * @description
257
+ * AES-128 key and iv info from the HLS manifest.
258
+ *
259
+ * @property {string} method
260
+ * The key method defined in the HLS manifest.
261
+ * @property {webCrypto.CryptoKey|undefined} cryptoKey
262
+ * Web crypto key object of the AES-128 CBC key. If unset, the "fetchKey"
263
+ * property should be provided.
264
+ * @property {shaka.extern.FetchCryptoKeysFunction|undefined} fetchKey
265
+ * A function that fetches the key.
266
+ * Should be provided if the "cryptoKey" property is unset.
267
+ * Should update this object in-place, to set "cryptoKey".
268
+ * @property {(!Uint8Array|undefined)} iv
269
+ * The IV in the HLS manifest, if defined. See HLS RFC 8216 Section 5.2 for
270
+ * handling undefined IV.
271
+ * @property {number} firstMediaSequenceNumber
272
+ * The starting Media Sequence Number of the playlist, used when IV is
273
+ * undefined.
274
+ *
275
+ * @exportDoc
276
+ */
277
+ shaka.extern.HlsAes128Key;
278
+
279
+
280
+ /**
281
+ * A function that fetches the crypto keys for AES-128.
282
+ * Returns a promise that resolves when the keys have been fetched.
283
+ *
284
+ * @typedef {function(): !Promise}
285
+ * @exportDoc
286
+ */
287
+ shaka.extern.FetchCryptoKeysFunction;
288
+
289
+
247
290
  /**
248
291
  * @typedef {{
249
292
  * id: number,
@@ -1000,7 +1000,9 @@ shaka.extern.StreamingConfiguration;
1000
1000
  * switchInterval: number,
1001
1001
  * bandwidthUpgradeTarget: number,
1002
1002
  * bandwidthDowngradeTarget: number,
1003
- * advanced: shaka.extern.AdvancedAbrConfiguration
1003
+ * advanced: shaka.extern.AdvancedAbrConfiguration,
1004
+ * restrictToElementSize: boolean,
1005
+ * ignoreDevicePixelRatio: boolean
1004
1006
  * }}
1005
1007
  *
1006
1008
  * @property {boolean} enabled
@@ -1029,7 +1031,16 @@ shaka.extern.StreamingConfiguration;
1029
1031
  * The largest fraction of the estimated bandwidth we should use. We should
1030
1032
  * downgrade to avoid this.
1031
1033
  * @property {shaka.extern.AdvancedAbrConfiguration} advanced
1032
- * Advanced ABR configuration.
1034
+ * Advanced ABR configuration
1035
+ * @property {boolean} restrictToElementSize
1036
+ * If true, restrict the quality to media element size.
1037
+ * Note: The use of ResizeObserver is required for it to work properly. If
1038
+ * true without ResizeObserver, it behaves as false.
1039
+ * Defaults false.
1040
+ * @property {boolean} ignoreDevicePixelRatio
1041
+ * If true,device pixel ratio is ignored when restricting the quality to
1042
+ * media element size.
1043
+ * Defaults false.
1033
1044
  * @exportDoc
1034
1045
  */
1035
1046
  shaka.extern.AbrConfiguration;
package/karma.conf.js CHANGED
@@ -160,10 +160,6 @@ module.exports = (config) => {
160
160
  'node_modules/es6-promise-polyfill/promise.js',
161
161
  // Babel polyfill, required for async/await
162
162
  'node_modules/@babel/polyfill/dist/polyfill.js',
163
- // TextDecoder polyfill, required for TextDecoder/TextEncoder on IE and
164
- // legacy Edge
165
- // eslint-disable-next-line max-len
166
- 'node_modules/fastestsmallesttextencoderdecoder/EncoderDecoderTogether.min.js',
167
163
 
168
164
  // muxjs module next
169
165
  'node_modules/mux.js/dist/mux.min.js',
@@ -306,13 +302,6 @@ module.exports = (config) => {
306
302
  // Force failure when running empty test-suites.
307
303
  failOnEmptyTestSuite: true,
308
304
 
309
- coverageReporter: {
310
- includeAllSources: true,
311
- reporters: [
312
- {type: 'text'},
313
- ],
314
- },
315
-
316
305
  specReporter: {
317
306
  suppressSkipped: true,
318
307
  showBrowser: true,
@@ -405,9 +394,12 @@ module.exports = (config) => {
405
394
 
406
395
  config.set({
407
396
  coverageReporter: {
397
+ includeAllSources: true,
408
398
  reporters: [
409
399
  {type: 'html', dir: 'coverage'},
410
400
  {type: 'cobertura', dir: 'coverage', file: 'coverage.xml'},
401
+ {type: 'json-summary', dir: 'coverage', file: 'coverage.json'},
402
+ {type: 'json', dir: 'coverage', file: 'coverage-details.json'},
411
403
  ],
412
404
  },
413
405
  });
@@ -10,6 +10,7 @@ goog.require('goog.asserts');
10
10
  goog.require('shaka.abr.EwmaBandwidthEstimator');
11
11
  goog.require('shaka.log');
12
12
  goog.require('shaka.util.StreamUtils');
13
+ goog.require('shaka.util.Timer');
13
14
 
14
15
 
15
16
  /**
@@ -85,6 +86,22 @@ shaka.abr.SimpleAbrManager = class {
85
86
 
86
87
  /** @private {?shaka.extern.AbrConfiguration} */
87
88
  this.config_ = null;
89
+
90
+ /** @private {HTMLMediaElement} */
91
+ this.mediaElement_ = null;
92
+
93
+ /** @private {ResizeObserver} */
94
+ this.resizeObserver_ = null;
95
+
96
+ /** @private {shaka.util.Timer} */
97
+ this.resizeObserverTimer_ = new shaka.util.Timer(() => {
98
+ if (this.config_.restrictToElementSize) {
99
+ const chosenVariant = this.chooseVariant();
100
+ if (chosenVariant) {
101
+ this.switch_(chosenVariant);
102
+ }
103
+ }
104
+ });
88
105
  }
89
106
 
90
107
 
@@ -98,6 +115,14 @@ shaka.abr.SimpleAbrManager = class {
98
115
  this.variants_ = [];
99
116
  this.playbackRate_ = 1;
100
117
  this.lastTimeChosenMs_ = null;
118
+ this.mediaElement_ = null;
119
+
120
+ if (this.resizeObserver_) {
121
+ this.resizeObserver_.disconnect();
122
+ this.resizeObserver_ = null;
123
+ }
124
+
125
+ this.resizeObserverTimer_.stop();
101
126
 
102
127
  // Don't reset |startupComplete_|: if we've left the startup interval, we
103
128
  // can start using bandwidth estimates right away after init() is called.
@@ -120,9 +145,19 @@ shaka.abr.SimpleAbrManager = class {
120
145
  chooseVariant() {
121
146
  const SimpleAbrManager = shaka.abr.SimpleAbrManager;
122
147
 
148
+ let maxHeight = Infinity;
149
+ let maxWidth = Infinity;
150
+
151
+ if (this.resizeObserver_ && this.config_.restrictToElementSize) {
152
+ const devicePixelRatio =
153
+ this.config_.ignoreDevicePixelRatio ? 1 : window.devicePixelRatio;
154
+ maxHeight = this.mediaElement_.clientWidth * devicePixelRatio;
155
+ maxWidth = this.mediaElement_.clientHeight * devicePixelRatio;
156
+ }
157
+
123
158
  // Get sorted Variants.
124
159
  let sortedVariants = SimpleAbrManager.filterAndSortVariants_(
125
- this.config_.restrictions, this.variants_);
160
+ this.config_.restrictions, this.variants_, maxHeight, maxWidth);
126
161
 
127
162
  const defaultBandwidthEstimate = this.getDefaultBandwidth_();
128
163
  const currentBandwidth = this.bandwidthEstimator_.getBandwidthEstimate(
@@ -137,7 +172,8 @@ shaka.abr.SimpleAbrManager = class {
137
172
  shaka.log.warning('No variants met the ABR restrictions. ' +
138
173
  'Choosing a variant by lowest bandwidth.');
139
174
  sortedVariants = SimpleAbrManager.filterAndSortVariants_(
140
- /* restrictions= */ null, this.variants_);
175
+ /* restrictions= */ null, this.variants_,
176
+ /* maxHeight= */ Infinity, /* maxWidth= */ Infinity);
141
177
  sortedVariants = [sortedVariants[0]];
142
178
  }
143
179
 
@@ -243,6 +279,28 @@ shaka.abr.SimpleAbrManager = class {
243
279
  }
244
280
 
245
281
 
282
+ /**
283
+ * @override
284
+ * @export
285
+ */
286
+ setMediaElement(mediaElement) {
287
+ this.mediaElement_ = mediaElement;
288
+ if (this.resizeObserver_) {
289
+ this.resizeObserver_.disconnect();
290
+ this.resizeObserver_ = null;
291
+ }
292
+ if (this.mediaElement_ && 'ResizeObserver' in window) {
293
+ this.resizeObserver_ = new ResizeObserver(() => {
294
+ const SimpleAbrManager = shaka.abr.SimpleAbrManager;
295
+ // Batch up resize changes before checking them.
296
+ this.resizeObserverTimer_.tickAfter(
297
+ /* seconds= */ SimpleAbrManager.RESIZE_OBSERVER_BATCH_TIME);
298
+ });
299
+ this.resizeObserver_.observe(this.mediaElement_);
300
+ }
301
+ }
302
+
303
+
246
304
  /**
247
305
  * @override
248
306
  * @export
@@ -320,11 +378,13 @@ shaka.abr.SimpleAbrManager = class {
320
378
  /**
321
379
  * @param {?shaka.extern.Restrictions} restrictions
322
380
  * @param {!Array.<shaka.extern.Variant>} variants
381
+ * @param {!number} maxHeight
382
+ * @param {!number} maxWidth
323
383
  * @return {!Array.<shaka.extern.Variant>} variants filtered according to
324
384
  * |restrictions| and sorted in ascending order of bandwidth.
325
385
  * @private
326
386
  */
327
- static filterAndSortVariants_(restrictions, variants) {
387
+ static filterAndSortVariants_(restrictions, variants, maxHeight, maxWidth) {
328
388
  if (restrictions) {
329
389
  variants = variants.filter((variant) => {
330
390
  // This was already checked in another scope, but the compiler doesn't
@@ -333,7 +393,7 @@ shaka.abr.SimpleAbrManager = class {
333
393
 
334
394
  return shaka.util.StreamUtils.meetsRestrictions(
335
395
  variant, restrictions,
336
- /* maxHwRes= */ {width: Infinity, height: Infinity});
396
+ /* maxHwRes= */ {width: maxWidth, height: maxHeight});
337
397
  });
338
398
  }
339
399
 
@@ -342,3 +402,11 @@ shaka.abr.SimpleAbrManager = class {
342
402
  });
343
403
  }
344
404
  };
405
+
406
+
407
+ /**
408
+ * The amount of time, in seconds, we wait to batch up rapid resize changes.
409
+ * This allows us to avoid multiple resize events in most cases.
410
+ * @type {number}
411
+ */
412
+ shaka.abr.SimpleAbrManager.RESIZE_OBSERVER_BATCH_TIME = 1;
@@ -427,7 +427,7 @@ shaka.ads.ClientSideAdManager = class {
427
427
  onAdComplete_(e) {
428
428
  this.onEvent_(new shaka.util.FakeEvent(shaka.ads.AdManager.AD_STOPPED,
429
429
  (new Map()).set('originalEvent', e)));
430
- if (this.ad_.isLinear()) {
430
+ if (this.ad_ && this.ad_.isLinear()) {
431
431
  this.adContainer_.removeAttribute('ad-active');
432
432
  this.video_.play();
433
433
  }
@@ -513,6 +513,11 @@ shaka.dash.DashParser = class {
513
513
  }
514
514
  presentationTimeline.setClockOffset(offset);
515
515
  }
516
+
517
+ // This is the first point where we have a meaningful presentation start
518
+ // time, and we need to tell PresentationTimeline that so that it can
519
+ // maintain consistency from here on.
520
+ presentationTimeline.lockStartTime();
516
521
  } else {
517
522
  // Just update the variants and text streams, which may change as periods
518
523
  // are added or removed.