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,333 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ goog.provide('shaka.media.PreferenceBasedCriteria');
8
+
9
+ goog.require('shaka.config.CodecSwitchingStrategy');
10
+ goog.require('shaka.log');
11
+ goog.require('shaka.media.AdaptationSet');
12
+ goog.require('shaka.media.AdaptationSetCriteria');
13
+ goog.require('shaka.media.Capabilities');
14
+ goog.require('shaka.util.LanguageUtils');
15
+
16
+
17
+ /**
18
+ * @implements {shaka.media.AdaptationSetCriteria}
19
+ * @final
20
+ */
21
+ shaka.media.PreferenceBasedCriteria = class {
22
+ /** */
23
+ constructor() {
24
+ /** @private {?shaka.media.AdaptationSetCriteria.Configuration} */
25
+ this.config_ = null;
26
+ }
27
+
28
+ /**
29
+ * @override
30
+ */
31
+ configure(config) {
32
+ this.config_ = config;
33
+ }
34
+
35
+ /**
36
+ * @override
37
+ */
38
+ create(variants) {
39
+ const Class = shaka.media.PreferenceBasedCriteria;
40
+
41
+ let current = [];
42
+
43
+ const byLanguage = Class.filterByLanguage_(variants, this.config_.language);
44
+ const byPrimary = variants.filter((variant) => variant.primary);
45
+
46
+ if (byLanguage.length) {
47
+ current = byLanguage;
48
+ } else if (byPrimary.length) {
49
+ current = byPrimary;
50
+ } else {
51
+ current = variants;
52
+ }
53
+
54
+ // Now refine the choice based on role preference. Even the empty string
55
+ // works here, and will match variants without any roles.
56
+ const byRole = Class.filterVariantsByRole_(current, this.config_.role);
57
+ if (byRole.length) {
58
+ current = byRole;
59
+ } else {
60
+ shaka.log.warning('No exact match for variant role could be found.');
61
+ }
62
+
63
+ if (this.config_.videoLayout) {
64
+ const byVideoLayout = Class.filterVariantsByVideoLayout_(
65
+ current, this.config_.videoLayout);
66
+ if (byVideoLayout.length) {
67
+ current = byVideoLayout;
68
+ } else {
69
+ shaka.log.warning(
70
+ 'No exact match for the video layout could be found.');
71
+ }
72
+ }
73
+
74
+ if (this.config_.hdrLevel) {
75
+ const byHdrLevel = Class.filterVariantsByHDRLevel_(
76
+ current, this.config_.hdrLevel);
77
+ if (byHdrLevel.length) {
78
+ current = byHdrLevel;
79
+ } else {
80
+ shaka.log.warning(
81
+ 'No exact match for the hdr level could be found.');
82
+ }
83
+ }
84
+
85
+ if (this.config_.channelCount) {
86
+ const byChannel = Class.filterVariantsByAudioChannelCount_(
87
+ current, this.config_.channelCount);
88
+ if (byChannel.length) {
89
+ current = byChannel;
90
+ } else {
91
+ shaka.log.warning(
92
+ 'No exact match for the channel count could be found.');
93
+ }
94
+ }
95
+
96
+ if (this.config_.audioLabel) {
97
+ const byLabel = Class.filterVariantsByAudioLabel_(
98
+ current, this.config_.audioLabel);
99
+ if (byLabel.length) {
100
+ current = byLabel;
101
+ } else {
102
+ shaka.log.warning('No exact match for audio label could be found.');
103
+ }
104
+ }
105
+
106
+ if (this.config_.videoLabel) {
107
+ const byLabel = Class.filterVariantsByVideoLabel_(
108
+ current, this.config_.videoLabel);
109
+ if (byLabel.length) {
110
+ current = byLabel;
111
+ } else {
112
+ shaka.log.warning('No exact match for video label could be found.');
113
+ }
114
+ }
115
+
116
+ const bySpatialAudio = Class.filterVariantsBySpatialAudio_(
117
+ current, this.config_.spatialAudio);
118
+ if (bySpatialAudio.length) {
119
+ current = bySpatialAudio;
120
+ } else {
121
+ shaka.log.warning('No exact match for spatial audio could be found.');
122
+ }
123
+
124
+ if (this.config_.audioCodec) {
125
+ const byAudioCodec = Class.filterVariantsByAudioCodec_(
126
+ current, this.config_.audioCodec);
127
+ if (byAudioCodec.length) {
128
+ current = byAudioCodec;
129
+ } else {
130
+ shaka.log.warning('No exact match for audio codec could be found.');
131
+ }
132
+ }
133
+
134
+ const supportsSmoothCodecTransitions =
135
+ this.config_.codecSwitchingStrategy ==
136
+ shaka.config.CodecSwitchingStrategy.SMOOTH &&
137
+ shaka.media.Capabilities.isChangeTypeSupported();
138
+
139
+ return new shaka.media.AdaptationSet(current[0], current,
140
+ !supportsSmoothCodecTransitions);
141
+ }
142
+
143
+ /**
144
+ * @param {!Array<shaka.extern.Variant>} variants
145
+ * @param {string} preferredLanguage
146
+ * @return {!Array<shaka.extern.Variant>}
147
+ * @private
148
+ */
149
+ static filterByLanguage_(variants, preferredLanguage) {
150
+ const LanguageUtils = shaka.util.LanguageUtils;
151
+
152
+ /** @type {string} */
153
+ const preferredLocale = LanguageUtils.normalize(preferredLanguage);
154
+
155
+ /** @type {?string} */
156
+ const closestLocale = LanguageUtils.findClosestLocale(
157
+ preferredLocale,
158
+ variants.map((variant) => LanguageUtils.getLocaleForVariant(variant)));
159
+
160
+ // There were no locales close to what we preferred.
161
+ if (!closestLocale) {
162
+ return [];
163
+ }
164
+
165
+ // Find the variants that use the closest variant.
166
+ return variants.filter((variant) => {
167
+ return closestLocale == LanguageUtils.getLocaleForVariant(variant);
168
+ });
169
+ }
170
+
171
+ /**
172
+ * Filter Variants by role.
173
+ *
174
+ * @param {!Array<shaka.extern.Variant>} variants
175
+ * @param {string} preferredRole
176
+ * @return {!Array<shaka.extern.Variant>}
177
+ * @private
178
+ */
179
+ static filterVariantsByRole_(variants, preferredRole) {
180
+ return variants.filter((variant) => {
181
+ if (!variant.audio) {
182
+ return false;
183
+ }
184
+
185
+ if (preferredRole) {
186
+ return variant.audio.roles.includes(preferredRole);
187
+ } else {
188
+ return variant.audio.roles.length == 0;
189
+ }
190
+ });
191
+ }
192
+
193
+ /**
194
+ * Filter Variants by audio label.
195
+ *
196
+ * @param {!Array<shaka.extern.Variant>} variants
197
+ * @param {string} preferredLabel
198
+ * @return {!Array<shaka.extern.Variant>}
199
+ * @private
200
+ */
201
+ static filterVariantsByAudioLabel_(variants, preferredLabel) {
202
+ return variants.filter((variant) => {
203
+ if (!variant.audio || !variant.audio.label) {
204
+ return false;
205
+ }
206
+
207
+ const label1 = variant.audio.label.toLowerCase();
208
+ const label2 = preferredLabel.toLowerCase();
209
+ return label1 == label2;
210
+ });
211
+ }
212
+
213
+ /**
214
+ * Filter Variants by video label.
215
+ *
216
+ * @param {!Array<shaka.extern.Variant>} variants
217
+ * @param {string} preferredLabel
218
+ * @return {!Array<shaka.extern.Variant>}
219
+ * @private
220
+ */
221
+ static filterVariantsByVideoLabel_(variants, preferredLabel) {
222
+ return variants.filter((variant) => {
223
+ if (!variant.video || !variant.video.label) {
224
+ return false;
225
+ }
226
+
227
+ const label1 = variant.video.label.toLowerCase();
228
+ const label2 = preferredLabel.toLowerCase();
229
+ return label1 == label2;
230
+ });
231
+ }
232
+
233
+ /**
234
+ * Filter Variants by channelCount.
235
+ *
236
+ * @param {!Array<shaka.extern.Variant>} variants
237
+ * @param {number} channelCount
238
+ * @return {!Array<shaka.extern.Variant>}
239
+ * @private
240
+ */
241
+ static filterVariantsByAudioChannelCount_(variants, channelCount) {
242
+ return variants.filter((variant) => {
243
+ if (variant.audio && variant.audio.channelsCount &&
244
+ variant.audio.channelsCount != channelCount) {
245
+ return false;
246
+ }
247
+ return true;
248
+ });
249
+ }
250
+
251
+ /**
252
+ * Filters variants according to the given hdr level config.
253
+ *
254
+ * @param {!Array<shaka.extern.Variant>} variants
255
+ * @param {string} hdrLevel
256
+ * @private
257
+ */
258
+ static filterVariantsByHDRLevel_(variants, hdrLevel) {
259
+ if (hdrLevel == 'AUTO') {
260
+ // Auto detect the ideal HDR level.
261
+ if (window.matchMedia('(color-gamut: p3)').matches) {
262
+ const someHLG = variants.some((variant) => {
263
+ if (variant.video && variant.video.hdr &&
264
+ variant.video.hdr == 'HLG') {
265
+ return true;
266
+ }
267
+ return false;
268
+ });
269
+ hdrLevel = someHLG ? 'HLG' : 'PQ';
270
+ } else {
271
+ hdrLevel = 'SDR';
272
+ }
273
+ }
274
+ return variants.filter((variant) => {
275
+ if (variant.video && variant.video.hdr && variant.video.hdr != hdrLevel) {
276
+ return false;
277
+ }
278
+ return true;
279
+ });
280
+ }
281
+
282
+
283
+ /**
284
+ * Filters variants according to the given video layout config.
285
+ *
286
+ * @param {!Array<shaka.extern.Variant>} variants
287
+ * @param {string} videoLayout
288
+ * @private
289
+ */
290
+ static filterVariantsByVideoLayout_(variants, videoLayout) {
291
+ return variants.filter((variant) => {
292
+ if (variant.video && variant.video.videoLayout &&
293
+ variant.video.videoLayout != videoLayout) {
294
+ return false;
295
+ }
296
+ return true;
297
+ });
298
+ }
299
+
300
+
301
+ /**
302
+ * Filters variants according to the given spatial audio config.
303
+ *
304
+ * @param {!Array<shaka.extern.Variant>} variants
305
+ * @param {boolean} spatialAudio
306
+ * @private
307
+ */
308
+ static filterVariantsBySpatialAudio_(variants, spatialAudio) {
309
+ return variants.filter((variant) => {
310
+ if (variant.audio && variant.audio.spatialAudio != spatialAudio) {
311
+ return false;
312
+ }
313
+ return true;
314
+ });
315
+ }
316
+
317
+
318
+ /**
319
+ * Filters variants according to the given audio codec.
320
+ *
321
+ * @param {!Array<shaka.extern.Variant>} variants
322
+ * @param {string} audioCodec
323
+ * @private
324
+ */
325
+ static filterVariantsByAudioCodec_(variants, audioCodec) {
326
+ return variants.filter((variant) => {
327
+ if (variant.audio && variant.audio.codecs != audioCodec) {
328
+ return false;
329
+ }
330
+ return true;
331
+ });
332
+ }
333
+ };
@@ -7,28 +7,26 @@
7
7
  goog.provide('shaka.media.PreloadManager');
