shaka-player 4.12.9 → 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.
- package/AUTHORS +1 -0
- package/CONTRIBUTORS +4 -0
- package/README.md +22 -21
- package/cspell.config.yaml +18 -0
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/deps.js +29 -24
- package/dist/locales.js +36 -36
- package/dist/shaka-player.compiled.d.ts +131 -36
- package/dist/shaka-player.compiled.debug.d.ts +131 -36
- package/dist/shaka-player.compiled.debug.externs.js +355 -107
- package/dist/shaka-player.compiled.debug.js +799 -742
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +355 -107
- package/dist/shaka-player.compiled.js +1456 -1423
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +165 -38
- package/dist/shaka-player.ui.debug.d.ts +165 -38
- package/dist/shaka-player.ui.debug.externs.js +394 -113
- package/dist/shaka-player.ui.debug.js +808 -738
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +394 -113
- package/dist/shaka-player.ui.js +1671 -1632
- package/dist/shaka-player.ui.map +4 -4
- package/eslint.config.mjs +343 -0
- package/externs/airplay.js +1 -1
- package/externs/audiotrack.js +1 -1
- package/externs/awesomplete.js +1 -1
- package/externs/cast-sdk-v2.js +2 -2
- package/externs/cmcd.js +16 -1
- package/externs/device_sensor_event.js +1 -1
- package/externs/ima.js +8 -8
- package/externs/isoboxer.js +31 -31
- package/externs/jwk_set.js +1 -1
- package/externs/lcevc.js +8 -8
- package/externs/mediakeys.js +1 -1
- package/externs/mediasession.js +3 -2
- package/externs/mediatailor.js +18 -18
- package/externs/pictureinpicture.js +41 -1
- package/externs/playstation.js +2 -2
- package/externs/prefixed_eme.js +1 -1
- package/externs/shaka/abortable.js +4 -4
- package/externs/shaka/abr_manager.js +1 -1
- package/externs/shaka/ads.js +45 -6
- package/externs/shaka/cea.js +2 -2
- package/externs/shaka/codecs.js +4 -4
- package/externs/shaka/drm_info.js +6 -6
- package/externs/shaka/error.js +5 -5
- package/externs/shaka/manifest.js +51 -56
- package/externs/shaka/manifest_parser.js +3 -9
- package/externs/shaka/net.js +23 -20
- package/externs/shaka/offline.js +37 -37
- package/externs/shaka/offline_compat_v1.js +10 -10
- package/externs/shaka/offline_compat_v2.js +10 -10
- package/externs/shaka/player.js +137 -108
- package/externs/shaka/text.js +3 -3
- package/externs/shaka/transmuxer.js +1 -1
- package/externs/videotrack.js +1 -1
- package/lib/abr/ewma.js +1 -1
- package/lib/abr/simple_abr_manager.js +70 -22
- package/lib/ads/ad_manager.js +43 -18
- package/lib/ads/ad_utils.js +160 -58
- package/lib/ads/ads_stats.js +1 -1
- package/lib/ads/client_side_ad_manager.js +2 -2
- package/lib/ads/interstitial_ad.js +16 -11
- package/lib/ads/interstitial_ad_manager.js +419 -72
- package/lib/ads/interstitial_static_ad.js +299 -0
- package/lib/ads/media_tailor_ad.js +1 -0
- package/lib/ads/media_tailor_ad_manager.js +37 -36
- package/lib/ads/server_side_ad_manager.js +7 -6
- package/lib/cast/cast_receiver.js +5 -3
- package/lib/cast/cast_sender.js +2 -2
- package/lib/cast/cast_utils.js +20 -13
- package/lib/cea/cea608_data_channel.js +53 -53
- package/lib/cea/cea708_service.js +34 -24
- package/lib/cea/cea708_window.js +5 -2
- package/lib/cea/cea_decoder.js +5 -7
- package/lib/cea/mp4_cea_parser.js +1 -1
- package/lib/cea/sei_processor.js +1 -1
- package/lib/dash/content_protection.js +62 -192
- package/lib/dash/dash_parser.js +98 -108
- package/lib/dash/mpd_utils.js +14 -13
- package/lib/dash/segment_base.js +5 -5
- package/lib/dash/segment_list.js +10 -10
- package/lib/dash/segment_template.js +14 -14
- package/lib/debug/log.js +2 -2
- package/lib/dependencies/all.js +2 -1
- package/lib/{media → drm}/drm_engine.js +274 -143
- package/lib/{util → drm}/drm_utils.js +20 -11
- package/lib/drm/playready.js +233 -0
- package/lib/hls/hls_classes.js +14 -14
- package/lib/hls/hls_parser.js +257 -196
- package/lib/hls/hls_utils.js +14 -14
- package/lib/hls/manifest_text_parser.js +10 -10
- package/lib/media/adaptation_set.js +6 -5
- package/lib/media/adaptation_set_criteria.js +51 -379
- package/lib/media/buffering_observer.js +5 -4
- package/lib/media/closed_caption_parser.js +2 -2
- package/lib/media/content_workarounds.js +2 -2
- package/lib/media/example_based_criteria.js +69 -0
- package/lib/media/manifest_filterer.js +8 -8
- package/lib/media/manifest_parser.js +2 -2
- package/lib/media/media_source_capabilities.js +20 -1
- package/lib/media/media_source_engine.js +71 -26
- package/lib/media/mp4_segment_index_parser.js +5 -5
- package/lib/media/playhead.js +2 -8
- package/lib/media/playhead_observer.js +1 -1
- package/lib/media/preference_based_criteria.js +333 -0
- package/lib/media/preload_manager.js +53 -37
- package/lib/media/presentation_timeline.js +2 -2
- package/lib/media/quality_observer.js +35 -35
- package/lib/media/region_observer.js +2 -2
- package/lib/media/region_timeline.js +3 -3
- package/lib/media/segment_index.js +14 -14
- package/lib/media/segment_prefetch.js +17 -13
- package/lib/media/segment_reference.js +7 -7
- package/lib/media/segment_utils.js +9 -9
- package/lib/media/streaming_engine.js +77 -38
- package/lib/media/time_ranges_utils.js +1 -1
- package/lib/media/video_wrapper.js +1 -1
- package/lib/media/webm_segment_index_parser.js +4 -4
- package/lib/mss/content_protection.js +17 -222
- package/lib/mss/mss_parser.js +23 -24
- package/lib/net/data_uri_plugin.js +1 -0
- package/lib/net/http_fetch_plugin.js +8 -7
- package/lib/net/http_plugin_utils.js +5 -2
- package/lib/net/http_xhr_plugin.js +4 -3
- package/lib/net/networking_engine.js +72 -17
- package/lib/net/networking_utils.js +5 -2
- package/lib/offline/download_info.js +5 -1
- package/lib/offline/download_manager.js +15 -4
- package/lib/offline/download_progress_estimator.js +1 -1
- package/lib/offline/indexeddb/base_storage_cell.js +9 -9
- package/lib/offline/indexeddb/db_connection.js +1 -1
- package/lib/offline/indexeddb/db_operation.js +2 -2
- package/lib/offline/indexeddb/eme_session_storage_cell.js +1 -1
- package/lib/offline/indexeddb/storage_mechanism.js +1 -1
- package/lib/offline/indexeddb/v1_storage_cell.js +3 -3
- package/lib/offline/indexeddb/v2_storage_cell.js +2 -2
- package/lib/offline/manifest_converter.js +11 -12
- package/lib/offline/offline_scheme.js +8 -4
- package/lib/offline/session_deleter.js +11 -11
- package/lib/offline/storage.js +137 -88
- package/lib/offline/storage_muxer.js +8 -8
- package/lib/offline/stored_content_utils.js +3 -3
- package/lib/offline/stream_bandwidth_estimator.js +1 -1
- package/lib/player.js +270 -207
- package/lib/polyfill/all.js +1 -1
- package/lib/polyfill/media_capabilities.js +5 -5
- package/lib/polyfill/patchedmediakeys_apple.js +6 -6
- package/lib/polyfill/patchedmediakeys_webkit.js +8 -8
- package/lib/polyfill/video_play_promise.js +0 -1
- package/lib/text/cue.js +3 -2
- package/lib/text/lrc_text_parser.js +1 -1
- package/lib/text/mp4_ttml_parser.js +1 -1
- package/lib/text/mp4_vtt_parser.js +3 -3
- package/lib/text/sbv_text_parser.js +1 -1
- package/lib/text/ssa_text_parser.js +3 -1
- package/lib/text/stub_text_displayer.js +5 -5
- package/lib/text/text_engine.js +5 -4
- package/lib/text/text_utils.js +4 -4
- package/lib/text/ttml_text_parser.js +21 -20
- package/lib/text/ui_text_displayer.js +13 -13
- package/lib/text/vtt_text_parser.js +10 -10
- package/lib/text/web_vtt_generator.js +2 -2
- package/lib/transmuxer/aac_transmuxer.js +2 -2
- package/lib/transmuxer/ac3_transmuxer.js +2 -2
- package/lib/transmuxer/adts.js +2 -0
- package/lib/transmuxer/ec3.js +3 -3
- package/lib/transmuxer/ec3_transmuxer.js +2 -2
- package/lib/transmuxer/h264.js +5 -5
- package/lib/transmuxer/h265.js +3 -3
- package/lib/transmuxer/mp3_transmuxer.js +2 -2
- package/lib/transmuxer/mpeg_audio.js +6 -6
- package/lib/transmuxer/mss_transmuxer.js +2 -0
- package/lib/transmuxer/transmuxer_engine.js +1 -1
- package/lib/transmuxer/ts_transmuxer.js +10 -10
- package/lib/util/abortable_operation.js +10 -10
- package/lib/util/array_utils.js +6 -6
- package/lib/util/cmcd_manager.js +149 -18
- package/lib/util/cmsd_manager.js +11 -11
- package/lib/util/config_utils.js +3 -3
- package/lib/util/content_steering_manager.js +17 -17
- package/lib/util/data_view_reader.js +3 -3
- package/lib/util/ebml_parser.js +1 -1
- package/lib/util/error.js +11 -6
- package/lib/util/event_manager.js +1 -1
- package/lib/util/exp_golomb.js +1 -1
- package/lib/util/fairplay_utils.js +6 -1
- package/lib/util/fake_event.js +3 -2
- package/lib/util/fake_event_target.js +1 -1
- package/lib/util/functional.js +8 -8
- package/lib/util/id3_utils.js +1 -1
- package/lib/util/iterables.js +6 -6
- package/lib/util/language_utils.js +17 -17
- package/lib/util/manifest_parser_utils.js +13 -13
- package/lib/util/map_utils.js +6 -6
- package/lib/util/media_ready_state_utils.js +1 -1
- package/lib/util/mime_utils.js +15 -4
- package/lib/util/mp4_box_parsers.js +5 -5
- package/lib/util/mp4_generator.js +31 -30
- package/lib/util/mp4_parser.js +2 -2
- package/lib/util/multi_map.js +5 -5
- package/lib/util/mutex.js +1 -1
- package/lib/util/networking.js +1 -1
- package/lib/util/object_utils.js +5 -1
- package/lib/util/operation_manager.js +1 -1
- package/lib/util/periods.js +24 -24
- package/lib/util/platform.js +8 -4
- package/lib/util/player_configuration.js +50 -17
- package/lib/util/pssh.js +34 -6
- package/lib/util/public_promise.js +2 -2
- package/lib/util/state_history.js +2 -2
- package/lib/util/stream_utils.js +138 -120
- package/lib/util/string_utils.js +4 -3
- package/lib/util/switch_history.js +2 -2
- package/lib/util/tXml.js +22 -17
- package/lib/util/text_parser.js +2 -2
- package/lib/util/timer.js +1 -1
- package/lib/util/ts_parser.js +22 -22
- package/lib/util/xml_utils.js +1 -0
- package/package.json +7 -4
- package/project-words.txt +485 -0
- package/shaka-player.uncompiled.js +1 -1
- package/third_party/closure-uri/uri.js +2 -2
- package/third_party/closure-uri/utils.js +2 -2
- package/third_party/language-mapping-list/language-mapping-list.js +1 -1
- package/ui/ad_statistics_button.js +9 -5
- package/ui/airplay_button.js +1 -0
- package/ui/audio_language_selection.js +2 -1
- package/ui/context_menu.js +2 -2
- package/ui/controls.js +7 -7
- package/ui/externs/ui.js +29 -21
- package/ui/externs/watermark.js +64 -0
- package/ui/fast_forward_button.js +1 -1
- package/ui/gl_matrix/matrix_4x4.js +11 -5
- package/ui/hidden_fast_forward_button.js +1 -1
- package/ui/hidden_seek_button.js +1 -1
- package/ui/language_utils.js +27 -26
- package/ui/less/buttons.less +2 -2
- package/ui/localization.js +21 -21
- package/ui/loop_button.js +2 -2
- package/ui/overflow_menu.js +2 -2
- package/ui/playback_rate_selection.js +1 -1
- package/ui/presentation_time.js +4 -1
- package/ui/range_element.js +2 -2
- package/ui/resolution_selection.js +42 -6
- package/ui/rewind_button.js +1 -1
- package/ui/seek_bar.js +5 -5
- package/ui/statistics_button.js +8 -4
- package/ui/text_selection.js +3 -2
- package/ui/ui.js +32 -2
- package/ui/vr_manager.js +3 -3
- package/ui/vr_utils.js +14 -14
- package/ui/vr_webgl.js +5 -5
- package/ui/watermark.js +313 -0
- package/.eslintignore +0 -4
- package/.eslintrc.js +0 -310
- package/lib/polyfill/patchedmediakeys_nop.js +0 -148
package/lib/hls/hls_parser.js
CHANGED
|
@@ -10,6 +10,9 @@ goog.provide('shaka.hls.HlsParser');
|
|
|
10
10
|
goog.require('goog.Uri');
|
|
11
11
|
goog.require('goog.asserts');
|
|
12
12
|
goog.require('shaka.abr.Ewma');
|
|
13
|
+
goog.require('shaka.drm.DrmUtils');
|
|
14
|
+
goog.require('shaka.drm.PlayReady');
|
|
15
|
+
goog.require('shaka.hls.Attribute');
|
|
13
16
|
goog.require('shaka.hls.ManifestTextParser');
|
|
14
17
|
goog.require('shaka.hls.Playlist');
|
|
15
18
|
goog.require('shaka.hls.PlaylistType');
|
|
@@ -22,12 +25,12 @@ goog.require('shaka.media.PresentationTimeline');
|
|
|
22
25
|
goog.require('shaka.media.QualityObserver');
|
|
23
26
|
goog.require('shaka.media.SegmentIndex');
|
|
24
27
|
goog.require('shaka.media.SegmentReference');
|
|
28
|
+
goog.require('shaka.media.SegmentUtils');
|
|
25
29
|
goog.require('shaka.net.DataUriPlugin');
|
|
26
30
|
goog.require('shaka.net.NetworkingEngine');
|
|
27
31
|
goog.require('shaka.net.NetworkingEngine.PendingRequest');
|
|
28
32
|
goog.require('shaka.util.ArrayUtils');
|
|
29
33
|
goog.require('shaka.util.BufferUtils');
|
|
30
|
-
goog.require('shaka.util.DrmUtils');
|
|
31
34
|
goog.require('shaka.util.ContentSteeringManager');
|
|
32
35
|
goog.require('shaka.util.Error');
|
|
33
36
|
goog.require('shaka.util.EventManager');
|
|
@@ -38,7 +41,6 @@ goog.require('shaka.util.MimeUtils');
|
|
|
38
41
|
goog.require('shaka.util.Networking');
|
|
39
42
|
goog.require('shaka.util.OperationManager');
|
|
40
43
|
goog.require('shaka.util.Pssh');
|
|
41
|
-
goog.require('shaka.media.SegmentUtils');
|
|
42
44
|
goog.require('shaka.util.Timer');
|
|
43
45
|
goog.require('shaka.util.TsParser');
|
|
44
46
|
goog.require('shaka.util.TXml');
|
|
@@ -68,12 +70,12 @@ shaka.hls.HlsParser = class {
|
|
|
68
70
|
/** @private {number} */
|
|
69
71
|
this.globalId_ = 1;
|
|
70
72
|
|
|
71
|
-
/** @private {!Map
|
|
73
|
+
/** @private {!Map<string, string>} */
|
|
72
74
|
this.globalVariables_ = new Map();
|
|
73
75
|
|
|
74
76
|
/**
|
|
75
77
|
* A map from group id to stream infos created from the media tags.
|
|
76
|
-
* @private {!Map
|
|
78
|
+
* @private {!Map<string, !Array<?shaka.hls.HlsParser.StreamInfo>>}
|
|
77
79
|
*/
|
|
78
80
|
this.groupIdToStreamInfosMap_ = new Map();
|
|
79
81
|
|
|
@@ -84,7 +86,7 @@ shaka.hls.HlsParser = class {
|
|
|
84
86
|
* This map stores those relationships.
|
|
85
87
|
* Only used during livestreams; we do not assume that VOD content is
|
|
86
88
|
* aligned in that way.
|
|
87
|
-
* @private {!Map
|
|
89
|
+
* @private {!Map<string, !Map<number, number>>}
|
|
88
90
|
*/
|
|
89
91
|
this.mediaSequenceToStartTimeByType_ = new Map();
|
|
90
92
|
|
|
@@ -102,7 +104,7 @@ shaka.hls.HlsParser = class {
|
|
|
102
104
|
*
|
|
103
105
|
* Used to avoid duplicates that vary only in their text stream.
|
|
104
106
|
*
|
|
105
|
-
* @private {!Set
|
|
107
|
+
* @private {!Set<string>}
|
|
106
108
|
*/
|
|
107
109
|
this.variantUriSet_ = new Set();
|
|
108
110
|
|
|
@@ -119,7 +121,7 @@ shaka.hls.HlsParser = class {
|
|
|
119
121
|
* createStreamInfoFromMediaTags_, createStreamInfoFromImageTag_ and
|
|
120
122
|
* createStreamInfoFromVariantTags_.
|
|
121
123
|
*
|
|
122
|
-
* @private {!Map
|
|
124
|
+
* @private {!Map<string, shaka.hls.HlsParser.StreamInfo>}
|
|
123
125
|
*/
|
|
124
126
|
this.uriToStreamInfosMap_ = new Map();
|
|
125
127
|
|
|
@@ -208,7 +210,8 @@ shaka.hls.HlsParser = class {
|
|
|
208
210
|
/** @private {number} */
|
|
209
211
|
this.lastTargetDuration_ = Infinity;
|
|
210
212
|
|
|
211
|
-
/**
|
|
213
|
+
/**
|
|
214
|
+
* Partial segments target duration.
|
|
212
215
|
* @private {number}
|
|
213
216
|
*/
|
|
214
217
|
this.partialTargetDuration_ = 0;
|
|
@@ -222,32 +225,35 @@ shaka.hls.HlsParser = class {
|
|
|
222
225
|
/** @private {shaka.util.OperationManager} */
|
|
223
226
|
this.operationManager_ = new shaka.util.OperationManager();
|
|
224
227
|
|
|
225
|
-
/**
|
|
228
|
+
/**
|
|
229
|
+
* A map from closed captions' group id, to a map of closed captions info.
|
|
226
230
|
* {group id -> {closed captions channel id -> language}}
|
|
227
|
-
* @private {Map
|
|
231
|
+
* @private {Map<string, Map<string, string>>}
|
|
228
232
|
*/
|
|
229
233
|
this.groupIdToClosedCaptionsMap_ = new Map();
|
|
230
234
|
|
|
231
|
-
/** @private {Map
|
|
235
|
+
/** @private {Map<string, string>} */
|
|
232
236
|
this.groupIdToCodecsMap_ = new Map();
|
|
233
237
|
|
|
234
|
-
/**
|
|
238
|
+
/**
|
|
239
|
+
* A cache mapping EXT-X-MAP tag info to the InitSegmentReference created
|
|
235
240
|
* from the tag.
|
|
236
241
|
* The key is a string combining the EXT-X-MAP tag's absolute uri, and
|
|
237
242
|
* its BYTERANGE if available.
|
|
238
|
-
* {!Map
|
|
243
|
+
* @private {!Map<string, !shaka.media.InitSegmentReference>}
|
|
244
|
+
*/
|
|
239
245
|
this.mapTagToInitSegmentRefMap_ = new Map();
|
|
240
246
|
|
|
241
|
-
/** @private {Map
|
|
247
|
+
/** @private {Map<string, !shaka.extern.aesKey>} */
|
|
242
248
|
this.aesKeyInfoMap_ = new Map();
|
|
243
249
|
|
|
244
|
-
/** @private {Map
|
|
250
|
+
/** @private {Map<string, !Promise<shaka.extern.Response>>} */
|
|
245
251
|
this.aesKeyMap_ = new Map();
|
|
246
252
|
|
|
247
|
-
/** @private {Map
|
|
253
|
+
/** @private {Map<string, !Promise<shaka.extern.Response>>} */
|
|
248
254
|
this.identityKeyMap_ = new Map();
|
|
249
255
|
|
|
250
|
-
/** @private {Map
|
|
256
|
+
/** @private {Map<!shaka.media.InitSegmentReference, ?string>} */
|
|
251
257
|
this.identityKidMap_ = new Map();
|
|
252
258
|
|
|
253
259
|
/** @private {boolean} */
|
|
@@ -269,7 +275,7 @@ shaka.hls.HlsParser = class {
|
|
|
269
275
|
/** @private {boolean} */
|
|
270
276
|
this.needsClosedCaptionsDetection_ = true;
|
|
271
277
|
|
|
272
|
-
/** @private {Set
|
|
278
|
+
/** @private {Set<string>} */
|
|
273
279
|
this.dateRangeIdsEmitted_ = new Set();
|
|
274
280
|
|
|
275
281
|
/** @private {shaka.util.EventManager} */
|
|
@@ -344,7 +350,7 @@ shaka.hls.HlsParser = class {
|
|
|
344
350
|
this.updatePlaylistTimer_ = null;
|
|
345
351
|
}
|
|
346
352
|
|
|
347
|
-
/** @type {!Array
|
|
353
|
+
/** @type {!Array<!Promise>} */
|
|
348
354
|
const pending = [];
|
|
349
355
|
|
|
350
356
|
if (this.operationManager_) {
|
|
@@ -388,7 +394,7 @@ shaka.hls.HlsParser = class {
|
|
|
388
394
|
return;
|
|
389
395
|
}
|
|
390
396
|
|
|
391
|
-
/** @type {!Array
|
|
397
|
+
/** @type {!Array<!Promise>} */
|
|
392
398
|
const updates = [];
|
|
393
399
|
const streamInfos = Array.from(this.uriToStreamInfosMap_.values());
|
|
394
400
|
|
|
@@ -438,7 +444,7 @@ shaka.hls.HlsParser = class {
|
|
|
438
444
|
|
|
439
445
|
/**
|
|
440
446
|
* @param {!shaka.hls.HlsParser.StreamInfo} streamInfo
|
|
441
|
-
* @return {!Map
|
|
447
|
+
* @return {!Map<number, number>}
|
|
442
448
|
* @private
|
|
443
449
|
*/
|
|
444
450
|
getMediaSequenceToStartTimeFor_(streamInfo) {
|
|
@@ -519,7 +525,7 @@ shaka.hls.HlsParser = class {
|
|
|
519
525
|
streamInfo.redirectUris.push(responseUri);
|
|
520
526
|
}
|
|
521
527
|
|
|
522
|
-
/** @type {!Array
|
|
528
|
+
/** @type {!Array<!shaka.hls.Tag>} */
|
|
523
529
|
const variablesTags = shaka.hls.Utils.filterTagsByName(playlist.tags,
|
|
524
530
|
'EXT-X-DEFINE');
|
|
525
531
|
|
|
@@ -640,7 +646,7 @@ shaka.hls.HlsParser = class {
|
|
|
640
646
|
/**
|
|
641
647
|
* Align the streams by sequence number by dropping early segments. Then
|
|
642
648
|
* offset the streams to begin at presentation time 0.
|
|
643
|
-
* @param {!Array
|
|
649
|
+
* @param {!Array<!shaka.hls.HlsParser.StreamInfo>} streamInfos
|
|
644
650
|
* @param {boolean=} force
|
|
645
651
|
* @private
|
|
646
652
|
*/
|
|
@@ -728,7 +734,7 @@ shaka.hls.HlsParser = class {
|
|
|
728
734
|
* Synchronize streams by the EXT-X-PROGRAM-DATE-TIME tags attached to their
|
|
729
735
|
* segments. Also normalizes segment times so that the earliest segment in
|
|
730
736
|
* any stream is at time 0.
|
|
731
|
-
* @param {!Array
|
|
737
|
+
* @param {!Array<!shaka.hls.HlsParser.StreamInfo>} streamInfos
|
|
732
738
|
* @private
|
|
733
739
|
*/
|
|
734
740
|
syncStreamsWithProgramDateTime_(streamInfos) {
|
|
@@ -836,14 +842,14 @@ shaka.hls.HlsParser = class {
|
|
|
836
842
|
|
|
837
843
|
const playlist = this.manifestTextParser_.parsePlaylist(data);
|
|
838
844
|
|
|
839
|
-
/** @type {!Array
|
|
845
|
+
/** @type {!Array<!shaka.hls.Tag>} */
|
|
840
846
|
const variablesTags = Utils.filterTagsByName(playlist.tags, 'EXT-X-DEFINE');
|
|
841
847
|
|
|
842
|
-
/** @type {!Array
|
|
848
|
+
/** @type {!Array<!shaka.extern.Variant>} */
|
|
843
849
|
let variants = [];
|
|
844
|
-
/** @type {!Array
|
|
850
|
+
/** @type {!Array<!shaka.extern.Stream>} */
|
|
845
851
|
let textStreams = [];
|
|
846
|
-
/** @type {!Array
|
|
852
|
+
/** @type {!Array<!shaka.extern.Stream>} */
|
|
847
853
|
let imageStreams = [];
|
|
848
854
|
|
|
849
855
|
// This assert is our own sanity check.
|
|
@@ -865,14 +871,14 @@ shaka.hls.HlsParser = class {
|
|
|
865
871
|
/** @type {?string} */
|
|
866
872
|
let mediaPlaylistType = null;
|
|
867
873
|
|
|
868
|
-
/** @type {!Map
|
|
874
|
+
/** @type {!Map<string, string>} */
|
|
869
875
|
let mediaVariables = new Map();
|
|
870
876
|
|
|
871
877
|
// Parsing a media playlist results in a single-variant stream.
|
|
872
878
|
if (playlist.type == shaka.hls.PlaylistType.MEDIA) {
|
|
873
879
|
this.needsClosedCaptionsDetection_ = false;
|
|
874
880
|
|
|
875
|
-
/** @type {!Array
|
|
881
|
+
/** @type {!Array<!shaka.hls.Tag>} */
|
|
876
882
|
const variablesTags = shaka.hls.Utils.filterTagsByName(playlist.tags,
|
|
877
883
|
'EXT-X-DEFINE');
|
|
878
884
|
|
|
@@ -932,31 +938,58 @@ shaka.hls.HlsParser = class {
|
|
|
932
938
|
} else {
|
|
933
939
|
this.parseMasterVariables_(variablesTags);
|
|
934
940
|
|
|
935
|
-
/** @type {!Array
|
|
941
|
+
/** @type {!Array<!shaka.hls.Tag>} */
|
|
936
942
|
const mediaTags = Utils.filterTagsByName(
|
|
937
943
|
playlist.tags, 'EXT-X-MEDIA');
|
|
938
|
-
/** @type {!Array
|
|
944
|
+
/** @type {!Array<!shaka.hls.Tag>} */
|
|
939
945
|
const variantTags = Utils.filterTagsByName(
|
|
940
946
|
playlist.tags, 'EXT-X-STREAM-INF');
|
|
941
|
-
/** @type {!Array
|
|
947
|
+
/** @type {!Array<!shaka.hls.Tag>} */
|
|
942
948
|
const imageTags = Utils.filterTagsByName(
|
|
943
949
|
playlist.tags, 'EXT-X-IMAGE-STREAM-INF');
|
|
944
|
-
/** @type {!Array
|
|
950
|
+
/** @type {!Array<!shaka.hls.Tag>} */
|
|
945
951
|
const iFrameTags = Utils.filterTagsByName(
|
|
946
952
|
playlist.tags, 'EXT-X-I-FRAME-STREAM-INF');
|
|
947
|
-
/** @type {!Array
|
|
953
|
+
/** @type {!Array<!shaka.hls.Tag>} */
|
|
948
954
|
const sessionKeyTags = Utils.filterTagsByName(
|
|
949
955
|
playlist.tags, 'EXT-X-SESSION-KEY');
|
|
950
|
-
/** @type {!Array
|
|
956
|
+
/** @type {!Array<!shaka.hls.Tag>} */
|
|
951
957
|
const sessionDataTags = Utils.filterTagsByName(
|
|
952
958
|
playlist.tags, 'EXT-X-SESSION-DATA');
|
|
953
|
-
/** @type {!Array
|
|
959
|
+
/** @type {!Array<!shaka.hls.Tag>} */
|
|
954
960
|
const contentSteeringTags = Utils.filterTagsByName(
|
|
955
961
|
playlist.tags, 'EXT-X-CONTENT-STEERING');
|
|
956
962
|
|
|
957
963
|
this.processSessionData_(sessionDataTags);
|
|
958
964
|
await this.processContentSteering_(contentSteeringTags);
|
|
959
965
|
|
|
966
|
+
if (!this.config_.hls.ignoreSupplementalCodecs) {
|
|
967
|
+
// Duplicate variant tags with supplementalCodecs
|
|
968
|
+
const newVariantTags = [];
|
|
969
|
+
for (const tag of variantTags) {
|
|
970
|
+
const supplementalCodecsString =
|
|
971
|
+
tag.getAttributeValue('SUPPLEMENTAL-CODECS');
|
|
972
|
+
if (!supplementalCodecsString) {
|
|
973
|
+
continue;
|
|
974
|
+
}
|
|
975
|
+
const supplementalCodecs = supplementalCodecsString.split(/\s*,\s*/)
|
|
976
|
+
.map((codec) => {
|
|
977
|
+
return codec.split('/')[0];
|
|
978
|
+
});
|
|
979
|
+
const newAttributes = tag.attributes.map((attr) => {
|
|
980
|
+
const name = attr.name;
|
|
981
|
+
let value = attr.value;
|
|
982
|
+
if (name == 'CODECS') {
|
|
983
|
+
value = supplementalCodecs.join(',');
|
|
984
|
+
}
|
|
985
|
+
return new shaka.hls.Attribute(name, value);
|
|
986
|
+
});
|
|
987
|
+
newVariantTags.push(
|
|
988
|
+
new shaka.hls.Tag(tag.id, tag.name, newAttributes, null));
|
|
989
|
+
}
|
|
990
|
+
variantTags.push(...newVariantTags);
|
|
991
|
+
}
|
|
992
|
+
|
|
960
993
|
this.parseCodecs_(variantTags);
|
|
961
994
|
|
|
962
995
|
this.parseClosedCaptions_(mediaTags);
|
|
@@ -1002,7 +1035,6 @@ shaka.hls.HlsParser = class {
|
|
|
1002
1035
|
textStreams,
|
|
1003
1036
|
imageStreams,
|
|
1004
1037
|
offlineSessionIds: [],
|
|
1005
|
-
minBufferTime: 0,
|
|
1006
1038
|
sequenceMode: this.config_.hls.sequenceMode,
|
|
1007
1039
|
ignoreManifestTimestampsInSegmentsMode:
|
|
1008
1040
|
this.config_.hls.ignoreManifestTimestampsInSegmentsMode,
|
|
@@ -1033,24 +1065,11 @@ shaka.hls.HlsParser = class {
|
|
|
1033
1065
|
}
|
|
1034
1066
|
|
|
1035
1067
|
this.playerInterface_.makeTextStreamsForClosedCaptions(this.manifest_);
|
|
1036
|
-
|
|
1037
|
-
if (variants.length == 1) {
|
|
1038
|
-
const createSegmentIndexPromises = [];
|
|
1039
|
-
const variant = variants[0];
|
|
1040
|
-
for (const stream of [variant.video, variant.audio]) {
|
|
1041
|
-
if (stream && !stream.segmentIndex) {
|
|
1042
|
-
createSegmentIndexPromises.push(stream.createSegmentIndex());
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
if (createSegmentIndexPromises.length > 0) {
|
|
1046
|
-
await Promise.all(createSegmentIndexPromises);
|
|
1047
|
-
}
|
|
1048
|
-
}
|
|
1049
1068
|
}
|
|
1050
1069
|
|
|
1051
1070
|
/**
|
|
1052
|
-
* @param {!Array
|
|
1053
|
-
* @return {!Promise
|
|
1071
|
+
* @param {!Array<!shaka.media.SegmentReference>} segments
|
|
1072
|
+
* @return {!Promise<shaka.media.SegmentUtils.BasicInfo>}
|
|
1054
1073
|
* @private
|
|
1055
1074
|
*/
|
|
1056
1075
|
async getBasicInfoFromSegments_(segments) {
|
|
@@ -1222,7 +1241,7 @@ shaka.hls.HlsParser = class {
|
|
|
1222
1241
|
|
|
1223
1242
|
/**
|
|
1224
1243
|
* Get the variables of each variant tag, and store in a map.
|
|
1225
|
-
* @param {!Array
|
|
1244
|
+
* @param {!Array<!shaka.hls.Tag>} tags Variant tags from the playlist.
|
|
1226
1245
|
* @private
|
|
1227
1246
|
*/
|
|
1228
1247
|
parseMasterVariables_(tags) {
|
|
@@ -1247,9 +1266,9 @@ shaka.hls.HlsParser = class {
|
|
|
1247
1266
|
|
|
1248
1267
|
/**
|
|
1249
1268
|
* Get the variables of each variant tag, and store in a map.
|
|
1250
|
-
* @param {!Array
|
|
1269
|
+
* @param {!Array<!shaka.hls.Tag>} tags Variant tags from the playlist.
|
|
1251
1270
|
* @param {string} uri Media playlist URI.
|
|
1252
|
-
* @return {!Map
|
|
1271
|
+
* @return {!Map<string, string>}
|
|
1253
1272
|
* @private
|
|
1254
1273
|
*/
|
|
1255
1274
|
parseMediaVariables_(tags, uri) {
|
|
@@ -1283,8 +1302,8 @@ shaka.hls.HlsParser = class {
|
|
|
1283
1302
|
|
|
1284
1303
|
/**
|
|
1285
1304
|
* Get the codecs of each variant tag, and store in a map from
|
|
1286
|
-
* audio/video/subtitle group id to the codecs
|
|
1287
|
-
* @param {!Array
|
|
1305
|
+
* audio/video/subtitle group id to the codecs array list.
|
|
1306
|
+
* @param {!Array<!shaka.hls.Tag>} tags Variant tags from the playlist.
|
|
1288
1307
|
* @private
|
|
1289
1308
|
*/
|
|
1290
1309
|
parseCodecs_(tags) {
|
|
@@ -1325,7 +1344,7 @@ shaka.hls.HlsParser = class {
|
|
|
1325
1344
|
/**
|
|
1326
1345
|
* Process EXT-X-SESSION-DATA tags.
|
|
1327
1346
|
*
|
|
1328
|
-
* @param {!Array
|
|
1347
|
+
* @param {!Array<!shaka.hls.Tag>} tags
|
|
1329
1348
|
* @private
|
|
1330
1349
|
*/
|
|
1331
1350
|
processSessionData_(tags) {
|
|
@@ -1355,7 +1374,7 @@ shaka.hls.HlsParser = class {
|
|
|
1355
1374
|
/**
|
|
1356
1375
|
* Process EXT-X-CONTENT-STEERING tags.
|
|
1357
1376
|
*
|
|
1358
|
-
* @param {!Array
|
|
1377
|
+
* @param {!Array<!shaka.hls.Tag>} tags
|
|
1359
1378
|
* @return {!Promise}
|
|
1360
1379
|
* @private
|
|
1361
1380
|
*/
|
|
@@ -1388,8 +1407,8 @@ shaka.hls.HlsParser = class {
|
|
|
1388
1407
|
* Parse Subtitles and Closed Captions from 'EXT-X-MEDIA' tags.
|
|
1389
1408
|
* Create text streams for Subtitles, but not Closed Captions.
|
|
1390
1409
|
*
|
|
1391
|
-
* @param {!Array
|
|
1392
|
-
* @return {!Array
|
|
1410
|
+
* @param {!Array<!shaka.hls.Tag>} mediaTags Media tags from the playlist.
|
|
1411
|
+
* @return {!Array<!shaka.extern.Stream>}
|
|
1393
1412
|
* @private
|
|
1394
1413
|
*/
|
|
1395
1414
|
parseTexts_(mediaTags) {
|
|
@@ -1454,9 +1473,9 @@ shaka.hls.HlsParser = class {
|
|
|
1454
1473
|
}
|
|
1455
1474
|
|
|
1456
1475
|
/**
|
|
1457
|
-
* @param {!Array
|
|
1458
|
-
* @param {!Array
|
|
1459
|
-
* @return {!Promise
|
|
1476
|
+
* @param {!Array<!shaka.hls.Tag>} imageTags from the playlist.
|
|
1477
|
+
* @param {!Array<!shaka.hls.Tag>} iFrameTags from the playlist.
|
|
1478
|
+
* @return {!Promise<!Array<!shaka.extern.Stream>>}
|
|
1460
1479
|
* @private
|
|
1461
1480
|
*/
|
|
1462
1481
|
async parseImages_(imageTags, iFrameTags) {
|
|
@@ -1499,8 +1518,8 @@ shaka.hls.HlsParser = class {
|
|
|
1499
1518
|
}
|
|
1500
1519
|
|
|
1501
1520
|
/**
|
|
1502
|
-
* @param {!Array
|
|
1503
|
-
* @param {!Map
|
|
1521
|
+
* @param {!Array<!shaka.hls.Tag>} mediaTags Media tags from the playlist.
|
|
1522
|
+
* @param {!Map<string, string>} groupIdPathwayIdMapping
|
|
1504
1523
|
* @private
|
|
1505
1524
|
*/
|
|
1506
1525
|
createStreamInfosFromMediaTags_(mediaTags, groupIdPathwayIdMapping) {
|
|
@@ -1529,8 +1548,8 @@ shaka.hls.HlsParser = class {
|
|
|
1529
1548
|
}
|
|
1530
1549
|
|
|
1531
1550
|
/**
|
|
1532
|
-
* @param {!Array
|
|
1533
|
-
* @return {!Array
|
|
1551
|
+
* @param {!Array<!shaka.hls.Tag>} iFrameTags from the playlist.
|
|
1552
|
+
* @return {!Array<!shaka.extern.Stream>}
|
|
1534
1553
|
* @private
|
|
1535
1554
|
*/
|
|
1536
1555
|
parseIFrames_(iFrameTags) {
|
|
@@ -1549,15 +1568,15 @@ shaka.hls.HlsParser = class {
|
|
|
1549
1568
|
}
|
|
1550
1569
|
|
|
1551
1570
|
/**
|
|
1552
|
-
* @param {!Array
|
|
1553
|
-
* @param {!Array
|
|
1571
|
+
* @param {!Array<!shaka.hls.Tag>} tags Variant tags from the playlist.
|
|
1572
|
+
* @param {!Array<!shaka.hls.Tag>} sessionKeyTags EXT-X-SESSION-KEY tags
|
|
1554
1573
|
* from the playlist.
|
|
1555
|
-
* @param {!Array
|
|
1574
|
+
* @param {!Array<!shaka.hls.Tag>} mediaTags EXT-X-MEDIA tags from the
|
|
1556
1575
|
* playlist.
|
|
1557
|
-
* @param {function()
|
|
1558
|
-
* @param {?Map
|
|
1559
|
-
* @param {!Array
|
|
1560
|
-
* @return {!Promise
|
|
1576
|
+
* @param {function(): !Array<string>} getUris
|
|
1577
|
+
* @param {?Map<string, string>} variables
|
|
1578
|
+
* @param {!Array<!shaka.extern.Stream>} iFrameStreams
|
|
1579
|
+
* @return {!Promise<!Array<!shaka.extern.Variant>>}
|
|
1561
1580
|
* @private
|
|
1562
1581
|
*/
|
|
1563
1582
|
async createVariantsForTags_(tags, sessionKeyTags, mediaTags, getUris,
|
|
@@ -1681,8 +1700,8 @@ shaka.hls.HlsParser = class {
|
|
|
1681
1700
|
* Create audio and video streamInfos from an 'EXT-X-STREAM-INF' tag and its
|
|
1682
1701
|
* related media tags.
|
|
1683
1702
|
*
|
|
1684
|
-
* @param {!Array
|
|
1685
|
-
* @param {!Array
|
|
1703
|
+
* @param {!Array<!shaka.hls.Tag>} tags
|
|
1704
|
+
* @param {!Array<!shaka.hls.Tag>} mediaTags
|
|
1686
1705
|
* @param {?string} resolution
|
|
1687
1706
|
* @param {?string} frameRate
|
|
1688
1707
|
* @return {!shaka.hls.HlsParser.StreamInfos}
|
|
@@ -1757,7 +1776,7 @@ shaka.hls.HlsParser = class {
|
|
|
1757
1776
|
});
|
|
1758
1777
|
});
|
|
1759
1778
|
|
|
1760
|
-
/** @type {!Array
|
|
1779
|
+
/** @type {!Array<string>} */
|
|
1761
1780
|
let allCodecs = this.getCodecsForVariantTag_(tags[0]);
|
|
1762
1781
|
const videoCodecs = shaka.util.ManifestParserUtils.guessCodecsSafe(
|
|
1763
1782
|
ContentType.VIDEO, allCodecs);
|
|
@@ -1809,15 +1828,12 @@ shaka.hls.HlsParser = class {
|
|
|
1809
1828
|
* Get the codecs from the 'EXT-X-STREAM-INF' tag.
|
|
1810
1829
|
*
|
|
1811
1830
|
* @param {!shaka.hls.Tag} tag
|
|
1812
|
-
* @return {!Array
|
|
1831
|
+
* @return {!Array<string>} codecs
|
|
1813
1832
|
* @private
|
|
1814
1833
|
*/
|
|
1815
1834
|
getCodecsForVariantTag_(tag) {
|
|
1816
1835
|
let codecsString = tag.getAttributeValue('CODECS') || '';
|
|
1817
1836
|
|
|
1818
|
-
const supplementalCodecsString =
|
|
1819
|
-
tag.getAttributeValue('SUPPLEMENTAL-CODECS');
|
|
1820
|
-
|
|
1821
1837
|
this.codecInfoInManifest_ = codecsString.length > 0;
|
|
1822
1838
|
|
|
1823
1839
|
if (!this.codecInfoInManifest_ && !this.config_.hls.disableCodecGuessing) {
|
|
@@ -1835,17 +1851,9 @@ shaka.hls.HlsParser = class {
|
|
|
1835
1851
|
}
|
|
1836
1852
|
|
|
1837
1853
|
// Strip out internal whitespace while splitting on commas:
|
|
1838
|
-
/** @type {!Array
|
|
1854
|
+
/** @type {!Array<string>} */
|
|
1839
1855
|
const codecs = codecsString.split(/\s*,\s*/);
|
|
1840
1856
|
|
|
1841
|
-
if (supplementalCodecsString) {
|
|
1842
|
-
const supplementalCodecs = supplementalCodecsString.split(/\s*,\s*/)
|
|
1843
|
-
.map((codec) => {
|
|
1844
|
-
return codec.split('/')[0];
|
|
1845
|
-
});
|
|
1846
|
-
codecs.push(...supplementalCodecs);
|
|
1847
|
-
}
|
|
1848
|
-
|
|
1849
1857
|
return shaka.media.SegmentUtils.codecsFiltering(codecs);
|
|
1850
1858
|
}
|
|
1851
1859
|
|
|
@@ -1865,8 +1873,8 @@ shaka.hls.HlsParser = class {
|
|
|
1865
1873
|
if (!channels) {
|
|
1866
1874
|
return null;
|
|
1867
1875
|
}
|
|
1868
|
-
const
|
|
1869
|
-
const count = parseInt(
|
|
1876
|
+
const channelCountString = channels.split('/')[0];
|
|
1877
|
+
const count = parseInt(channelCountString, 10);
|
|
1870
1878
|
return count;
|
|
1871
1879
|
}
|
|
1872
1880
|
|
|
@@ -1911,7 +1919,7 @@ shaka.hls.HlsParser = class {
|
|
|
1911
1919
|
* create the stream info.
|
|
1912
1920
|
* @param {!shaka.hls.Tag} tag
|
|
1913
1921
|
* @param {string} type
|
|
1914
|
-
* @return {Map
|
|
1922
|
+
* @return {Map<string, string>} closedCaptions
|
|
1915
1923
|
* @private
|
|
1916
1924
|
*/
|
|
1917
1925
|
getClosedCaptions_(tag, type) {
|
|
@@ -1973,25 +1981,25 @@ shaka.hls.HlsParser = class {
|
|
|
1973
1981
|
}
|
|
1974
1982
|
|
|
1975
1983
|
/**
|
|
1976
|
-
* @param {!Array
|
|
1977
|
-
* @param {!Array
|
|
1984
|
+
* @param {!Array<shaka.hls.HlsParser.StreamInfo>} audioInfos
|
|
1985
|
+
* @param {!Array<shaka.hls.HlsParser.StreamInfo>} videoInfos
|
|
1978
1986
|
* @param {number} bandwidth
|
|
1979
1987
|
* @param {?string} width
|
|
1980
1988
|
* @param {?string} height
|
|
1981
1989
|
* @param {?string} frameRate
|
|
1982
1990
|
* @param {?string} videoRange
|
|
1983
1991
|
* @param {?string} videoLayout
|
|
1984
|
-
* @param {!Array
|
|
1985
|
-
* @param {!Set
|
|
1986
|
-
* @param {!Array
|
|
1987
|
-
* @return {!Array
|
|
1992
|
+
* @param {!Array<shaka.extern.DrmInfo>} drmInfos
|
|
1993
|
+
* @param {!Set<string>} keyIds
|
|
1994
|
+
* @param {!Array<!shaka.extern.Stream>} iFrameStreams
|
|
1995
|
+
* @return {!Array<!shaka.extern.Variant>}
|
|
1988
1996
|
* @private
|
|
1989
1997
|
*/
|
|
1990
1998
|
createVariants_(
|
|
1991
1999
|
audioInfos, videoInfos, bandwidth, width, height, frameRate, videoRange,
|
|
1992
2000
|
videoLayout, drmInfos, keyIds, iFrameStreams) {
|
|
1993
2001
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
1994
|
-
const DrmUtils = shaka.
|
|
2002
|
+
const DrmUtils = shaka.drm.DrmUtils;
|
|
1995
2003
|
|
|
1996
2004
|
for (const info of videoInfos) {
|
|
1997
2005
|
this.addVideoAttributes_(
|
|
@@ -2041,7 +2049,18 @@ shaka.hls.HlsParser = class {
|
|
|
2041
2049
|
videoInfo ? videoInfo.getUris().sort().join(',') : '';
|
|
2042
2050
|
const audioStreamUri =
|
|
2043
2051
|
audioInfo ? audioInfo.getUris().sort().join(',') : '';
|
|
2044
|
-
const
|
|
2052
|
+
const codecs = [];
|
|
2053
|
+
if (audioStream && audioStream.codecs) {
|
|
2054
|
+
codecs.push(audioStream.codecs);
|
|
2055
|
+
}
|
|
2056
|
+
if (videoStream && videoStream.codecs) {
|
|
2057
|
+
codecs.push(videoStream.codecs);
|
|
2058
|
+
}
|
|
2059
|
+
const variantUriKey = [
|
|
2060
|
+
videoStreamUri,
|
|
2061
|
+
audioStreamUri,
|
|
2062
|
+
codecs.sort(),
|
|
2063
|
+
].join('-');
|
|
2045
2064
|
|
|
2046
2065
|
if (audioStream && videoStream) {
|
|
2047
2066
|
if (!DrmUtils.areDrmCompatible(audioDrmInfos, videoDrmInfos)) {
|
|
@@ -2090,7 +2109,7 @@ shaka.hls.HlsParser = class {
|
|
|
2090
2109
|
* Parses an array of EXT-X-MEDIA tags, then stores the values of all tags
|
|
2091
2110
|
* with TYPE="CLOSED-CAPTIONS" into a map of group id to closed captions.
|
|
2092
2111
|
*
|
|
2093
|
-
* @param {!Array
|
|
2112
|
+
* @param {!Array<!shaka.hls.Tag>} mediaTags
|
|
2094
2113
|
* @private
|
|
2095
2114
|
*/
|
|
2096
2115
|
parseClosedCaptions_(mediaTags) {
|
|
@@ -2129,8 +2148,8 @@ shaka.hls.HlsParser = class {
|
|
|
2129
2148
|
/**
|
|
2130
2149
|
* Parse EXT-X-MEDIA media tag into a Stream object.
|
|
2131
2150
|
*
|
|
2132
|
-
* @param {!Array
|
|
2133
|
-
* @param {!Map
|
|
2151
|
+
* @param {!Array<!shaka.hls.Tag>} tags
|
|
2152
|
+
* @param {!Map<string, string>} groupIdPathwayIdMapping
|
|
2134
2153
|
* @param {boolean=} requireUri
|
|
2135
2154
|
* @return {!shaka.hls.HlsParser.StreamInfo}
|
|
2136
2155
|
* @private
|
|
@@ -2139,7 +2158,7 @@ shaka.hls.HlsParser = class {
|
|
|
2139
2158
|
requireUri = true) {
|
|
2140
2159
|
const verbatimMediaPlaylistUris = [];
|
|
2141
2160
|
const globalGroupIds = [];
|
|
2142
|
-
const
|
|
2161
|
+
const groupIdUriMapping = new Map();
|
|
2143
2162
|
for (const tag of tags) {
|
|
2144
2163
|
goog.asserts.assert(tag.name == 'EXT-X-MEDIA',
|
|
2145
2164
|
'Should only be called on media tags!');
|
|
@@ -2148,7 +2167,7 @@ shaka.hls.HlsParser = class {
|
|
|
2148
2167
|
const groupId = tag.getRequiredAttrValue('GROUP-ID');
|
|
2149
2168
|
verbatimMediaPlaylistUris.push(uri);
|
|
2150
2169
|
globalGroupIds.push(groupId);
|
|
2151
|
-
|
|
2170
|
+
groupIdUriMapping.set(groupId, uri);
|
|
2152
2171
|
}
|
|
2153
2172
|
|
|
2154
2173
|
const globalGroupId = globalGroupIds.sort().join(',');
|
|
@@ -2175,7 +2194,7 @@ shaka.hls.HlsParser = class {
|
|
|
2175
2194
|
}
|
|
2176
2195
|
const streamId = this.globalId_++;
|
|
2177
2196
|
if (this.contentSteeringManager_) {
|
|
2178
|
-
for (const [groupId, uri] of
|
|
2197
|
+
for (const [groupId, uri] of groupIdUriMapping) {
|
|
2179
2198
|
const pathwayId = groupIdPathwayIdMapping.get(groupId);
|
|
2180
2199
|
if (pathwayId) {
|
|
2181
2200
|
this.contentSteeringManager_.addLocation(streamId, pathwayId, uri);
|
|
@@ -2227,7 +2246,7 @@ shaka.hls.HlsParser = class {
|
|
|
2227
2246
|
* Parse EXT-X-IMAGE-STREAM-INF media tag into a Stream object.
|
|
2228
2247
|
*
|
|
2229
2248
|
* @param {shaka.hls.Tag} tag
|
|
2230
|
-
* @return {!Promise
|
|
2249
|
+
* @return {!Promise<!shaka.hls.HlsParser.StreamInfo>}
|
|
2231
2250
|
* @private
|
|
2232
2251
|
*/
|
|
2233
2252
|
async createStreamInfoFromImageTag_(tag) {
|
|
@@ -2341,8 +2360,8 @@ shaka.hls.HlsParser = class {
|
|
|
2341
2360
|
/**
|
|
2342
2361
|
* Parse an EXT-X-STREAM-INF media tag into a Stream object.
|
|
2343
2362
|
*
|
|
2344
|
-
* @param {!Array
|
|
2345
|
-
* @param {!Array
|
|
2363
|
+
* @param {!Array<!shaka.hls.Tag>} tags
|
|
2364
|
+
* @param {!Array<string>} allCodecs
|
|
2346
2365
|
* @param {string} type
|
|
2347
2366
|
* @return {!shaka.hls.HlsParser.StreamInfo}
|
|
2348
2367
|
* @private
|
|
@@ -2361,7 +2380,8 @@ shaka.hls.HlsParser = class {
|
|
|
2361
2380
|
verbatimMediaPlaylistUris.push(uri);
|
|
2362
2381
|
}
|
|
2363
2382
|
|
|
2364
|
-
const key = verbatimMediaPlaylistUris.sort().join(',')
|
|
2383
|
+
const key = verbatimMediaPlaylistUris.sort().join(',') +
|
|
2384
|
+
allCodecs.sort().join(',');
|
|
2365
2385
|
if (this.uriToStreamInfosMap_.has(key)) {
|
|
2366
2386
|
return this.uriToStreamInfosMap_.get(key);
|
|
2367
2387
|
}
|
|
@@ -2371,7 +2391,7 @@ shaka.hls.HlsParser = class {
|
|
|
2371
2391
|
const streamInfo = this.createStreamInfo_(
|
|
2372
2392
|
streamId, verbatimMediaPlaylistUris,
|
|
2373
2393
|
codecs, type, /* language= */ null, /* primary= */ false,
|
|
2374
|
-
/* name= */ null, /*
|
|
2394
|
+
/* name= */ null, /* channelCount= */ null, closedCaptions,
|
|
2375
2395
|
/* characteristics= */ null, /* forced= */ false,
|
|
2376
2396
|
/* sampleRate= */ null, /* spatialAudio= */ false);
|
|
2377
2397
|
|
|
@@ -2382,14 +2402,14 @@ shaka.hls.HlsParser = class {
|
|
|
2382
2402
|
|
|
2383
2403
|
/**
|
|
2384
2404
|
* @param {number} streamId
|
|
2385
|
-
* @param {!Array
|
|
2405
|
+
* @param {!Array<string>} verbatimMediaPlaylistUris
|
|
2386
2406
|
* @param {string} codecs
|
|
2387
2407
|
* @param {string} type
|
|
2388
2408
|
* @param {?string} languageValue
|
|
2389
2409
|
* @param {boolean} primary
|
|
2390
2410
|
* @param {?string} name
|
|
2391
2411
|
* @param {?number} channelsCount
|
|
2392
|
-
* @param {Map
|
|
2412
|
+
* @param {Map<string, string>} closedCaptions
|
|
2393
2413
|
* @param {?string} characteristics
|
|
2394
2414
|
* @param {boolean} forced
|
|
2395
2415
|
* @param {?number} sampleRate
|
|
@@ -2477,7 +2497,7 @@ shaka.hls.HlsParser = class {
|
|
|
2477
2497
|
shaka.util.Error.Code.HLS_INVALID_PLAYLIST_HIERARCHY);
|
|
2478
2498
|
}
|
|
2479
2499
|
|
|
2480
|
-
/** @type {!Array
|
|
2500
|
+
/** @type {!Array<!shaka.hls.Tag>} */
|
|
2481
2501
|
const variablesTags = shaka.hls.Utils.filterTagsByName(playlist.tags,
|
|
2482
2502
|
'EXT-X-DEFINE');
|
|
2483
2503
|
|
|
@@ -2735,7 +2755,7 @@ shaka.hls.HlsParser = class {
|
|
|
2735
2755
|
}
|
|
2736
2756
|
|
|
2737
2757
|
/**
|
|
2738
|
-
* @param {!Array
|
|
2758
|
+
* @param {!Array<!shaka.extern.Stream>} streams
|
|
2739
2759
|
* @private
|
|
2740
2760
|
*/
|
|
2741
2761
|
notifySegmentsForStreams_(streams) {
|
|
@@ -2753,7 +2773,7 @@ shaka.hls.HlsParser = class {
|
|
|
2753
2773
|
}
|
|
2754
2774
|
|
|
2755
2775
|
/**
|
|
2756
|
-
* @param {!Array
|
|
2776
|
+
* @param {!Array<!shaka.hls.HlsParser.StreamInfo>} streamInfos
|
|
2757
2777
|
* @private
|
|
2758
2778
|
*/
|
|
2759
2779
|
finalizeStreams_(streamInfos) {
|
|
@@ -2836,8 +2856,9 @@ shaka.hls.HlsParser = class {
|
|
|
2836
2856
|
|
|
2837
2857
|
/**
|
|
2838
2858
|
* @param {number} streamId
|
|
2859
|
+
* @param {!Map<string, string>} variables
|
|
2839
2860
|
* @param {!shaka.hls.Playlist} playlist
|
|
2840
|
-
* @param {function()
|
|
2861
|
+
* @param {function(): !Array<string>} getUris
|
|
2841
2862
|
* @param {string} responseUri
|
|
2842
2863
|
* @param {string} codecs
|
|
2843
2864
|
* @param {string} type
|
|
@@ -2845,7 +2866,7 @@ shaka.hls.HlsParser = class {
|
|
|
2845
2866
|
* @param {boolean} primary
|
|
2846
2867
|
* @param {?string} name
|
|
2847
2868
|
* @param {?number} channelsCount
|
|
2848
|
-
* @param {Map
|
|
2869
|
+
* @param {Map<string, string>} closedCaptions
|
|
2849
2870
|
* @param {?string} characteristics
|
|
2850
2871
|
* @param {boolean} forced
|
|
2851
2872
|
* @param {?number} sampleRate
|
|
@@ -2853,7 +2874,7 @@ shaka.hls.HlsParser = class {
|
|
|
2853
2874
|
* @param {(string|undefined)} mimeType
|
|
2854
2875
|
* @param {boolean=} requestBasicInfo
|
|
2855
2876
|
* @param {boolean=} allowOverrideMimeType
|
|
2856
|
-
* @return {!Promise
|
|
2877
|
+
* @return {!Promise<!shaka.hls.HlsParser.StreamInfo>}
|
|
2857
2878
|
* @private
|
|
2858
2879
|
*/
|
|
2859
2880
|
async convertParsedPlaylistIntoStreamInfo_(streamId, variables, playlist,
|
|
@@ -2943,7 +2964,7 @@ shaka.hls.HlsParser = class {
|
|
|
2943
2964
|
const stream = this.makeStreamObject_(streamId, codecs, type,
|
|
2944
2965
|
languageValue, primary, name, channelsCount, closedCaptions,
|
|
2945
2966
|
characteristics, forced, sampleRate, spatialAudio);
|
|
2946
|
-
stream.encrypted = encrypted;
|
|
2967
|
+
stream.encrypted = encrypted && !aesEncrypted;
|
|
2947
2968
|
stream.drmInfos = drmInfos;
|
|
2948
2969
|
stream.keyIds = keyIds;
|
|
2949
2970
|
stream.mimeType = mimeType;
|
|
@@ -3005,7 +3026,7 @@ shaka.hls.HlsParser = class {
|
|
|
3005
3026
|
* Get the next msn and part
|
|
3006
3027
|
*
|
|
3007
3028
|
* @param {number} mediaSequenceNumber
|
|
3008
|
-
* @param {!Array
|
|
3029
|
+
* @param {!Array<!shaka.media.SegmentReference>} segments
|
|
3009
3030
|
* @return {{nextMediaSequence: number, nextPart:number}}}
|
|
3010
3031
|
* @private
|
|
3011
3032
|
*/
|
|
@@ -3058,7 +3079,7 @@ shaka.hls.HlsParser = class {
|
|
|
3058
3079
|
* @param {boolean} primary
|
|
3059
3080
|
* @param {?string} name
|
|
3060
3081
|
* @param {?number} channelsCount
|
|
3061
|
-
* @param {Map
|
|
3082
|
+
* @param {Map<string, string>} closedCaptions
|
|
3062
3083
|
* @param {?string} characteristics
|
|
3063
3084
|
* @param {boolean} forced
|
|
3064
3085
|
* @param {?number} sampleRate
|
|
@@ -3152,11 +3173,11 @@ shaka.hls.HlsParser = class {
|
|
|
3152
3173
|
/**
|
|
3153
3174
|
* @param {!shaka.hls.Playlist} playlist
|
|
3154
3175
|
* @param {string} mimeType
|
|
3155
|
-
* @param {function()
|
|
3156
|
-
* @param {?Map
|
|
3157
|
-
* @return {Promise
|
|
3158
|
-
* drmInfos: !Array
|
|
3159
|
-
* keyIds: !Set
|
|
3176
|
+
* @param {function(): !Array<string>} getUris
|
|
3177
|
+
* @param {?Map<string, string>=} variables
|
|
3178
|
+
* @return {Promise<{
|
|
3179
|
+
* drmInfos: !Array<shaka.extern.DrmInfo>,
|
|
3180
|
+
* keyIds: !Set<string>,
|
|
3160
3181
|
* encrypted: boolean,
|
|
3161
3182
|
* aesEncrypted: boolean
|
|
3162
3183
|
* }>}
|
|
@@ -3183,7 +3204,7 @@ shaka.hls.HlsParser = class {
|
|
|
3183
3204
|
let encrypted = false;
|
|
3184
3205
|
let aesEncrypted = false;
|
|
3185
3206
|
|
|
3186
|
-
/** @type {!Array
|
|
3207
|
+
/** @type {!Array<shaka.extern.DrmInfo>}*/
|
|
3187
3208
|
const drmInfos = [];
|
|
3188
3209
|
const keyIds = new Set();
|
|
3189
3210
|
|
|
@@ -3234,8 +3255,8 @@ shaka.hls.HlsParser = class {
|
|
|
3234
3255
|
/**
|
|
3235
3256
|
* @param {!shaka.hls.Tag} drmTag
|
|
3236
3257
|
* @param {!shaka.hls.Playlist} playlist
|
|
3237
|
-
* @param {function()
|
|
3238
|
-
* @param {?Map
|
|
3258
|
+
* @param {function(): !Array<string>} getUris
|
|
3259
|
+
* @param {?Map<string, string>=} variables
|
|
3239
3260
|
* @return {!shaka.extern.aesKey}
|
|
3240
3261
|
* @private
|
|
3241
3262
|
*/
|
|
@@ -3274,7 +3295,11 @@ shaka.hls.HlsParser = class {
|
|
|
3274
3295
|
}
|
|
3275
3296
|
}
|
|
3276
3297
|
|
|
3277
|
-
const
|
|
3298
|
+
const keyUris = shaka.hls.Utils.constructSegmentUris(
|
|
3299
|
+
getUris(), drmTag.getRequiredAttrValue('URI'), variables);
|
|
3300
|
+
const keyMapKey = keyUris.sort().join('');
|
|
3301
|
+
const aesKeyInfoKey =
|
|
3302
|
+
`${drmTag.toString()}-${firstMediaSequenceNumber}-${keyMapKey}`;
|
|
3278
3303
|
if (!this.aesKeyInfoMap_.has(aesKeyInfoKey)) {
|
|
3279
3304
|
// Default AES-128
|
|
3280
3305
|
const keyInfo = {
|
|
@@ -3298,10 +3323,6 @@ shaka.hls.HlsParser = class {
|
|
|
3298
3323
|
// Don't download the key object until the segment is parsed, to avoid a
|
|
3299
3324
|
// startup delay for long manifests with lots of keys.
|
|
3300
3325
|
keyInfo.fetchKey = async () => {
|
|
3301
|
-
const keyUris = shaka.hls.Utils.constructSegmentUris(
|
|
3302
|
-
getUris(), drmTag.getRequiredAttrValue('URI'), variables);
|
|
3303
|
-
|
|
3304
|
-
const keyMapKey = keyUris.sort().join('');
|
|
3305
3326
|
if (!this.aesKeyMap_.has(keyMapKey)) {
|
|
3306
3327
|
const requestType = shaka.net.NetworkingEngine.RequestType.KEY;
|
|
3307
3328
|
const request = shaka.net.NetworkingEngine.makeRequest(
|
|
@@ -3521,9 +3542,9 @@ shaka.hls.HlsParser = class {
|
|
|
3521
3542
|
/**
|
|
3522
3543
|
* Get the InitSegmentReference for a segment if it has a EXT-X-MAP tag.
|
|
3523
3544
|
* @param {!shaka.hls.Playlist} playlist
|
|
3524
|
-
* @param {!Array
|
|
3525
|
-
* @param {function()
|
|
3526
|
-
* @param {?Map
|
|
3545
|
+
* @param {!Array<!shaka.hls.Tag>} tags Segment tags
|
|
3546
|
+
* @param {function(): !Array<string>} getUris
|
|
3547
|
+
* @param {?Map<string, string>=} variables
|
|
3527
3548
|
* @return {shaka.media.InitSegmentReference}
|
|
3528
3549
|
* @private
|
|
3529
3550
|
*/
|
|
@@ -3568,7 +3589,7 @@ shaka.hls.HlsParser = class {
|
|
|
3568
3589
|
/**
|
|
3569
3590
|
* Create an InitSegmentReference object for the EXT-X-MAP tag in the media
|
|
3570
3591
|
* playlist.
|
|
3571
|
-
* @param {!Array
|
|
3592
|
+
* @param {!Array<string>} absoluteInitSegmentUris
|
|
3572
3593
|
* @param {!shaka.hls.Tag} mapTag EXT-X-MAP
|
|
3573
3594
|
* @param {shaka.hls.Tag=} byteRangeTag EXT-X-BYTERANGE
|
|
3574
3595
|
* @param {shaka.extern.aesKey=} aesKey
|
|
@@ -3620,10 +3641,10 @@ shaka.hls.HlsParser = class {
|
|
|
3620
3641
|
* @param {shaka.media.SegmentReference} previousReference
|
|
3621
3642
|
* @param {!shaka.hls.Segment} hlsSegment
|
|
3622
3643
|
* @param {number} startTime
|
|
3623
|
-
* @param {!Map
|
|
3644
|
+
* @param {!Map<string, string>} variables
|
|
3624
3645
|
* @param {!shaka.hls.Playlist} playlist
|
|
3625
3646
|
* @param {string} type
|
|
3626
|
-
* @param {function()
|
|
3647
|
+
* @param {function(): !Array<string>} getUris
|
|
3627
3648
|
* @param {shaka.extern.aesKey=} aesKey
|
|
3628
3649
|
* @return {shaka.media.SegmentReference}
|
|
3629
3650
|
* @private
|
|
@@ -3837,7 +3858,7 @@ shaka.hls.HlsParser = class {
|
|
|
3837
3858
|
} else if (partialSegmentRefs.length) {
|
|
3838
3859
|
endTime = partialSegmentRefs[partialSegmentRefs.length - 1].endTime;
|
|
3839
3860
|
} else {
|
|
3840
|
-
// Skip segments without duration and without
|
|
3861
|
+
// Skip segments without duration and without partial segments
|
|
3841
3862
|
return null;
|
|
3842
3863
|
}
|
|
3843
3864
|
|
|
@@ -3941,7 +3962,7 @@ shaka.hls.HlsParser = class {
|
|
|
3941
3962
|
* Parse the startByte and endByte.
|
|
3942
3963
|
* @param {shaka.media.SegmentReference} previousReference
|
|
3943
3964
|
* @param {?string} byterange
|
|
3944
|
-
* @return {!Array
|
|
3965
|
+
* @return {!Array<number>} An array with the start byte and end byte.
|
|
3945
3966
|
* @private
|
|
3946
3967
|
*/
|
|
3947
3968
|
parseByteRange_(previousReference, byterange) {
|
|
@@ -3965,10 +3986,10 @@ shaka.hls.HlsParser = class {
|
|
|
3965
3986
|
}
|
|
3966
3987
|
|
|
3967
3988
|
/**
|
|
3968
|
-
* @param {!Array
|
|
3989
|
+
* @param {!Array<!shaka.hls.Tag>} tags
|
|
3969
3990
|
* @param {string} contentType
|
|
3970
|
-
* @param {!Map
|
|
3971
|
-
* @param {function()
|
|
3991
|
+
* @param {!Map<string, string>} variables
|
|
3992
|
+
* @param {function(): !Array<string>} getUris
|
|
3972
3993
|
* @private
|
|
3973
3994
|
*/
|
|
3974
3995
|
processDateRangeTags_(tags, contentType, variables, getUris) {
|
|
@@ -4090,7 +4111,7 @@ shaka.hls.HlsParser = class {
|
|
|
4090
4111
|
'END-ON-NEXT',
|
|
4091
4112
|
];
|
|
4092
4113
|
|
|
4093
|
-
/* @type {!Array
|
|
4114
|
+
/* @type {!Array<shaka.extern.MetadataFrame>} */
|
|
4094
4115
|
const values = [];
|
|
4095
4116
|
for (const attribute of tag.attributes) {
|
|
4096
4117
|
if (excludedAttributes.includes(attribute.name)) {
|
|
@@ -4119,7 +4140,7 @@ shaka.hls.HlsParser = class {
|
|
|
4119
4140
|
|
|
4120
4141
|
this.dateRangeIdsEmitted_.add(id);
|
|
4121
4142
|
} catch (e) {
|
|
4122
|
-
shaka.log.warning('
|
|
4143
|
+
shaka.log.warning('Ignoring DATERANGE with errors', tag.toString());
|
|
4123
4144
|
}
|
|
4124
4145
|
}
|
|
4125
4146
|
}
|
|
@@ -4130,17 +4151,17 @@ shaka.hls.HlsParser = class {
|
|
|
4130
4151
|
* playlist.
|
|
4131
4152
|
*
|
|
4132
4153
|
* @param {!shaka.hls.Playlist} playlist
|
|
4133
|
-
* @param {!Map
|
|
4134
|
-
* @param {!Map
|
|
4135
|
-
* @param {function()
|
|
4154
|
+
* @param {!Map<number, number>} mediaSequenceToStartTime
|
|
4155
|
+
* @param {!Map<string, string>} variables
|
|
4156
|
+
* @param {function(): !Array<string>} getUris
|
|
4136
4157
|
* @param {string} type
|
|
4137
|
-
* @return {{segments: !Array
|
|
4158
|
+
* @return {{segments: !Array<!shaka.media.SegmentReference>,
|
|
4138
4159
|
* bandwidth: (number|undefined)}}
|
|
4139
4160
|
* @private
|
|
4140
4161
|
*/
|
|
4141
4162
|
createSegments_(playlist, mediaSequenceToStartTime, variables,
|
|
4142
4163
|
getUris, type) {
|
|
4143
|
-
/** @type {Array
|
|
4164
|
+
/** @type {Array<!shaka.hls.Segment>} */
|
|
4144
4165
|
const hlsSegments = playlist.segments;
|
|
4145
4166
|
goog.asserts.assert(hlsSegments.length, 'Playlist should have segments!');
|
|
4146
4167
|
|
|
@@ -4175,12 +4196,12 @@ shaka.hls.HlsParser = class {
|
|
|
4175
4196
|
firstStartTime = this.presentationTimeline_.getSegmentAvailabilityStart();
|
|
4176
4197
|
}
|
|
4177
4198
|
|
|
4178
|
-
/** @type {!Array
|
|
4199
|
+
/** @type {!Array<!shaka.media.SegmentReference>} */
|
|
4179
4200
|
const references = [];
|
|
4180
4201
|
|
|
4181
4202
|
let previousReference = null;
|
|
4182
4203
|
|
|
4183
|
-
/** @type {!Array
|
|
4204
|
+
/** @type {!Array<{bitrate: number, duration: number}>} */
|
|
4184
4205
|
const bitrates = [];
|
|
4185
4206
|
|
|
4186
4207
|
for (let i = 0; i < hlsSegments.length; i++) {
|
|
@@ -4212,18 +4233,6 @@ shaka.hls.HlsParser = class {
|
|
|
4212
4233
|
initSegmentRef = this.getInitSegmentReference_(playlist,
|
|
4213
4234
|
item.tags, getUris, variables);
|
|
4214
4235
|
|
|
4215
|
-
// If the stream is low latency and the user has not configured the
|
|
4216
|
-
// lowLatencyMode, but if it has been configured to activate the
|
|
4217
|
-
// lowLatencyMode if a stream of this type is detected, we automatically
|
|
4218
|
-
// activate the lowLatencyMode.
|
|
4219
|
-
if (!this.lowLatencyMode_) {
|
|
4220
|
-
const autoLowLatencyMode = this.playerInterface_.isAutoLowLatencyMode();
|
|
4221
|
-
if (autoLowLatencyMode) {
|
|
4222
|
-
this.playerInterface_.enableLowLatencyMode();
|
|
4223
|
-
this.lowLatencyMode_ = this.playerInterface_.isLowLatencyMode();
|
|
4224
|
-
}
|
|
4225
|
-
}
|
|
4226
|
-
|
|
4227
4236
|
const reference = this.createSegmentReference_(
|
|
4228
4237
|
initSegmentRef,
|
|
4229
4238
|
previousReference,
|
|
@@ -4430,7 +4439,7 @@ shaka.hls.HlsParser = class {
|
|
|
4430
4439
|
}
|
|
4431
4440
|
|
|
4432
4441
|
/**
|
|
4433
|
-
* @param {!Array
|
|
4442
|
+
* @param {!Array<!shaka.media.SegmentReference>} segments
|
|
4434
4443
|
* @return {{segment: !shaka.media.SegmentReference, segmentIndex: number}}
|
|
4435
4444
|
* @private
|
|
4436
4445
|
*/
|
|
@@ -4456,8 +4465,8 @@ shaka.hls.HlsParser = class {
|
|
|
4456
4465
|
*
|
|
4457
4466
|
* @param {string} contentType
|
|
4458
4467
|
* @param {string} codecs
|
|
4459
|
-
* @param {!Array
|
|
4460
|
-
* @return {!Promise
|
|
4468
|
+
* @param {!Array<!shaka.media.SegmentReference>} segments
|
|
4469
|
+
* @return {!Promise<string>}
|
|
4461
4470
|
* @private
|
|
4462
4471
|
*/
|
|
4463
4472
|
async guessMimeType_(contentType, codecs, segments) {
|
|
@@ -4528,7 +4537,7 @@ shaka.hls.HlsParser = class {
|
|
|
4528
4537
|
* Returns a tag with a given name.
|
|
4529
4538
|
* Throws an error if tag was not found.
|
|
4530
4539
|
*
|
|
4531
|
-
* @param {!Array
|
|
4540
|
+
* @param {!Array<shaka.hls.Tag>} tags
|
|
4532
4541
|
* @param {string} tagName
|
|
4533
4542
|
* @return {!shaka.hls.Tag}
|
|
4534
4543
|
* @private
|
|
@@ -4571,7 +4580,7 @@ shaka.hls.HlsParser = class {
|
|
|
4571
4580
|
* Makes a network request for the manifest and returns a Promise
|
|
4572
4581
|
* with the resulting data.
|
|
4573
4582
|
*
|
|
4574
|
-
* @param {!Array
|
|
4583
|
+
* @param {!Array<string>} uris
|
|
4575
4584
|
* @param {boolean=} isPlaylist
|
|
4576
4585
|
* @return {!shaka.net.NetworkingEngine.PendingRequest}
|
|
4577
4586
|
* @private
|
|
@@ -4871,6 +4880,56 @@ shaka.hls.HlsParser = class {
|
|
|
4871
4880
|
{initDataType: 'cenc', initData: pssh},
|
|
4872
4881
|
]);
|
|
4873
4882
|
|
|
4883
|
+
const input = shaka.util.TXml.parseXmlString([
|
|
4884
|
+
'<PLAYREADY>',
|
|
4885
|
+
shaka.util.Uint8ArrayUtils.toBase64(data),
|
|
4886
|
+
'</PLAYREADY>',
|
|
4887
|
+
].join('\n'));
|
|
4888
|
+
if (input) {
|
|
4889
|
+
drmInfo.licenseServerUri = shaka.drm.PlayReady.getLicenseUrl(input);
|
|
4890
|
+
}
|
|
4891
|
+
|
|
4892
|
+
return drmInfo;
|
|
4893
|
+
}
|
|
4894
|
+
|
|
4895
|
+
/**
|
|
4896
|
+
* @param {!shaka.hls.Tag} drmTag
|
|
4897
|
+
* @return {?shaka.extern.DrmInfo}
|
|
4898
|
+
* @private
|
|
4899
|
+
*/
|
|
4900
|
+
static wiseplayDrmParser_(drmTag) {
|
|
4901
|
+
const method = drmTag.getRequiredAttrValue('METHOD');
|
|
4902
|
+
const VALID_METHODS = ['SAMPLE-AES', 'SAMPLE-AES-CTR'];
|
|
4903
|
+
if (!VALID_METHODS.includes(method)) {
|
|
4904
|
+
shaka.log.error('WisePlay in HLS is only supported with [',
|
|
4905
|
+
VALID_METHODS.join(', '), '], not', method);
|
|
4906
|
+
return null;
|
|
4907
|
+
}
|
|
4908
|
+
|
|
4909
|
+
let encryptionScheme = 'cenc';
|
|
4910
|
+
if (method == 'SAMPLE-AES') {
|
|
4911
|
+
encryptionScheme = 'cbcs';
|
|
4912
|
+
}
|
|
4913
|
+
|
|
4914
|
+
const uri = drmTag.getRequiredAttrValue('URI');
|
|
4915
|
+
const parsedData = shaka.net.DataUriPlugin.parseRaw(uri.split('?')[0]);
|
|
4916
|
+
|
|
4917
|
+
// The data encoded in the URI is a PSSH box to be used as init data.
|
|
4918
|
+
const pssh = shaka.util.BufferUtils.toUint8(parsedData.data);
|
|
4919
|
+
const drmInfo = shaka.util.ManifestParserUtils.createDrmInfo(
|
|
4920
|
+
'com.huawei.wiseplay', encryptionScheme, [
|
|
4921
|
+
{initDataType: 'cenc', initData: pssh},
|
|
4922
|
+
]);
|
|
4923
|
+
|
|
4924
|
+
const keyId = drmTag.getAttributeValue('KEYID');
|
|
4925
|
+
if (keyId) {
|
|
4926
|
+
const keyIdLowerCase = keyId.toLowerCase();
|
|
4927
|
+
// This value should begin with '0x':
|
|
4928
|
+
goog.asserts.assert(
|
|
4929
|
+
keyIdLowerCase.startsWith('0x'), 'Incorrect KEYID format!');
|
|
4930
|
+
// But the output should not contain the '0x':
|
|
4931
|
+
drmInfo.keyIds = new Set([keyIdLowerCase.substr(2)]);
|
|
4932
|
+
}
|
|
4874
4933
|
return drmInfo;
|
|
4875
4934
|
}
|
|
4876
4935
|
|
|
@@ -4879,10 +4938,10 @@ shaka.hls.HlsParser = class {
|
|
|
4879
4938
|
*
|
|
4880
4939
|
* @param {!shaka.hls.Tag} drmTag
|
|
4881
4940
|
* @param {string} mimeType
|
|
4882
|
-
* @param {function()
|
|
4941
|
+
* @param {function(): !Array<string>} getUris
|
|
4883
4942
|
* @param {?shaka.media.InitSegmentReference} initSegmentRef
|
|
4884
|
-
* @param {?Map
|
|
4885
|
-
* @return {!Promise
|
|
4943
|
+
* @param {?Map<string, string>=} variables
|
|
4944
|
+
* @return {!Promise<?shaka.extern.DrmInfo>}
|
|
4886
4945
|
* @private
|
|
4887
4946
|
*/
|
|
4888
4947
|
async identityDrmParser_(drmTag, mimeType, getUris, initSegmentRef,
|
|
@@ -4986,11 +5045,11 @@ shaka.hls.HlsParser = class {
|
|
|
4986
5045
|
* @typedef {{
|
|
4987
5046
|
* stream: !shaka.extern.Stream,
|
|
4988
5047
|
* type: string,
|
|
4989
|
-
* redirectUris: !Array
|
|
4990
|
-
* getUris: function():!Array
|
|
5048
|
+
* redirectUris: !Array<string>,
|
|
5049
|
+
* getUris: function():!Array<string>,
|
|
4991
5050
|
* minTimestamp: number,
|
|
4992
5051
|
* maxTimestamp: number,
|
|
4993
|
-
* mediaSequenceToStartTime: !Map
|
|
5052
|
+
* mediaSequenceToStartTime: !Map<number, number>,
|
|
4994
5053
|
* canSkipSegments: boolean,
|
|
4995
5054
|
* canBlockReload: boolean,
|
|
4996
5055
|
* hasEndList: boolean,
|
|
@@ -5007,15 +5066,15 @@ shaka.hls.HlsParser = class {
|
|
|
5007
5066
|
* The Stream itself.
|
|
5008
5067
|
* @property {string} type
|
|
5009
5068
|
* The type value. Could be 'video', 'audio', 'text', or 'image'.
|
|
5010
|
-
* @property {!Array
|
|
5069
|
+
* @property {!Array<string>} redirectUris
|
|
5011
5070
|
* The redirect URIs.
|
|
5012
|
-
* @property {function():!Array
|
|
5071
|
+
* @property {function():!Array<string>} getUris
|
|
5013
5072
|
* The verbatim media playlist URIs, as it appeared in the master playlist.
|
|
5014
5073
|
* @property {number} minTimestamp
|
|
5015
5074
|
* The minimum timestamp found in the stream.
|
|
5016
5075
|
* @property {number} maxTimestamp
|
|
5017
5076
|
* The maximum timestamp found in the stream.
|
|
5018
|
-
* @property {!Map
|
|
5077
|
+
* @property {!Map<number, number>} mediaSequenceToStartTime
|
|
5019
5078
|
* A map of media sequence numbers to media start times.
|
|
5020
5079
|
* Only used for VOD content.
|
|
5021
5080
|
* @property {boolean} canSkipSegments
|
|
@@ -5041,19 +5100,19 @@ shaka.hls.HlsParser.StreamInfo;
|
|
|
5041
5100
|
|
|
5042
5101
|
/**
|
|
5043
5102
|
* @typedef {{
|
|
5044
|
-
* audio: !Array
|
|
5045
|
-
* video: !Array
|
|
5103
|
+
* audio: !Array<shaka.hls.HlsParser.StreamInfo>,
|
|
5104
|
+
* video: !Array<shaka.hls.HlsParser.StreamInfo>
|
|
5046
5105
|
* }}
|
|
5047
5106
|
*
|
|
5048
5107
|
* @description Audio and video stream infos.
|
|
5049
|
-
* @property {!Array
|
|
5050
|
-
* @property {!Array
|
|
5108
|
+
* @property {!Array<shaka.hls.HlsParser.StreamInfo>} audio
|
|
5109
|
+
* @property {!Array<shaka.hls.HlsParser.StreamInfo>} video
|
|
5051
5110
|
*/
|
|
5052
5111
|
shaka.hls.HlsParser.StreamInfos;
|
|
5053
5112
|
|
|
5054
5113
|
|
|
5055
5114
|
/**
|
|
5056
|
-
* @const {!Object
|
|
5115
|
+
* @const {!Object<string, string>}
|
|
5057
5116
|
* @private
|
|
5058
5117
|
*/
|
|
5059
5118
|
shaka.hls.HlsParser.RAW_FORMATS_TO_MIME_TYPES_ = {
|
|
@@ -5065,7 +5124,7 @@ shaka.hls.HlsParser.RAW_FORMATS_TO_MIME_TYPES_ = {
|
|
|
5065
5124
|
|
|
5066
5125
|
|
|
5067
5126
|
/**
|
|
5068
|
-
* @const {!Object
|
|
5127
|
+
* @const {!Object<string, string>}
|
|
5069
5128
|
* @private
|
|
5070
5129
|
*/
|
|
5071
5130
|
shaka.hls.HlsParser.AUDIO_EXTENSIONS_TO_MIME_TYPES_ = {
|
|
@@ -5083,7 +5142,7 @@ shaka.hls.HlsParser.AUDIO_EXTENSIONS_TO_MIME_TYPES_ = {
|
|
|
5083
5142
|
|
|
5084
5143
|
|
|
5085
5144
|
/**
|
|
5086
|
-
* @const {!Object
|
|
5145
|
+
* @const {!Object<string, string>}
|
|
5087
5146
|
* @private
|
|
5088
5147
|
*/
|
|
5089
5148
|
shaka.hls.HlsParser.VIDEO_EXTENSIONS_TO_MIME_TYPES_ = {
|
|
@@ -5100,7 +5159,7 @@ shaka.hls.HlsParser.VIDEO_EXTENSIONS_TO_MIME_TYPES_ = {
|
|
|
5100
5159
|
|
|
5101
5160
|
|
|
5102
5161
|
/**
|
|
5103
|
-
* @const {!Object
|
|
5162
|
+
* @const {!Object<string, string>}
|
|
5104
5163
|
* @private
|
|
5105
5164
|
*/
|
|
5106
5165
|
shaka.hls.HlsParser.TEXT_EXTENSIONS_TO_MIME_TYPES_ = {
|
|
@@ -5116,7 +5175,7 @@ shaka.hls.HlsParser.TEXT_EXTENSIONS_TO_MIME_TYPES_ = {
|
|
|
5116
5175
|
|
|
5117
5176
|
|
|
5118
5177
|
/**
|
|
5119
|
-
* @const {!Object
|
|
5178
|
+
* @const {!Object<string, string>}
|
|
5120
5179
|
* @private
|
|
5121
5180
|
*/
|
|
5122
5181
|
shaka.hls.HlsParser.IMAGE_EXTENSIONS_TO_MIME_TYPES_ = {
|
|
@@ -5129,7 +5188,7 @@ shaka.hls.HlsParser.IMAGE_EXTENSIONS_TO_MIME_TYPES_ = {
|
|
|
5129
5188
|
|
|
5130
5189
|
|
|
5131
5190
|
/**
|
|
5132
|
-
* @const {!Object
|
|
5191
|
+
* @const {!Object<string, !Object<string, string>>}
|
|
5133
5192
|
* @private
|
|
5134
5193
|
*/
|
|
5135
5194
|
shaka.hls.HlsParser.EXTENSION_MAP_BY_CONTENT_TYPE_ = {
|
|
@@ -5143,7 +5202,7 @@ shaka.hls.HlsParser.EXTENSION_MAP_BY_CONTENT_TYPE_ = {
|
|
|
5143
5202
|
/**
|
|
5144
5203
|
* MIME types without init segment.
|
|
5145
5204
|
*
|
|
5146
|
-
* @const {!Set
|
|
5205
|
+
* @const {!Set<string>}
|
|
5147
5206
|
* @private
|
|
5148
5207
|
*/
|
|
5149
5208
|
shaka.hls.HlsParser.MIME_TYPES_WITHOUT_INIT_SEGMENT_ = new Set([
|
|
@@ -5161,7 +5220,7 @@ shaka.hls.HlsParser.DrmParser_;
|
|
|
5161
5220
|
|
|
5162
5221
|
|
|
5163
5222
|
/**
|
|
5164
|
-
* @const {!Object
|
|
5223
|
+
* @const {!Object<string, shaka.hls.HlsParser.DrmParser_>}
|
|
5165
5224
|
* @private
|
|
5166
5225
|
*/
|
|
5167
5226
|
shaka.hls.HlsParser.KEYFORMATS_TO_DRM_PARSERS_ = {
|
|
@@ -5171,6 +5230,8 @@ shaka.hls.HlsParser.KEYFORMATS_TO_DRM_PARSERS_ = {
|
|
|
5171
5230
|
shaka.hls.HlsParser.widevineDrmParser_,
|
|
5172
5231
|
'com.microsoft.playready':
|
|
5173
5232
|
shaka.hls.HlsParser.playreadyDrmParser_,
|
|
5233
|
+
'urn:uuid:3d5e6d35-9b9a-41e8-b843-dd3c6e72c42c':
|
|
5234
|
+
shaka.hls.HlsParser.wiseplayDrmParser_,
|
|
5174
5235
|
};
|
|
5175
5236
|
|
|
5176
5237
|
|