8
8
 
9
9
  goog.require('goog.asserts');
10
+ goog.require('shaka.drm.DrmEngine');
10
11
  goog.require('shaka.log');
11
- goog.require('shaka.util.Error');
12
+ goog.require('shaka.media.AdaptationSetCriteria');
12
13
  goog.require('shaka.media.ManifestFilterer');
13
14
  goog.require('shaka.media.ManifestParser');
14
- goog.require('shaka.util.PublicPromise');
15
- goog.require('shaka.media.PreferenceBasedCriteria');
16
- goog.require('shaka.util.Stats');
17
- goog.require('shaka.media.SegmentPrefetch');
18
- goog.require('shaka.util.IDestroyable');
19
- goog.require('shaka.net.NetworkingEngine');
20
- goog.require('shaka.media.AdaptationSetCriteria');
21
- goog.require('shaka.media.DrmEngine');
22
- goog.require('shaka.media.RegionTimeline');
23
15
  goog.require('shaka.media.QualityObserver');
24
- goog.require('shaka.util.StreamUtils');
25
- goog.require('shaka.media.StreamingEngine');
16
+ goog.require('shaka.media.RegionTimeline');
26
17
  goog.require('shaka.media.SegmentPrefetch');
18
+ goog.require('shaka.media.StreamingEngine');
19
+ goog.require('shaka.net.NetworkingEngine');
27
20
  goog.require('shaka.util.ConfigUtils');
21
+ goog.require('shaka.util.Error');
28
22
  goog.require('shaka.util.FakeEvent');
29
23
  goog.require('shaka.util.FakeEventTarget');
24
+ goog.require('shaka.util.IDestroyable');
30
25
  goog.require('shaka.util.ObjectUtils');
31
26
  goog.require('shaka.util.PlayerConfiguration');
27
+ goog.require('shaka.util.PublicPromise');
28
+ goog.require('shaka.util.Stats');
29
+ goog.require('shaka.util.StreamUtils');
32
30
 
33
31
  /**
34
32
  * @implements {shaka.util.IDestroyable}
@@ -69,7 +67,7 @@ shaka.media.PreloadManager = class extends shaka.util.FakeEventTarget {
69
67
  /** @private {number} */
70
68
  this.startTimeOfDrm_ = 0;
71
69
 
72
- /** @private {function():!shaka.media.DrmEngine} */
70
+ /** @private {function():!shaka.drm.DrmEngine} */
73
71
  this.createDrmEngine_ = typedPlayerInterface.createDrmEngine;
74
72
 
75
73
  /** @private {!shaka.media.ManifestFilterer} */
@@ -100,7 +98,7 @@ shaka.media.PreloadManager = class extends shaka.util.FakeEventTarget {
100
98
  /** @private {boolean} */
101
99
  this.regionTimelineEntrusted_ = false;
102
100
 
103
- /** @private {?shaka.media.DrmEngine} */
101
+ /** @private {?shaka.drm.DrmEngine} */
104
102
  this.drmEngine_ = null;
105
103
 
106
104
  /** @private {boolean} */
@@ -115,7 +113,7 @@ shaka.media.PreloadManager = class extends shaka.util.FakeEventTarget {
115
113
  /** @private {boolean} */
116
114
  this.abrManagerEntrusted_ = false;
117
115
 
118
- /** @private {!Map.<number, shaka.media.SegmentPrefetch>} */
116
+ /** @private {!Map<number, shaka.media.SegmentPrefetch>} */
119
117
  this.segmentPrefetchById_ = new Map();
120
118
 
121
119
  /** @private {boolean} */
@@ -151,10 +149,10 @@ shaka.media.PreloadManager = class extends shaka.util.FakeEventTarget {
151
149
  /** @private {boolean} */
152
150
  this.hasBeenAttached_ = false;
153
151
 
154
- /** @private {?Array.<function()>} */
152
+ /** @private {?Array<function()>} */
155
153
  this.queuedOperations_ = [];
156
154
 
157
- /** @private {?Array.<function()>} */
155
+ /** @private {?Array<function()>} */
158
156
  this.latePhaseQueuedOperations_ = [];
159
157
 
160
158
  /** @private {boolean} */
@@ -322,7 +320,7 @@ shaka.media.PreloadManager = class extends shaka.util.FakeEventTarget {
322
320
  /**
323
321
  * Gets the drm engine, if it exists. Also marks that the drm engine should
324
322
  * not be destroyed if this manager is destroyed.
325
- * @return {?shaka.media.DrmEngine}
323
+ * @return {?shaka.drm.DrmEngine}
326
324
  */
327
325
  receiveDrmEngine() {
328
326
  this.drmEngineEntrusted_ = true;
@@ -330,7 +328,7 @@ shaka.media.PreloadManager = class extends shaka.util.FakeEventTarget {
330
328
  }
331
329
 
332
330
  /**
333
- * @return {?shaka.media.DrmEngine}
331
+ * @return {?shaka.drm.DrmEngine}
334
332
  */
335
333
  getDrmEngine() {
336
334
  return this.drmEngine_;
@@ -346,7 +344,7 @@ shaka.media.PreloadManager = class extends shaka.util.FakeEventTarget {
346
344
  /**
347
345
  * Gets the SegmentPrefetch objects for the initial stream ids. Also marks
348
346
  * that those objects should not be aborted if this manager is destroyed.
349
- * @return {!Map.<number, shaka.media.SegmentPrefetch>}
347
+ * @return {!Map<number, shaka.media.SegmentPrefetch>}
350
348
  */
351
349
  receiveSegmentPrefetchesById() {
352
350
  this.segmentPrefetchEntrusted_ = true;
@@ -478,7 +476,7 @@ shaka.media.PreloadManager = class extends shaka.util.FakeEventTarget {
478
476
 
479
477
  /**
480
478
  * @param {!shaka.util.FakeEvent.EventName} name
481
- * @param {Map.<string, Object>=} data
479
+ * @param {Map<string, Object>=} data
482
480
  * @return {!shaka.util.FakeEvent}
483
481
  * @private
484
482
  */
@@ -513,6 +511,19 @@ shaka.media.PreloadManager = class extends shaka.util.FakeEventTarget {
513
511
  if (!this.manifest_) {
514
512
  this.manifest_ = await this.parser_.start(
515
513
  this.assetUri_, this.manifestPlayerInterface_);
514
+
515
+ if (this.manifest_.variants.length == 1) {
516
+ const createSegmentIndexPromises = [];
517
+ const variant = this.manifest_.variants[0];
518
+ for (const stream of [variant.video, variant.audio]) {
519
+ if (stream && !stream.segmentIndex) {
520
+ createSegmentIndexPromises.push(stream.createSegmentIndex());
521
+ }
522
+ }
523
+ if (createSegmentIndexPromises.length > 0) {
524
+ await Promise.all(createSegmentIndexPromises);
525
+ }
526
+ }
516
527
  }
517
528
 
518
529
  this.manifestPromise_.resolve();
@@ -632,17 +643,20 @@ shaka.media.PreloadManager = class extends shaka.util.FakeEventTarget {
632
643
  // Copy preferred languages from the config again, in case the config was
633
644
  // changed between construction and playback.
634
645
  this.currentAdaptationSetCriteria_ =
635
- new shaka.media.PreferenceBasedCriteria(
636
- this.config_.preferredAudioLanguage,
637
- this.config_.preferredVariantRole,
638
- this.config_.preferredAudioChannelCount,
639
- this.config_.preferredVideoHdrLevel,
640
- this.config_.preferSpatialAudio,
641
- this.config_.preferredVideoLayout,
642
- this.config_.preferredAudioLabel,
643
- this.config_.preferredVideoLabel,
644
- this.config_.mediaSource.codecSwitchingStrategy,
645
- /* audioCodec= */ '');
646
+ this.config_.adaptationSetCriteriaFactory();
647
+ this.currentAdaptationSetCriteria_.configure({
648
+ language: this.config_.preferredAudioLanguage,
649
+ role: this.config_.preferredVariantRole,
650
+ channelCount: this.config_.preferredAudioChannelCount,
651
+ hdrLevel: this.config_.preferredVideoHdrLevel,
652
+ spatialAudio: this.config_.preferSpatialAudio,
653
+ videoLayout: this.config_.preferredVideoLayout,
654
+ audioLabel: this.config_.preferredAudioLabel,
655
+ videoLabel: this.config_.preferredVideoLabel,
656
+ codecSwitchingStrategy:
657
+ this.config_.mediaSource.codecSwitchingStrategy,
658
+ audioCodec: '',
659
+ });
646
660
  }
647
661
 
648
662
  // Make the ABR manager.
@@ -699,7 +713,9 @@ shaka.media.PreloadManager = class extends shaka.util.FakeEventTarget {
699
713
  this.segmentPrefetchById_.set(stream.id, prefetch);
700
714
 
701
715
  // Start prefetching a bit.
702
- await stream.createSegmentIndex();
716
+ if (!stream.segmentIndex) {
717
+ await stream.createSegmentIndex();
718
+ }
703
719
  const startTime = this.startTime_ || 0;
704
720
  const prefetchSegmentIterator =
705
721
  stream.segmentIndex.getIteratorForTime(startTime);
@@ -823,7 +839,7 @@ shaka.media.PreloadManager = class extends shaka.util.FakeEventTarget {
823
839
  * manifestPlayerInterface: !shaka.extern.ManifestParser.PlayerInterface,
824
840
  * regionTimeline: !shaka.media.RegionTimeline,
825
841
  * qualityObserver: ?shaka.media.QualityObserver,
826
- * createDrmEngine: function():!shaka.media.DrmEngine,
842
+ * createDrmEngine: function():!shaka.drm.DrmEngine,
827
843
  * networkingEngine: !shaka.net.NetworkingEngine,
828
844
  * manifestFilterer: !shaka.media.ManifestFilterer,
829
845
  * allowPrefetch: boolean,
@@ -831,11 +847,11 @@ shaka.media.PreloadManager = class extends shaka.util.FakeEventTarget {
831
847
  * }}
832
848
  *
833
849
  * @property {!shaka.extern.PlayerConfiguration} config
834
- * @property {!shaka.extern.ManifestParser.PlayerInterface}
835
- * manifestPlayerInterface
850
+ * @property {!shaka.extern.ManifestParser.PlayerInterface
851
+ * } manifestPlayerInterface
836
852
  * @property {!shaka.media.RegionTimeline} regionTimeline
837
853
  * @property {?shaka.media.QualityObserver} qualityObserver
838
- * @property {function():!shaka.media.DrmEngine} createDrmEngine
854
+ * @property {function():!shaka.drm.DrmEngine} createDrmEngine
839
855
  * @property {!shaka.net.NetworkingEngine} networkingEngine
840
856
  * @property {!shaka.media.ManifestFilterer} manifestFilterer
841
857
  * @property {boolean} allowPrefetch
@@ -244,7 +244,7 @@ shaka.media.PresentationTimeline = class {
244
244
  * the segment availability window, and account for missing segment
245
245
  * information.
246
246
  *
247
- * @param {!Array.<shaka.media.PresentationTimeline.TimeRange>} timeline
247
+ * @param {!Array<shaka.media.PresentationTimeline.TimeRange>} timeline
248
248
  * @param {number} startOffset
249
249
  * @export
250
250
  */
@@ -294,7 +294,7 @@ shaka.media.PresentationTimeline = class {
294
294
  * information. These segments do not necessarily need to all be from the
295
295
  * same stream.
296
296
  *
297
- * @param {!Array.<!shaka.media.SegmentReference>} references
297
+ * @param {!Array<!shaka.media.SegmentReference>} references
298
298
  * @export
299
299
  */
300
300
  notifySegments(references) {
@@ -32,7 +32,7 @@ shaka.media.QualityObserver = class extends shaka.util.FakeEventTarget {
32
32
  super();
33
33
 
34
34
  /**
35
- * @private {!Map.<string,!shaka.media.QualityObserver.ContentTypeState>}
35
+ * @private {!Map<string, !shaka.media.QualityObserver.ContentTypeState>}
36
36
  */
37
37
  this.contentTypeStates_ = new Map();
38
38
 
@@ -47,7 +47,7 @@ shaka.media.QualityObserver = class extends shaka.util.FakeEventTarget {
47
47
  }
48
48
 
49
49
  /**
50
- * Get the ContenTypeState for a contentType, creating a new
50
+ * Get the ContentTypeState for a contentType, creating a new
51
51
  * one if necessary.
52
52
  *
53
53
  * @param {!string} contentType
@@ -301,40 +301,40 @@ shaka.media.QualityObserver = class extends shaka.util.FakeEventTarget {
301
301
  };
302
302
 
303
303
  /**
304
- * @typedef {{
305
- * mediaQuality: !shaka.extern.MediaQualityInfo,
306
- * position: !number
307
- * }}
308
- *
309
- * @description
310
- * Identifies the position of a media quality change in the
311
- * source buffer.
312
- *
313
- * @property {shaka.extern.MediaQualityInfo} !mediaQuality
314
- * The new media quality for content after position in the source buffer.
315
- * @property {number} !position
316
- * A position in seconds in the source buffer
317
- */
304
+ * @typedef {{
305
+ * mediaQuality: !shaka.extern.MediaQualityInfo,
306
+ * position: !number
307
+ * }}
308
+ *
309
+ * @description
310
+ * Identifies the position of a media quality change in the
311
+ * source buffer.
312
+ *
313
+ * @property {!shaka.extern.MediaQualityInfo} mediaQuality
314
+ * The new media quality for content after position in the source buffer.
315
+ * @property {!number} position
316
+ * A position in seconds in the source buffer
317
+ */
318
318
  shaka.media.QualityObserver.QualityChangePosition;
319
319
 
320
320
  /**
321
- * @typedef {{
322
- * qualityChangePositions:
323
- * !Array.<shaka.media.QualityObserver.QualityChangePosition>,
324
- * currentQuality: ?shaka.extern.MediaQualityInfo,
325
- * contentType: !string
326
- * }}
327
- *
328
- * @description
329
- * Contains media quality information for a specific content type
330
- * e.g. video or audio.
331
- *
332
- * @property {!Array.<shaka.media.QualityObserver.QualityChangePosition>}
333
- * qualityChangePositions
334
- * Quality changes ordered by position ascending.
335
- * @property {?shaka.media.MediaQualityInfo} currentMediaQuality
336
- * The media quality at the playhead position.
337
- * @property {string} contentType
338
- * The contentType e.g. 'video' or 'audio'
339
- */
321
+ * @typedef {{
322
+ * qualityChangePositions:
323
+ * !Array<shaka.media.QualityObserver.QualityChangePosition>,
324
+ * currentQuality: ?shaka.extern.MediaQualityInfo,
325
+ * contentType: !string
326
+ * }}
327
+ *
328
+ * @description
329
+ * Contains media quality information for a specific content type
330
+ * e.g. video or audio.
331
+ *
332
+ * @property {!Array<shaka.media.QualityObserver.QualityChangePosition>
333
+ * } qualityChangePositions
334
+ * Quality changes ordered by position ascending.
335
+ * @property {?shaka.media.MediaQualityInfo} currentMediaQuality
336
+ * The media quality at the playhead position.
337
+ * @property {string} contentType
338
+ * The contentType e.g. 'video' or 'audio'
339
+ */
340
340
  shaka.media.QualityObserver.ContentTypeState;
@@ -50,7 +50,7 @@ shaka.media.RegionObserver = class extends shaka.util.FakeEventTarget {
50
50
  * When the value here differs from what we calculate, it means we moved and
51
51
  * should fire an event.
52
52
  *
53
- * @private {!Map.<shaka.extern.TimelineRegionInfo,
53
+ * @private {!Map<shaka.extern.TimelineRegionInfo,
54
54
  * shaka.media.RegionObserver.RelativePosition_>}
55
55
  */
56
56
  this.oldPosition_ = new Map();
@@ -65,7 +65,7 @@ shaka.media.RegionObserver = class extends shaka.util.FakeEventTarget {
65
65
  * A read-only collection of rules for what to do when we change position
66
66
  * relative to a region.
67
67
  *
68
- * @private {!Iterable.<shaka.media.RegionObserver.Rule_>}
68
+ * @private {!Iterable<shaka.media.RegionObserver.Rule_>}
69
69
  */
70
70
  this.rules_ = [
71
71
  {
@@ -27,7 +27,7 @@ shaka.media.RegionTimeline = class extends shaka.util.FakeEventTarget {
27
27
  constructor(getSeekRange) {
28
28
  super();
29
29
 
30
- /** @private {!Set.<shaka.extern.TimelineRegionInfo>} */
30
+ /** @private {!Set<shaka.extern.TimelineRegionInfo>} */
31
31
  this.regions_ = new Set();
32
32
 
33
33
  /** @private {!function():{start: number, end: number}} */
@@ -80,7 +80,7 @@ shaka.media.RegionTimeline = class extends shaka.util.FakeEventTarget {
80
80
  // Future regions might become relevant eventually,
81
81
  // but regions that are in the past and can't ever be
82
82
  // seeked to will never come up again, and there's no
83
- // reson to store or process them.
83
+ // reason to store or process them.
84
84
  if (region.endTime < seekRange.start) {
85
85
  this.regions_.delete(region);
86
86
  const event = new shaka.util.FakeEvent('regionremove', new Map([
@@ -123,7 +123,7 @@ shaka.media.RegionTimeline = class extends shaka.util.FakeEventTarget {
123
123
  * others to see what regions are in the timeline while not being able to
124
124
  * change the collection.
125
125
  *
126
- * @return {!Iterable.<shaka.extern.TimelineRegionInfo>}
126
+ * @return {!Iterable<shaka.extern.TimelineRegionInfo>}
127
127
  */
128
128
  regions() {
129
129
  return this.regions_;