1typeof window !== "undefined" && 2(function webpackUniversalModuleDefinition(root, factory) { 3 if(typeof exports === 'object' && typeof module === 'object') 4 module.exports = factory(); 5 else if(typeof define === 'function' && define.amd) 6 define([], factory); 7 else if(typeof exports === 'object') 8 exports["Hls"] = factory(); 9 else 10 root["Hls"] = factory(); 11})(this, () => { 12return /******/ (() => { // webpackBootstrap 13/******/ var __webpack_modules__ = ({ 14
15/***/ "./src/config.ts": 16/*!***********************!*\ 17 !*** ./src/config.ts ***! 18 \***********************/ 19/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 20 21"use strict"; 22__webpack_require__.r(__webpack_exports__); 23/* harmony export */ __webpack_require__.d(__webpack_exports__, { 24/* harmony export */ "enableStreamingMode": () => (/* binding */ enableStreamingMode), 25/* harmony export */ "hlsDefaultConfig": () => (/* binding */ hlsDefaultConfig), 26/* harmony export */ "mergeConfig": () => (/* binding */ mergeConfig) 27/* harmony export */ }); 28/* harmony import */ var _controller_abr_controller__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./controller/abr-controller */ "./src/controller/abr-controller.ts"); 29/* harmony import */ var _controller_audio_stream_controller__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./controller/audio-stream-controller */ "./src/controller/audio-stream-controller.ts"); 30/* harmony import */ var _controller_audio_track_controller__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./controller/audio-track-controller */ "./src/controller/audio-track-controller.ts"); 31/* harmony import */ var _controller_subtitle_stream_controller__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./controller/subtitle-stream-controller */ "./src/controller/subtitle-stream-controller.ts"); 32/* harmony import */ var _controller_subtitle_track_controller__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./controller/subtitle-track-controller */ "./src/controller/subtitle-track-controller.ts"); 33/* harmony import */ var _controller_buffer_controller__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./controller/buffer-controller */ "./src/controller/buffer-controller.ts"); 34/* harmony import */ var _controller_timeline_controller__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./controller/timeline-controller */ "./src/controller/timeline-controller.ts"); 35/* harmony import */ var _controller_cap_level_controller__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./controller/cap-level-controller */ "./src/controller/cap-level-controller.ts"); 36/* harmony import */ var _controller_fps_controller__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./controller/fps-controller */ "./src/controller/fps-controller.ts"); 37/* harmony import */ var _controller_eme_controller__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./controller/eme-controller */ "./src/controller/eme-controller.ts"); 38/* harmony import */ var _controller_cmcd_controller__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./controller/cmcd-controller */ "./src/controller/cmcd-controller.ts"); 39/* harmony import */ var _utils_xhr_loader__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./utils/xhr-loader */ "./src/utils/xhr-loader.ts"); 40/* harmony import */ var _utils_fetch_loader__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./utils/fetch-loader */ "./src/utils/fetch-loader.ts"); 41/* harmony import */ var _utils_cues__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./utils/cues */ "./src/utils/cues.ts"); 42/* harmony import */ var _utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./utils/mediakeys-helper */ "./src/utils/mediakeys-helper.ts"); 43/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./utils/logger */ "./src/utils/logger.ts"); 44function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } 45function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } 46function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {};
vendor: 5,224 bytes, lines 46-191
46 i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } 47function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 48function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } 49function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66// If possible, keep hlsDefaultConfig shallow 67// It is cloned whenever a new Hls instance is created, by keeping the config 68// shallow the properties are cloned, and we don't end up manipulating the default 69var hlsDefaultConfig = _objectSpread(_objectSpread({ 70 autoStartLoad: true, 71 // used by stream-controller 72 startPosition: -1, 73 // used by stream-controller 74 defaultAudioCodec: undefined, 75 // used by stream-controller 76 debug: false, 77 // used by logger 78 capLevelOnFPSDrop: false, 79 // used by fps-controller 80 capLevelToPlayerSize: false, 81 // used by cap-level-controller 82 ignoreDevicePixelRatio: false, 83 // used by cap-level-controller 84 initialLiveManifestSize: 1, 85 // used by stream-controller 86 maxBufferLength: 30, 87 // used by stream-controller 88 backBufferLength: Infinity, 89 // used by buffer-controller 90 maxBufferSize: 60 * 1000 * 1000, 91 // used by stream-controller 92 maxBufferHole: 0.1, 93 // used by stream-controller 94 highBufferWatchdogPeriod: 2, 95 // used by stream-controller 96 nudgeOffset: 0.1, 97 // used by stream-controller 98 nudgeMaxRetry: 3, 99 // used by stream-controller 100 maxFragLookUpTolerance: 0.25, 101 // used by stream-controller 102 liveSyncDurationCount: 3, 103 // used by latency-controller 104 liveMaxLatencyDurationCount: Infinity, 105 // used by latency-controller 106 liveSyncDuration: undefined, 107 // used by latency-controller 108 liveMaxLatencyDuration: undefined, 109 // used by latency-controller 110 maxLiveSyncPlaybackRate: 1, 111 // used by latency-controller 112 liveDurationInfinity: false, 113 // used by buffer-controller 114 liveBackBufferLength: null, 115 // used by buffer-controller 116 maxMaxBufferLength: 600, 117 // used by stream-controller 118 enableWorker: true, 119 // used by demuxer 120 enableSoftwareAES: true, 121 // used by decrypter 122 manifestLoadingTimeOut: 10000, 123 // used by playlist-loader 124 manifestLoadingMaxRetry: 1, 125 // used by playlist-loader 126 manifestLoadingRetryDelay: 1000, 127 // used by playlist-loader 128 manifestLoadingMaxRetryTimeout: 64000, 129 // used by playlist-loader 130 startLevel: undefined, 131 // used by level-controller 132 levelLoadingTimeOut: 10000, 133 // used by playlist-loader 134 levelLoadingMaxRetry: 4, 135 // used by playlist-loader 136 levelLoadingRetryDelay: 1000, 137 // used by playlist-loader 138 levelLoadingMaxRetryTimeout: 64000, 139 // used by playlist-loader 140 fragLoadingTimeOut: 20000, 141 // used by fragment-loader 142 fragLoadingMaxRetry: 6, 143 // used by fragment-loader 144 fragLoadingRetryDelay: 1000, 145 // used by fragment-loader 146 fragLoadingMaxRetryTimeout: 64000, 147 // used by fragment-loader 148 startFragPrefetch: false, 149 // used by stream-controller 150 fpsDroppedMonitoringPeriod: 5000, 151 // used by fps-controller 152 fpsDroppedMonitoringThreshold: 0.2, 153 // used by fps-controller 154 appendErrorMaxRetry: 3, 155 // used by buffer-controller 156 loader: _utils_xhr_loader__WEBPACK_IMPORTED_MODULE_11__["default"], 157 // loader: FetchLoader, 158 fLoader: undefined, 159 // used by fragment-loader 160 pLoader: undefined, 161 // used by playlist-loader 162 xhrSetup: undefined, 163 // used by xhr-loader 164 licenseXhrSetup: undefined, 165 // used by eme-controller 166 licenseResponseCallback: undefined, 167 // used by eme-controller 168 abrController: _controller_abr_controller__WEBPACK_IMPORTED_MODULE_0__["default"], 169 bufferController: _controller_buffer_controller__WEBPACK_IMPORTED_MODULE_5__["default"], 170 capLevelController: _controller_cap_level_controller__WEBPACK_IMPORTED_MODULE_7__["default"], 171 fpsController: _controller_fps_controller__WEBPACK_IMPORTED_MODULE_8__["default"], 172 stretchShortVideoTrack: false, 173 // used by mp4-remuxer 174 maxAudioFramesDrift: 1, 175 // used by mp4-remuxer 176 forceKeyFrameOnDiscontinuity: true, 177 // used by ts-demuxer 178 abrEwmaFastLive: 3, 179 // used by abr-controller 180 abrEwmaSlowLive: 9, 181 // used by abr-controller 182 abrEwmaFastVoD: 3, 183 // used by abr-controller 184 abrEwmaSlowVoD: 9, 185 // used by abr-controller 186 abrEwmaDefaultEstimate: 5e5, 187 // 500 kbps // used by abr-controller 188 abrBandWidthFactor: 0.95, 189 // used by abr-controller 190 abrBandWidthUpFactor: 0.7, 191 // used by abr-controller
192 abrMaxWithRealBitrate: false, 193 // used by abr-controller 194 maxStarvationDelay: 4, 195 // used by abr-controller 196 maxLoadingDelay: 4, 197 // used by abr-controller 198 minAutoBitrate: 0, 199 // used by hls 200 emeEnabled: false, 201 // used by eme-controller 202 widevineLicenseUrl: undefined, 203 // used by eme-controller 204 drmSystems: {}, 205 // used by eme-controller 206 drmSystemOptions: {}, 207 // used by eme-controller 208 requestMediaKeySystemAccessFunc: _utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_14__.requestMediaKeySystemAccess, 209 // used by eme-controller 210 testBandwidth: true, 211 progressive: false, 212 lowLatencyMode: true, 213 cmcd: undefined, 214 enableDateRangeMetadataCues: true, 215 enableEmsgMetadataCues: true, 216 enableID3MetadataCues: true 217}, timelineConfig()), {}, { 218 subtitleStreamController: true ? _controller_subtitle_stream_controller__WEBPACK_IMPORTED_MODULE_3__.SubtitleStreamController : 0, 219 subtitleTrackController: true ? _controller_subtitle_track_controller__WEBPACK_IMPORTED_MODULE_4__["default"] : 0, 220 timelineController: true ? _controller_timeline_controller__WEBPACK_IMPORTED_MODULE_6__.TimelineController : 0, 221 audioStreamController: true ? _controller_audio_stream_controller__WEBPACK_IMPORTED_MODULE_1__["default"] : 0, 222 audioTrackController: true ? _controller_audio_track_controller__WEBPACK_IMPORTED_MODULE_2__["default"] : 0, 223 emeController: true ? _controller_eme_controller__WEBPACK_IMPORTED_MODULE_9__["default"] : 0, 224 cmcdController: true ? _controller_cmcd_controller__WEBPACK_IMPORTED_MODULE_10__["default"] : 0 225}); 226function timelineConfig() { 227 return { 228 cueHandler: _utils_cues__WEBPACK_IMPORTED_MODULE_13__["default"], 229 // used by timeline-controller 230 enableWebVTT: true, 231 // used by timeline-controller 232 enableIMSC1: true, 233 // used by timeline-controller 234 enableCEA708Captions: true, 235 // used by timeline-controller 236 captionsTextTrack1Label: 'English', 237 // used by timeline-controller 238 captionsTextTrack1LanguageCode: 'en', 239 // used by timeline-controller 240 captionsTextTrack2Label: 'Spanish', 241 // used by timeline-controller 242 captionsTextTrack2LanguageCode: 'es', 243 // used by timeline-controller 244 captionsTextTrack3Label: 'Unknown CC', 245 // used by timeline-controller 246 captionsTextTrack3LanguageCode: '', 247 // used by timeline-controller 248 captionsTextTrack4Label: 'Unknown CC', 249 // used by timeline-controller 250 captionsTextTrack4LanguageCode: '', 251 // used by timeline-controller 252 renderTextTracksNatively: true 253 }; 254} 255function mergeConfig(defaultConfig, userConfig) { 256 if ((userConfig.liveSyncDurationCount || userConfig.liveMaxLatencyDurationCount) && (userConfig.liveSyncDuration || userConfig.liveMaxLatencyDuration)) { 257 throw new Error("Illegal hls.js config: don't mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration"); 258 } 259 if (userConfig.liveMaxLatencyDurationCount !== undefined && (userConfig.liveSyncDurationCount === undefined || userConfig.liveMaxLatencyDurationCount <= userConfig.liveSyncDurationCount)) { 260 throw new Error('Illegal hls.js config: "liveMaxLatencyDurationCount" must be greater than "liveSyncDurationCount"'); 261 } 262 if (userConfig.liveMaxLatencyDuration !== undefined && (userConfig.liveSyncDuration === undefined || userConfig.liveMaxLatencyDuration <= userConfig.liveSyncDuration)) { 263 throw new Error('Illegal hls.js config: "liveMaxLatencyDuration" must be greater than "liveSyncDuration"'); 264 } 265 return _extends({}, defaultConfig, userConfig); 266} 267function enableStreamingMode(config) { 268 var currentLoader = config.loader; 269 if (currentLoader !== _utils_fetch_loader__WEBPACK_IMPORTED_MODULE_12__["default"] && currentLoader !== _utils_xhr_loader__WEBPACK_IMPORTED_MODULE_11__["default"]) { 270 // If a developer has configured their own loader, respect that choice 271 _utils_logger__WEBPACK_IMPORTED_MODULE_15__.logger.log('[config]: Custom loader detected, cannot enable progressive streaming'); 272 config.progressive = false; 273 } else { 274 var canStreamProgressively = (0,_utils_fetch_loader__WEBPACK_IMPORTED_MODULE_12__.fetchSupported)(); 275 if (canStreamProgressively) { 276 config.loader = _utils_fetch_loader__WEBPACK_IMPORTED_MODULE_12__["default"]; 277 config.progressive = true;
278 config.enableSoftwareAES = true; 279 _utils_logger__WEBPACK_IMPORTED_MODULE_15
vendor: 21,271 bytes, lines 279-675
279__.logger.log('[config]: Progressive streaming enabled, using FetchLoader'); 280 } 281 } 282} 283 284/***/ }), 285 286/***/ "./src/controller/abr-controller.ts": 287/*!******************************************!*\ 288 !*** ./src/controller/abr-controller.ts ***! 289 \******************************************/ 290/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 291 292"use strict"; 293__webpack_require__.r(__webpack_exports__); 294/* harmony export */ __webpack_require__.d(__webpack_exports__, { 295/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 296/* harmony export */ }); 297/* harmony import */ var _home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.ts"); 298/* harmony import */ var _utils_ewma_bandwidth_estimator__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils/ewma-bandwidth-estimator */ "./src/utils/ewma-bandwidth-estimator.ts"); 299/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 300/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../errors */ "./src/errors.ts"); 301/* harmony import */ var _types_loader__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../types/loader */ "./src/types/loader.ts"); 302/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 303 304 305 306function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } 307function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } 308function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } 309function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } 310 311 312 313 314 315var AbrController = /*#__PURE__*/function () { 316 function AbrController(hls) { 317 this.hls = void 0; 318 this.lastLoadedFragLevel = 0; 319 this._nextAutoLevel = -1; 320 this.timer = void 0; 321 this.onCheck = this._abandonRulesCheck.bind(this); 322 this.fragCurrent = null; 323 this.partCurrent = null; 324 this.bitrateTestDelay = 0; 325 this.bwEstimator = void 0; 326 this.hls = hls; 327 var config = hls.config; 328 this.bwEstimator = new _utils_ewma_bandwidth_estimator__WEBPACK_IMPORTED_MODULE_1__["default"](config.abrEwmaSlowVoD, config.abrEwmaFastVoD, config.abrEwmaDefaultEstimate); 329 this.registerListeners(); 330 } 331 var _proto = AbrController.prototype; 332 _proto.registerListeners = function registerListeners() { 333 var hls = this.hls; 334 hls.on(_events__WEBPACK_IMPORTED_MODULE_2__.Events.FRAG_LOADING, this.onFragLoading, this); 335 hls.on(_events__WEBPACK_IMPORTED_MODULE_2__.Events.FRAG_LOADED, this.onFragLoaded, this); 336 hls.on(_events__WEBPACK_IMPORTED_MODULE_2__.Events.FRAG_BUFFERED, this.onFragBuffered, this); 337 hls.on(_events__WEBPACK_IMPORTED_MODULE_2__.Events.LEVEL_LOADED, this.onLevelLoaded, this); 338 hls.on(_events__WEBPACK_IMPORTED_MODULE_2__.Events.ERROR, this.onError, this); 339 }; 340 _proto.unregisterListeners = function unregisterListeners() { 341 var hls = this.hls; 342 hls.off(_events__WEBPACK_IMPORTED_MODULE_2__.Events.FRAG_LOADING, this.onFragLoading, this); 343 hls.off(_events__WEBPACK_IMPORTED_MODULE_2__.Events.FRAG_LOADED, this.onFragLoaded, this); 344 hls.off(_events__WEBPACK_IMPORTED_MODULE_2__.Events.FRAG_BUFFERED, this.onFragBuffered, this); 345 hls.off(_events__WEBPACK_IMPORTED_MODULE_2__.Events.LEVEL_LOADED, this.onLevelLoaded, this); 346 hls.off(_events__WEBPACK_IMPORTED_MODULE_2__.Events.ERROR, this.onError, this); 347 }; 348 _proto.destroy = function destroy() { 349 this.unregisterListeners(); 350 this.clearTimer(); 351 // @ts-ignore 352 this.hls = this.onCheck = null; 353 this.fragCurrent = this.partCurrent = null; 354 }; 355 _proto.onFragLoading = function onFragLoading(event, data) { 356 var frag = data.frag; 357 if (frag.type === _types_loader__WEBPACK_IMPORTED_MODULE_4__.PlaylistLevelType.MAIN) { 358 if (!this.timer) { 359 var _data$part; 360 this.fragCurrent = frag; 361 this.partCurrent = (_data$part = data.part) != null ? _data$part : null; 362 this.timer = self.setInterval(this.onCheck, 100); 363 } 364 } 365 }; 366 _proto.onLevelLoaded = function onLevelLoaded(event, data) { 367 var config = this.hls.config; 368 if (data.details.live) { 369 this.bwEstimator.update(config.abrEwmaSlowLive, config.abrEwmaFastLive); 370 } else { 371 this.bwEstimator.update(config.abrEwmaSlowVoD, config.abrEwmaFastVoD); 372 } 373 } 374 375 /* 376 This method monitors the download rate of the current fragment, and will downswitch if that fragment will not load 377 quickly enough to prevent underbuffering 378 */; 379 _proto._abandonRulesCheck = function _abandonRulesCheck() { 380 var frag = this.fragCurrent, 381 part = this.partCurrent, 382 hls = this.hls; 383 var autoLevelEnabled = hls.autoLevelEnabled, 384 media = hls.media; 385 if (!frag || !media) { 386 return; 387 } 388 var stats = part ? part.stats : frag.stats; 389 var duration = part ? part.duration : frag.duration; 390 // If frag loading is aborted, complete, or from lowest level, stop timer and return 391 if (stats.aborted || stats.loaded && stats.loaded === stats.total || frag.level === 0) { 392 this.clearTimer(); 393 // reset forced auto level value so that next level will be selected 394 this._nextAutoLevel = -1; 395 return; 396 } 397 398 // This check only runs if we're in ABR mode and actually playing 399 if (!autoLevelEnabled || media.paused || !media.playbackRate || !media.readyState) { 400 return; 401 } 402 var bufferInfo = hls.mainForwardBufferInfo; 403 if (bufferInfo === null) { 404 return; 405 } 406 var requestDelay = performance.now() - stats.loading.start; 407 var playbackRate = Math.abs(media.playbackRate); 408 // In order to work with a stable bandwidth, only begin monitoring bandwidth after half of the fragment has been loaded 409 if (requestDelay <= 500 * duration / playbackRate) { 410 return; 411 } 412 var loadedFirstByte = stats.loaded && stats.loading.first; 413 var bwEstimate = this.bwEstimator.getEstimate(); 414 var levels = hls.levels, 415 minAutoLevel = hls.minAutoLevel; 416 var level = levels[frag.level]; 417 var expectedLen = stats.total || Math.max(stats.loaded, Math.round(duration * level.maxBitrate / 8)); 418 var loadRate = loadedFirstByte ? stats.loaded * 1000 / requestDelay : 0; 419 420 // fragLoadDelay is an estimate of the time (in seconds) it will take to buffer the remainder of the fragment 421 var fragLoadedDelay = loadRate ? (expectedLen - stats.loaded) / loadRate : expectedLen * 8 / bwEstimate; 422 423 // bufferStarvationDelay is an estimate of the amount time (in seconds) it will take to exhaust the buffer 424 var bufferStarvationDelay = bufferInfo.len / playbackRate; 425 426 // Only downswitch if the time to finish loading the current fragment is greater than the amount of buffer left 427 if (fragLoadedDelay <= bufferStarvationDelay) { 428 return; 429 } 430 var fragLevelNextLoadedDelay = Number.POSITIVE_INFINITY; 431 var nextLoadLevel; 432 // Iterate through lower level and try to find the largest one that avoids rebuffering 433 for (nextLoadLevel = frag.level - 1; nextLoadLevel > minAutoLevel; nextLoadLevel--) { 434 // compute time to load next fragment at lower level 435 // 0.8 : consider only 80% of current bw to be conservative 436 // 8 = bits per byte (bps/Bps) 437 var levelNextBitrate = levels[nextLoadLevel].maxBitrate; 438 fragLevelNextLoadedDelay = loadRate ? duration * levelNextBitrate / (8 * 0.8 * loadRate) : duration * levelNextBitrate / bwEstimate; 439 if (fragLevelNextLoadedDelay < bufferStarvationDelay) { 440 break; 441 } 442 } 443 // Only emergency switch down if it takes less time to load a new fragment at lowest level instead of continuing 444 // to load the current one 445 if (fragLevelNextLoadedDelay >= fragLoadedDelay) { 446 return; 447 } 448 _utils_logger__WEBPACK_IMPORTED_MODULE_5__.logger.warn("Fragment " + frag.sn + (part ? ' part ' + part.index : '') + " of level " + frag.level + " is loading too slowly and will cause an underbuffer; aborting and switching to level " + nextLoadLevel + "\n Current BW estimate: " + ((0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(bwEstimate) ? (bwEstimate / 1024).toFixed(3) : 'Unknown') + " Kb/s\n Estimated load time for current fragment: " + fragLoadedDelay.toFixed(3) + " s\n Estimated load time for the next fragment: " + fragLevelNextLoadedDelay.toFixed(3) + " s\n Time to underbuffer: " + bufferStarvationDelay.toFixed(3) + " s"); 449 hls.nextLoadLevel = nextLoadLevel; 450 if (loadedFirstByte) { 451 // If there has been loading progress, sample bandwidth 452 this.bwEstimator.sample(requestDelay, stats.loaded); 453 } 454 this.clearTimer(); 455 if (frag.loader || frag.keyLoader) { 456 this.fragCurrent = this.partCurrent = null; 457 frag.abortRequests(); 458 } 459 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_2__.Events.FRAG_LOAD_EMERGENCY_ABORTED, { 460 frag: frag, 461 part: part, 462 stats: stats 463 }); 464 }; 465 _proto.onFragLoaded = function onFragLoaded(event, _ref) { 466 var frag = _ref.frag, 467 part = _ref.part; 468 if (frag.type === _types_loader__WEBPACK_IMPORTED_MODULE_4__.PlaylistLevelType.MAIN && (0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(frag.sn)) { 469 var stats = part ? part.stats : frag.stats; 470 var duration = part ? part.duration : frag.duration; 471 // stop monitoring bw once frag loaded 472 this.clearTimer(); 473 // store level id after successful fragment load 474 this.lastLoadedFragLevel = frag.level; 475 // reset forced auto level value so that next level will be selected 476 this._nextAutoLevel = -1; 477 478 // compute level average bitrate 479 if (this.hls.config.abrMaxWithRealBitrate) { 480 var level = this.hls.levels[frag.level]; 481 var loadedBytes = (level.loaded ? level.loaded.bytes : 0) + stats.loaded; 482 var loadedDuration = (level.loaded ? level.loaded.duration : 0) + duration; 483 level.loaded = { 484 bytes: loadedBytes, 485 duration: loadedDuration 486 }; 487 level.realBitrate = Math.round(8 * loadedBytes / loadedDuration); 488 } 489 if (frag.bitrateTest) { 490 var fragBufferedData = { 491 stats: stats, 492 frag: frag, 493 part: part, 494 id: frag.type 495 }; 496 this.onFragBuffered(_events__WEBPACK_IMPORTED_MODULE_2__.Events.FRAG_BUFFERED, fragBufferedData); 497 } 498 } 499 }; 500 _proto.onFragBuffered = function onFragBuffered(event, data) { 501 var frag = data.frag, 502 part = data.part; 503 var stats = part ? part.stats : frag.stats; 504 if (stats.aborted) { 505 return; 506 } 507 // Only count non-alt-audio frags which were actually buffered in our BW calculations 508 if (frag.type !== _types_loader__WEBPACK_IMPORTED_MODULE_4__.PlaylistLevelType.MAIN || frag.sn === 'initSegment') { 509 return; 510 } 511 // Use the difference between parsing and request instead of buffering and request to compute fragLoadingProcessing; 512 // rationale is that buffer appending only happens once media is attached. This can happen when config.startFragPrefetch 513 // is used. If we used buffering in that case, our BW estimate sample will be very large. 514 var processingMs = stats.parsing.end - stats.loading.start; 515 this.bwEstimator.sample(processingMs, stats.loaded); 516 stats.bwEstimate = this.bwEstimator.getEstimate(); 517 if (frag.bitrateTest) { 518 this.bitrateTestDelay = processingMs / 1000; 519 } else { 520 this.bitrateTestDelay = 0; 521 } 522 }; 523 _proto.onError = function onError(event, data) { 524 var _data$frag; 525 // stop timer in case of frag loading error 526 if (((_data$frag = data.frag) === null || _data$frag === void 0 ? void 0 : _data$frag.type) === _types_loader__WEBPACK_IMPORTED_MODULE_4__.PlaylistLevelType.MAIN) { 527 if (data.type === _errors__WEBPACK_IMPORTED_MODULE_3__.ErrorTypes.KEY_SYSTEM_ERROR) { 528 this.clearTimer(); 529 return; 530 } 531 switch (data.details) { 532 case _errors__WEBPACK_IMPORTED_MODULE_3__.ErrorDetails.FRAG_LOAD_ERROR: 533 case _errors__WEBPACK_IMPORTED_MODULE_3__.ErrorDetails.FRAG_LOAD_TIMEOUT: 534 case _errors__WEBPACK_IMPORTED_MODULE_3__.ErrorDetails.KEY_LOAD_ERROR: 535 case _errors__WEBPACK_IMPORTED_MODULE_3__.ErrorDetails.KEY_LOAD_TIMEOUT: 536 this.clearTimer(); 537 break; 538 default: 539 break; 540 } 541 } 542 }; 543 _proto.clearTimer = function clearTimer() { 544 self.clearInterval(this.timer); 545 this.timer = undefined; 546 } 547 548 // return next auto level 549 ; 550 _proto.getNextABRAutoLevel = function getNextABRAutoLevel() { 551 var fragCurrent = this.fragCurrent, 552 partCurrent = this.partCurrent, 553 hls = this.hls; 554 var maxAutoLevel = hls.maxAutoLevel, 555 config = hls.config, 556 minAutoLevel = hls.minAutoLevel, 557 media = hls.media; 558 var currentFragDuration = partCurrent ? partCurrent.duration : fragCurrent ? fragCurrent.duration : 0; 559 560 // playbackRate is the absolute value of the playback rate; if media.playbackRate is 0, we use 1 to load as 561 // if we're playing back at the normal rate. 562 var playbackRate = media && media.playbackRate !== 0 ? Math.abs(media.playbackRate) : 1.0; 563 var avgbw = this.bwEstimator ? this.bwEstimator.getEstimate() : config.abrEwmaDefaultEstimate; 564 // bufferStarvationDelay is the wall-clock time left until the playback buffer is exhausted. 565 var bufferInfo = hls.mainForwardBufferInfo; 566 var bufferStarvationDelay = (bufferInfo ? bufferInfo.len : 0) / playbackRate; 567 568 // First, look to see if we can find a level matching with our avg bandwidth AND that could also guarantee no rebuffering at all 569 var bestLevel = this.findBestLevel(avgbw, minAutoLevel, maxAutoLevel, bufferStarvationDelay, config.abrBandWidthFactor, config.abrBandWidthUpFactor); 570 if (bestLevel >= 0) { 571 return bestLevel; 572 } 573 _utils_logger__WEBPACK_IMPORTED_MODULE_5__.logger.trace((bufferStarvationDelay ? 'rebuffering expected' : 'buffer is empty') + ", finding optimal quality level"); 574 // not possible to get rid of rebuffering ... let's try to find level that will guarantee less than maxStarvationDelay of rebuffering 575 // if no matching level found, logic will return 0 576 var maxStarvationDelay = currentFragDuration ? Math.min(currentFragDuration, config.maxStarvationDelay) : config.maxStarvationDelay; 577 var bwFactor = config.abrBandWidthFactor; 578 var bwUpFactor = config.abrBandWidthUpFactor; 579 if (!bufferStarvationDelay) { 580 // in case buffer is empty, let's check if previous fragment was loaded to perform a bitrate test 581 var bitrateTestDelay = this.bitrateTestDelay; 582 if (bitrateTestDelay) { 583 // if it is the case, then we need to adjust our max starvation delay using maxLoadingDelay config value 584 // max video loading delay used in automatic start level selection : 585 // in that mode ABR controller will ensure that video loading time (ie the time to fetch the first fragment at lowest quality level + 586 // the time to fetch the fragment at the appropriate quality level is less than ```maxLoadingDelay``` ) 587 // cap maxLoadingDelay and ensure it is not bigger 'than bitrate test' frag duration 588 var maxLoadingDelay = currentFragDuration ? Math.min(currentFragDuration, config.maxLoadingDelay) : config.maxLoadingDelay; 589 maxStarvationDelay = maxLoadingDelay - bitrateTestDelay; 590 _utils_logger__WEBPACK_IMPORTED_MODULE_5__.logger.trace("bitrate test took " + Math.round(1000 * bitrateTestDelay) + "ms, set first fragment max fetchDuration to " + Math.round(1000 * maxStarvationDelay) + " ms"); 591 // don't use conservative factor on bitrate test 592 bwFactor = bwUpFactor = 1; 593 } 594 } 595 bestLevel = this.findBestLevel(avgbw, minAutoLevel, maxAutoLevel, bufferStarvationDelay + maxStarvationDelay, bwFactor, bwUpFactor); 596 return Math.max(bestLevel, 0); 597 }; 598 _proto.findBestLevel = function findBestLevel(currentBw, minAutoLevel, maxAutoLevel, maxFetchDuration, bwFactor, bwUpFactor) { 599 var _level$details; 600 var fragCurrent = this.fragCurrent, 601 partCurrent = this.partCurrent, 602 currentLevel = this.lastLoadedFragLevel; 603 var levels = this.hls.levels; 604 var level = levels[currentLevel]; 605 var live = !!(level !== null && level !== void 0 && (_level$details = level.details) !== null && _level$details !== void 0 && _level$details.live); 606 var currentCodecSet = level === null || level === void 0 ? void 0 : level.codecSet; 607 var currentFragDuration = partCurrent ? partCurrent.duration : fragCurrent ? fragCurrent.duration : 0; 608 for (var i = maxAutoLevel; i >= minAutoLevel; i--) { 609 var levelInfo = levels[i]; 610 if (!levelInfo || currentCodecSet && levelInfo.codecSet !== currentCodecSet) { 611 continue; 612 } 613 var levelDetails = levelInfo.details; 614 var avgDuration = (partCurrent ? levelDetails === null || levelDetails === void 0 ? void 0 : levelDetails.partTarget : levelDetails === null || levelDetails === void 0 ? void 0 : levelDetails.averagetargetduration) || currentFragDuration; 615 var adjustedbw = void 0; 616 // follow algorithm captured from stagefright : 617 // https://android.googlesource.com/platform/frameworks/av/+/master/media/libstagefright/httplive/LiveSession.cpp 618 // Pick the highest bandwidth stream below or equal to estimated bandwidth. 619 // consider only 80% of the available bandwidth, but if we are switching up, 620 // be even more conservative (70%) to avoid overestimating and immediately 621 // switching back. 622 if (i <= currentLevel) { 623 adjustedbw = bwFactor * currentBw; 624 } else { 625 adjustedbw = bwUpFactor * currentBw; 626 } 627 var bitrate = levels[i].maxBitrate; 628 var fetchDuration = bitrate * avgDuration / adjustedbw; 629 _utils_logger__WEBPACK_IMPORTED_MODULE_5__.logger.trace("level/adjustedbw/bitrate/avgDuration/maxFetchDuration/fetchDuration: " + i + "/" + Math.round(adjustedbw) + "/" + bitrate + "/" + avgDuration + "/" + maxFetchDuration + "/" + fetchDuration); 630 // if adjusted bw is greater than level bitrate AND 631 if (adjustedbw > bitrate && ( 632 // fragment fetchDuration unknown OR live stream OR fragment fetchDuration less than max allowed fetch duration, then this level matches 633 // we don't account for max Fetch Duration for live streams, this is to avoid switching down when near the edge of live sliding window ... 634 // special case to support startLevel = -1 (bitrateTest) on live streams : in that case we should not exit loop so that findBestLevel will return -1 635 fetchDuration === 0 || !(0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(fetchDuration) || live && !this.bitrateTestDelay || fetchDuration < maxFetchDuration)) { 636 // as we are looping from highest to lowest, this will return the best achievable quality level 637 return i; 638 } 639 } 640 // not enough time budget even with quality level 0 ... rebuffering might happen 641 return -1; 642 }; 643 _createClass(AbrController, [{ 644 key: "nextAutoLevel", 645 get: function get() { 646 var forcedAutoLevel = this._nextAutoLevel; 647 var bwEstimator = this.bwEstimator; 648 // in case next auto level has been forced, and bw not available or not reliable, return forced value 649 if (forcedAutoLevel !== -1 && !bwEstimator.canEstimate()) { 650 return forcedAutoLevel; 651 } 652 653 // compute next level using ABR logic 654 var nextABRAutoLevel = this.getNextABRAutoLevel(); 655 // use forced auto level when ABR selected level has errored 656 if (forcedAutoLevel !== -1 && this.hls.levels[nextABRAutoLevel].loadError) { 657 return forcedAutoLevel; 658 } 659 // if forced auto level has been defined, use it to cap ABR computed quality level 660 if (forcedAutoLevel !== -1) { 661 nextABRAutoLevel = Math.min(forcedAutoLevel, nextABRAutoLevel); 662 } 663 return nextABRAutoLevel; 664 }, 665 set: function set(nextLevel) { 666 this._nextAutoLevel = nextLevel; 667 } 668 }]); 669 return AbrController; 670}(); 671/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AbrController); 672 673/***/ }), 674 675/***/ "./src/controller/
vendor: 4,467 bytes, lines 675-742
675audio-stream-controller.ts": 676/*!***************************************************!*\ 677 !*** ./src/controller/audio-stream-controller.ts ***! 678 \***************************************************/ 679/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 680 681"use strict"; 682__webpack_require__.r(__webpack_exports__); 683/* harmony export */ __webpack_require__.d(__webpack_exports__, { 684/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 685/* harmony export */ }); 686/* harmony import */ var _home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.ts"); 687/* harmony import */ var _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./base-stream-controller */ "./src/controller/base-stream-controller.ts"); 688/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 689/* harmony import */ var _utils_buffer_helper__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils/buffer-helper */ "./src/utils/buffer-helper.ts"); 690/* harmony import */ var _fragment_tracker__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./fragment-tracker */ "./src/controller/fragment-tracker.ts"); 691/* harmony import */ var _types_level__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../types/level */ "./src/types/level.ts"); 692/* harmony import */ var _types_loader__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../types/loader */ "./src/types/loader.ts"); 693/* harmony import */ var _loader_fragment__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../loader/fragment */ "./src/loader/fragment.ts"); 694/* harmony import */ var _demux_chunk_cache__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../demux/chunk-cache */ "./src/demux/chunk-cache.ts"); 695/* harmony import */ var _demux_transmuxer_interface__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../demux/transmuxer-interface */ "./src/demux/transmuxer-interface.ts"); 696/* harmony import */ var _types_transmuxer__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../types/transmuxer */ "./src/types/transmuxer.ts"); 697/* harmony import */ var _fragment_finders__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./fragment-finders */ "./src/controller/fragment-finders.ts"); 698/* harmony import */ var _utils_discontinuities__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../utils/discontinuities */ "./src/utils/discontinuities.ts"); 699/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../errors */ "./src/errors.ts"); 700 701function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } 702function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); } 703function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } 704 705 706 707 708 709 710 711 712 713 714 715 716 717var TICK_INTERVAL = 100; // how often to tick in ms 718var AudioStreamController = /*#__PURE__*/function (_BaseStreamController) { 719 _inheritsLoose(AudioStreamController, _BaseStreamController); 720 function AudioStreamController(hls, fragmentTracker, keyLoader) { 721 var _this; 722 _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '[audio-stream-controller]') || this; 723 _this.videoBuffer = null; 724 _this.videoTrackCC = -1; 725 _this.waitingVideoCC = -1; 726 _this.audioSwitch = false; 727 _this.trackId = -1; 728 _this.waitingData = null; 729 _this.mainDetails = null; 730 _this.bufferFlushed = false; 731 _this.cachedTrackLoadedData = null; 732 _this._registerListeners(); 733 return _this; 734 } 735 var _proto = AudioStreamController.prototype; 736 _proto.onHandlerDestroying = function onHandlerDestroying() { 737 this._unregisterListeners(); 738 this.mainDetails = null; 739 }; 740 _proto._registerListeners = function _registerListeners() { 741 var hls = this.hls; 742 hls.on(_events__WEBPACK_IMPORTED_MODULE_2__.Events.MEDIA_ATTA
742CHED, this.onMediaAttached, this); 743 hls.on(_events__WEBPACK_IMPORTED_MODULE_2__.Events.MEDIA_DETACHING, this.onMediaDetaching, this); 744 hls.on(_events__WEBPACK_IMPORTED_MODULE_2__.Events.MANIFEST_LOADING, this.onManifestLoading, this); 745 hls.on(_events__WEBPACK_IMPORTED_MODULE_2__.Events.LEVEL_LOADED, this.onLevelLoaded, this); 746 hls.on(_events__WEBPACK_IMPORTED_MODULE_2__.Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this); 747 hls.on(_events__WEBPACK_IMPORTED_MODULE_2__.Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this); 748 hls.on(_events__WEBPACK_IMPORTED_MODULE_2__.Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this); 749 hls.on(_events__WEBPACK_IMPORTED_MODULE_2__.Events.ERROR, this.onError, this); 750 hls.on(_events__WEBPACK_IMPORTED_MODULE_2__.Events.BUFFER_RESET, this.onBufferReset, this); 751 hls.on(_events__WEBPACK_IMPORTED_MODULE_2__.Events.BUFFER_CREATED, this.onBufferCreated, this); 752 hls.on(_events__WEBPACK_IMPORTED_MODULE_2__.Events.BUFFER_FLUSHED, this.onBufferFlushed, this); 753 hls.on(_events__WEBPACK_IMPORTED_MODULE_2__.Events.INIT_PTS_FOUND, this.onInitPtsFound, this); 754 hls.on(_events__WEBPACK_IMPORTED_MODULE_2__.Events.FRAG_BUFFERED, this.onFragBuffered, this); 755 }; 756 _proto._unregisterListeners = function _unregisterListeners() { 757 var hls = this.hls; 758 hls.off(_events__WEBPACK_IMPORTED_MODULE_2__.Events.MEDIA_ATTACHED, this.onMediaAttached, this); 759 hls.off(_events__WEBPACK_IMPORTED_MODULE_2__.Events.MEDIA_DETACHING, this.onMediaDetaching, this); 760 hls.off(_events__WEBPACK_IMPORTED_MODULE_2__.Events.MANIFEST_LOADING, this.onManifestLoading, this); 761 hls.off(_events__WEBPACK_IMPORTED_MODULE_2__.Events.LEVEL_LOADED, this.onLevelLoaded, this); 762 hls.off(_events__WEBPACK_IMPORTED_MODULE_2__.Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this); 763 hls.off(_events__WEBPACK_IMPORTED_MODULE_2__.Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this); 764 hls.off(_events__WEBPACK_IMPORTED_MODULE_2__.Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this); 765 hls.off(_events__WEBPACK_IMPORTED_MODULE_2__.Events.ERROR, this.onError, this); 766 hls.off(_events__WEBPACK_IMPORTED_MODULE_2__.Events.BUFFER_RESET, this.onBufferReset, this); 767 hls.off(_events__WEBPACK_IMPORTED_MODULE_2__.Events.BUFFER_CREATED, this.onBufferCreated, this); 768 hls.off(_events__WEBPACK_IMPORTED_MODULE_2__.Events.BUFFER_FLUSHED, this.onBufferFlushed, this); 769 hls.off(_events__WEBPACK_IMPORTED_MODULE_2__.Events.INIT_PTS_FOUND, this.onInitPtsFound, this); 770 hls.off(_events__WEBPACK_IMPORTED_MODULE_2__.Events.FRAG_BUFFERED, this.onFragBuffered, this); 771 } 772 773 // INIT_PTS_FOUND is triggered when the video track parsed in the stream-controller has a new PTS value 774 ; 775 _proto.onInitPtsFound = function onInitPtsFound(event, _ref) { 776 var frag = _ref.frag, 777 id = _ref.id, 778 initPTS = _ref.initPTS; 779 // Always update the new INIT PTS 780 // Can change due level switch 781 if (id === 'main') { 782 var cc = frag.cc; 783 this.initPTS[frag.cc] = initPTS; 784 this.log("InitPTS for cc: " + cc + " found from main: " + initPTS); 785 this.videoTrackCC = cc; 786 // If we are waiting, tick immediately to unblock audio fragment transmuxing 787 if (this.state === _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.WAITING_INIT_PTS) { 788 this.tick(); 789 } 790 } 791 }; 792 _proto.startLoad = function startLoad(startPosition) { 793 if (!this.levels) { 794 this.startPosition = startPosition; 795 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.STOPPED; 796 return; 797 } 798 var lastCurrentTime = this.lastCurrentTime; 799 this.stopLoad(); 800 this.setInterval(TICK_INTERVAL); 801 this.fragLoadError = 0; 802 if (lastCurrentTime > 0 && startPosition === -1) { 803 this.log("Override startPosition with lastCurrentTime @" + lastCurrentTime.toFixed(3)); 804 startPosition = lastCurrentTime; 805 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.IDLE; 806 } else { 807 this.loadedmetadata = false; 808 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.WAITING_TRACK; 809 } 810 this.nextLoadPosition = this.startPosition = this.lastCurrentTime = startPosition; 811 this.tick(); 812 }; 813 _proto.doTick = function doTick() { 814 switch (this.state) { 815 case _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.IDLE: 816 this.doTickIdle(); 817 break; 818 case _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.WAITING_TRACK: 819 { 820 var _levels$trackId; 821 var levels = this.levels, 822 trackId = this.trackId; 823 var details = levels === null || levels === void 0 ? void 0 : (_levels$trackId = levels[trackId]) === null || _levels$trackId === void 0 ? void 0 : _levels$trackId.details; 824 if (details) { 825 if (this.waitForCdnTuneIn(details)) { 826 break; 827 } 828 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.WAITING_INIT_PTS; 829 } 830 break; 831 } 832 case _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.FRAG_LOADING_WAITING_RETRY: 833 { 834 var _this$media; 835 var now = performance.now(); 836 var retryDate = this.retryDate; 837 // if current time is gt than retryDate, or if media seeking let's switch to IDLE state to retry loading 838 if (!retryDate || now >= retryDate || (_this$media = this.media) !== null && _this$media !== void 0 && _this$media.seeking) { 839 this.log('RetryDate reached, switch back to IDLE state'); 840 this.resetStartWhenNotLoaded(this.trackId); 841 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.IDLE; 842 } 843 break; 844 } 845 case _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.WAITING_INIT_PTS: 846 { 847 // Ensure we don't get stuck in the WAITING_INIT_PTS state if the waiting frag CC doesn't match any initPTS 848 var waitingData = this.waitingData; 849 if (waitingData) { 850 var frag = waitingData.frag, 851 part = waitingData.part, 852 cache = waitingData.cache, 853 complete = waitingData.complete; 854 if (this.initPTS[frag.cc] !== undefined) { 855 this.waitingData = null; 856 this.waitingVideoCC = -1; 857 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.FRAG_LOADING; 858 var payload = cache.flush(); 859 var data = { 860 frag: frag, 861 part: part, 862 payload: payload, 863 networkDetails: null 864 }; 865 this._handleFragmentLoadProgress(data); 866 if (complete) { 867 _BaseStreamController.prototype._handleFragmentLoadComplete.call(this, data); 868 } 869 } else if (this.videoTrackCC !== this.waitingVideoCC) { 870 // Drop waiting fragment if videoTrackCC has changed since waitingFragment was set and initPTS was not found 871 this.log("Waiting fragment cc (" + frag.cc + ") cancelled because video is at cc " + this.videoTrackCC); 872 this.clearWaitingFragment(); 873 } else { 874 // Drop waiting fragment if an earlier fragment is needed 875 var pos = this.getLoadPosition(); 876 var bufferInfo = _utils_buffer_helper__WEBPACK_IMPORTED_MODULE_3__.BufferHelper.bufferInfo(this.mediaBuffer, pos, this.config.maxBufferHole); 877 var waitingFragmentAtPosition = (0,_fragment_finders__WEBPACK_IMPORTED_MODULE_11__.fragmentWithinToleranceTest)(bufferInfo.end, this.config.maxFragLookUpTolerance, frag); 878 if (waitingFragmentAtPosition < 0) { 879 this.log("Waiting fragment cc (" + frag.cc + ") @ " + frag.start + " cancelled because another fragment at " + bufferInfo.end + " is needed"); 880 this.clearWaitingFragment(); 881 } 882 } 883 } else { 884 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.IDLE; 885 } 886 } 887 } 888 this.onTickEnd(); 889 }; 890 _proto.clearWaitingFragment = function clearWaitingFragment() { 891 var waitingData = this.waitingData; 892 if (waitingData) { 893 this.fragmentTracker.removeFragment(waitingData.frag); 894 this.waitingData = null; 895 this.waitingVideoCC = -1; 896 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.IDLE; 897 } 898 }; 899 _proto.resetLoadingState = function resetLoadingState() { 900 this.clearWaitingFragment(); 901 _BaseStreamController.prototype.resetLoadingState.call(this); 902 }; 903 _proto.onTickEnd = function onTickEnd() { 904 var media = this.media; 905 if (!media || !media.readyState) { 906 // Exit early if we don't have media or if the media hasn't buffered anything yet (readyState 0) 907 return; 908 } 909 this.lastCurrentTime = media.currentTime; 910 }; 911 _proto.doTickIdle = function doTickIdle() { 912 var hls = this.hls, 913 levels = this.levels, 914 media = this.media, 915 trackId = this.trackId; 916 var config = hls.config; 917 if (!levels || !levels[trackId]) { 918 return; 919 } 920 921 // if video not attached AND 922 // start fragment already requested OR start frag prefetch not enabled 923 // exit loop 924 // => if media not attached but start frag prefetch is enabled and start frag not requested yet, we will not exit loop 925 if (!media && (this.startFragRequested || !config.startFragPrefetch)) { 926 return; 927 } 928 var levelInfo = levels[trackId];
929 var trackDetails = levelInfo.details; 930 if (!trackDetails || trackDetails.live && this.levelLastLoaded !== trackId || this.waitForCdnTuneIn(trackDetails)) { 931 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.WAITING_TRACK; 932 return; 933 } 934 var bufferable = this.mediaBuffer ? this.mediaBuffer : this.media; 935 if (this.bufferFlushed && bufferable) { 936 this.bufferFlushed = false; 937 this.afterBufferFlushed(bufferable, _loader_fragment__WEBPACK_IMPORTED_MODULE_7__.ElementaryStreamTypes.AUDIO, _types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistLevelType.AUDIO); 938 } 939 var bufferInfo = this.getFwdBufferInfo(bufferable, _types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistLevelType.AUDIO); 940 if (bufferInfo === null) { 941 return; 942 } 943 var audioSwitch = this.audioSwitch; 944 if (!audioSwitch && this._streamEnded(bufferInfo, trackDetails)) { 945 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_2__.Events.BUFFER_EOS, { 946 type: 'audio' 947 }); 948 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.ENDED; 949 return; 950 } 951 var mainBufferInfo = this.getFwdBufferInfo(this.videoBuffer ? this.videoBuffer : this.media, _types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistLevelType.MAIN); 952 var bufferLen = bufferInfo.len; 953 var maxBufLen = this.getMaxBufferLength(mainBufferInfo === null || mainBufferInfo === void 0 ? void 0 : mainBufferInfo.len); 954 955 // if buffer length is less than maxBufLen try to load a new fragment 956 if (bufferLen >= maxBufLen && !audioSwitch) { 957 return; 958 } 959 var fragments = trackDetails.fragments; 960 var start = fragments[0].start; 961 var targetBufferTime = bufferInfo.end; 962 if (audioSwitch && media) { 963 var pos = this.getLoadPosition(); 964 targetBufferTime = pos; 965 // if currentTime (pos) is less than alt audio playlist start time, it means that alt audio is ahead of currentTime 966 if (trackDetails.PTSKnown && pos < start) { 967 // if everything is buffered from pos to start or if audio buffer upfront, let's seek to start 968 if (bufferInfo.end > start || bufferInfo.nextStart) { 969 this.log('Alt audio track ahead of main track, seek to start of alt audio track'); 970 media.currentTime = start + 0.05; 971 } 972 } 973 } 974 975 // buffer audio up to one target duration ahead of main buffer 976 if (mainBufferInfo && targetBufferTime > mainBufferInfo.end + trackDetails.targetduration) { 977 return; 978 } 979 // wait for main buffer after buffing some audio 980 if ((!mainBufferInfo || !mainBufferInfo.len) && bufferInfo.len) { 981 return; 982 } 983 var frag = this.getNextFragment(targetBufferTime, trackDetails); 984 if (!frag) { 985 this.bufferFlushed = true; 986 return; 987 } 988 this.loadFragment(frag, trackDetails, targetBufferTime); 989 }; 990 _proto.getMaxBufferLength = function getMaxBufferLength(mainBufferLength) { 991 var maxConfigBuffer = _BaseStreamController.prototype.getMaxBufferLength.call(this); 992 if (!mainBufferLength) { 993 return maxConfigBuffer; 994 } 995 return Math.max(maxConfigBuffer, mainBufferLength); 996 }; 997 _proto.onMediaDetaching = function onMediaDetaching() { 998 this.videoBuffer = null; 999 _BaseStreamController.prototype.onMediaDetaching.call(this); 1000 }; 1001 _proto.onAudioTracksUpdated = function onAudioTracksUpdated(event, _ref2) { 1002 var audioTracks = _ref2.audioTracks; 1003 this.resetTransmuxer(); 1004 this.levels = audioTracks.map(function (mediaPlaylist) { 1005 return new _types_level__WEBPACK_IMPORTED_MODULE_5__.Level(mediaPlaylist); 1006 }); 1007 }; 1008 _proto.onAudioTrackSwitching = function onAudioTrackSwitching(event, data) { 1009 // if any URL found on new audio track, it is an alternate audio track 1010 var altAudio = !!data.url; 1011 this.trackId = data.id; 1012 var fragCurrent = this.fragCurrent; 1013 if (fragCurrent) { 1014 fragCurrent.abortRequests(); 1015 } 1016 this.fragCurrent = null; 1017 this.clearWaitingFragment(); 1018 // destroy useless transmuxer when switching audio to main 1019 if (!altAudio) { 1020 this.resetTransmuxer(); 1021 } else { 1022 // switching to audio track, start timer if not already started 1023 this.setInterval(TICK_INTERVAL); 1024 } 1025 1026 // should we switch tracks ? 1027 if (altAudio) { 1028 this.audioSwitch = true; 1029 // main audio track are handled by stream-controller, just do something if switching to alt audio track 1030 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.IDLE; 1031 } else { 1032 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.STOPPED; 1033 } 1034 this.tick(); 1035 }; 1036 _proto.onManifestLoading = function onManifestLoading() { 1037 this.mainDetails = null; 1038 this.fragmentTracker.removeAllFragments(); 1039 this.startPosition = this.lastCurrentTime = 0; 1040 this.bufferFlushed = false;
1041 }; 1042 _proto.onLevelLoaded = function onLevelLoaded(event, data) { 1043 this.mainDetails = data.details; 1044 if (this.cachedTrackLoadedData !== null) { 1045 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_2__.Events.AUDIO_TRACK_LOADED, this.cachedTrackLoadedData); 1046 this.cachedTrackLoadedData = null; 1047 } 1048 }; 1049 _proto.onAudioTrackLoaded = function onAudioTrackLoaded(event, data) { 1050 var _track$details; 1051 if (this.mainDetails == null) { 1052 this.cachedTrackLoadedData = data; 1053 return; 1054 } 1055 var levels = this.levels; 1056 var newDetails = data.details, 1057 trackId = data.id; 1058 if (!levels) { 1059 this.warn("Audio tracks were reset while loading level " + trackId); 1060 return; 1061 } 1062 this.log("Track " + trackId + " loaded [" + newDetails.startSN + "," + newDetails.endSN + "],duration:" + newDetails.totalduration); 1063 var track = levels[trackId]; 1064 var sliding = 0; 1065 if (newDetails.live || (_track$details = track.details) !== null && _track$details !== void 0 && _track$details.live) { 1066 var mainDetails = this.mainDetails; 1067 if (!newDetails.fragments[0]) { 1068 newDetails.deltaUpdateFailed = true; 1069 } 1070 if (newDetails.deltaUpdateFailed || !mainDetails) { 1071 return; 1072 } 1073 if (!track.details && newDetails.hasProgramDateTime && mainDetails.hasProgramDateTime) { 1074 // Make sure our audio rendition is aligned with the "main" rendition, using 1075 // pdt as our reference times. 1076 (0,_utils_discontinuities__WEBPACK_IMPORTED_MODULE_12__.alignMediaPlaylistByPDT)(newDetails, mainDetails); 1077 sliding = newDetails.fragments[0].start; 1078 } else { 1079 sliding = this.alignPlaylists(newDetails, track.details); 1080 } 1081 } 1082 track.details = newDetails; 1083 this.levelLastLoaded = trackId; 1084 1085 // compute start position if we are aligned with the main playlist 1086 if (!this.startFragRequested && (this.mainDetails || !newDetails.live)) { 1087 this.setStartPosition(track.details, sliding); 1088 } 1089 // only switch back to IDLE state if we were waiting for track to start downloading a new fragment 1090 if (this.state === _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.WAITING_TRACK && !this.waitForCdnTuneIn(newDetails)) { 1091 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.IDLE; 1092 } 1093 1094 // trigger handler right now 1095 this.tick(); 1096 }; 1097 _proto._handleFragmentLoadProgress = function _handleFragmentLoadProgress(data) { 1098 var _frag$initSegment; 1099 var frag = data.frag, 1100 part = data.part, 1101 payload = data.payload; 1102 var config = this.config, 1103 trackId = this.trackId, 1104 levels = this.levels; 1105 if (!levels) { 1106 this.warn("Audio tracks were reset while fragment load was in progress. Fragment " + frag.sn + " of level " + frag.level + " will not be buffered"); 1107 return; 1108 } 1109 var track = levels[trackId]; 1110 console.assert(track, 'Audio track is defined on fragment load progress'); 1111 var details = track.details; 1112 console.assert(details, 'Audio track details are defined on fragment load progress'); 1113 var audioCodec = config.defaultAudioCodec || track.audioCodec || 'mp4a.40.2'; 1114 var transmuxer = this.transmuxer; 1115 if (!transmuxer) { 1116 transmuxer = this.transmuxer = new _demux_transmuxer_interface__WEBPACK_IMPORTED_MODULE_9__["default"](this.hls, _types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistLevelType.AUDIO, this._handleTransmuxComplete.bind(this), this._handleTransmuxerFlush.bind(this)); 1117 } 1118 1119 // Check if we have video initPTS 1120 // If not we need to wait for it 1121 var initPTS = this.initPTS[frag.cc]; 1122 var initSegmentData = (_frag$initSegment = frag.initSegment) === null || _frag$initSegment === void 0 ? void 0 : _frag$initSegment.data; 1123 if (initPTS !== undefined) { 1124 // this.log(`Transmuxing ${sn} of [${details.startSN} ,${details.endSN}],track ${trackId}`); 1125 // time Offset is accurate if level PTS is known, or if playlist is not sliding (not live) 1126 var accurateTimeOffset = false; // details.PTSKnown || !details.live; 1127 var partIndex = part ? part.index : -1; 1128 var partial = partIndex !== -1; 1129 var chunkMeta = new _types_transmuxer__WEBPACK_IMPORTED_MODULE_10__.ChunkMetadata(frag.level, frag.sn, frag.stats.chunkCount, payload.byteLength, partIndex, partial); 1130 transmuxer.push(payload, initSegmentData, audioCodec, '', frag, part, details.totalduration, accurateTimeOff
1130set, chunkMeta, initPTS); 1131 } else { 1132 this.log("Unknown video PTS for cc " + frag.cc + ", waiting for video PTS before demuxing audio frag " + frag.sn + " of [" + details.startSN + " ," + details.endSN + "],track " + trackId); 1133 var _this$waitingData = this.waitingData = this.waitingData || { 1134 frag: frag, 1135 part: part, 1136 cache: new _demux_chunk_cache__WEBPACK_IMPORTED_MODULE_8__["default"](), 1137 complete: false 1138 }, 1139 cache = _this$waitingData.cache; 1140 cache.push(new Uint8Array(payload)); 1141 this.waitingVideoCC = this.videoTrackCC; 1142 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.WAITING_INIT_PTS; 1143 } 1144 }; 1145 _proto._handleFragmentLoadComplete = function _handleFragmentLoadComplete(fragLoadedData) { 1146 if (this.waitingData) { 1147 this.waitingData.complete = true; 1148 return; 1149 } 1150 _BaseStreamController.prototype._handleFragmentLoadComplete.call(this, fragLoadedData); 1151 }; 1152 _proto.onBufferReset = function onBufferReset( /* event: Events.BUFFER_RESET */ 1153 ) { 1154 // reset reference to sourcebuffers 1155 this.mediaBuffer = this.videoBuffer = null; 1156 this.loadedmetadata = false; 1157 }; 1158 _proto.onBufferCreated = function onBufferCreated(event, data) { 1159 var audioTrack = data.tracks.audio; 1160 if (audioTrack) { 1161 this.mediaBuffer = audioTrack.buffer || null; 1162 } 1163 if (data.tracks.video) { 1164 this.videoBuffer = data.tracks.video.buffer || null; 1165 } 1166 }; 1167 _proto.onFragBuffered = function onFragBuffered(event, data) { 1168 var frag = data.frag, 1169 part = data.part; 1170 if (frag.type !== _types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistLevelType.AUDIO) { 1171 if (!this.loadedmetadata && frag.type === _types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistLevelType.MAIN) { 1172 var _ref3; 1173 if ((_ref3 = this.videoBuffer || this.media) !== null && _ref3 !== void 0 && _ref3.buffered.length) { 1174 this.loadedmetadata = true; 1175 } 1176 } 1177 return; 1178 } 1179 if (this.fragContextChanged(frag)) { 1180 // If a level switch was requested while a fragment was buffering, it will emit the FRAG_BUFFERED event upon completion 1181 // Avoid setting state back to IDLE or concluding the audio switch; otherwise, the switched-to track will not buffer 1182 this.warn("Fragment " + frag.sn + (part ? ' p: ' + part.index : '') + " of level " + frag.level + " finished buffering, but was aborted. state: " + this.state + ", audioSwitch: " + this.audioSwitch); 1183 return; 1184 } 1185 if (frag.sn !== 'initSegment') { 1186 this.fragPrevious = frag; 1187 if (this.audioSwitch) { 1188 this.audioSwitch = false; 1189 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_2__.Events.AUDIO_TRACK_SWITCHED, { 1190 id: this.trackId 1191 }); 1192 } 1193 } 1194 this.fragBufferedComplete(frag, part); 1195 }; 1196 _proto.onError = function onError(event, data) {
1197 if (data.type === _errors__WEBPACK_IMPORTED_MODULE_13__.ErrorTypes.KEY_SYSTEM_ERROR) { 1198 this.onFragmentOrKeyLoadError(_types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistLevelType.AUDIO, data); 1199 return; 1200 } 1201 switch (data.details) { 1202 case _errors__WEBPACK_IMPORTED_MODULE_13__.ErrorDetails.FRAG_LOAD_ERROR: 1203 case _errors__WEBPACK_IMPORTED_MODULE_13__.ErrorDetails.FRAG_LOAD_TIMEOUT: 1204 case _errors__WEBPACK_IMPORTED_MODULE_13__.ErrorDetails.FRAG_PARSING_ERROR: 1205 case _errors__WEBPACK_IMPORTED_MODULE_13__.ErrorDetails.KEY_LOAD_ERROR: 1206 case _errors__WEBPACK_IMPORTED_MODULE_13__.ErrorDetails.KEY_LOAD_TIMEOUT: 1207 // TODO: Skip fragments that do not belong to this.fragCurrent audio-group id 1208 this.onFragmentOrKeyLoadError(_types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistLevelType.AUDIO, data); 1209 break; 1210 case _errors__WEBPACK_IMPORTED_MODULE_13__.ErrorDetails.AUDIO_TRACK_LOAD_ERROR: 1211 case _errors__WEBPACK_IMPORTED_MODULE_13__.ErrorDetails.AUDIO_TRACK_LOAD_TIMEOUT: 1212 // when in ERROR state, don't switch back to IDLE state in case a non-fatal error is received 1213 if (this.state !== _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.ERROR && this.state !== _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.STOPPED) { 1214 // if fatal error, stop processing, otherwise move to IDLE to retry loading 1215 this.state = data.fatal ? _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.ERROR : _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.IDLE; 1216 this.warn(data.details + " while loading frag, switching to " + this.state + " state"); 1217 } 1218 break;
1219 case _errors__WEBPACK_IMPORTED_MODULE_13__.ErrorDetails.BUFFER_FULL_ERROR: 1220 // if in appending state 1221 if (data.parent === 'audio' && (this.state === _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.PARSING || this.state === _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.PARSED)) { 1222 var flushBuffer = true; 1223 var bufferedInfo = this.getFwdBufferInfo(this.mediaBuffer, _types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistLevelType.AUDIO); 1224 // 0.5 : tolerance needed as some browsers stalls playback before reaching buffered end 1225 // reduce max buf len if current position is buffered 1226 if (bufferedInfo && bufferedInfo.len > 0.5) { 1227 flushBuffer = !this.reduceMaxBufferLength(bufferedInfo.len); 1228 } 1229 if (flushBuffer) { 1230 // current position is not buffered, but browser is still complaining about buffer full error 1231 // this happens on IE/Edge, refer to https://github.com/video-dev/hls.js/pull/708 1232 // in that case flush the whole audio buffer to recover 1233 this.warn('Buffer full error also media.currentTime is not buffered, flush audio buffer'); 1234 this.fragCurrent = null; 1235 _BaseStreamController.prototype.flushMainBuffer.call(this, 0, Number.POSITIVE_INFINITY, 'audio'); 1236 } 1237 this.resetLoadingState(); 1238 } 1239 break; 1240 default: 1241 break; 1242 } 1243 }; 1244 _proto.onBufferFlushed = function onBufferFlushed(event, _ref4) { 1245 var type = _ref4.type; 1246 if (type === _loader_fragment__WEBPACK_IMPORTED_MODULE_7__.ElementaryStreamTypes.AUDIO) { 1247 this.bufferFlushed = true; 1248 if (this.state === _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.ENDED) { 1249 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.IDLE; 1250 } 1251 } 1252 }; 1253 _proto._handleTransmuxComplete = function _handleTransmuxComplete(transmuxResult) { 1254 var _id3$samples; 1255 var id = 'audio'; 1256 var hls = this.hls; 1257 var remuxResult = transmuxResult.remuxResult, 1258 chunkMeta = transmuxResult.chunkMeta; 1259 var context = this.getCurrentContext(chunkMeta); 1260 if (!context) { 1261 this.warn("The loading context changed while buffering fragment " + chunkMeta.sn + " of level " + chunkMeta.level + ". This chunk will not be buffered."); 1262 this.resetStartWhenNotLoaded(chunkMeta.level); 1263 return; 1264 } 1265 var frag = context.frag, 1266 part = context.part, 1267 details = context.level.details; 1268 var audio = remuxResult.audio, 1269 text = remuxResult.text, 1270 id3 = remuxResult.id3, 1271 initSegment = remuxResult.initSegment; 1272 1273 // Check if the current fragment has been aborted. We check this by first seeing if we're still playing the current level. 1274 // If we are, subsequently check if the currently loading fragment (fragCurrent) has changed. 1275 if (this.fragContextChanged(frag) || !details) { 1276 return; 1277 } 1278 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.PARSING; 1279 if (this.audioSwitch && audio) { 1280 this.completeAudioSwitch(); 1281 } 1282 if (initSegment !== null && initSegment !== void 0 && initSegment.tracks) { 1283 this._bufferInitSegment(initSegment.tracks, frag, chunkMeta); 1284 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_2__.Events.FRAG_PARSING_INIT_SEGMENT, { 1285 frag: frag, 1286 id: id, 1287 tracks: initSegment.tracks 1288 }); 1289 // Only flush audio from old audio tracks when PTS is known on new audio track 1290 } 1291 1292 if (audio) { 1293 var startPTS = audio.startPTS, 1294 endPTS = audio.endPTS, 1295 startDTS = audio.startDTS, 1296 endDTS = audio.endDTS; 1297 if (part) { 1298 part.elementaryStreams[_loader_fragment__WEBPACK_IMPORTED_MODULE_7__.ElementaryStreamTypes.AUDIO] = { 1299 startPTS: startPTS, 1300 endPTS: endPTS, 1301 startDTS: startDTS, 1302 endDTS: endDTS 1303 }; 1304 } 1305 frag.setElementaryStreamInfo(_loader_fragment__WEBPACK_IMPORTED_MODULE_7__.ElementaryStreamTypes.AUDIO, startPTS, endPTS, startDTS, endDTS); 1306 this.bufferFragmentData(audio, frag, part, chunkMeta); 1307 } 1308 if (id3 !== null && id3 !== void 0 && (_id3$samples = id3.samples) !== null && _id3$samples !== void 0 && _id3$samples.length) { 1309 var emittedID3 = _extends({ 1310 id: id, 1311 frag: frag, 1312 details: details 1313 }, id3); 1314 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_2__.Events.FRAG_PARSING_METADATA, emittedID3); 1315 } 1316 if (text) { 1317 var emittedText = _extends({ 1318 id: id, 1319 frag: frag, 1320 details: details 1321 }, text); 1322 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_2__.Events.FRAG_PARSING_USERDATA, emittedText); 1323 } 1324 }; 1325 _proto._bufferInitSegment = function _bufferInitSegment(tracks, frag, chunkMeta) { 1326 if (this.state !== _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.PARSING) { 1327 return; 1328 } 1329 // delete any video track found on audio transmuxer 1330 if (tracks.video) { 1331 delete tracks.video; 1332 } 1333 1334 // include levelCodec in audio and video tracks 1335 var track = tracks.audio; 1336 if (!track) { 1337 return; 1338 } 1339 track.levelCodec = track.codec; 1340 track.id = 'audio'; 1341 this.log("Init audio buffer, container:" + track.container + ", codecs[parsed]=[" + track.codec + "]"); 1342 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_2__.Events.BUFFER_CODECS, tracks); 1343 var initSegment = track.initSegment; 1344 if (initSegment !== null && initSegment !== void 0 && initSegment.byteLength) { 1345 var segment = { 1346 type: 'audio', 1347 frag: frag, 1348 part: null, 1349 chunkMeta: chunkMeta, 1350 parent: frag.type, 1351 data: initSegment 1352 }; 1353 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_2__.Events.BUFFER_APPENDING, segment); 1354 } 1355 // trigger handler right now 1356 this.tick(); 1357 };
1358 _proto.loadFragment = function loadFragment(frag, trackDetails, targetBufferTime) { 1359 // only load if fragment is not loaded or if in audio switch 1360 var fragState = this.fragmentTracker.getState(frag); 1361 this.fragCurrent = frag; 1362 1363 // we force a frag loading in audio switch as fragment tracker might not have evicted previous frags in case of quick audio switch 1364 if (this.audioSwitch || fragState === _fragment_tracker__WEBPACK_IMPORTED_MODULE_4__.FragmentState.NOT_LOADED || fragState === _fragment_tracker__WEBPACK_IMPORTED_MODULE_4__.FragmentState.PARTIAL) { 1365 if (frag.sn === 'initSegment') { 1366 this._loadInitSegment(frag, trackDetails); 1367 } else if (trackDetails.live && !(0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(this.initPTS[frag.cc])) { 1368 this.log("Waiting for video PTS in continuity counter " + frag.cc + " of live stream before loading audio fragment " + frag.sn + " of level " + this.trackId); 1369 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.WAITING_INIT_PTS; 1370 } else { 1371 this.startFragRequested = true; 1372 _BaseStreamController.prototype.loadFragment.call(this, frag, trackDetails, targetBufferTime); 1373 } 1374 } 1375 }; 1376 _proto.completeAudioSwitch = function completeAudioSwitch() { 1377 var hls = this.hls, 1378 media = this.media, 1379 trackId = this.trackId; 1380 if (media) { 1381 this.log('Switching audio track : flushing all audio'); 1382 _BaseStreamController.prototype.flushMainBuffer.call(this, 0, Number.POSITIVE_INFINITY, 'audio'); 1383 } 1384 this.audioSwitch = false; 1385 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_2__.Events.AUDIO_TRACK_SWITCHED, { 1386 id: trackId 1387 }); 1388 }; 1389 return AudioStreamController; 1390}(_base_stream_controller__WEBPACK_IMPORTED_MODULE_1__["default"]); 1391/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AudioStreamController); 1392 1393/***/ }), 1394
vendor: 6,550 bytes, lines 1395-1508
1395/***/ "./src/controller/audio-track-controller.ts": 1396/*!**************************************************!*\ 1397 !*** ./src/controller/audio-track-controller.ts ***! 1398 \**************************************************/ 1399/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 1400 1401"use strict"; 1402__webpack_require__.r(__webpack_exports__); 1403/* harmony export */ __webpack_require__.d(__webpack_exports__, { 1404/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 1405/* harmony export */ }); 1406/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 1407/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../errors */ "./src/errors.ts"); 1408/* harmony import */ var _base_playlist_controller__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./base-playlist-controller */ "./src/controller/base-playlist-controller.ts"); 1409/* harmony import */ var _types_loader__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../types/loader */ "./src/types/loader.ts"); 1410function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } 1411function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } 1412function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } 1413function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } 1414function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); } 1415function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } 1416 1417 1418 1419 1420var AudioTrackController = /*#__PURE__*/function (_BasePlaylistControll) { 1421 _inheritsLoose(AudioTrackController, _BasePlaylistControll); 1422 function AudioTrackController(hls) { 1423 var _this; 1424 _this = _BasePlaylistControll.call(this, hls, '[audio-track-controller]') || this; 1425 _this.tracks = []; 1426 _this.groupId = null; 1427 _this.tracksInGroup = []; 1428 _this.trackId = -1; 1429 _this.trackName = ''; 1430 _this.selectDefaultTrack = true; 1431 _this.registerListeners(); 1432 return _this; 1433 } 1434 var _proto = AudioTrackController.prototype; 1435 _proto.registerListeners = function registerListeners() { 1436 var hls = this.hls; 1437 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MANIFEST_LOADING, this.onManifestLoading, this); 1438 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MANIFEST_PARSED, this.onManifestParsed, this); 1439 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.LEVEL_LOADING, this.onLevelLoading, this); 1440 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.LEVEL_SWITCHING, this.onLevelSwitching, this); 1441 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this); 1442 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.ERROR, this.onError, this); 1443 }; 1444 _proto.unregisterListeners = function unregisterListeners() { 1445 var hls = this.hls; 1446 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MANIFEST_LOADING, this.onManifestLoading, this); 1447 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MANIFEST_PARSED, this.onManifestParsed, this); 1448 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.LEVEL_LOADING, this.onLevelLoading, this); 1449 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.LEVEL_SWITCHING, this.onLevelSwitching, this); 1450 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this); 1451 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.ERROR, this.onError, this); 1452 }; 1453 _proto.destroy = function destroy() { 1454 this.unregisterListeners(); 1455 this.tracks.length = 0; 1456 this.tracksInGroup.length = 0; 1457 _BasePlaylistControll.prototype.destroy.call(this); 1458 }; 1459 _proto.onManifestLoading = function onManifestLoading() { 1460 this.tracks = []; 1461 this.groupId = null; 1462 this.tracksInGroup = []; 1463 this.trackId = -1; 1464 this.trackName = ''; 1465 this.selectDefaultTrack = true; 1466 }; 1467 _proto.onManifestParsed = function onManifestParsed(event, data) { 1468 this.tracks = data.audioTracks || []; 1469 }; 1470 _proto.onAudioTrackLoaded = function onAudioTrackLoaded(event, data) { 1471 var id = data.id, 1472 details = data.details; 1473 var currentTrack = this.tracksInGroup[id]; 1474 if (!currentTrack) { 1475 this.warn("Invalid audio track id " + id); 1476 return; 1477 } 1478 var curDetails = currentTrack.details; 1479 currentTrack.details = data.details; 1480 this.log("audioTrack " + id + " loaded [" + details.startSN + "-" + details.endSN + "]"); 1481 if (id === this.trackId) { 1482 this.retryCount = 0; 1483 this.playlistLoaded(id, data, curDetails); 1484 } 1485 }; 1486 _proto.onLevelLoading = function onLevelLoading(event, data) { 1487 this.switchLevel(data.level); 1488 }; 1489 _proto.onLevelSwitching = function onLevelSwitching(event, data) { 1490 this.switchLevel(data.level); 1491 }; 1492 _proto.switchLevel = function switchLevel(levelIndex) { 1493 var levelInfo = this.hls.levels[levelIndex]; 1494 if (!(levelInfo !== null && levelInfo !== void 0 && levelInfo.audioGroupIds)) { 1495 return; 1496 } 1497 var audioGroupId = levelInfo.audioGroupIds[levelInfo.urlId]; 1498 if (this.groupId !== audioGroupId) { 1499 this.groupId = audioGroupId; 1500 var audioTracks = this.tracks.filter(function (track) { 1501 return !audioGroupId || track.groupId === audioGroupId; 1502 }); 1503 1504 // Disable selectDefaultTrack if there are no default tracks 1505 if (this.selectDefaultTrack && !audioTracks.some(function (track) { 1506 return track.default; 1507 })) { 1508 this.selectDefaultTrack = false;
1509 } 1510 this.tracksInGroup = audioTracks; 1511 var audioTracksUpdated = { 1512 audioTracks: audioTracks 1513 }; 1514 this.log("Updating audio tracks, " + audioTracks.length + " track(s) found in \"" + audioGroupId + "\" group-id"); 1515 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_0__.Events.AUDIO_TRACKS_UPDATED, audioTracksUpdated); 1516 this.selectInitialTrack(); 1517 } 1518 }; 1519 _proto.onError = function onError(event, data) { 1520 _BasePlaylistControll.prototype.onError.call(this, event, data); 1521 if (data.fatal || !data.context) { 1522 return; 1523 } 1524 if (data.context.type === _types_loader__WEBPACK_IMPORTED_MODULE_3__.PlaylistContextType.AUDIO_TRACK && data.context.id === this.trackId && data.context.groupId === this.groupId) { 1525 this.retryLoadingOrFail(data); 1526 } 1527 }; 1528 _proto.setAudioTrack = function setAudioTrack(newId) { 1529 var tracks = this.tracksInGroup; 1530 1531 // check if level idx is valid 1532 if (newId < 0 || newId >= tracks.length) { 1533 this.warn('Invalid id passed to audio-track controller'); 1534 return; 1535 } 1536 1537 // stopping live reloading timer if any 1538 this.clearTimer(); 1539 var lastTrack = tracks[this.trackId]; 1540 this.log("Now switching to audio-track index " + newId); 1541 var track = tracks[newId]; 1542 var id = track.id, 1543 _track$groupId = track.groupId, 1544 groupId = _track$groupId === void 0 ? '' : _track$groupId, 1545 name = track.name, 1546 type = track.type, 1547 url = track.url; 1548 this.trackId = newId; 1549 this.trackName = name; 1550 this.selectDefaultTrack = false; 1551 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_0__.Events.AUDIO_TRACK_SWITCHING, { 1552 id: id, 1553 groupId: groupId, 1554 name: name, 1555 type: type, 1556 url: url 1557 }); 1558 // Do not reload track unless live 1559 if (track.details && !track.details.live) { 1560 return; 1561 } 1562 var hlsUrlParameters = this.switchParams(track.url, lastTrack === null || lastTrack === void 0 ? void 0 : lastTrack.details); 1563 this.loadPlaylist(hlsUrlParameters); 1564 }; 1565 _proto.selectInitialTrack = function selectInitialTrack() { 1566 var audioTracks = this.tracksInGroup; 1567 console.assert(audioTracks.length, 'Initial audio track should be selected when tracks are known'); 1568 var currentAudioTrackName = this.trackName; 1569 var trackId = this.findTrackId(currentAudioTrackName) || this.findTrackId(); 1570 if (trackId !== -1) { 1571 this.setAudioTrack(trackId); 1572 } else { 1573 this.warn("No track found for running audio group-ID: " + this.groupId); 1574 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_0__.Events.ERROR, { 1575 type: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorTypes.MEDIA_ERROR, 1576 details: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorDetails.AUDIO_TRACK_LOAD_ERROR, 1577 fatal: true 1578 }); 1579 } 1580 }; 1581 _proto.findTrackId = function findTrackId(name) { 1582 var audioTracks = this.tracksInGroup; 1583 for (var i = 0; i < audioTracks.length; i++) { 1584 var track = audioTracks[i]; 1585 if (!this.selectDefaultTrack || track.default) { 1586 if (!name || name === track.name) { 1587 return track.id; 1588 } 1589 } 1590 } 1591 return -1; 1592 }; 1593 _proto.loadPlaylist = function loadPlaylist(hlsUrlParameters) { 1594 _BasePlaylistControll.prototype.loadPlaylist.call(this); 1595 var audioTrack = this.tracksInGroup[this.trackId]; 1596 if (this.shouldLoadTrack(audioTrack)) { 1597 var id = audioTrack.id; 1598 var groupId = audioTrack.groupId; 1599 var url = audioTrack.url; 1600 if (hlsUrlParameters) { 1601 try { 1602 url = hlsUrlParameters.addDirectives(url); 1603 } catch (error) { 1604 this.warn("Could not construct new URL with HLS Delivery Directives: " + error); 1605 } 1606 } 1607 // track not retrieved yet, or live playlist we need to (re)load it 1608 this.log("loading audio-track playlist for id: " + id); 1609 this.clearTimer(); 1610 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_0__.Events.AUDIO_TRACK_LOADING, { 1611 url: url, 1612 id: id, 1613 groupId: groupId, 1614 deliveryDirectives: hlsUrlParameters || null 1615 }); 1616 } 1617 }; 1618 _createClass(AudioTrackController, [{ 1619 key: "audioTracks", 1620 get: function get() { 1621 return this.tracksInGroup; 1622 } 1623 }, { 1624 key: "audioTrack", 1625 get: function get() { 1626 return this.trackId; 1627 }, 1628 set: function set(newId) { 1629 // If audio track is selected from API then don't choose from the manifest default track 1630 this.selectDefaultTrack = false;
1631 this.setAudioTrack(newId); 1632 } 1633 }]); 1634 return AudioTrackController; 1635}(_base_playlist_controller__WEBPACK_IMPORTED_MODULE_2__["default"]); 1636/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AudioTrack
vendor: 30,778 bytes, lines 1636-2282
1636Controller); 1637 1638/***/ }), 1639 1640/***/ "./src/controller/base-playlist-controller.ts": 1641/*!****************************************************!*\ 1642 !*** ./src/controller/base-playlist-controller.ts ***! 1643 \****************************************************/ 1644/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 1645 1646"use strict"; 1647__webpack_require__.r(__webpack_exports__); 1648/* harmony export */ __webpack_require__.d(__webpack_exports__, { 1649/* harmony export */ "default": () => (/* binding */ BasePlaylistController) 1650/* harmony export */ }); 1651/* harmony import */ var _types_level__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../types/level */ "./src/types/level.ts"); 1652/* harmony import */ var _level_helper__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./level-helper */ "./src/controller/level-helper.ts"); 1653/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 1654/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../errors */ "./src/errors.ts"); 1655 1656 1657 1658 1659var BasePlaylistController = /*#__PURE__*/function () { 1660 function BasePlaylistController(hls, logPrefix) { 1661 this.hls = void 0; 1662 this.timer = -1; 1663 this.requestScheduled = -1; 1664 this.canLoad = false; 1665 this.retryCount = 0; 1666 this.log = void 0; 1667 this.warn = void 0; 1668 this.log = _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.log.bind(_utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger, logPrefix + ":"); 1669 this.warn = _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.warn.bind(_utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger, logPrefix + ":"); 1670 this.hls = hls; 1671 } 1672 var _proto = BasePlaylistController.prototype; 1673 _proto.destroy = function destroy() { 1674 this.clearTimer(); 1675 // @ts-ignore 1676 this.hls = this.log = this.warn = null; 1677 }; 1678 _proto.onError = function onError(event, data) { 1679 if (data.fatal && (data.type === _errors__WEBPACK_IMPORTED_MODULE_3__.ErrorTypes.NETWORK_ERROR || data.type === _errors__WEBPACK_IMPORTED_MODULE_3__.ErrorTypes.KEY_SYSTEM_ERROR)) { 1680 this.stopLoad(); 1681 } 1682 }; 1683 _proto.clearTimer = function clearTimer() { 1684 clearTimeout(this.timer); 1685 this.timer = -1; 1686 }; 1687 _proto.startLoad = function startLoad() { 1688 this.canLoad = true; 1689 this.retryCount = 0; 1690 this.requestScheduled = -1; 1691 this.loadPlaylist(); 1692 }; 1693 _proto.stopLoad = function stopLoad() { 1694 this.canLoad = false; 1695 this.clearTimer(); 1696 }; 1697 _proto.switchParams = function switchParams(playlistUri, previous) { 1698 var renditionReports = previous === null || previous === void 0 ? void 0 : previous.renditionReports; 1699 if (renditionReports) { 1700 for (var i = 0; i < renditionReports.length; i++) { 1701 var attr = renditionReports[i]; 1702 var uri = void 0; 1703 try { 1704 uri = new self.URL(attr.URI, previous.url).href; 1705 } catch (error) { 1706 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.warn("Could not construct new URL for Rendition Report: " + error); 1707 uri = attr.URI || ''; 1708 } 1709 if (uri === playlistUri.slice(-uri.length)) { 1710 var msn = parseInt(attr['LAST-MSN']) || (previous === null || previous === void 0 ? void 0 : previous.lastPartSn); 1711 var part = parseInt(attr['LAST-PART']) || (previous === null || previous === void 0 ? void 0 : previous.lastPartIndex); 1712 if (this.hls.config.lowLatencyMode) { 1713 var currentGoal = Math.min(previous.age - previous.partTarget, previous.targetduration); 1714 if (part >= 0 && currentGoal > previous.partTarget) { 1715 part += 1; 1716 } 1717 } 1718 return new _types_level__WEBPACK_IMPORTED_MODULE_0__.HlsUrlParameters(msn, part >= 0 ? part : undefined, _types_level__WEBPACK_IMPORTED_MODULE_0__.HlsSkip.No); 1719 } 1720 } 1721 } 1722 }; 1723 _proto.loadPlaylist = function loadPlaylist(hlsUrlParameters) { 1724 if (this.requestScheduled === -1) { 1725 this.requestScheduled = self.performance.now(); 1726 } 1727 }; 1728 _proto.shouldLoadTrack = function shouldLoadTrack(track) { 1729 return this.canLoad && track && !!track.url && (!track.details || track.details.live); 1730 }; 1731 _proto.playlistLoaded = function playlistLoaded(index, data, previousDetails) { 1732 var _this = this; 1733 var details = data.details, 1734 stats = data.stats; 1735 1736 // Set last updated date-time 1737 var now = self.performance.now(); 1738 var elapsed = stats.loading.first ? Math.max(0, now - stats.loading.first) : 0; 1739 details.advancedDateTime = Date.now() - elapsed; 1740 1741 // if current playlist is a live playlist, arm a timer to reload it 1742 if (details.live || previousDetails !== null && previousDetails !== void 0 && previousDetails.live) { 1743 details.reloaded(previousDetails); 1744 if (previousDetails) { 1745 this.log("live playlist " + index + " " + (details.advanced ? 'REFRESHED ' + details.lastPartSn + '-' + details.lastPartIndex : 'MISSED')); 1746 } 1747 // Merge live playlists to adjust fragment starts and fill in delta playlist skipped segments 1748 if (previousDetails && details.fragments.length > 0) { 1749 (0,_level_helper__WEBPACK_IMPORTED_MODULE_1__.mergeDetails)(previousDetails, details); 1750 } 1751 if (!this.canLoad || !details.live) { 1752 return; 1753 } 1754 var deliveryDirectives; 1755 var msn = undefined; 1756 var part = undefined; 1757 if (details.canBlockReload && details.endSN && details.advanced) { 1758 // Load level with LL-HLS delivery directives 1759 var lowLatencyMode = this.hls.config.lowLatencyMode; 1760 var lastPartSn = details.lastPartSn; 1761 var endSn = details.endSN; 1762 var lastPartIndex = details.lastPartIndex; 1763 var hasParts = lastPartIndex !== -1; 1764 var lastPart = lastPartSn === endSn; 1765 // When low latency mode is disabled, we'll skip part requests once the last part index is found 1766 var nextSnStartIndex = lowLatencyMode ? 0 : lastPartIndex; 1767 if (hasParts) { 1768 msn = lastPart ? endSn + 1 : lastPartSn; 1769 part = lastPart ? nextSnStartIndex : lastPartIndex + 1; 1770 } else { 1771 msn = endSn + 1; 1772 } 1773 // Low-Latency CDN Tune-in: "age" header and time since load indicates we're behind by more than one part 1774 // Update directives to obtain the Playlist that has the estimated additional duration of media 1775 var lastAdvanced = details.age; 1776 var cdnAge = lastAdvanced + details.ageHeader; 1777 var currentGoal = Math.min(cdnAge - details.partTarget, details.targetduration * 1.5); 1778 if (currentGoal > 0) { 1779 if (previousDetails && currentGoal > previousDetails.tuneInGoal) { 1780 // If we attempted to get the next or latest playlist update, but currentGoal increased, 1781 // then we either can't catchup, or the "age" header cannot be trusted. 1782 this.warn("CDN Tune-in goal increased from: " + previousDetails.tuneInGoal + " to: " + currentGoal + " with playlist age: " + details.age); 1783 currentGoal = 0; 1784 } else { 1785 var segments = Math.floor(currentGoal / details.targetduration); 1786 msn += segments; 1787 if (part !== undefined) { 1788 var parts = Math.round(currentGoal % details.targetduration / details.partTarget); 1789 part += parts; 1790 } 1791 this.log("CDN Tune-in age: " + details.ageHeader + "s last advanced " + lastAdvanced.toFixed(2) + "s goal: " + currentGoal + " skip sn " + segments + " to part " + part); 1792 } 1793 details.tuneInGoal = currentGoal; 1794 } 1795 deliveryDirectives = this.getDeliveryDirectives(details, data.deliveryDirectives, msn, part); 1796 if (lowLatencyMode || !lastPart) { 1797 this.loadPlaylist(deliveryDirectives); 1798 return; 1799 } 1800 } else { 1801 deliveryDirectives = this.getDeliveryDirectives(details, data.deliveryDirectives, msn, part); 1802 } 1803 var bufferInfo = this.hls.mainForwardBufferInfo; 1804 var position = bufferInfo ? bufferInfo.end - bufferInfo.len : 0; 1805 var distanceToLiveEdgeMs = (details.edge - position) * 1000; 1806 var reloadInterval = (0,_level_helper__WEBPACK_IMPORTED_MODULE_1__.computeReloadInterval)(details, distanceToLiveEdgeMs); 1807 if (!details.updated) { 1808 this.requestScheduled = -1; 1809 } else if (now > this.requestScheduled + reloadInterval) { 1810 this.requestScheduled = stats.loading.start; 1811 } 1812 if (msn !== undefined && details.canBlockReload) { 1813 this.requestScheduled = stats.loading.first + reloadInterval - (details.partTarget * 1000 || 1000); 1814 } else { 1815 this.requestScheduled = (this.requestScheduled === -1 ? now : this.requestScheduled) + reloadInterval; 1816 } 1817 var estimatedTimeUntilUpdate = this.requestScheduled - now; 1818 estimatedTimeUntilUpdate = Math.max(0, estimatedTimeUntilUpdate); 1819 this.log("reload live playlist " + index + " in " + Math.round(estimatedTimeUntilUpdate) + " ms"); 1820 // this.log( 1821 // `live reload ${details.updated ? 'REFRESHED' : 'MISSED'} 1822 // reload in ${estimatedTimeUntilUpdate / 1000} 1823 // round trip ${(stats.loading.end - stats.loading.start) / 1000} 1824 // diff ${ 1825 // (reloadInterval - 1826 // (estimatedTimeUntilUpdate + stats.loading.end - stats.loading.start)) / 1827 // 1000 1828 // } 1829 // reload interval ${reloadInterval / 1000} 1830 // target duration ${details.targetduration} 1831 // distance to edge ${distanceToLiveEdgeMs / 1000}` 1832 // ); 1833 1834 this.timer = self.setTimeout(function () { 1835 return _this.loadPlaylist(deliveryDirectives); 1836 }, estimatedTimeUntilUpdate); 1837 } else { 1838 this.clearTimer(); 1839 } 1840 }; 1841 _proto.getDeliveryDirectives = function getDeliveryDirectives(details, previousDeliveryDirectives, msn, part) { 1842 var skip = (0,_types_level__WEBPACK_IMPORTED_MODULE_0__.getSkipValue)(details, msn); 1843 if (previousDeliveryDirectives !== null && previousDeliveryDirectives !== void 0 && previousDeliveryDirectives.skip && details.deltaUpdateFailed) { 1844 msn = previousDeliveryDirectives.msn; 1845 part = previousDeliveryDirectives.part; 1846 skip = _types_level__WEBPACK_IMPORTED_MODULE_0__.HlsSkip.No; 1847 } 1848 return new _types_level__WEBPACK_IMPORTED_MODULE_0__.HlsUrlParameters(msn, part, skip); 1849 }; 1850 _proto.retryLoadingOrFail = function retryLoadingOrFail(errorEvent) { 1851 var _this2 = this; 1852 var config = this.hls.config; 1853 var retry = this.retryCount < config.levelLoadingMaxRetry; 1854 if (retry) { 1855 var _errorEvent$context; 1856 this.requestScheduled = -1; 1857 this.retryCount++; 1858 if (errorEvent.details.indexOf('LoadTimeOut') > -1 && (_errorEvent$context = errorEvent.context) !== null && _errorEvent$context !== void 0 && _errorEvent$context.deliveryDirectives) { 1859 // The LL-HLS request already timed out so retry immediately 1860 this.warn("retry playlist loading #" + this.retryCount + " after \"" + errorEvent.details + "\""); 1861 this.loadPlaylist(); 1862 } else { 1863 // exponential backoff capped to max retry timeout 1864 var delay = Math.min(Math.pow(2, this.retryCount) * config.levelLoadingRetryDelay, config.levelLoadingMaxRetryTimeout); 1865 // Schedule level/track reload 1866 this.timer = self.setTimeout(function () { 1867 return _this2.loadPlaylist(); 1868 }, delay); 1869 this.warn("retry playlist loading #" + this.retryCount + " in " + delay + " ms after \"" + errorEvent.details + "\""); 1870 } 1871 } else { 1872 this.warn("cannot recover from error \"" + errorEvent.details + "\""); 1873 // stopping live reloading timer if any 1874 this.clearTimer(); 1875 // switch error to fatal 1876 errorEvent.fatal = true; 1877 } 1878 return retry; 1879 }; 1880 return BasePlaylistController; 1881}(); 1882 1883 1884/***/ }), 1885 1886/***/ "./src/controller/base-stream-controller.ts": 1887/*!**************************************************!*\ 1888 !*** ./src/controller/base-stream-controller.ts ***! 1889 \**************************************************/ 1890/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 1891 1892"use strict"; 1893__webpack_require__.r(__webpack_exports__); 1894/* harmony export */ __webpack_require__.d(__webpack_exports__, { 1895/* harmony export */ "State": () => (/* binding */ State), 1896/* harmony export */ "default": () => (/* binding */ BaseStreamController) 1897/* harmony export */ }); 1898/* harmony import */ var _home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.ts"); 1899/* harmony import */ var _task_loop__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../task-loop */ "./src/task-loop.ts"); 1900/* harmony import */ var _fragment_tracker__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./fragment-tracker */ "./src/controller/fragment-tracker.ts"); 1901/* harmony import */ var _utils_buffer_helper__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils/buffer-helper */ "./src/utils/buffer-helper.ts"); 1902/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 1903/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 1904/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../errors */ "./src/errors.ts"); 1905/* harmony import */ var _types_transmuxer__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../types/transmuxer */ "./src/types/transmuxer.ts"); 1906/* harmony import */ var _utils_mp4_tools__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../utils/mp4-tools */ "./src/utils/mp4-tools.ts"); 1907/* harmony import */ var _utils_discontinuities__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../utils/discontinuities */ "./src/utils/discontinuities.ts"); 1908/* harmony import */ var _fragment_finders__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./fragment-finders */ "./src/controller/fragment-finders.ts"); 1909/* harmony import */ var _level_helper__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./level-helper */ "./src/controller/level-helper.ts"); 1910/* harmony import */ var _loader_fragment_loader__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../loader/fragment-loader */ "./src/loader/fragment-loader.ts"); 1911/* harmony import */ var _crypt_decrypter__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../crypt/decrypter */ "./src/crypt/decrypter.ts"); 1912/* harmony import */ var _utils_time_ranges__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../utils/time-ranges */ "./src/utils/time-ranges.ts"); 1913/* harmony import */ var _types_loader__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../types/loader */ "./src/types/loader.ts"); 1914 1915 1916 1917 1918 1919function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } 1920function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } 1921function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } 1922function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } 1923function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } 1924function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); } 1925function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941var State = { 1942 STOPPED: 'STOPPED', 1943 IDLE: 'IDLE', 1944 KEY_LOADING: 'KEY_LOADING', 1945 FRAG_LOADING: 'FRAG_LOADING', 1946 FRAG_LOADING_WAITING_RETRY: 'FRAG_LOADING_WAITING_RETRY', 1947 WAITING_TRACK: 'WAITING_TRACK', 1948 PARSING: 'PARSING', 1949 PARSED: 'PARSED', 1950 ENDED: 'ENDED', 1951 ERROR: 'ERROR', 1952 WAITING_INIT_PTS: 'WAITING_INIT_PTS', 1953 WAITING_LEVEL: 'WAITING_LEVEL' 1954}; 1955var BaseStreamController = /*#__PURE__*/function (_TaskLoop) { 1956 _inheritsLoose(BaseStreamController, _TaskLoop); 1957 function BaseStreamController(hls, fragmentTracker, keyLoader, logPrefix) { 1958 var _this; 1959 _this = _TaskLoop.call(this) || this; 1960 _this.hls = void 0; 1961 _this.fragPrevious = null; 1962 _this.fragCurrent = null; 1963 _this.fragmentTracker = void 0; 1964 _this.transmuxer = null; 1965 _this._state = State.STOPPED; 1966 _this.media = null; 1967 _this.mediaBuffer = null; 1968 _this.config = void 0; 1969 _this.bitrateTest = false; 1970 _this.lastCurrentTime = 0; 1971 _this.nextLoadPosition = 0; 1972 _this.startPosition = 0; 1973 _this.loadedmetadata = false; 1974 _this.fragLoadError = 0; 1975 _this.retryDate = 0; 1976 _this.levels = null; 1977 _this.fragmentLoader = void 0; 1978 _this.keyLoader = void 0; 1979 _this.levelLastLoaded = null; 1980 _this.startFragRequested = false; 1981 _this.decrypter = void 0; 1982 _this.initPTS = []; 1983 _this.onvseeking = null; 1984 _this.onvended = null; 1985 _this.logPrefix = ''; 1986 _this.log = void 0; 1987 _this.warn = void 0; 1988 _this.logPrefix = logPrefix; 1989 _this.log = _utils_logger__WEBPACK_IMPORTED_MODULE_4__.logger.log.bind(_utils_logger__WEBPACK_IMPORTED_MODULE_4__.logger, logPrefix + ":"); 1990 _this.warn = _utils_logger__WEBPACK_IMPORTED_MODULE_4__.logger.warn.bind(_utils_logger__WEBPACK_IMPORTED_MODULE_4__.logger, logPrefix + ":"); 1991 _this.hls = hls; 1992 _this.fragmentLoader = new _loader_fragment_loader__WEBPACK_IMPORTED_MODULE_12__["default"](hls.config); 1993 _this.keyLoader = keyLoader; 1994 _this.fragmentTracker = fragmentTracker; 1995 _this.config = hls.config; 1996 _this.decrypter = new _crypt_decrypter__WEBPACK_IMPORTED_MODULE_13__["default"](hls.config); 1997 hls.on(_events__WEBPACK_IMPORTED_MODULE_5__.Events.LEVEL_SWITCHING, _this.onLevelSwitching, _assertThisInitialized(_this)); 1998 return _this; 1999 } 2000 var _proto = BaseStreamController.prototype; 2001 _proto.doTick = function doTick() { 2002 this.onTickEnd(); 2003 }; 2004 _proto.onTickEnd = function onTickEnd() {} 2005 2006 // eslint-disable-next-line @typescript-eslint/no-unused-vars 2007 ; 2008 _proto.startLoad = function startLoad(startPosition) {}; 2009 _proto.stopLoad = function stopLoad() { 2010 this.fragmentLoader.abort(); 2011 this.keyLoader.abort(); 2012 var frag = this.fragCurrent; 2013 if (frag) { 2014 frag.abortRequests(); 2015 this.fragmentTracker.removeFragment(frag); 2016 } 2017 this.resetTransmuxer(); 2018 this.fragCurrent = null; 2019 this.fragPrevious = null; 2020 this.clearInterval(); 2021 this.clearNextTick(); 2022 this.state = State.STOPPED; 2023 }; 2024 _proto._streamEnded = function _streamEnded(bufferInfo, levelDetails) { 2025 // If playlist is live, there is another buffered range after the current range, nothing buffered, media is detached, 2026 // of nothing loading/loaded return false 2027 if (levelDetails.live || bufferInfo.nextStart || !bufferInfo.end || !this.media) { 2028 return false; 2029 } 2030 var partList = levelDetails.partList; 2031 // Since the last part isn't guaranteed to correspond to the last playlist segment for Low-Latency HLS, 2032 // check instead if the last part is buffered. 2033 if (partList !== null && partList !== void 0 && partList.length) { 2034 var lastPart = partList[partList.length - 1]; 2035 2036 // Checking the midpoint of the part for potential margin of error and related issues. 2037 // NOTE: Technically I believe parts could yield content that is < the computed duration (including potential a duration of 0) 2038 // and still be spec-compliant, so there may still be edge cases here. Likewise, there could be issues in end of stream 2039 // part mismatches for independent audio and video playlists/segments. 2040 var lastPartBuffered = _utils_buffer_helper__WEBPACK_IMPORTED_MODULE_3__.BufferHelper.isBuffered(this.media, lastPart.start + lastPart.duration / 2); 2041 return lastPartBuffered; 2042 } 2043 var playlistType = levelDetails.fragments[levelDetails.fragments.length - 1].type; 2044 return this.fragmentTracker.isEndListAppended(playlistType); 2045 }; 2046 _proto.getLevelDetails = function getLevelDetails() { 2047 if (this.levels && this.levelLastLoaded !== null) { 2048 var _this$levels$this$lev; 2049 return (_this$levels$this$lev = this.levels[this.levelLastLoaded]) === null || _this$levels$this$lev === void 0 ? void 0 : _this$levels$this$lev.details; 2050 } 2051 }; 2052 _proto.onMediaAttached = function onMediaAttached(event, data) { 2053 var media = this.media = this.mediaBuffer = data.media; 2054 this.onvseeking = this.onMediaSeeking.bind(this); 2055 this.onvended = this.onMediaEnded.bind(this); 2056 media.addEventListener('seeking', this.onvseeking); 2057 media.addEventListener('ended', this.onvended); 2058 var config = this.config; 2059 if (this.levels && config.autoStartLoad && this.state === State.STOPPED) { 2060 this.startLoad(config.startPosition); 2061 } 2062 }; 2063 _proto.onMediaDetaching = function onMediaDetaching() { 2064 var media = this.media; 2065 if (media !== null && media !== void 0 && media.ended) { 2066 this.log('MSE detaching and video ended, reset startPosition'); 2067 this.startPosition = this.lastCurrentTime = 0; 2068 } 2069 2070 // remove video listeners 2071 if (media && this.onvseeking && this.onvended) { 2072 media.removeEventListener('seeking', this.onvseeking); 2073 media.removeEventListener('ended', this.onvended); 2074 this.onvseeking = this.onvended = null; 2075 } 2076 if (this.keyLoader) { 2077 this.keyLoader.detach(); 2078 } 2079 this.media = this.mediaBuffer = null; 2080 this.loadedmetadata = false; 2081 this.fragmentTracker.removeAllFragments(); 2082 this.stopLoad(); 2083 }; 2084 _proto.onMediaSeeking = function onMediaSeeking() { 2085 var config = this.config, 2086 fragCurrent = this.fragCurrent, 2087 media = this.media, 2088 mediaBuffer = this.mediaBuffer, 2089 state = this.state; 2090 var currentTime = media ? media.currentTime : 0; 2091 var bufferInfo = _utils_buffer_helper__WEBPACK_IMPORTED_MODULE_3__.BufferHelper.bufferInfo(mediaBuffer ? mediaBuffer : media, currentTime, config.maxBufferHole); 2092 this.log("media seeking to " + ((0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(currentTime) ? currentTime.toFixed(3) : currentTime) + ", state: " + state); 2093 if (this.state === State.ENDED) { 2094 this.resetLoadingState(); 2095 } else if (fragCurrent) { 2096 // Seeking while frag load is in progress 2097 var tolerance = config.maxFragLookUpTolerance; 2098 var fragStartOffset = fragCurrent.start - tolerance; 2099 var fragEndOffset = fragCurrent.start + fragCurrent.duration + tolerance; 2100 // if seeking out of buffered range or into new one 2101 if (!bufferInfo.len || fragEndOffset < bufferInfo.start || fragStartOffset > bufferInfo.end) { 2102 var pastFragment = currentTime > fragEndOffset; 2103 // if the seek position is outside the current fragment range 2104 if (currentTime < fragStartOffset || pastFragment) { 2105 if (pastFragment && fragCurrent.loader) { 2106 this.log('seeking outside of buffer while fragment load in progress, cancel fragment load'); 2107 fragCurrent.abortRequests(); 2108 } 2109 this.resetLoadingState(); 2110 } 2111 } 2112 } 2113 if (media) { 2114 this.lastCurrentTime = currentTime; 2115 } 2116 2117 // in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target 2118 if (!this.loadedmetadata && !bufferInfo.len) { 2119 this.nextLoadPosition = this.startPosition = currentTime; 2120 } 2121 2122 // Async tick to speed up processing 2123 this.tickImmediate(); 2124 }; 2125 _proto.onMediaEnded = function onMediaEnded() { 2126 // reset startPosition and lastCurrentTime to restart playback @ stream beginning 2127 this.startPosition = this.lastCurrentTime = 0; 2128 }; 2129 _proto.onLevelSwitching = function onLevelSwitching(event, data) { 2130 this.fragLoadError = 0; 2131 }; 2132 _proto.onHandlerDestroying = function onHandlerDestroying() { 2133 this.stopLoad(); 2134 _TaskLoop.prototype.onHandlerDestroying.call(this); 2135 }; 2136 _proto.onHandlerDestroyed = function onHandlerDestroyed() { 2137 this.state = State.STOPPED; 2138 this.hls.off(_events__WEBPACK_IMPORTED_MODULE_5__.Events.LEVEL_SWITCHING, this.onLevelSwitching, this); 2139 if (this.fragmentLoader) { 2140 this.fragmentLoader.destroy(); 2141 } 2142 if (this.keyLoader) { 2143 this.keyLoader.destroy(); 2144 } 2145 if (this.decrypter) { 2146 this.decrypter.destroy(); 2147 } 2148 this.hls = this.log = this.warn = this.decrypter = this.keyLoader = this.fragmentLoader = this.fragmentTracker = null; 2149 _TaskLoop.prototype.onHandlerDestroyed.call(this); 2150 }; 2151 _proto.loadFragment = function loadFragment(frag, levelDetails, targetBufferTime) { 2152 this._loadFragForPlayback(frag, levelDetails, targetBufferTime); 2153 }; 2154 _proto._loadFragForPlayback = function _loadFragForPlayback(frag, levelDetails, targetBufferTime) { 2155 var _this2 = this; 2156 var progressCallback = function progressCallback(data) { 2157 if (_this2.fragContextChanged(frag)) { 2158 _this2.warn("Fragment " + frag.sn + (data.part ? ' p: ' + data.part.index : '') + " of level " + frag.level + " was dropped during download."); 2159 _this2.fragmentTracker.removeFragment(frag); 2160 return; 2161 } 2162 frag.stats.chunkCount++; 2163 _this2._handleFragmentLoadProgress(data); 2164 }; 2165 this._doFragLoad(frag, levelDetails, targetBufferTime, progressCallback).then(function (data) { 2166 if (!data) { 2167 // if we're here we probably needed to backtrack or are waiting for more parts 2168 return; 2169 } 2170 _this2.fragLoadError = 0; 2171 var state = _this2.state; 2172 if (_this2.fragContextChanged(frag)) { 2173 if (state === State.FRAG_LOADING || !_this2.fragCurrent && state === State.PARSING) { 2174 _this2.fragmentTracker.removeFragment(frag); 2175 _this2.state = State.IDLE; 2176 } 2177 return; 2178 } 2179 if ('payload' in data) { 2180 _this2.log("Loaded fragment " + frag.sn + " of level " + frag.level); 2181 _this2.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_5__.Events.FRAG_LOADED, data); 2182 } 2183 2184 // Pass through the whole payload; controllers not implementing progressive loading receive data from this callback 2185 _this2._handleFragmentLoadComplete(data); 2186 }).catch(function (reason) { 2187 if (_this2.state === State.STOPPED || _this2.state === State.ERROR) { 2188 return; 2189 } 2190 _this2.warn(reason); 2191 _this2.resetFragmentLoading(frag); 2192 }); 2193 }; 2194 _proto.flushMainBuffer = function flushMainBuffer(startOffset, endOffset, type) { 2195 if (type === void 0) { 2196 type = null; 2197 } 2198 if (!(startOffset - endOffset)) { 2199 return; 2200 } 2201 // When alternate audio is playing, the audio-stream-controller is responsible for the audio buffer. Otherwise, 2202 // passing a null type flushes both buffers 2203 var flushScope = { 2204 startOffset: startOffset, 2205 endOffset: endOffset, 2206 type: type 2207 }; 2208 // Reset load errors on flush 2209 this.fragLoadError = 0; 2210 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_5__.Events.BUFFER_FLUSHING, flushScope); 2211 }; 2212 _proto._loadInitSegment = function _loadInitSegment(frag, details) { 2213 var _this3 = this; 2214 this._doFragLoad(frag, details).then(function (data) { 2215 if (!data || _this3.fragContextChanged(frag) || !_this3.levels) { 2216 throw new Error('init load aborted'); 2217 } 2218 return data; 2219 }).then(function (data) { 2220 var hls = _this3.hls; 2221 var payload = data.payload; 2222 var decryptData = frag.decryptdata; 2223 2224 // check to see if the payload needs to be decrypted 2225 if (payload && payload.byteLength > 0 && decryptData && decryptData.key && decryptData.iv && decryptData.method === 'AES-128') { 2226 var startTime = self.performance.now(); 2227 // decrypt the subtitles 2228 return _this3.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer).then(function (decryptedData) { 2229 var endTime = self.performance.now(); 2230 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_5__.Events.FRAG_DECRYPTED, { 2231 frag: frag, 2232 payload: decryptedData, 2233 stats: { 2234 tstart: startTime, 2235 tdecrypt: endTime 2236 } 2237 }); 2238 data.payload = decryptedData; 2239 return data; 2240 }); 2241 } 2242 return data; 2243 }).then(function (data) { 2244 var fragCurrent = _this3.fragCurrent, 2245 hls = _this3.hls, 2246 levels = _this3.levels; 2247 if (!levels) { 2248 throw new Error('init load aborted, missing levels'); 2249 } 2250 var details = levels[frag.level].details; 2251 console.assert(details, 'Level details are defined when init segment is loaded'); 2252 var stats = frag.stats; 2253 _this3.state = State.IDLE; 2254 _this3.fragLoadError = 0; 2255 frag.data = new Uint8Array(data.payload); 2256 stats.parsing.start = stats.buffering.start = self.performance.now(); 2257 stats.parsing.end = stats.buffering.end = self.performance.now(); 2258 2259 // Silence FRAG_BUFFERED event if fragCurrent is null 2260 if (data.frag === fragCurrent) { 2261 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_5__.Events.FRAG_BUFFERED, { 2262 stats: stats, 2263 frag: fragCurrent, 2264 part: null, 2265 id: frag.type 2266 }); 2267 } 2268 _this3.tick(); 2269 }).catch(function (reason) { 2270 if (_this3.state === State.STOPPED || _this3.state === State.ERROR) { 2271 return; 2272 } 2273 _this3.warn(reason); 2274 _this3.resetFragmentLoading(frag); 2275 }); 2276 }; 2277 _proto.fragContextChanged = function fragContextChanged(frag) { 2278 var fragCurrent = this.fragCurrent; 2279 return !frag || !fragCurrent || frag.level !== fragCurrent.level || frag.sn !== fragCurrent.sn || frag.urlId !== fragCurrent.urlId; 2280 }; 2281 _proto.fragBufferedComplete = function fragBufferedComplete(frag, part) { 2282 var _
vendor: 3,069 bytes, lines 2282-2331
2282this$fragCurrent, _this$fragPrevious; 2283 var media = this.mediaBuffer ? this.mediaBuffer : this.media; 2284 this.log("Buffered " + frag.type + " sn: " + frag.sn + (part ? ' part: ' + part.index : '') + " of " + (this.logPrefix === '[stream-controller]' ? 'level' : 'track') + " " + frag.level + " (frag:[" + (frag.startPTS || NaN).toFixed(3) + "-" + (frag.endPTS || NaN).toFixed(3) + "] > buffer:" + (media ? _utils_time_ranges__WEBPACK_IMPORTED_MODULE_14__["default"].toString(_utils_buffer_helper__WEBPACK_IMPORTED_MODULE_3__.BufferHelper.getBuffered(media)) : '(detached)') + ")"); 2285 this.state = State.IDLE; 2286 if (!media) { 2287 return; 2288 } 2289 if (!this.loadedmetadata && frag.type == _types_loader__WEBPACK_IMPORTED_MODULE_15__.PlaylistLevelType.MAIN && media.buffered.length && ((_this$fragCurrent = this.fragCurrent) === null || _this$fragCurrent === void 0 ? void 0 : _this$fragCurrent.sn) === ((_this$fragPrevious = this.fragPrevious) === null || _this$fragPrevious === void 0 ? void 0 : _this$fragPrevious.sn)) { 2290 this.loadedmetadata = true; 2291 this.seekToStartPos(); 2292 } 2293 this.tick(); 2294 }; 2295 _proto.seekToStartPos = function seekToStartPos() {}; 2296 _proto._handleFragmentLoadComplete = function _handleFragmentLoadComplete(fragLoadedEndData) { 2297 var transmuxer = this.transmuxer; 2298 if (!transmuxer) { 2299 return; 2300 } 2301 var frag = fragLoadedEndData.frag, 2302 part = fragLoadedEndData.part, 2303 partsLoaded = fragLoadedEndData.partsLoaded; 2304 // If we did not load parts, or loaded all parts, we have complete (not partial) fragment data 2305 var complete = !partsLoaded || partsLoaded.length === 0 || partsLoaded.some(function (fragLoaded) { 2306 return !fragLoaded; 2307 }); 2308 var chunkMeta = new _types_transmuxer__WEBPACK_IMPORTED_MODULE_7__.ChunkMetadata(frag.level, frag.sn, frag.stats.chunkCount + 1, 0, part ? part.index : -1, !complete); 2309 transmuxer.flush(chunkMeta); 2310 } 2311 2312 // eslint-disable-next-line @typescript-eslint/no-unused-vars 2313 ; 2314 _proto._handleFragmentLoadProgress = function _handleFragmentLoadProgress(frag) {}; 2315 _proto._doFragLoad = function _doFragLoad(frag, details, targetBufferTime, progressCallback) { 2316 var _frag$decryptdata, 2317 _this4 = this; 2318 if (targetBufferTime === void 0) { 2319 targetBufferTime = null; 2320 } 2321 if (!this.levels) { 2322 throw new Error('frag load aborted, missing levels'); 2323 } 2324 var keyLoadingPromise = null; 2325 if (frag.encrypted && !((_frag$decryptdata = frag.decryptdata) !== null && _frag$decryptdata !== void 0 && _frag$decryptdata.key)) { 2326 this.log("Loading key for " + frag.sn + " of [" + details.startSN + "-" + details.endSN + "], " + (this.logPrefix === '[stream-controller]' ? 'level' : 'track') + " " + frag.level); 2327 this.state = State.KEY_LOADING; 2328 this.fragCurrent = frag; 2329 keyLoadingPromise = this.keyLoader.load(frag).then(function (keyLoadedData) { 2330 if (!_this4.fragContextChanged(keyLoadedData.frag)) { 2331 _this4.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_5__.Events.KEY_LOADED, keyLoadedData);
vendor: 33,701 bytes, lines 2331-3063
2331 2332 return keyLoadedData; 2333 } 2334 }); 2335 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_5__.Events.KEY_LOADING, { 2336 frag: frag 2337 }); 2338 this.throwIfFragContextChanged('KEY_LOADING'); 2339 } else if (!frag.encrypted && details.encryptedFragments.length) { 2340 this.keyLoader.loadClear(frag, details.encryptedFragments); 2341 } 2342 targetBufferTime = Math.max(frag.start, targetBufferTime || 0); 2343 if (this.config.lowLatencyMode && details) { 2344 var partList = details.partList; 2345 if (partList && progressCallback) { 2346 if (targetBufferTime > frag.end && details.fragmentHint) { 2347 frag = details.fragmentHint; 2348 } 2349 var partIndex = this.getNextPart(partList, frag, targetBufferTime); 2350 if (partIndex > -1) { 2351 var part = partList[partIndex]; 2352 this.log("Loading part sn: " + frag.sn + " p: " + part.index + " cc: " + frag.cc + " of playlist [" + details.startSN + "-" + details.endSN + "] parts [0-" + partIndex + "-" + (partList.length - 1) + "] " + (this.logPrefix === '[stream-controller]' ? 'level' : 'track') + ": " + frag.level + ", target: " + parseFloat(targetBufferTime.toFixed(3))); 2353 this.nextLoadPosition = part.start + part.duration; 2354 this.state = State.FRAG_LOADING; 2355 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_5__.Events.FRAG_LOADING, { 2356 frag: frag, 2357 part: partList[partIndex], 2358 targetBufferTime: targetBufferTime 2359 }); 2360 this.throwIfFragContextChanged('FRAG_LOADING parts'); 2361 if (keyLoadingPromise) { 2362 return keyLoadingPromise.then(function (keyLoadedData) { 2363 if (!keyLoadedData || _this4.fragContextChanged(keyLoadedData.frag)) { 2364 return null; 2365 } 2366 return _this4.doFragPartsLoad(frag, partList, partIndex, progressCallback); 2367 }).catch(function (error) { 2368 return _this4.handleFragLoadError(error); 2369 }); 2370 } 2371 return this.doFragPartsLoad(frag, partList, partIndex, progressCallback).catch(function (error) { 2372 return _this4.handleFragLoadError(error); 2373 }); 2374 } else if (!frag.url || this.loadedEndOfParts(partList, targetBufferTime)) { 2375 // Fragment hint has no parts 2376 return Promise.resolve(null); 2377 } 2378 } 2379 } 2380 this.log("Loading fragment " + frag.sn + " cc: " + frag.cc + " " + (details ? 'of [' + details.startSN + '-' + details.endSN + '] ' : '') + (this.logPrefix === '[stream-controller]' ? 'level' : 'track') + ": " + frag.level + ", target: " + parseFloat(targetBufferTime.toFixed(3))); 2381 // Don't update nextLoadPosition for fragments which are not buffered 2382 if ((0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(frag.sn) && !this.bitrateTest) { 2383 this.nextLoadPosition = frag.start + frag.duration; 2384 } 2385 this.state = State.FRAG_LOADING; 2386 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_5__.Events.FRAG_LOADING, { 2387 frag: frag, 2388 targetBufferTime: targetBufferTime 2389 }); 2390 this.throwIfFragContextChanged('FRAG_LOADING'); 2391 2392 // Load key before streaming fragment data 2393 var dataOnProgress = this.config.progressive; 2394 if (dataOnProgress && keyLoadingPromise) { 2395 return keyLoadingPromise.then(function (keyLoadedData) { 2396 if (!keyLoadedData || _this4.fragContextChanged(keyLoadedData === null || keyLoadedData === void 0 ? void 0 : keyLoadedData.frag)) { 2397 return null; 2398 } 2399 return _this4.fragmentLoader.load(frag, progressCallback); 2400 }).catch(function (error) { 2401 return _this4.handleFragLoadError(error); 2402 }); 2403 } 2404 2405 // load unencrypted fragment data with progress event, 2406 // or handle fragment result after key and fragment are finished loading 2407 return Promise.all([this.fragmentLoader.load(frag, dataOnProgress ? progressCallback : undefined), keyLoadingPromise]).then(function (_ref) { 2408 var fragLoadedData = _ref[0]; 2409 if (!dataOnProgress && fragLoadedData && progressCallback) { 2410 progressCallback(fragLoadedData); 2411 } 2412 return fragLoadedData; 2413 }).catch(function (error) { 2414 return _this4.handleFragLoadError(error); 2415 }); 2416 }; 2417 _proto.throwIfFragContextChanged = function throwIfFragContextChanged(context) { 2418 // exit if context changed during event loop 2419 if (this.fragCurrent === null) { 2420 throw new Error("frag load aborted, context changed in " + context); 2421 } 2422 }; 2423 _proto.doFragPartsLoad = function doFragPartsLoad(frag, partList, partIndex, progressCallback) { 2424 var _this5 = this; 2425 return new Promise(function (resolve, reject) { 2426 var partsLoaded = []; 2427 var loadPartIndex = function loadPartIndex(index) { 2428 var part = partList[index]; 2429 _this5.fragmentLoader.loadPart(frag, part, progressCallback).then(function (partLoadedData) { 2430 partsLoaded[part.index] = partLoadedData; 2431 var loadedPart = partLoadedData.part; 2432 _this5.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_5__.Events.FRAG_LOADED, partLoadedData); 2433 var nextPart = partList[index + 1]; 2434 if (nextPart && nextPart.fragment === frag) { 2435 loadPartIndex(index + 1); 2436 } else { 2437 return resolve({ 2438 frag: frag, 2439 part: loadedPart, 2440 partsLoaded: partsLoaded 2441 }); 2442 } 2443 }).catch(reject); 2444 }; 2445 loadPartIndex(partIndex); 2446 }); 2447 }; 2448 _proto.handleFragLoadError = function handleFragLoadError(error) { 2449 if ('data' in error) { 2450 var data = error.data; 2451 if (error.data && data.details === _errors__WEBPACK_IMPORTED_MODULE_6__.ErrorDetails.INTERNAL_ABORTED) { 2452 this.handleFragLoadAborted(data.frag, data.part); 2453 } else { 2454 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_5__.Events.ERROR, data); 2455 } 2456 } else { 2457 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_5__.Events.ERROR, { 2458 type: _errors__WEBPACK_IMPORTED_MODULE_6__.ErrorTypes.OTHER_ERROR, 2459 details: _errors__WEBPACK_IMPORTED_MODULE_6__.ErrorDetails.INTERNAL_EXCEPTION, 2460 err: error, 2461 fatal: true 2462 }); 2463 } 2464 return null; 2465 }; 2466 _proto._handleTransmuxerFlush = function _handleTransmuxerFlush(chunkMeta) { 2467 var context = this.getCurrentContext(chunkMeta); 2468 if (!context || this.state !== State.PARSING) { 2469 if (!this.fragCurrent && this.state !== State.STOPPED && this.state !== State.ERROR) { 2470 this.state = State.IDLE; 2471 } 2472 return; 2473 } 2474 var frag = context.frag, 2475 part = context.part, 2476 level = context.level; 2477 var now = self.performance.now(); 2478 frag.stats.parsing.end = now; 2479 if (part) { 2480 part.stats.parsing.end = now; 2481 } 2482 this.updateLevelTiming(frag, part, level, chunkMeta.partial); 2483 }; 2484 _proto.getCurrentContext = function getCurrentContext(chunkMeta) { 2485 var levels = this.levels; 2486 var levelIndex = chunkMeta.level, 2487 sn = chunkMeta.sn, 2488 partIndex = chunkMeta.part; 2489 if (!levels || !levels[levelIndex]) { 2490 this.warn("Levels object was unset while buffering fragment " + sn + " of level " + levelIndex + ". The current chunk will not be buffered."); 2491 return null; 2492 } 2493 var level = levels[levelIndex]; 2494 var part = partIndex > -1 ? (0,_level_helper__WEBPACK_IMPORTED_MODULE_11__.getPartWith)(level, sn, partIndex) : null; 2495 var frag = part ? part.fragment : (0,_level_helper__WEBPACK_IMPORTED_MODULE_11__.getFragmentWithSN)(level, sn, this.fragCurrent); 2496 if (!frag) { 2497 return null; 2498 } 2499 return { 2500 frag: frag, 2501 part: part, 2502 level: level 2503 }; 2504 }; 2505 _proto.bufferFragmentData = function bufferFragmentData(data, frag, part, chunkMeta) { 2506 if (!data || this.state !== State.PARSING) { 2507 return; 2508 } 2509 var data1 = data.data1, 2510 data2 = data.data2; 2511 var buffer = data1; 2512 if (data1 && data2) { 2513 // Combine the moof + mdat so that we buffer with a single append 2514 buffer = (0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_8__.appendUint8Array)(data1, data2); 2515 } 2516 if (!buffer || !buffer.length) { 2517 return; 2518 } 2519 var segment = { 2520 type: data.type, 2521 frag: frag, 2522 part: part, 2523 chunkMeta: chunkMeta, 2524 parent: frag.type, 2525 data: buffer 2526 }; 2527 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_5__.Events.BUFFER_APPENDING, segment); 2528 if (data.dropped && data.independent && !part) { 2529 // Clear buffer so that we reload previous segments sequentially if required 2530 this.flushBufferGap(frag); 2531 } 2532 }; 2533 _proto.flushBufferGap = function flushBufferGap(frag) { 2534 var media = this.media; 2535 if (!media) { 2536 return; 2537 } 2538 // If currentTime is not buffered, clear the back buffer so that we can backtrack as much as needed 2539 if (!_utils_buffer_helper__WEBPACK_IMPORTED_MODULE_3__.BufferHelper.isBuffered(media, media.currentTime)) { 2540 this.flushMainBuffer(0, frag.start); 2541 return; 2542 } 2543 // Remove back-buffer without interrupting playback to allow back tracking 2544 var currentTime = media.currentTime; 2545 var bufferInfo = _utils_buffer_helper__WEBPACK_IMPORTED_MODULE_3__.BufferHelper.bufferInfo(media, currentTime, 0); 2546 var fragDuration = frag.duration; 2547 var segmentFraction = Math.min(this.config.maxFragLookUpTolerance * 2, fragDuration * 0.25); 2548 var start = Math.max(Math.min(frag.start - segmentFraction, bufferInfo.end - segmentFraction), currentTime + segmentFraction); 2549 if (frag.start - start > segmentFraction) { 2550 this.flushMainBuffer(start, frag.start); 2551 } 2552 }; 2553 _proto.getFwdBufferInfo = function getFwdBufferInfo(bufferable, type) { 2554 var config = this.config; 2555 var pos = this.getLoadPosition(); 2556 if (!(0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(pos)) { 2557 return null; 2558 } 2559 var bufferInfo = _utils_buffer_helper__WEBPACK_IMPORTED_MODULE_3__.BufferHelper.bufferInfo(bufferable, pos, config.maxBufferHole); 2560 // Workaround flaw in getting forward buffer when maxBufferHole is smaller than gap at current pos 2561 if (bufferInfo.len === 0 && bufferInfo.nextStart !== undefined) { 2562 var bufferedFragAtPos = this.fragmentTracker.getBufferedFrag(pos, type); 2563 if (bufferedFragAtPos && bufferInfo.nextStart < bufferedFragAtPos.end) { 2564 return _utils_buffer_helper__WEBPACK_IMPORTED_MODULE_3__.BufferHelper.bufferInfo(bufferable, pos, Math.max(bufferInfo.nextStart, config.maxBufferHole)); 2565 } 2566 } 2567 return bufferInfo; 2568 }; 2569 _proto.getMaxBufferLength = function getMaxBufferLength(levelBitrate) { 2570 var config = this.config; 2571 var maxBufLen; 2572 if (levelBitrate) { 2573 maxBufLen = Math.max(8 * config.maxBufferSize / levelBitrate, config.maxBufferLength); 2574 } else { 2575 maxBufLen = config.maxBufferLength; 2576 } 2577 return Math.min(maxBufLen, config.maxMaxBufferLength); 2578 }; 2579 _proto.reduceMaxBufferLength = function reduceMaxBufferLength(threshold) { 2580 var config = this.config; 2581 var minLength = threshold || config.maxBufferLength; 2582 if (config.maxMaxBufferLength >= minLength) { 2583 // reduce max buffer length as it might be too high. we do this to avoid loop flushing ... 2584 config.maxMaxBufferLength /= 2; 2585 this.warn("Reduce max buffer length to " + config.maxMaxBufferLength + "s"); 2586 return true; 2587 } 2588 return false; 2589 }; 2590 _proto.getNextFragment = function getNextFragment(pos, levelDetails) { 2591 var fragments = levelDetails.fragments; 2592 var fragLen = fragments.length; 2593 if (!fragLen) { 2594 return null; 2595 } 2596 2597 // find fragment index, contiguous with end of buffer position 2598 var config = this.config; 2599 var start = fragments[0].start; 2600 var frag; 2601 if (levelDetails.live) { 2602 var initialLiveManifestSize = config.initialLiveManifestSize; 2603 if (fragLen < initialLiveManifestSize) { 2604 this.warn("Not enough fragments to start playback (have: " + fragLen + ", need: " + initialLiveManifestSize + ")"); 2605 return null; 2606 } 2607 // The real fragment start times for a live stream are only known after the PTS range for that level is known. 2608 // In order to discover the range, we load the best matching fragment for that level and demux it. 2609 // Do not load using live logic if the starting frag is requested - we want to use getFragmentAtPosition() so that 2610 // we get the fragment matching that start time 2611 if (!levelDetails.PTSKnown && !this.startFragRequested && this.startPosition === -1) { 2612 frag = this.getInitialLiveFragment(levelDetails, fragments); 2613 this.startPosition = frag ? this.hls.liveSyncPosition || frag.start : pos; 2614 } 2615 } else if (pos <= start) { 2616 // VoD playlist: if loadPosition before start of playlist, load first fragment 2617 frag = fragments[0]; 2618 } 2619 2620 // If we haven't run into any special cases already, just load the fragment most closely matching the requested position 2621 if (!frag) { 2622 var end = config.lowLatencyMode ? levelDetails.partEnd : levelDetails.fragmentEnd; 2623 frag = this.getFragmentAtPosition(pos, end, levelDetails); 2624 } 2625 return this.mapToInitFragWhenRequired(frag); 2626 }; 2627 _proto.mapToInitFragWhenRequired = function mapToInitFragWhenRequired(frag) { 2628 // If an initSegment is present, it must be buffered first 2629 if (frag !== null && frag !== void 0 && frag.initSegment && !(frag !== null && frag !== void 0 && frag.initSegment.data) && !this.bitrateTest) { 2630 return frag.initSegment; 2631 } 2632 return frag; 2633 }; 2634 _proto.getNextPart = function getNextPart(partList, frag, targetBufferTime) { 2635 var nextPart = -1; 2636 var contiguous = false; 2637 var independentAttrOmitted = true; 2638 for (var i = 0, len = partList.length; i < len; i++) { 2639 var part = partList[i]; 2640 independentAttrOmitted = independentAttrOmitted && !part.independent; 2641 if (nextPart > -1 && targetBufferTime < part.start) { 2642 break; 2643 } 2644 var loaded = part.loaded; 2645 if (loaded) { 2646 nextPart = -1; 2647 } else if ((contiguous || part.independent || independentAttrOmitted) && part.fragment === frag) { 2648 nextPart = i; 2649 } 2650 contiguous = loaded; 2651 } 2652 return nextPart; 2653 }; 2654 _proto.loadedEndOfParts = function loadedEndOfParts(partList, targetBufferTime) { 2655 var lastPart = partList[partList.length - 1]; 2656 return lastPart && targetBufferTime > lastPart.start && lastPart.loaded; 2657 } 2658 2659 /* 2660 This method is used find the best matching first fragment for a live playlist. This fragment is used to calculate the 2661 "sliding" of the playlist, which is its offset from the start of playback. After sliding we can compute the real 2662 start and end times for each fragment in the playlist (after which this method will not need to be called). 2663 */; 2664 _proto.getInitialLiveFragment = function getInitialLiveFragment(levelDetails, fragments) { 2665 var fragPrevious = this.fragPrevious; 2666 var frag = null; 2667 if (fragPrevious) { 2668 if (levelDetails.hasProgramDateTime) { 2669 // Prefer using PDT, because it can be accurate enough to choose the correct fragment without knowing the level sliding 2670 this.log("Live playlist, switching playlist, load frag with same PDT: " + fragPrevious.programDateTime); 2671 frag = (0,_fragment_finders__WEBPACK_IMPORTED_MODULE_10__.findFragmentByPDT)(fragments, fragPrevious.endProgramDateTime, this.config.maxFragLookUpTolerance); 2672 } 2673 if (!frag) { 2674 // SN does not need to be accurate between renditions, but depending on the packaging it may be so. 2675 var targetSN = fragPrevious.sn + 1; 2676 if (targetSN >= levelDetails.startSN && targetSN <= levelDetails.endSN) { 2677 var fragNext = fragments[targetSN - levelDetails.startSN]; 2678 // Ensure that we're staying within the continuity range, since PTS resets upon a new range 2679 if (fragPrevious.cc === fragNext.cc) { 2680 frag = fragNext; 2681 this.log("Live playlist, switching playlist, load frag with next SN: " + frag.sn); 2682 } 2683 } 2684 // It's important to stay within the continuity range if available; otherwise the fragments in the playlist 2685 // will have the wrong start times 2686 if (!frag) { 2687 frag = (0,_fragment_finders__WEBPACK_IMPORTED_MODULE_10__.findFragWithCC)(fragments, fragPrevious.cc); 2688 if (frag) { 2689 this.log("Live playlist, switching playlist, load frag with same CC: " + frag.sn); 2690 } 2691 } 2692 } 2693 } else { 2694 // Find a new start fragment when fragPrevious is null 2695 var liveStart = this.hls.liveSyncPosition; 2696 if (liveStart !== null) { 2697 frag = this.getFragmentAtPosition(liveStart, this.bitrateTest ? levelDetails.fragmentEnd : levelDetails.edge, levelDetails); 2698 } 2699 } 2700 return frag; 2701 } 2702 2703 /* 2704 This method finds the best matching fragment given the provided position. 2705 */; 2706 _proto.getFragmentAtPosition = function getFragmentAtPosition(bufferEnd, end, levelDetails) { 2707 var config = this.config; 2708 var fragPrevious = this.fragPrevious; 2709 var fragments = levelDetails.fragments, 2710 endSN = levelDetails.endSN; 2711 var fragmentHint = levelDetails.fragmentHint; 2712 var tolerance = config.maxFragLookUpTolerance; 2713 var loadingParts = !!(config.lowLatencyMode && levelDetails.partList && fragmentHint); 2714 if (loadingParts && fragmentHint && !this.bitrateTest) { 2715 // Include incomplete fragment with parts at end 2716 fragments = fragments.concat(fragmentHint); 2717 endSN = fragmentHint.sn; 2718 } 2719 var frag; 2720 if (bufferEnd < end) { 2721 var lookupTolerance = bufferEnd > end - tolerance ? 0 : tolerance; 2722 // Remove the tolerance if it would put the bufferEnd past the actual end of stream 2723 // Uses buffer and sequence number to calculate switch segment (required if using EXT-X-DISCONTINUITY-SEQUENCE) 2724 frag = (0,_fragment_finders__WEBPACK_IMPORTED_MODULE_10__.findFragmentByPTS)(fragPrevious, fragments, bufferEnd, lookupTolerance); 2725 } else { 2726 // reach end of playlist 2727 frag = fragments[fragments.length - 1]; 2728 } 2729 if (frag) { 2730 var curSNIdx = frag.sn - levelDetails.startSN; 2731 // Move fragPrevious forward to support forcing the next fragment to load 2732 // when the buffer catches up to a previously buffered range. 2733 if (this.fragmentTracker.getState(frag) === _fragment_tracker__WEBPACK_IMPORTED_MODULE_2__.FragmentState.OK) { 2734 fragPrevious = frag; 2735 } 2736 if (fragPrevious && frag.sn === fragPrevious.sn && !loadingParts) { 2737 // Force the next fragment to load if the previous one was already selected. This can occasionally happen with 2738 // non-uniform fragment durations 2739 var sameLevel = fragPrevious && frag.level === fragPrevious.level; 2740 if (sameLevel) { 2741 var nextFrag = fragments[curSNIdx + 1]; 2742 if (frag.sn < endSN && this.fragmentTracker.getState(nextFrag) !== _fragment_tracker__WEBPACK_IMPORTED_MODULE_2__.FragmentState.OK) { 2743 this.log("SN " + frag.sn + " just loaded, load next one: " + nextFrag.sn); 2744 frag = nextFrag; 2745 } else { 2746 frag = null; 2747 } 2748 } 2749 } 2750 } 2751 return frag; 2752 }; 2753 _proto.synchronizeToLiveEdge = function synchronizeToLiveEdge(levelDetails) { 2754 var config = this.config, 2755 media = this.media; 2756 if (!media) { 2757 return; 2758 } 2759 var liveSyncPosition = this.hls.liveSyncPosition; 2760 var currentTime = media.currentTime; 2761 var start = levelDetails.fragments[0].start; 2762 var end = levelDetails.edge; 2763 var withinSlidingWindow = currentTime >= start - config.maxFragLookUpTolerance && currentTime <= end; 2764 // Continue if we can seek forward to sync position or if current time is outside of sliding window 2765 if (liveSyncPosition !== null && media.duration > liveSyncPosition && (currentTime < liveSyncPosition || !withinSlidingWindow)) { 2766 // Continue if buffer is starving or if current time is behind max latency 2767 var maxLatency = config.liveMaxLatencyDuration !== undefined ? config.liveMaxLatencyDuration : config.liveMaxLatencyDurationCount * levelDetails.targetduration; 2768 if (!withinSlidingWindow && media.readyState < 4 || currentTime < end - maxLatency) { 2769 if (!this.loadedmetadata) { 2770 this.nextLoadPosition = liveSyncPosition; 2771 } 2772 // Only seek if ready and there is not a significant forward buffer available for playback 2773 if (media.readyState) { 2774 this.warn("Playback: " + currentTime.toFixed(3) + " is located too far from the end of live sliding playlist: " + end + ", reset currentTime to : " + liveSyncPosition.toFixed(3)); 2775 media.currentTime = liveSyncPosition; 2776 } 2777 } 2778 } 2779 }; 2780 _proto.alignPlaylists = function alignPlaylists(details, previousDetails) { 2781 var levels = this.levels, 2782 levelLastLoaded = this.levelLastLoaded, 2783 fragPrevious = this.fragPrevious; 2784 var lastLevel = levelLastLoaded !== null ? levels[levelLastLoaded] : null; 2785 2786 // FIXME: If not for `shouldAlignOnDiscontinuities` requiring fragPrevious.cc, 2787 // this could all go in level-helper mergeDetails() 2788 var length = details.fragments.length; 2789 if (!length) { 2790 this.warn("No fragments in live playlist"); 2791 return 0; 2792 } 2793 var slidingStart = details.fragments[0].start; 2794 var firstLevelLoad = !previousDetails; 2795 var aligned = details.alignedSliding && (0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(slidingStart); 2796 if (firstLevelLoad || !aligned && !slidingStart) { 2797 (0,_utils_discontinuities__WEBPACK_IMPORTED_MODULE_9__.alignStream)(fragPrevious, lastLevel, details); 2798 var alignedSlidingStart = details.fragments[0].start; 2799 this.log("Live playlist sliding: " + alignedSlidingStart.toFixed(2) + " start-sn: " + (previousDetails ? previousDetails.startSN : 'na') + "->" + details.startSN + " prev-sn: " + (fragPrevious ? fragPrevious.sn : 'na') + " fragments: " + length); 2800 return alignedSlidingStart; 2801 } 2802 return slidingStart; 2803 }; 2804 _proto.waitForCdnTuneIn = function waitForCdnTuneIn(details) { 2805 // Wait for Low-Latency CDN Tune-in to get an updated playlist 2806 var advancePartLimit = 3; 2807 return details.live && details.canBlockReload && details.partTarget && details.tuneInGoal > Math.max(details.partHoldBack, details.partTarget * advancePartLimit); 2808 }; 2809 _proto.setStartPosition = function setStartPosition(details, sliding) { 2810 // compute start position if set to -1. use it straight away if value is defined 2811 var startPosition = this.startPosition; 2812 if (startPosition < sliding) { 2813 startPosition = -1; 2814 } 2815 if (startPosition === -1 || this.lastCurrentTime === -1) { 2816 // first, check if start time offset has been set in playlist, if yes, use this value 2817 var startTimeOffset = details.startTimeOffset; 2818 if ((0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(startTimeOffset)) { 2819 startPosition = sliding + startTimeOffset; 2820 if (startTimeOffset < 0) { 2821 startPosition += details.totalduration; 2822 } 2823 startPosition = Math.min(Math.max(sliding, startPosition), sliding + details.totalduration); 2824 this.log("Start time offset " + startTimeOffset + " found in playlist, adjust startPosition to " + startPosition); 2825 this.startPosition = startPosition; 2826 } else if (details.live) { 2827 // Leave this.startPosition at -1, so that we can use `getInitialLiveFragment` logic when startPosition has 2828 // not been specified via the config or an as an argument to startLoad (#3736). 2829 startPosition = this.hls.liveSyncPosition || sliding; 2830 } else { 2831 this.startPosition = startPosition = 0; 2832 } 2833 this.lastCurrentTime = startPosition; 2834 } 2835 this.nextLoadPosition = startPosition; 2836 }; 2837 _proto.getLoadPosition = function getLoadPosition() { 2838 var media = this.media; 2839 // if we have not yet loaded any fragment, start loading from start position 2840 var pos = 0; 2841 if (this.loadedmetadata && media) { 2842 pos = media.currentTime; 2843 } else if (this.nextLoadPosition) { 2844 pos = this.nextLoadPosition; 2845 } 2846 return pos; 2847 }; 2848 _proto.handleFragLoadAborted = function handleFragLoadAborted(frag, part) { 2849 if (this.transmuxer && frag.sn !== 'initSegment' && frag.stats.aborted) { 2850 this.warn("Fragment " + frag.sn + (part ? ' part' + part.index : '') + " of level " + frag.level + " was aborted"); 2851 this.resetFragmentLoading(frag); 2852 } 2853 }; 2854 _proto.resetFragmentLoading = function resetFragmentLoading(frag) { 2855 if (!this.fragCurrent || !this.fragContextChanged(frag) && this.state !== State.FRAG_LOADING_WAITING_RETRY) { 2856 this.state = State.IDLE; 2857 } 2858 }; 2859 _proto.onFragmentOrKeyLoadError = function onFragmentOrKeyLoadError(filterType, data) { 2860 if (data.fatal) { 2861 this.stopLoad(); 2862 this.state = State.ERROR; 2863 return; 2864 } 2865 var config = this.config; 2866 if (data.chunkMeta) { 2867 // Parsing Error: no retries 2868 var context = this.getCurrentContext(data.chunkMeta); 2869 if (context) { 2870 data.frag = context.frag; 2871 data.levelRetry = true; 2872 this.fragLoadError = config.fragLoadingMaxRetry; 2873 } 2874 } 2875 var frag = data.frag; 2876 // Handle frag error related to caller's filterType 2877 if (!frag || frag.type !== filterType) { 2878 return; 2879 } 2880 var fragCurrent = this.fragCurrent; 2881 console.assert(fragCurrent && frag.sn === fragCurrent.sn && frag.level === fragCurrent.level && frag.urlId === fragCurrent.urlId, 'Frag load error must match current frag to retry'); 2882 // keep retrying until the limit will be reached 2883 if (this.fragLoadError + 1 <= config.fragLoadingMaxRetry) { 2884 if (!this.loadedmetadata) { 2885 this.startFragRequested = false; 2886 this.nextLoadPosition = this.startPosition; 2887 } 2888 // exponential backoff capped to config.fragLoadingMaxRetryTimeout 2889 var delay = Math.min(Math.pow(2, this.fragLoadError) * config.fragLoadingRetryDelay, config.fragLoadingMaxRetryTimeout); 2890 this.warn("Fragment " + frag.sn + " of " + filterType + " " + frag.level + " failed to load, retrying in " + delay + "ms"); 2891 this.retryDate = self.performance.now() + delay; 2892 this.fragLoadError++; 2893 this.state = State.FRAG_LOADING_WAITING_RETRY; 2894 } else if (data.levelRetry) { 2895 if (filterType === _types_loader__WEBPACK_IMPORTED_MODULE_15__.PlaylistLevelType.AUDIO) { 2896 // Reset current fragment since audio track audio is essential and may not have a fail-over track 2897 this.fragCurrent = null; 2898 } 2899 // Fragment errors that result in a level switch or redundant fail-over 2900 // should reset the stream controller state to idle 2901 this.fragLoadError = 0; 2902 this.state = State.IDLE; 2903 } else { 2904 _utils_logger__WEBPACK_IMPORTED_MODULE_4__.logger.error(data.details + " reaches max retry, redispatch as fatal ..."); 2905 // switch error to fatal 2906 data.fatal = true; 2907 this.hls.stopLoad(); 2908 this.state = State.ERROR; 2909 } 2910 }; 2911 _proto.afterBufferFlushed = function afterBufferFlushed(media, bufferType, playlistType) { 2912 if (!media) { 2913 return; 2914 } 2915 // After successful buffer flushing, filter flushed fragments from bufferedFrags use mediaBuffered instead of media 2916 // (so that we will check against video.buffered ranges in case of alt audio track) 2917 var bufferedTimeRanges = _utils_buffer_helper__WEBPACK_IMPORTED_MODULE_3__.BufferHelper.getBuffered(media); 2918 this.fragmentTracker.detectEvictedFragments(bufferType, bufferedTimeRanges, playlistType); 2919 if (this.state === State.ENDED) { 2920 this.resetLoadingState(); 2921 } 2922 }; 2923 _proto.resetLoadingState = function resetLoadingState() { 2924 this.log('Reset loading state'); 2925 this.fragCurrent = null; 2926 this.fragPrevious = null; 2927 this.state = State.IDLE; 2928 }; 2929 _proto.resetStartWhenNotLoaded = function resetStartWhenNotLoaded(level) { 2930 // if loadedmetadata is not set, it means that first frag request failed 2931 // in that case, reset startFragRequested flag 2932 if (!this.loadedmetadata) { 2933 this.startFragRequested = false; 2934 var details = this.levels ? this.levels[level].details : null; 2935 if (details !== null && details !== void 0 && details.live) { 2936 // Update the start position and return to IDLE to recover live start 2937 this.startPosition = -1; 2938 this.setStartPosition(details, 0); 2939 this.resetLoadingState(); 2940 } else { 2941 this.nextLoadPosition = this.startPosition; 2942 } 2943 } 2944 }; 2945 _proto.updateLevelTiming = function updateLevelTiming(frag, part, level, partial) { 2946 var _this6 = this; 2947 var details = level.details; 2948 console.assert(!!details, 'level.details must be defined'); 2949 var parsed = Object.keys(frag.elementaryStreams).reduce(function (result, type) { 2950 var info = frag.elementaryStreams[type]; 2951 if (info) { 2952 var parsedDuration = info.endPTS - info.startPTS; 2953 if (parsedDuration <= 0) { 2954 // Destroy the transmuxer after it's next time offset failed to advance because duration was <= 0. 2955 // The new transmuxer will be configured with a time offset matching the next fragment start, 2956 // preventing the timeline from shifting. 2957 _this6.warn("Could not parse fragment " + frag.sn + " " + type + " duration reliably (" + parsedDuration + ")"); 2958 return result || false; 2959 } 2960 var drift = partial ? 0 : (0,_level_helper__WEBPACK_IMPORTED_MODULE_11__.updateFragPTSDTS)(details, frag, info.startPTS, info.endPTS, info.startDTS, info.endDTS); 2961 _this6.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_5__.Events.LEVEL_PTS_UPDATED, { 2962 details: details, 2963 level: level, 2964 drift: drift, 2965 type: type, 2966 frag: frag, 2967 start: info.startPTS, 2968 end: info.endPTS 2969 }); 2970 return true; 2971 } 2972 return result; 2973 }, false); 2974 if (!parsed) { 2975 this.warn("Found no media in fragment " + frag.sn + " of level " + level.id + " resetting transmuxer to fallback to playlist timing"); 2976 this.resetTransmuxer(); 2977 } 2978 this.state = State.PARSED; 2979 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_5__.Events.FRAG_PARSED, { 2980 frag: frag, 2981 part: part 2982 }); 2983 }; 2984 _proto.resetTransmuxer = function resetTransmuxer() { 2985 if (this.transmuxer) { 2986 this.transmuxer.destroy(); 2987 this.transmuxer = null; 2988 } 2989 }; 2990 _createClass(BaseStreamController, [{ 2991 key: "state", 2992 get: function get() { 2993 return this._state; 2994 }, 2995 set: function set(nextState) { 2996 var previousState = this._state; 2997 if (previousState !== nextState) { 2998 this._state = nextState; 2999 this.log(previousState + "->" + nextState); 3000 } 3001 } 3002 }]); 3003 return BaseStreamController; 3004}(_task_loop__WEBPACK_IMPORTED_MODULE_1__["default"]); 3005 3006 3007/***/ }), 3008 3009/***/ "./src/controller/buffer-controller.ts": 3010/*!*********************************************!*\ 3011 !*** ./src/controller/buffer-controller.ts ***! 3012 \*********************************************/ 3013/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3014 3015"use strict"; 3016__webpack_require__.r(__webpack_exports__); 3017/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3018/* harmony export */ "default": () => (/* binding */ BufferController) 3019/* harmony export */ }); 3020/* harmony import */ var _home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.ts"); 3021/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 3022/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 3023/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../errors */ "./src/errors.ts"); 3024/* harmony import */ var _utils_buffer_helper__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../utils/buffer-helper */ "./src/utils/buffer-helper.ts"); 3025/* harmony import */ var _utils_mediasource_helper__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../utils/mediasource-helper */ "./src/utils/mediasource-helper.ts"); 3026/* harmony import */ var _loader_fragment__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../loader/fragment */ "./src/loader/fragment.ts"); 3027/* harmony import */ var _buffer_operation_queue__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./buffer-operation-queue */ "./src/controller/buffer-operation-queue.ts"); 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040var MediaSource = (0,_utils_mediasource_helper__WEBPACK_IMPORTED_MODULE_5__.getMediaSource)(); 3041var VIDEO_CODEC_PROFILE_REPACE = /([ha]vc.)(?:\.[^.,]+)+/; 3042var BufferController = /*#__PURE__*/function () { 3043 // The level details used to determine duration, target-duration and live 3044 3045 // cache the self generated object url to detect hijack of video tag 3046 3047 // A queue of buffer operations which require the SourceBuffer to not be updating upon execution 3048 3049 // References to event listeners for each SourceBuffer, so that they can be referenced for event removal 3050 3051 // The number of BUFFER_CODEC events received before any sourceBuffers are created 3052 3053 // The total number of BUFFER_CODEC events received 3054 3055 // A reference to the attached media element 3056 3057 // A reference to the active media source 3058 3059 // Last MP3 audio chunk appended 3060 3061 // counters 3062 3063 function BufferController(
3063_hls) { 3064 var _this = this; 3065 this.details = null; 3066 this._objectUrl = null; 3067 this.operationQueue = void 0; 3068 this.listeners = void 0; 3069 this.hls = void 0; 3070 this.bufferCodecEventsExpected = 0; 3071 this._bufferCodecEventsTotal = 0; 3072 this.media = null; 3073 this.mediaSource = null; 3074 this.lastMpegAudioChunk = null; 3075 this.appendError = 0; 3076 this.tracks = {}; 3077 this.pendingTracks = {}; 3078 this.sourceBuffer = void 0; 3079 this._onMediaSourceOpen = function () { 3080 var hls = _this.hls, 3081 media = _this.media, 3082 mediaSource = _this.mediaSource; 3083 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.log('[buffer-controller]: Media source opened'); 3084 if (media) { 3085 _this.updateMediaElementDuration(); 3086 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MEDIA_ATTACHED, { 3087 media: media 3088 }); 3089 } 3090 if (mediaSource) { 3091 // once received, don't listen anymore to sourceopen event 3092 mediaSource.removeEventListener('sourceopen', _this._onMediaSourceOpen); 3093 } 3094 _this.checkPendingTracks(); 3095 }; 3096 this._onMediaSourceClose = function () { 3097 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.log('[buffer-controller]: Media source closed'); 3098 }; 3099 this._onMediaSourceEnded = function () { 3100 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.log('[buffer-controller]: Media source ended'); 3101 }; 3102 this.hls = _hls; 3103 this._initSourceBuffer(); 3104 this.registerListeners(); 3105 } 3106 var _proto = BufferController.prototype; 3107 _proto.hasSourceTypes = function hasSourceTypes() {
vendor: 4,677 bytes, lines 3108-3185
3108 return this.getSourceBufferTypes().length > 0 || Object.keys(this.pendingTracks).length > 0; 3109 }; 3110 _proto.destroy = function destroy() { 3111 this.unregisterListeners(); 3112 this.details = null; 3113 this.lastMpegAudioChunk = null; 3114 }; 3115 _proto.registerListeners = function registerListeners() { 3116 var hls = this.hls; 3117 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MEDIA_ATTACHING, this.onMediaAttaching, this); 3118 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MEDIA_DETACHING, this.onMediaDetaching, this); 3119 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MANIFEST_PARSED, this.onManifestParsed, this); 3120 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.BUFFER_RESET, this.onBufferReset, this); 3121 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.BUFFER_APPENDING, this.onBufferAppending, this); 3122 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.BUFFER_CODECS, this.onBufferCodecs, this); 3123 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.BUFFER_EOS, this.onBufferEos, this); 3124 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.BUFFER_FLUSHING, this.onBufferFlushing, this); 3125 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.LEVEL_UPDATED, this.onLevelUpdated, this); 3126 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.FRAG_PARSED, this.onFragParsed, this); 3127 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.FRAG_CHANGED, this.onFragChanged, this); 3128 }; 3129 _proto.unregisterListeners = function unregisterListeners() { 3130 var hls = this.hls; 3131 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MEDIA_ATTACHING, this.onMediaAttaching, this); 3132 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MEDIA_DETACHING, this.onMediaDetaching, this); 3133 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MANIFEST_PARSED, this.onManifestParsed, this); 3134 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.BUFFER_RESET, this.onBufferReset, this); 3135 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.BUFFER_APPENDING, this.onBufferAppending, this); 3136 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.BUFFER_CODECS, this.onBufferCodecs, this); 3137 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.BUFFER_EOS, this.onBufferEos, this); 3138 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.BUFFER_FLUSHING, this.onBufferFlushing, this); 3139 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.LEVEL_UPDATED, this.onLevelUpdated, this); 3140 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.FRAG_PARSED, this.onFragParsed, this); 3141 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.FRAG_CHANGED, this.onFragChanged, this); 3142 }; 3143 _proto._initSourceBuffer = function _initSourceBuffer() { 3144 this.sourceBuffer = {}; 3145 this.operationQueue = new _buffer_operation_queue__WEBPACK_IMPORTED_MODULE_7__["default"](this.sourceBuffer); 3146 this.listeners = { 3147 audio: [], 3148 video: [], 3149 audiovideo: [] 3150 }; 3151 this.lastMpegAudioChunk = null; 3152 }; 3153 _proto.onManifestParsed = function onManifestParsed(event, data) { 3154 // in case of alt audio 2 BUFFER_CODECS events will be triggered, one per stream controller 3155 // sourcebuffers will be created all at once when the expected nb of tracks will be reached 3156 // in case alt audio is not used, only one BUFFER_CODEC event will be fired from main stream controller 3157 // it will contain the expected nb of source buffers, no need to compute it 3158 var codecEvents = 2; 3159 if (data.audio && !data.video || !data.altAudio) { 3160 codecEvents = 1; 3161 } 3162 this.bufferCodecEventsExpected = this._bufferCodecEventsTotal = codecEvents; 3163 this.details = null; 3164 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.log(this.bufferCodecEventsExpected + " bufferCodec event(s) expected"); 3165 }; 3166 _proto.onMediaAttaching = function onMediaAttaching(event, data) { 3167 var media = this.media = data.media; 3168 if (media && MediaSource) { 3169 var ms = this.mediaSource = new MediaSource(); 3170 // MediaSource listeners are arrow functions with a lexical scope, and do not need to be bound 3171 ms.addEventListener('sourceopen', this._onMediaSourceOpen); 3172 ms.addEventListener('sourceended', this._onMediaSourceEnded); 3173 ms.addEventListener('sourceclose', this._onMediaSourceClose); 3174 // link video and media Source 3175 media.src = self.URL.createObjectURL(ms); 3176 // cache the locally generated object url 3177 this._objectUrl = media.src; 3178 } 3179 }; 3180 _proto.onMediaDetaching = function onMediaDetaching() { 3181 var media = this.media, 3182 mediaSource = this.mediaSource, 3183 _objectUrl = this._objectUrl; 3184 if (mediaSource) { 3185 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.log('[buffer-controller]: media s
3185ource detaching'); 3186 if (mediaSource.readyState === 'open') { 3187 try { 3188 // endOfStream could trigger exception if any sourcebuffer is in updating state 3189 // we don't really care about checking sourcebuffer state here, 3190 // as we are anyway detaching the MediaSource 3191 // let's just avoid this exception to propagate 3192 mediaSource.endOfStream(); 3193 } catch (err) { 3194 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.warn("[buffer-controller]: onMediaDetaching: " + err.message + " while calling endOfStream"); 3195 } 3196 } 3197 // Clean up the SourceBuffers by invoking onBufferReset 3198 this.onBufferReset(); 3199 mediaSource.removeEventListener('sourceopen', this._onMediaSourceOpen); 3200 mediaSource.removeEventListener('sourceended', this._onMediaSourceEnded); 3201 mediaSource.removeEventListener('sourceclose', this._onMediaSourceClose); 3202 3203 // Detach properly the MediaSource from the HTMLMediaElement as 3204 // suggested in https://github.com/w3c/media-source/issues/53. 3205 if (media) {
vendor: 42,034 bytes, lines 3205-4172
3205 3206 if (_objectUrl) { 3207 self.URL.revokeObjectURL(_objectUrl); 3208 } 3209 3210 // clean up video tag src only if it's our own url. some external libraries might 3211 // hijack the video tag and change its 'src' without destroying the Hls instance first 3212 if (media.src === _objectUrl) { 3213 media.removeAttribute('src'); 3214 media.load(); 3215 } else { 3216 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.warn('[buffer-controller]: media.src was changed by a third party - skip cleanup'); 3217 } 3218 } 3219 this.mediaSource = null; 3220 this.media = null; 3221 this._objectUrl = null; 3222 this.bufferCodecEventsExpected = this._bufferCodecEventsTotal; 3223 this.pendingTracks = {}; 3224 this.tracks = {}; 3225 } 3226 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MEDIA_DETACHED, undefined); 3227 }; 3228 _proto.onBufferReset = function onBufferReset() { 3229 var _this2 = this; 3230 this.getSourceBufferTypes().forEach(function (type) { 3231 var sb = _this2.sourceBuffer[type]; 3232 try { 3233 if (sb) { 3234 _this2.removeBufferListeners(type); 3235 if (_this2.mediaSource) { 3236 _this2.mediaSource.removeSourceBuffer(sb); 3237 } 3238 // Synchronously remove the SB from the map before the next call in order to prevent an async function from 3239 // accessing it 3240 _this2.sourceBuffer[type] = undefined; 3241 } 3242 } catch (err) { 3243 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.warn("[buffer-controller]: Failed to reset the " + type + " buffer", err); 3244 } 3245 }); 3246 this._initSourceBuffer(); 3247 }; 3248 _proto.onBufferCodecs = function onBufferCodecs(event, data) { 3249 var _this3 = this; 3250 var sourceBufferCount = this.getSourceBufferTypes().length; 3251 Object.keys(data).forEach(function (trackName) { 3252 if (sourceBufferCount) { 3253 // check if SourceBuffer codec needs to change 3254 var track = _this3.tracks[trackName]; 3255 if (track && typeof track.buffer.changeType === 'function') { 3256 var _data$trackName = data[trackName], 3257 id = _data$trackName.id, 3258 codec = _data$trackName.codec, 3259 levelCodec = _data$trackName.levelCodec, 3260 container = _data$trackName.container, 3261 metadata = _data$trackName.metadata; 3262 var currentCodec = (track.levelCodec || track.codec).replace(VIDEO_CODEC_PROFILE_REPACE, '$1'); 3263 var nextCodec = (levelCodec || codec).replace(VIDEO_CODEC_PROFILE_REPACE, '$1'); 3264 if (currentCodec !== nextCodec) { 3265 var mimeType = container + ";codecs=" + (levelCodec || codec); 3266 _this3.appendChangeType(trackName, mimeType); 3267 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.log("[buffer-controller]: switching codec " + currentCodec + " to " + nextCodec); 3268 _this3.tracks[trackName] = { 3269 buffer: track.buffer, 3270 codec: codec, 3271 container: container, 3272 levelCodec: levelCodec, 3273 metadata: metadata, 3274 id: id 3275 }; 3276 } 3277 } 3278 } else { 3279 // if source buffer(s) not created yet, appended buffer tracks in this.pendingTracks 3280 _this3.pendingTracks[trackName] = data[trackName]; 3281 } 3282 }); 3283 3284 // if sourcebuffers already created, do nothing ... 3285 if (sourceBufferCount) { 3286 return; 3287 } 3288 this.bufferCodecEventsExpected = Math.max(this.bufferCodecEventsExpected - 1, 0); 3289 if (this.mediaSource && this.mediaSource.readyState === 'open') { 3290 this.checkPendingTracks(); 3291 } 3292 }; 3293 _proto.appendChangeType = function appendChangeType(type, mimeType) { 3294 var _this4 = this; 3295 var operationQueue = this.operationQueue; 3296 var operation = { 3297 execute: function execute() { 3298 var sb = _this4.sourceBuffer[type]; 3299 if (sb) { 3300 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.log("[buffer-controller]: changing " + type + " sourceBuffer type to " + mimeType); 3301 sb.changeType(mimeType); 3302 } 3303 operationQueue.shiftAndExecuteNext(type); 3304 }, 3305 onStart: function onStart() {}, 3306 onComplete: function onComplete() {}, 3307 onError: function onError(e) { 3308 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.warn("[buffer-controller]: Failed to change " + type + " SourceBuffer type", e); 3309 } 3310 }; 3311 operationQueue.append(operation, type); 3312 }; 3313 _proto.onBufferAppending = function onBufferAppending(event, eventData) { 3314 var _this5 = this; 3315 var hls = this.hls, 3316 operationQueue = this.operationQueue, 3317 tracks = this.tracks; 3318 var data = eventData.data, 3319 type = eventData.type, 3320 frag = eventData.frag, 3321 part = eventData.part, 3322 chunkMeta = eventData.chunkMeta; 3323 var chunkStats = chunkMeta.buffering[type]; 3324 var bufferAppendingStart = self.performance.now(); 3325 chunkStats.start = bufferAppendingStart; 3326 var fragBuffering = frag.stats.buffering; 3327 var partBuffering = part ? part.stats.buffering : null; 3328 if (fragBuffering.start === 0) { 3329 fragBuffering.start = bufferAppendingStart; 3330 } 3331 if (partBuffering && partBuffering.start === 0) { 3332 partBuffering.start = bufferAppendingStart; 3333 } 3334 3335 // TODO: Only update timestampOffset when audio/mpeg fragment or part is not contiguous with previously appended 3336 // Adjusting `SourceBuffer.timestampOffset` (desired point in the timeline where the next frames should be appended) 3337 // in Chrome browser when we detect MPEG audio container and time delta between level PTS and `SourceBuffer.timestampOffset` 3338 // is greater than 100ms (this is enough to handle seek for VOD or level change for LIVE videos). 3339 // More info here: https://github.com/video-dev/hls.js/issues/332#issuecomment-257986486 3340 var audioTrack = tracks.audio; 3341 var checkTimestampOffset = false; 3342 if (type === 'audio' && (audioTrack === null || audioTrack === void 0 ? void 0 : audioTrack.container) === 'audio/mpeg') { 3343 checkTimestampOffset = !this.lastMpegAudioChunk || chunkMeta.id === 1 || this.lastMpegAudioChunk.sn !== chunkMeta.sn; 3344 this.lastMpegAudioChunk = chunkMeta; 3345 } 3346 var fragStart = frag.start; 3347 var operation = { 3348 execute: function execute() { 3349 chunkStats.executeStart = self.performance.now(); 3350 if (checkTimestampOffset) { 3351 var sb = _this5.sourceBuffer[type]; 3352 if (sb) { 3353 var delta = fragStart - sb.timestampOffset; 3354 if (Math.abs(delta) >= 0.1) { 3355 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.log("[buffer-controller]: Updating audio SourceBuffer timestampOffset to " + fragStart + " (delta: " + delta + ") sn: " + frag.sn + ")"); 3356 sb.timestampOffset = fragStart; 3357 } 3358 } 3359 } 3360 _this5.appendExecutor(data, type); 3361 }, 3362 onStart: function onStart() { 3363 // logger.debug(`[buffer-controller]: ${type} SourceBuffer updatestart`); 3364 }, 3365 onComplete: function onComplete() { 3366 // logger.debug(`[buffer-controller]: ${type} SourceBuffer updateend`); 3367 var end = self.performance.now(); 3368 chunkStats.executeEnd = chunkStats.end = end; 3369 if (fragBuffering.first === 0) { 3370 fragBuffering.first = end; 3371 } 3372 if (partBuffering && partBuffering.first === 0) { 3373 partBuffering.first = end; 3374 } 3375 var sourceBuffer = _this5.sourceBuffer; 3376 var timeRanges = {}; 3377 for (var _type in sourceBuffer) { 3378 timeRanges[_type] = _utils_buffer_helper__WEBPACK_IMPORTED_MODULE_4__.BufferHelper.getBuffered(sourceBuffer[_type]); 3379 } 3380 _this5.appendError = 0; 3381 _this5.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.BUFFER_APPENDED, { 3382 type: type, 3383 frag: frag, 3384 part: part, 3385 chunkMeta: chunkMeta, 3386 parent: frag.type, 3387 timeRanges: timeRanges 3388 }); 3389 }, 3390 onError: function onError(err) { 3391 // in case any error occured while appending, put back segment in segments table 3392 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.error("[buffer-controller]: Error encountered while trying to append to the " + type + " SourceBuffer", err); 3393 var event = { 3394 type: _errors__WEBPACK_IMPORTED_MODULE_3__.ErrorTypes.MEDIA_ERROR, 3395 parent: frag.type, 3396 details: _errors__WEBPACK_IMPORTED_MODULE_3__.ErrorDetails.BUFFER_APPEND_ERROR, 3397 err: err, 3398 fatal: false 3399 }; 3400 if (err.code === DOMException.QUOTA_EXCEEDED_ERR) { 3401 // QuotaExceededError: http://www.w3.org/TR/html5/infrastructure.html#quotaexceedederror 3402 // let's stop appending any segments, and report BUFFER_FULL_ERROR error 3403 event.details = _errors__WEBPACK_IMPORTED_MODULE_3__.ErrorDetails.BUFFER_FULL_ERROR; 3404 } else { 3405 _this5.appendError++; 3406 event.details = _errors__WEBPACK_IMPORTED_MODULE_3__.ErrorDetails.BUFFER_APPEND_ERROR; 3407 /* with UHD content, we could get loop of quota exceeded error until 3408 browser is able to evict some data from sourcebuffer. Retrying can help recover. 3409 */ 3410 if (_this5.appendError > hls.config.appendErrorMaxRetry) { 3411 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.error("[buffer-controller]: Failed " + hls.config.appendErrorMaxRetry + " times to append segment in sourceBuffer"); 3412 event.fatal = true; 3413 hls.stopLoad(); 3414 } 3415 } 3416 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.ERROR, event); 3417 } 3418 }; 3419 operationQueue.append(operation, type); 3420 }; 3421 _proto.onBufferFlushing = function onBufferFlushing(event, data) { 3422 var _this6 = this; 3423 var operationQueue = this.operationQueue; 3424 var flushOperation = function flushOperation(type) { 3425 return { 3426 execute: _this6.removeExecutor.bind(_this6, type, data.startOffset, data.endOffset), 3427 onStart: function onStart() { 3428 // logger.debug(`[buffer-controller]: Started flushing ${data.startOffset} -> ${data.endOffset} for ${type} Source Buffer`); 3429 }, 3430 onComplete: function onComplete() { 3431 // logger.debug(`[buffer-controller]: Finished flushing ${data.startOffset} -> ${data.endOffset} for ${type} Source Buffer`); 3432 _this6.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.BUFFER_FLUSHED, { 3433 type: type 3434 }); 3435 }, 3436 onError: function onError(e) { 3437 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.warn("[buffer-controller]: Failed to remove from " + type + " SourceBuffer", e); 3438 } 3439 }; 3440 }; 3441 if (data.type) { 3442 operationQueue.append(flushOperation(data.type), data.type); 3443 } else { 3444 this.getSourceBufferTypes().forEach(function (type) { 3445 operationQueue.append(flushOperation(type), type); 3446 }); 3447 } 3448 }; 3449 _proto.onFragParsed = function onFragParsed(event, data) { 3450 var _this7 = this; 3451 var frag = data.frag, 3452 part = data.part; 3453 var buffersAppendedTo = []; 3454 var elementaryStreams = part ? part.elementaryStreams : frag.elementaryStreams; 3455 if (elementaryStreams[_loader_fragment__WEBPACK_IMPORTED_MODULE_6__.ElementaryStreamTypes.AUDIOVIDEO]) { 3456 buffersAppendedTo.push('audiovideo'); 3457 } else { 3458 if (elementaryStreams[_loader_fragment__WEBPACK_IMPORTED_MODULE_6__.ElementaryStreamTypes.AUDIO]) { 3459 buffersAppendedTo.push('audio'); 3460 } 3461 if (elementaryStreams[_loader_fragment__WEBPACK_IMPORTED_MODULE_6__.ElementaryStreamTypes.VIDEO]) { 3462 buffersAppendedTo.push('video'); 3463 } 3464 } 3465 var onUnblocked = function onUnblocked() { 3466 var now = self.performance.now(); 3467 frag.stats.buffering.end = now; 3468 if (part) { 3469 part.stats.buffering.end = now; 3470 } 3471 var stats = part ? part.stats : frag.stats; 3472 _this7.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.FRAG_BUFFERED, { 3473 frag: frag, 3474 part: part, 3475 stats: stats, 3476 id: frag.type 3477 }); 3478 }; 3479 if (buffersAppendedTo.length === 0) { 3480 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.warn("Fragments must have at least one ElementaryStreamType set. type: " + frag.type + " level: " + frag.level + " sn: " + frag.sn); 3481 } 3482 this.blockBuffers(onUnblocked, buffersAppendedTo); 3483 }; 3484 _proto.onFragChanged = function onFragChanged(event, data) { 3485 this.flushBackBuffer(); 3486 } 3487 3488 // on BUFFER_EOS mark matching sourcebuffer(s) as ended and trigger checkEos() 3489 // an undefined data.type will mark all buffers as EOS. 3490 ; 3491 _proto.onBufferEos = function onBufferEos(event, data) { 3492 var _this8 = this; 3493 var ended = this.getSourceBufferTypes().reduce(function (acc, type) { 3494 var sb = _this8.sourceBuffer[type]; 3495 if (sb && (!data.type || data.type === type)) { 3496 sb.ending = true; 3497 if (!sb.ended) { 3498 sb.ended = true; 3499 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.log("[buffer-controller]: " + type + " sourceBuffer now EOS"); 3500 } 3501 } 3502 return acc && !!(!sb || sb.ended); 3503 }, true); 3504 if (ended) { 3505 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.log("[buffer-controller]: Queueing mediaSource.endOfStream()"); 3506 this.blockBuffers(function () { 3507 _this8.getSourceBufferTypes().forEach(function (type) { 3508 var sb = _this8.sourceBuffer[type]; 3509 if (sb) { 3510 sb.ending = false; 3511 } 3512 }); 3513 var mediaSource = _this8.mediaSource; 3514 if (!mediaSource || mediaSource.readyState !== 'open') { 3515 if (mediaSource) { 3516 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.info("[buffer-controller]: Could not call mediaSource.endOfStream(). mediaSource.readyState: " + mediaSource.readyState); 3517 } 3518 return; 3519 } 3520 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.log("[buffer-controller]: Calling mediaSource.endOfStream()"); 3521 // Allow this to throw and be caught by the enqueueing function 3522 mediaSource.endOfStream(); 3523 }); 3524 } 3525 }; 3526 _proto.onLevelUpdated = function onLevelUpdated(event, _ref) { 3527 var details = _ref.details; 3528 if (!details.fragments.length) { 3529 return; 3530 } 3531 this.details = details; 3532 if (this.getSourceBufferTypes().length) { 3533 this.blockBuffers(this.updateMediaElementDuration.bind(this)); 3534 } else { 3535 this.updateMediaElementDuration(); 3536 } 3537 }; 3538 _proto.flushBackBuffer = function flushBackBuffer() { 3539 var hls = this.hls, 3540 details = this.details, 3541 media = this.media, 3542 sourceBuffer = this.sourceBuffer; 3543 if (!media || details === null) { 3544 return; 3545 } 3546 var sourceBufferTypes = this.getSourceBufferTypes(); 3547 if (!sourceBufferTypes.length) { 3548 return; 3549 } 3550 3551 // Support for deprecated liveBackBufferLength 3552 var backBufferLength = details.live && hls.config.liveBackBufferLength !== null ? hls.config.liveBackBufferLength : hls.config.backBufferLength; 3553 if (!(0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(backBufferLength) || backBufferLength < 0) { 3554 return; 3555 } 3556 var currentTime = media.currentTime; 3557 var targetDuration = details.levelTargetDuration; 3558 var maxBackBufferLength = Math.max(backBufferLength, targetDuration); 3559 var targetBackBufferPosition = Math.floor(currentTime / targetDuration) * targetDuration - maxBackBufferLength; 3560 sourceBufferTypes.forEach(function (type) { 3561 var sb = sourceBuffer[type]; 3562 if (sb) { 3563 var buffered = _utils_buffer_helper__WEBPACK_IMPORTED_MODULE_4__.BufferHelper.getBuffered(sb); 3564 // when target buffer start exceeds actual buffer start 3565 if (buffered.length > 0 && targetBackBufferPosition > buffered.start(0)) { 3566 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.BACK_BUFFER_REACHED, { 3567 bufferEnd: targetBackBufferPosition 3568 }); 3569 3570 // Support for deprecated event: 3571 if (details.live) { 3572 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.LIVE_BACK_BUFFER_REACHED, { 3573 bufferEnd: targetBackBufferPosition 3574 }); 3575 } else if (sb.ended && buffered.end(buffered.length - 1) - currentTime < targetDuration * 2) { 3576 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.info("[buffer-controller]: Cannot flush " + type + " back buffer while SourceBuffer is in ended state"); 3577 return; 3578 } 3579 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.BUFFER_FLUSHING, { 3580 startOffset: 0, 3581 endOffset: targetBackBufferPosition, 3582 type: type 3583 }); 3584 } 3585 } 3586 }); 3587 } 3588 3589 /** 3590 * Update Media Source duration to current level duration or override to Infinity if configuration parameter 3591 * 'liveDurationInfinity` is set to `true` 3592 * More details: https://github.com/video-dev/hls.js/issues/355 3593 */; 3594 _proto.updateMediaElementDuration = function updateMediaElementDuration() { 3595 if (!this.details || !this.media || !this.mediaSource || this.mediaSource.readyState !== 'open') { 3596 return; 3597 } 3598 var details = this.details, 3599 hls = this.hls, 3600 media = this.media, 3601 mediaSource = this.mediaSource; 3602 var levelDuration = details.fragments[0].start + details.totalduration; 3603 var mediaDuration = media.duration; 3604 var msDuration = (0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(mediaSource.duration) ? mediaSource.duration : 0; 3605 if (details.live && hls.config.liveDurationInfinity) { 3606 // Override duration to Infinity 3607 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.log('[buffer-controller]: Media Source duration is set to Infinity'); 3608 mediaSource.duration = Infinity; 3609 this.updateSeekableRange(details); 3610 } else if (levelDuration > msDuration && levelDuration > mediaDuration || !(0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(mediaDuration)) { 3611 // levelDuration was the last value we set. 3612 // not using mediaSource.duration as the browser may tweak this value 3613 // only update Media Source duration if its value increase, this is to avoid 3614 // flushing already buffered portion when switching between quality level 3615 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.log("[buffer-controller]: Updating Media Source duration to " + levelDuration.toFixed(3)); 3616 mediaSource.duration = levelDuration; 3617 } 3618 }; 3619 _proto.updateSeekableRange = function updateSeekableRange(levelDetails) { 3620 var mediaSource = this.mediaSource; 3621 var fragments = levelDetails.fragments; 3622 var len = fragments.length; 3623 if (len && levelDetails.live && mediaSource !== null && mediaSource !== void 0 && mediaSource.setLiveSeekableRange) { 3624 var start = Math.max(0, fragments[0].start); 3625 var end = Math.max(start, start + levelDetails.totalduration); 3626 mediaSource.setLiveSeekableRange(start, end); 3627 } 3628 }; 3629 _proto.checkPendingTracks = function checkPendingTracks() { 3630 var bufferCodecEventsExpected = this.bufferCodecEventsExpected, 3631 operationQueue = this.operationQueue, 3632 pendingTracks = this.pendingTracks; 3633 3634 // Check if we've received all of the expected bufferCodec events. When none remain, create all the sourceBuffers at once. 3635 // This is important because the MSE spec allows implementations to throw QuotaExceededErrors if creating new sourceBuffers after 3636 // data has been appended to existing ones. 3637 // 2 tracks is the max (one for audio, one for video). If we've reach this max go ahead and create the buffers. 3638 var pendingTracksCount = Object.keys(pendingTracks).length; 3639 if (pendingTracksCount && !bufferCodecEventsExpected || pendingTracksCount === 2) { 3640 // ok, let's create them now ! 3641 this.createSourceBuffers(pendingTracks); 3642 this.pendingTracks = {}; 3643 // append any pending segments now ! 3644 var buffers = this.getSourceBufferTypes(); 3645 if (buffers.length === 0) { 3646 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.ERROR, { 3647 type: _errors__WEBPACK_IMPORTED_MODULE_3__.ErrorTypes.MEDIA_ERROR, 3648 details: _errors__WEBPACK_IMPORTED_MODULE_3__.ErrorDetails.BUFFER_INCOMPATIBLE_CODECS_ERROR, 3649 fatal: true, 3650 reason: 'could not create source buffer for media codec(s)' 3651 }); 3652 return; 3653 } 3654 buffers.forEach(function (type) { 3655 operationQueue.executeNext(type); 3656 }); 3657 } 3658 }; 3659 _proto.createSourceBuffers = function createSourceBuffers(tracks) { 3660 var sourceBuffer = this.sourceBuffer, 3661 mediaSource = this.mediaSource; 3662 if (!mediaSource) { 3663 throw Error('createSourceBuffers called when mediaSource was null'); 3664 } 3665 var tracksCreated = 0; 3666 for (var trackName in tracks) { 3667 if (!sourceBuffer[trackName]) { 3668 var track = tracks[trackName]; 3669 if (!track) { 3670 throw Error("source buffer exists for track " + trackName + ", however track does not"); 3671 } 3672 // use levelCodec as first priority 3673 var codec = track.levelCodec || track.codec; 3674 var mimeType = track.container + ";codecs=" + codec; 3675 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.log("[buffer-controller]: creating sourceBuffer(" + mimeType + ")"); 3676 try { 3677 var sb = sourceBuffer[trackName] = mediaSource.addSourceBuffer(mimeType); 3678 var sbName = trackName; 3679 this.addBufferListener(sbName, 'updatestart', this._onSBUpdateStart); 3680 this.addBufferListener(sbName, 'updateend', this._onSBUpdateEnd); 3681 this.addBufferListener(sbName, 'error', this._onSBUpdateError); 3682 this.tracks[trackName] = { 3683 buffer: sb, 3684 codec: codec, 3685 container: track.container, 3686 levelCodec: track.levelCodec, 3687 metadata: track.metadata, 3688 id: track.id 3689 }; 3690 tracksCreated++; 3691 } catch (err) { 3692 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.error("[buffer-controller]: error while trying to add sourceBuffer: " + err.message); 3693 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.ERROR, { 3694 type: _errors__WEBPACK_IMPORTED_MODULE_3__.ErrorTypes.MEDIA_ERROR, 3695 details: _errors__WEBPACK_IMPORTED_MODULE_3__.ErrorDetails.BUFFER_ADD_CODEC_ERROR, 3696 fatal: false, 3697 error: err, 3698 mimeType: mimeType 3699 }); 3700 } 3701 } 3702 } 3703 if (tracksCreated) { 3704 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.BUFFER_CREATED, { 3705 tracks: this.tracks 3706 }); 3707 } 3708 } 3709 3710 // Keep as arrow functions so that we can directly reference these functions directly as event listeners 3711 ; 3712 _proto._onSBUpdateStart = function _onSBUpdateStart(type) { 3713 var operationQueue = this.operationQueue; 3714 var operation = operationQueue.current(type); 3715 operation.onStart(); 3716 }; 3717 _proto._onSBUpdateEnd = function _onSBUpdateEnd(type) { 3718 var operationQueue = this.operationQueue; 3719 var operation = operationQueue.current(type); 3720 operation.onComplete(); 3721 operationQueue.shiftAndExecuteNext(type); 3722 }; 3723 _proto._onSBUpdateError = function _onSBUpdateError(type, event) { 3724 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.error("[buffer-controller]: " + type + " SourceBuffer error", event); 3725 // according to http://www.w3.org/TR/media-source/#sourcebuffer-append-error 3726 // SourceBuffer errors are not necessarily fatal; if so, the HTMLMediaElement will fire an error event 3727 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.ERROR, { 3728 type: _errors__WEBPACK_IMPORTED_MODULE_3__.ErrorTypes.MEDIA_ERROR, 3729 details: _errors__WEBPACK_IMPORTED_MODULE_3__.ErrorDetails.BUFFER_APPENDING_ERROR, 3730 fatal: false 3731 }); 3732 // updateend is always fired after error, so we'll allow that to shift the current operation off of the queue 3733 var operation = this.operationQueue.current(type); 3734 if (operation) { 3735 operation.onError(event); 3736 } 3737 } 3738 3739 // This method must result in an updateend event; if remove is not called, _onSBUpdateEnd must be called manually 3740 ; 3741 _proto.removeExecutor = function removeExecutor(type, startOffset, endOffset) { 3742 var media = this.media, 3743 mediaSource = this.mediaSource, 3744 operationQueue = this.operationQueue, 3745 sourceBuffer = this.sourceBuffer; 3746 var sb = sourceBuffer[type]; 3747 if (!media || !mediaSource || !sb) { 3748 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.warn("[buffer-controller]: Attempting to remove from the " + type + " SourceBuffer, but it does not exist"); 3749 operationQueue.shiftAndExecuteNext(type); 3750 return; 3751 } 3752 var mediaDuration = (0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(media.duration) ? media.duration : Infinity; 3753 var msDuration = (0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(mediaSource.duration) ? mediaSource.duration : Infinity; 3754 var removeStart = Math.max(0, startOffset); 3755 var removeEnd = Math.min(endOffset, mediaDuration, msDuration); 3756 if (removeEnd > removeStart && !sb.ending) { 3757 sb.ended = false; 3758 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.log("[buffer-controller]: Removing [" + removeStart + "," + removeEnd + "] from the " + type + " SourceBuffer"); 3759 console.assert(!sb.updating, type + " sourceBuffer must not be updating"); 3760 sb.remove(removeStart, removeEnd); 3761 } else { 3762 // Cycle the queue 3763 operationQueue.shiftAndExecuteNext(type); 3764 } 3765 } 3766 3767 // This method must result in an updateend event; if append is not called, _onSBUpdateEnd must be called manually 3768 ; 3769 _proto.appendExecutor = function appendExecutor(data, type) { 3770 var operationQueue = this.operationQueue, 3771 sourceBuffer = this.sourceBuffer; 3772 var sb = sourceBuffer[type]; 3773 if (!sb) { 3774 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.warn("[buffer-controller]: Attempting to append to the " + type + " SourceBuffer, but it does not exist"); 3775 operationQueue.shiftAndExecuteNext(type); 3776 return; 3777 } 3778 sb.ended = false; 3779 console.assert(!sb.updating, type + " sourceBuffer must not be updating"); 3780 sb.appendBuffer(data); 3781 } 3782 3783 // Enqueues an operation to each SourceBuffer queue which, upon execution, resolves a promise. When all promises 3784 // resolve, the onUnblocked function is executed. Functions calling this method do not need to unblock the queue 3785 // upon completion, since we already do it here 3786 ; 3787 _proto.blockBuffers = function blockBuffers(onUnblocked, buffers) { 3788 var _this9 = this; 3789 if (buffers === void 0) { 3790 buffers = this.getSourceBufferTypes(); 3791 } 3792 if (!buffers.length) { 3793 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.log('[buffer-controller]: Blocking operation requested, but no SourceBuffers exist'); 3794 Promise.resolve().then(onUnblocked); 3795 return; 3796 } 3797 var operationQueue = this.operationQueue; 3798 3799 // logger.debug(`[buffer-controller]: Blocking ${buffers} SourceBuffer`); 3800 var blockingOperations = buffers.map(function (type) { 3801 return operationQueue.appendBlocker(type); 3802 }); 3803 Promise.all(blockingOperations).then(function () { 3804 // logger.debug(`[buffer-controller]: Blocking operation resolved; unblocking ${buffers} SourceBuffer`); 3805 onUnblocked(); 3806 buffers.forEach(function (type) { 3807 var sb = _this9.sourceBuffer[type]; 3808 // Only cycle the queue if the SB is not updating. There's a bug in Chrome which sets the SB updating flag to 3809 // true when changing the MediaSource duration (https://bugs.chromium.org/p/chromium/issues/detail?id=959359&can=2&q=mediasource%20duration) 3810 // While this is a workaround, it's probably useful to have around 3811 if (!sb || !sb.updating) { 3812 operationQueue.shiftAndExecuteNext(type); 3813 } 3814 }); 3815 }); 3816 }; 3817 _proto.getSourceBufferTypes = function getSourceBufferTypes() { 3818 return Object.keys(this.sourceBuffer); 3819 }; 3820 _proto.addBufferListener = function addBufferListener(type, event, fn) { 3821 var buffer = this.sourceBuffer[type]; 3822 if (!buffer) { 3823 return; 3824 } 3825 var listener = fn.bind(this, type); 3826 this.listeners[type].push({ 3827 event: event, 3828 listener: listener 3829 }); 3830 buffer.addEventListener(event, listener); 3831 }; 3832 _proto.removeBufferListeners = function removeBufferListeners(type) { 3833 var buffer = this.sourceBuffer[type]; 3834 if (!buffer) { 3835 return; 3836 } 3837 this.listeners[type].forEach(function (l) { 3838 buffer.removeEventListener(l.event, l.listener); 3839 }); 3840 }; 3841 return BufferController; 3842}(); 3843 3844 3845/***/ }), 3846 3847/***/ "./src/controller/buffer-operation-queue.ts": 3848/*!**************************************************!*\ 3849 !*** ./src/controller/buffer-operation-queue.ts ***! 3850 \**************************************************/ 3851/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3852 3853"use strict"; 3854__webpack_require__.r(__webpack_exports__); 3855/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3856/* harmony export */ "default": () => (/* binding */ BufferOperationQueue) 3857/* harmony export */ }); 3858/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 3859 3860var BufferOperationQueue = /*#__PURE__*/function () { 3861 function BufferOperationQueue(sourceBufferReference) { 3862 this.buffers = void 0; 3863 this.queues = { 3864 video: [], 3865 audio: [], 3866 audiovideo: [] 3867 }; 3868 this.buffers = sourceBufferReference; 3869 } 3870 var _proto = BufferOperationQueue.prototype; 3871 _proto.append = function append(operation, type) { 3872 var queue = this.queues[type]; 3873 queue.push(operation); 3874 if (queue.length === 1 && this.buffers[type]) { 3875 this.executeNext(type); 3876 } 3877 }; 3878 _proto.insertAbort = function insertAbort(operation, type) { 3879 var queue = this.queues[type]; 3880 queue.unshift(operation); 3881 this.executeNext(type); 3882 }; 3883 _proto.appendBlocker = function appendBlocker(type) { 3884 var execute; 3885 var promise = new Promise(function (resolve) { 3886 execute = resolve; 3887 }); 3888 var operation = { 3889 execute: execute, 3890 onStart: function onStart() {}, 3891 onComplete: function onComplete() {}, 3892 onError: function onError() {} 3893 }; 3894 this.append(operation, type); 3895 return promise; 3896 }; 3897 _proto.executeNext = function executeNext(type) { 3898 var buffers = this.buffers, 3899 queues = this.queues; 3900 var sb = buffers[type]; 3901 var queue = queues[type]; 3902 if (queue.length) { 3903 var operation = queue[0]; 3904 try { 3905 // Operations are expected to result in an 'updateend' event being fired. If not, the queue will lock. Operations 3906 // which do not end with this event must call _onSBUpdateEnd manually 3907 operation.execute(); 3908 } catch (e) { 3909 _utils_logger__WEBPACK_IMPORTED_MODULE_0__.logger.warn('[buffer-operation-queue]: Unhandled exception executing the current operation'); 3910 operation.onError(e); 3911 3912 // Only shift the current operation off, otherwise the updateend handler will do this for us 3913 if (!sb || !sb.updating) { 3914 queue.shift(); 3915 this.executeNext(type); 3916 } 3917 } 3918 } 3919 }; 3920 _proto.shiftAndExecuteNext = function shiftAndExecuteNext(type) { 3921 this.queues[type].shift(); 3922 this.executeNext(type); 3923 }; 3924 _proto.current = function current(type) { 3925 return this.queues[type][0]; 3926 }; 3927 return BufferOperationQueue; 3928}(); 3929 3930 3931/***/ }), 3932 3933/***/ "./src/controller/cap-level-controller.ts": 3934/*!************************************************!*\ 3935 !*** ./src/controller/cap-level-controller.ts ***! 3936 \************************************************/ 3937/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3938 3939"use strict"; 3940__webpack_require__.r(__webpack_exports__); 3941/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3942/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 3943/* harmony export */ }); 3944/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 3945function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } 3946function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } 3947function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } 3948function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } 3949/* 3950 * cap stream level to media size dimension controller 3951 */ 3952 3953 3954var CapLevelController = /*#__PURE__*/function () { 3955 function CapLevelController(hls) { 3956 this.autoLevelCapping = void 0; 3957 this.firstLevel = void 0; 3958 this.media = void 0; 3959 this.restrictedLevels = void 0; 3960 this.timer = void 0; 3961 this.hls = void 0; 3962 this.streamController = void 0; 3963 this.clientRect = void 0; 3964 this.hls = hls; 3965 this.autoLevelCapping = Number.POSITIVE_INFINITY; 3966 this.firstLevel = -1; 3967 this.media = null; 3968 this.restrictedLevels = []; 3969 this.timer = undefined; 3970 this.clientRect = null; 3971 this.registerListeners(); 3972 } 3973 var _proto = CapLevelController.prototype; 3974 _proto.setStreamController = function setStreamController(streamController) { 3975 this.streamController = streamController; 3976 }; 3977 _proto.destroy = function destroy() { 3978 this.unregisterListener(); 3979 if (this.hls.config.capLevelToPlayerSize) { 3980 this.stopCapping(); 3981 } 3982 this.media = null; 3983 this.clientRect = null; 3984 // @ts-ignore 3985 this.hls = this.streamController = null; 3986 }; 3987 _proto.registerListeners = function registerListeners() { 3988 var hls = this.hls; 3989 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.FPS_DROP_LEVEL_CAPPING, this.onFpsDropLevelCapping, this); 3990 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MEDIA_ATTACHING, this.onMediaAttaching, this); 3991 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MANIFEST_PARSED, this.onManifestParsed, this); 3992 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.BUFFER_CODECS, this.onBufferCodecs, this); 3993 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MEDIA_DETACHING, this.onMediaDetaching, this); 3994 }; 3995 _proto.unregisterListener = function unregisterListener() { 3996 var hls = this.hls; 3997 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.FPS_DROP_LEVEL_CAPPING, this.onFpsDropLevelCapping, this); 3998 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MEDIA_ATTACHING, this.onMediaAttaching, this); 3999 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MANIFEST_PARSED, this.onManifestParsed, this); 4000 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.BUFFER_CODECS, this.onBufferCodecs, this); 4001 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MEDIA_DETACHING, this.onMediaDetaching, this); 4002 }; 4003 _proto.onFpsDropLevelCapping = function onFpsDropLevelCapping(event, data) { 4004 // Don't add a restricted level more than once 4005 if (CapLevelController.isLevelAllowed(data.droppedLevel, this.restrictedLevels)) { 4006 this.restrictedLevels.push(data.droppedLevel); 4007 } 4008 }; 4009 _proto.onMediaAttaching = function onMediaAttaching(event, data) { 4010 this.media = data.media instanceof HTMLVideoElement ? data.media : null; 4011 this.clientRect = null; 4012 }; 4013 _proto.onManifestParsed = function onManifestParsed(event, data) { 4014 var hls = this.hls; 4015 this.restrictedLevels = []; 4016 this.firstLevel = data.firstLevel; 4017 if (hls.config.capLevelToPlayerSize && data.video) { 4018 // Start capping immediately if the manifest has signaled video codecs 4019 this.startCapping(); 4020 } 4021 } 4022 4023 // Only activate capping when playing a video stream; otherwise, multi-bitrate audio-only streams will be restricted 4024 // to the first level 4025 ; 4026 _proto.onBufferCodecs = function onBufferCodecs(event, data) { 4027 var hls = this.hls; 4028 if (hls.config.capLevelToPlayerSize && data.video) { 4029 // If the manifest did not signal a video codec capping has been deferred until we're certain video is present 4030 this.startCapping(); 4031 } 4032 }; 4033 _proto.onMediaDetaching = function onMediaDetaching() { 4034 this.stopCapping(); 4035 }; 4036 _proto.detectPlayerSize = function detectPlayerSize() { 4037 if (this.media && this.mediaHeight > 0 && this.mediaWidth > 0) { 4038 var levels = this.hls.levels; 4039 if (levels.length) { 4040 var hls = this.hls; 4041 hls.autoLevelCapping = this.getMaxLevel(levels.length - 1); 4042 if (hls.autoLevelCapping > this.autoLevelCapping && this.streamController) { 4043 // if auto level capping has a higher value for the previous one, flush the buffer using nextLevelSwitch 4044 // usually happen when the user go to the fullscreen mode. 4045 this.streamController.nextLevelSwitch(); 4046 } 4047 this.autoLevelCapping = hls.autoLevelCapping; 4048 } 4049 } 4050 } 4051 4052 /* 4053 * returns level should be the one with the dimensions equal or greater than the media (player) dimensions (so the video will be downscaled) 4054 */; 4055 _proto.getMaxLevel = function getMaxLevel(capLevelIndex) { 4056 var _this = this; 4057 var levels = this.hls.levels; 4058 if (!levels.length) { 4059 return -1; 4060 } 4061 var validLevels = levels.filter(function (level, index) { 4062 return CapLevelController.isLevelAllowed(index, _this.restrictedLevels) && index <= capLevelIndex; 4063 }); 4064 this.clientRect = null; 4065 return CapLevelController.getMaxLevelByMediaSize(validLevels, this.mediaWidth, this.mediaHeight); 4066 }; 4067 _proto.startCapping = function startCapping() { 4068 if (this.timer) { 4069 // Don't reset capping if started twice; this can happen if the manifest signals a video codec 4070 return; 4071 } 4072 this.autoLevelCapping = Number.POSITIVE_INFINITY; 4073 this.hls.firstLevel = this.getMaxLevel(this.firstLevel); 4074 self.clearInterval(this.timer); 4075 this.timer = self.setInterval(this.detectPlayerSize.bind(this), 1000); 4076 this.detectPlayerSize(); 4077 }; 4078 _proto.stopCapping = function stopCapping() { 4079 this.restrictedLevels = []; 4080 this.firstLevel = -1; 4081 this.autoLevelCapping = Number.POSITIVE_INFINITY; 4082 if (this.timer) { 4083 self.clearInterval(this.timer); 4084 this.timer = undefined; 4085 } 4086 }; 4087 _proto.getDimensions = function getDimensions() { 4088 if (this.clientRect) { 4089 return this.clientRect; 4090 } 4091 var media = this.media; 4092 var boundsRect = { 4093 width: 0, 4094 height: 0 4095 }; 4096 if (media) { 4097 var clientRect = media.getBoundingClientRect(); 4098 boundsRect.width = clientRect.width; 4099 boundsRect.height = clientRect.height; 4100 if (!boundsRect.width && !boundsRect.height) { 4101 // When the media element has no width or height (equivalent to not being in the DOM), 4102 // then use its width and height attributes (media.width, media.height) 4103 boundsRect.width = clientRect.right - clientRect.left || media.width || 0; 4104 boundsRect.height = clientRect.bottom - clientRect.top || media.height || 0; 4105 } 4106 } 4107 this.clientRect = boundsRect; 4108 return boundsRect; 4109 }; 4110 CapLevelController.isLevelAllowed = function isLevelAllowed(level, restrictedLevels) { 4111 if (restrictedLevels === void 0) { 4112 restrictedLevels = []; 4113 } 4114 return restrictedLevels.indexOf(level) === -1; 4115 }; 4116 CapLevelController.getMaxLevelByMediaSize = function getMaxLevelByMediaSize(levels, width, height) { 4117 if (!levels || !levels.length) { 4118 return -1; 4119 } 4120 4121 // Levels can have the same dimensions but differing bandwidths - since levels are ordered, we can look to the next 4122 // to determine whether we've chosen the greatest bandwidth for the media's dimensions 4123 var atGreatestBandwidth = function atGreatestBandwidth(curLevel, nextLevel) { 4124 if (!nextLevel) { 4125 return true; 4126 } 4127 return curLevel.width !== nextLevel.width || curLevel.height !== nextLevel.height; 4128 }; 4129 4130 // If we run through the loop without breaking, the media's dimensions are greater than every level, so default to 4131 // the max level 4132 var maxLevelIndex = levels.length - 1; 4133 for (var i = 0; i < levels.length; i += 1) { 4134 var level = levels[i]; 4135 if ((level.width >= width || level.height >= height) && atGreatestBandwidth(level, levels[i + 1])) { 4136 maxLevelIndex = i; 4137 break; 4138 } 4139 } 4140 return maxLevelIndex; 4141 }; 4142 _createClass(CapLevelController, [{ 4143 key: "mediaWidth", 4144 get: function get() { 4145 return this.getDimensions().width * this.contentScaleFactor; 4146 } 4147 }, { 4148 key: "mediaHeight", 4149 get: function get() { 4150 return this.getDimensions().height * this.contentScaleFactor; 4151 } 4152 }, { 4153 key: "contentScaleFactor", 4154 get: function get() { 4155 var pixelRatio = 1; 4156 if (!this.hls.config.ignoreDevicePixelRatio) { 4157 try { 4158 pixelRatio = self.devicePixelRatio; 4159 } catch (e) { 4160 /* no-op */ 4161 } 4162 } 4163 return pixelRatio; 4164 } 4165 }]); 4166 return CapLevelController; 4167}(); 4168/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CapLevelController); 4169 4170/***/ }), 4171 4172/***/ "./src/controller/
vendor: 4,197 bytes, lines 4172-4215
4172cmcd-controller.ts": 4173/*!*******************************************!*\ 4174 !*** ./src/controller/cmcd-controller.ts ***! 4175 \*******************************************/ 4176/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 4177 4178"use strict"; 4179__webpack_require__.r(__webpack_exports__); 4180/* harmony export */ __webpack_require__.d(__webpack_exports__, { 4181/* harmony export */ "default": () => (/* binding */ CMCDController) 4182/* harmony export */ }); 4183/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 4184/* harmony import */ var _types_cmcd__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../types/cmcd */ "./src/types/cmcd.ts"); 4185/* harmony import */ var _utils_buffer_helper__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils/buffer-helper */ "./src/utils/buffer-helper.ts"); 4186/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 4187function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } 4188function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } 4189function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } 4190function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } 4191function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (it) return (it = it.call(o)).next.bind(it); if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } 4192function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } 4193function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } 4194function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } 4195 4196 4197 4198 4199 4200/** 4201 * Controller to deal with Common Media Client Data (CMCD) 4202 * @see https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf 4203 */ 4204var CMCDController = /*#__PURE__*/function () { 4205 // eslint-disable-line no-restricted-globals 4206 // eslint-disable-line no-restricted-globals 4207 4208 function CMCDController(hls) { 4209 var _this = this; 4210 this.hls = void 0; 4211 this.config = void 0; 4212 this.media = void 0; 4213 this.sid = void 0; 4214 this.cid = void 0; 4215 this.useHeaders = false;
vendor: 5,021 bytes, lines 4216-4342
4216 this.initialized = false; 4217 this.starved = false; 4218 this.buffering = true; 4219 this.audioBuffer = void 0; 4220 this.videoBuffer = void 0; 4221 this.onWaiting = function () { 4222 if (_this.initialized) { 4223 _this.starved = true; 4224 } 4225 _this.buffering = true; 4226 }; 4227 this.onPlaying = function () { 4228 if (!_this.initialized) { 4229 _this.initialized = true; 4230 } 4231 _this.buffering = false; 4232 }; 4233 this.applyPlaylistData = function (context) { 4234 try { 4235 _this.apply(context, { 4236 ot: _types_cmcd__WEBPACK_IMPORTED_MODULE_1__.CMCDObjectType.MANIFEST, 4237 su: !_this.initialized 4238 }); 4239 } catch (error) { 4240 _utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger.warn('Could not generate manifest CMCD data.', error); 4241 } 4242 }; 4243 this.applyFragmentData = function (context) { 4244 try { 4245 var fragment = context.frag; 4246 var level = _this.hls.levels[fragment.level]; 4247 var ot = _this.getObjectType(fragment); 4248 var data = { 4249 d: fragment.duration * 1000, 4250 ot: ot 4251 }; 4252 if (ot === _types_cmcd__WEBPACK_IMPORTED_MODULE_1__.CMCDObjectType.VIDEO || ot === _types_cmcd__WEBPACK_IMPORTED_MODULE_1__.CMCDObjectType.AUDIO || ot == _types_cmcd__WEBPACK_IMPORTED_MODULE_1__.CMCDObjectType.MUXED) { 4253 data.br = level.bitrate / 1000; 4254 data.tb = _this.getTopBandwidth(ot) / 1000; 4255 data.bl = _this.getBufferLength(ot); 4256 } 4257 _this.apply(context, data); 4258 } catch (error) { 4259 _utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger.warn('Could not generate segment CMCD data.', error); 4260 } 4261 }; 4262 this.hls = hls; 4263 var config = this.config = hls.config; 4264 var cmcd = config.cmcd; 4265 if (cmcd != null) { 4266 config.pLoader = this.createPlaylistLoader(); 4267 config.fLoader = this.createFragmentLoader(); 4268 this.sid = cmcd.sessionId || CMCDController.uuid(); 4269 this.cid = cmcd.contentId; 4270 this.useHeaders = cmcd.useHeaders === true; 4271 this.registerListeners(); 4272 } 4273 } 4274 var _proto = CMCDController.prototype; 4275 _proto.registerListeners = function registerListeners() { 4276 var hls = this.hls; 4277 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MEDIA_ATTACHED, this.onMediaAttached, this); 4278 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MEDIA_DETACHED, this.onMediaDetached, this); 4279 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.BUFFER_CREATED, this.onBufferCreated, this); 4280 }; 4281 _proto.unregisterListeners = function unregisterListeners() { 4282 var hls = this.hls; 4283 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MEDIA_ATTACHED, this.onMediaAttached, this); 4284 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MEDIA_DETACHED, this.onMediaDetached, this); 4285 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.BUFFER_CREATED, this.onBufferCreated, this); 4286 this.onMediaDetached(); 4287 }; 4288 _proto.destroy = function destroy() { 4289 this.unregisterListeners(); 4290 4291 // @ts-ignore 4292 this.hls = this.config = this.audioBuffer = this.videoBuffer = null; 4293 }; 4294 _proto.onMediaAttached = function onMediaAttached(event, data) { 4295 this.media = data.media; 4296 this.media.addEventListener('waiting', this.onWaiting); 4297 this.media.addEventListener('playing', this.onPlaying); 4298 }; 4299 _proto.onMediaDetached = function onMediaDetached() { 4300 if (!this.media) { 4301 return; 4302 } 4303 this.media.removeEventListener('waiting', this.onWaiting); 4304 this.media.removeEventListener('playing', this.onPlaying); 4305 4306 // @ts-ignore 4307 this.media = null; 4308 }; 4309 _proto.onBufferCreated = function onBufferCreated(event, data) { 4310 var _data$tracks$audio, _data$tracks$video; 4311 this.audioBuffer = (_data$tracks$audio = data.tracks.audio) === null || _data$tracks$audio === void 0 ? void 0 : _data$tracks$audio.buffer; 4312 this.videoBuffer = (_data$tracks$video = data.tracks.video) === null || _data$tracks$video === void 0 ? void 0 : _data$tracks$video.buffer; 4313 }; 4314 /** 4315 * Create baseline CMCD data 4316 */ 4317 _proto.createData = function createData() { 4318 var _this$media; 4319 return { 4320 v: _types_cmcd__WEBPACK_IMPORTED_MODULE_1__.CMCDVersion, 4321 sf: _types_cmcd__WEBPACK_IMPORTED_MODULE_1__.CMCDStreamingFormat.HLS, 4322 sid: this.sid, 4323 cid: this.cid, 4324 pr: (_this$media = this.media) === null || _this$media === void 0 ? void 0 : _this$media.playbackRate, 4325 mtp: this.hls.bandwidthEstimate / 1000 4326 }; 4327 } 4328 4329 /** 4330 * Apply CMCD data to a request. 4331 */; 4332 _proto.apply = function apply(context, data) { 4333 if (data === void 0) { 4334 data = {}; 4335 } 4336 // apply baseline data 4337 _extends(data, this.createData()); 4338 var isVideo = data.ot === _types_cmcd__WEBPACK_IMPORTED_MODULE_1__.CMCDObjectType.INIT || data.ot === _types_cmcd__WEBPACK_IMPORTED_MODULE_1__.CMCDObjectType.VIDEO || data.ot === _types_cmcd__WEBPACK_IMPORTED_MODULE_1__.CMCDObjectType.MUXED; 4339 if (this.starved && isVideo) { 4340 data.bs = true; 4341 data.su = true; 4342 this.starved = false;
4343 } 4344 if (data.su == null) { 4345 data.su = this.buffering; 4346 } 4347 4348 // TODO: Implement rtp, nrr, nor, dl 4349 4350 if (this.useHeaders) { 4351 var headers = CMCDController.toHeaders(data); 4352 if (!Object.keys(headers).length) { 4353 return; 4354 } 4355 if (!context.headers) { 4356 context.headers = {}; 4357 } 4358 _extends(context.headers, headers); 4359 } else { 4360 var query = CMCDController.toQuery(data); 4361 if (!query) { 4362 return; 4363 } 4364 context.url = CMCDController.appendQueryToUri(context.url, query); 4365 } 4366 } 4367 4368 /** 4369 * Apply CMCD data to a manifest request. 4370 */; 4371 /** 4372 * The CMCD object type. 4373 */ 4374 _proto.getObjectType = function getObjectType(fragment) { 4375 var type = fragment.type; 4376 if (type === 'subtitle') { 4377 return _types_cmcd__WEBPACK_IMPORTED_MODULE_1__.CMCDObjectType.TIMED_TEXT; 4378 } 4379 if (fragment.sn === 'initSegment') { 4380 return _types_cmcd__WEBPACK_IMPORTED_MODULE_1__.CMCDObjectType.INIT; 4381 } 4382 if (type === 'audio') { 4383 return _types_cmcd__WEBPACK_IMPORTED_MODULE_1__.CMCDObjectType.AUDIO; 4384 } 4385 if (type === 'main') { 4386 if (!this.hls.audioTracks.length) { 4387 return _types_cmcd__WEBPACK_IMPORTED_MODULE_1__.CMCDObjectType.MUXED; 4388 } 4389 return _types_cmcd__WEBPACK_IMPORTED_MODULE_1__.CMCDObjectType.VIDEO; 4390 } 4391 return undefined; 4392 } 4393 4394 /** 4395 * Get the highest bitrate. 4396 */; 4397 _proto.getTopBandwidth = function getTopBandwidth(type) { 4398 var bitrate = 0; 4399 var levels; 4400 var hls = this.hls; 4401 if (type === _types_cmcd__WEBPACK_IMPORTED_MODULE_1__.CMCDObjectType.AUDIO) { 4402 levels = hls.audioTracks; 4403 } else { 4404 var max = hls.maxAutoLevel; 4405 var len = max > -1 ? max + 1 : hls.levels.length; 4406 levels = hls.levels.slice(0, len); 4407 } 4408 for (var _iterator = _createForOfIteratorHelperLoose(levels), _step; !(_step = _iterator()).done;) { 4409 var level = _step.value; 4410 if (level.bitrate > bitrate) { 4411 bitrate = level.bitrate; 4412 } 4413 } 4414 return bitrate > 0 ? bitrate : NaN; 4415 } 4416 4417 /** 4418 * Get the buffer length for a media type in milliseconds 4419 */; 4420 _proto.getBufferLength = function getBufferLength(type) { 4421 var media = this.hls.media; 4422 var buffer = type === _types_cmcd__WEBPACK_IMPORTED_MODULE_1__.CMCDObjectType.AUDIO ? this.audioBuffer : this.videoBuffer; 4423 if (!buffer || !media) { 4424 return NaN; 4425 } 4426 var info = _utils_buffer_helper__WEBPACK_IMPORTED_MODULE_2__.BufferHelper.bufferInfo(buffer, media.currentTime, this.config.maxBufferHole); 4427 return info.len * 1000; 4428 } 4429 4430 /** 4431 * Create a playlist loader 4432 */; 4433 _proto.createPlaylistLoader = function createPlaylistLoader() { 4434 var pLoader = this.config.pLoader; 4435 var apply = this.applyPlaylistData; 4436 var Ctor = pLoader || this.config.loader; 4437 return /*#__PURE__*/function () { 4438 function CmcdPlaylistLoader(config) { 4439 this.loader = void 0; 4440 this.loader = new Ctor(config); 4441 } 4442 var _proto2 = CmcdPlaylistLoader.prototype; 4443 _proto2.destroy = function destroy() { 4444 this.loader.destroy(); 4445 }; 4446 _proto2.abort = function abort() { 4447 this.loader.abort(); 4448 }; 4449 _proto2.load = function load(context, config, callbacks) { 4450 apply(context); 4451 this.loader.load(context, config, callbacks); 4452 }; 4453 _createClass(CmcdPlaylistLoader, [{ 4454 key: "stats", 4455 get: function get() { 4456 return this.loader.stats; 4457 } 4458 }, { 4459 key: "context", 4460 get: function get() { 4461 return this.loader.context; 4462 } 4463 }]); 4464 return CmcdPlaylistLoader; 4465 }(); 4466 } 4467 4468 /** 4469 * Create a playlist loader 4470 */; 4471 _proto.createFragmentLoader = function createFragmentLoader() { 4472 var fLoader = this.config.fLoader; 4473 var apply = this.applyFragmentData; 4474 var Ctor = fLoader || this.config.loader; 4475 return /*#__PURE__*/function () { 4476 function CmcdFragmentLoader(config) { 4477 this.loader = void 0; 4478 this.loader = new Ctor(config); 4479 } 4480 var _proto3 = CmcdFragmentLoader.prototype; 4481 _proto3.destroy = function destroy() { 4482 this.loader.destroy(); 4483 }; 4484 _proto3.abort = function abort() { 4485 this.loader.abort(); 4486 }; 4487 _proto3.load = function load(context, config, callbacks) { 4488 apply(context); 4489 this.loader.load(context, config, callbacks); 4490 }; 4491 _createClass(CmcdFragmentLoader, [{ 4492 key: "stats", 4493 get: function get() { 4494 return this.loader.stats; 4495 } 4496 }, { 4497 key: "context", 4498 get: function get() { 4499 return this.loader.context; 4500 } 4501 }]); 4502 return CmcdFragmentLoader; 4503 }(); 4504 } 4505 4506 /** 4507 * Generate a random v4 UUI 4508 * 4509 * @returns {string} 4510 */; 4511 CMCDController.uuid = function uuid() { 4512 var url = URL.createObjectURL(new Blob()); 4513 var uuid = url.toString(); 4514 URL.revokeObjectURL(url); 4515 return uuid.slice(uuid.lastIndexOf('/') + 1); 4516 } 4517 4518 /** 4519 * Serialize a CMCD data object according to the rules defined in the 4520 * section 3.2 of 4521 * [CTA-5004](https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf). 4522 */; 4523 CMCDController.serialize = function serialize(data) { 4524 var results = []; 4525 var isValid = function isValid(value) { 4526 return !Number.isNaN(value) && value != null && value !== '' && value !== false; 4527 }; 4528 var toRounded = function toRounded(value) { 4529 return Math.round(value); 4530 }; 4531 var toHundred = function toHundred(value) { 4532 return toRounded(value / 100) * 100; 4533 }; 4534 var toUrlSafe = function toUrlSafe(value) { 4535 return encodeURIComponent(value); 4536 }; 4537 var formatters = { 4538 br: toRounded, 4539 d: toRounded, 4540 bl: toHundred, 4541 dl: toHundred, 4542 mtp: toHundred, 4543 nor: toUrlSafe, 4544 rtp: toHundred, 4545 tb: toRounded 4546 }; 4547 var keys = Object.keys(data || {}).sort(); 4548 for (var _iterator2 = _createForOfIteratorHelperLoose(keys), _step2; !(_step2 = _iterator2()).done;) { 4549 var key = _step2.value; 4550 var value = data[key]; 4551 4552 // ignore invalid values 4553 if (!isValid(value)) { 4554 continue; 4555 } 4556 4557 // Version should only be reported if not equal to 1. 4558 if (key === 'v' && value === 1) { 4559 continue; 4560 } 4561 4562 // Playback rate should only be sent if not equal to 1. 4563 if (key == 'pr' && value === 1) { 4564 continue; 4565 } 4566 4567 // Certain values require special formatting 4568 var formatter = formatters[key]; 4569 if (formatter) { 4570 value = formatter(value); 4571 } 4572 4573 // Serialize the key/value pair 4574 var type = typeof value; 4575 var result = void 0; 4576 if (key === 'ot' || key === 'sf' || key === 'st') { 4577 result = key + "=" + value; 4578 } else if (type === 'boolean') { 4579 result = key; 4580 } else if (type === 'number') { 4581 result = key + "=" + value; 4582 } else { 4583 result = key + "=" + JSON.stringify(value); 4584 } 4585 results.push(result); 4586 } 4587 return results.join(','); 4588 } 4589 4590 /** 4591 * Convert a CMCD data object to request headers according to the rules 4592 * defined in the section 2.1 and 3.2 of 4593 * [CTA-5004](https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf). 4594 */; 4595 CMCDController.toHeaders = function toHeaders(data) { 4596 var keys = Object.keys(data); 4597 var headers = {};
4598 var headerNames = ['Object', 'Request', 'Session', 'Status']; 4599 var headerGroups = [{}, {}, {}, {}]; 4600 var headerMap = { 4601 br: 0, 4602 d: 0, 4603 ot: 0, 4604 tb: 0, 4605 bl: 1, 4606 dl: 1, 4607 mtp: 1, 4608 nor: 1, 4609 nrr: 1, 4610 su: 1, 4611 cid: 2, 4612 pr: 2, 4613 sf: 2, 4614 sid: 2, 4615 st: 2, 4616 v: 2, 4617 bs: 3, 4618 rtp: 3 4619 }; 4620 for (var _i = 0, _keys = keys; _i < _keys.length; _i++) { 4621 var key = _keys[_i]; 4622 // Unmapped fields are mapped to the Request header 4623 var index = headerMap[key] != null ? headerMap[key] : 1; 4624 headerGroups[index][key] = data[key]; 4625 } 4626 for (var i = 0; i < headerGroups.length; i++) { 4627 var value = CMCDController.serialize(headerGroups[i]); 4628 if (value) { 4629 headers["CMCD-" + headerNames[i]] = value; 4630 } 4631 } 4632 return headers; 4633 } 4634 4635 /** 4636 * Convert a CMCD data object to query args according to the rules 4637 * defined in the section 2.2 and 3.2 of 4638 * [CTA-5004](https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf). 4639 */; 4640 CMCDController.toQuery = function toQuery(data) { 4641 return "CMCD=" + encodeURIComponent(CMCDController.serialize(data)); 4642 } 4643 4644 /** 4645 * Append query args to a uri. 4646 */; 4647 CMCDController.appendQueryToUri = function appendQueryToUri(uri, query) { 4648 if (!query) { 4649 return uri; 4650 } 4651 var separator = uri.includes('?') ? '&' : '?'; 4652 return "" + uri + separator + query; 4653 }; 4654 return CMCDController; 4655}(); 4656 4657 4658/***/ }), 4659
vendor: 4,135 bytes, lines 4660-4687
4660/***/ "./src/controller/eme-controller.ts": 4661/*!******************************************!*\ 4662 !*** ./src/controller/eme-controller.ts ***! 4663 \******************************************/ 4664/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 4665 4666"use strict"; 4667__webpack_require__.r(__webpack_exports__); 4668/* harmony export */ __webpack_require__.d(__webpack_exports__, { 4669/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 4670/* harmony export */ }); 4671/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 4672/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../errors */ "./src/errors.ts"); 4673/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 4674/* harmony import */ var _utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils/mediakeys-helper */ "./src/utils/mediakeys-helper.ts"); 4675/* harmony import */ var _utils_keysystem_util__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../utils/keysystem-util */ "./src/utils/keysystem-util.ts"); 4676/* harmony import */ var _utils_numeric_encoding_utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../utils/numeric-encoding-utils */ "./src/utils/numeric-encoding-utils.ts"); 4677/* harmony import */ var _loader_level_key__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../loader/level-key */ "./src/loader/level-key.ts"); 4678/* harmony import */ var _utils_hex__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../utils/hex */ "./src/utils/hex.ts"); 4679/* harmony import */ var _utils_mp4_tools__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../utils/mp4-tools */ "./src/utils/mp4-tools.ts"); 4680/* harmony import */ var eventemitter3__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! eventemitter3 */ "./node_modules/eventemitter3/index.js"); 4681/* harmony import */ var eventemitter3__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(eventemitter3__WEBPACK_IMPORTED_MODULE_9__); 4682function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); } 4683function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); } 4684function _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct.bind(); } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); } 4685function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } 4686function _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; } 4687function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
4688function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } 4689/** 4690 * @author Stephan Hesse <[email protected]> | <[email protected]> 4691 * 4692 * DRM support for Hls.js 4693 */ 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705var MAX_LICENSE_REQUEST_FAILURES = 3; 4706var LOGGER_PREFIX = '[eme]'; 4707/** 4708 * Controller to deal with encrypted media extensions (EME) 4709 * @see https://developer.mozilla.org/en-US/docs/Web/API/Encrypted_Media_Extensions_API 4710 * 4711 * @class 4712 * @constructor 4713 */ 4714var EMEController = /*#__PURE__*/function () { 4715 function EMEController(hls) { 4716 this.hls = void 0; 4717 this.config = void 0; 4718 this.media = null; 4719 this.keyFormatPromise = null; 4720 this.keySystemAccessPromises = {}; 4721 this._requestLicenseFailureCount = 0; 4722 this.mediaKeySessions = []; 4723 this.keyIdToKeySessionPromise = {}; 4724 this.setMediaKeysQueue = EMEController.CDMCleanupPromise ? [EMEController.CDMCleanupPromise] : []; 4725 this.onMediaEncrypted = this._onMediaEncrypted.bind(this); 4726 this.onWaitingForKey = this._onWaitingForKey.bind(this); 4727 this.debug = _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.debug.bind(_utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger, LOGGER_PREFIX); 4728 this.log = _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.log.bind(_utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger, LOGGER_PREFIX); 4729 this.warn = _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.warn.bind(_utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger, LOGGER_PREFIX); 4730 this.error = _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.error.bind(_utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger, LOGGER_PREFIX); 4731 this.hls = hls; 4732 this.config = hls.config; 4733 this.registerListeners(); 4734 } 4735 var _proto = EMEController.prototype; 4736 _proto.destroy = function destroy() { 4737 this.unregisterListeners(); 4738 this.onMediaDetached(); 4739 // @ts-ignore 4740 this.hls = this.onMediaEncrypted = this.onWaitingForKey = this.keyIdToKeySessionPromise = null; 4741 }; 4742 _proto.registerListeners = function registerListeners() { 4743 this.hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MEDIA_ATTACHED, this.onMediaAttached, this); 4744 this.hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MEDIA_DETACHED, this.onMediaDetached, this); 4745 this.hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MANIFEST_LOADED, this.onManifestLoaded, this); 4746 }; 4747 _proto.unregisterListeners = function unregisterListeners() { 4748 this.hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MEDIA_ATTACHED, this.onMediaAttached, this); 4749 this.hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MEDIA_DETACHED, this.onMediaDetached, this); 4750 this.hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MANIFEST_LOADED, this.onManifestLoaded, this); 4751 }; 4752 _proto.getLicenseServerUrl = function getLicenseServerUrl(keySystem) { 4753 var _this$config = this.config, 4754 drmSystems = _this$config.drmSystems, 4755 widevineLicenseUrl = _this$config.widevineLicenseUrl; 4756 var keySystemConfiguration = drmSystems[keySystem]; 4757 if (keySystemConfiguration) { 4758 return keySystemConfiguration.licenseUrl; 4759 } 4760 4761 // For backward compatibility 4762 if (keySystem === _utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_3__.KeySystems.WIDEVINE && widevineLicenseUrl) { 4763 return widevineLicenseUrl; 4764 } 4765 throw new Error("no license server URL configured for key-system \"" + keySystem + "\""); 4766 }; 4767 _proto.getServerCertificateUrl = function getServerCertificateUrl(keySystem) { 4768 var drmSystems = this.config.drmSystems; 4769 var keySystemConfiguration = drmSystems[keySystem]; 4770 if (keySystemConfiguration) { 4771 return keySystemConfiguration.serverCertificateUrl; 4772 } else { 4773 this.log("No Server Certificate in config.drmSystems[\"" + keySystem + "\"]"); 4774 } 4775 }; 4776 _proto.attemptKeySystemAccess = function attemptKeySystemAccess(keySystemsToAttempt) { 4777 var _this = this; 4778 var levels = this.hls.levels; 4779 var uniqueCodec = function uniqueCodec(value, i, a) { 4780 return !!value && a.indexOf(value) === i; 4781 }; 4782 var audioCodecs = levels.map(function (level) { 4783 return level.audioCodec; 4784 }
vendor: 6,453 bytes, lines 4784-4907
4784).filter(uniqueCodec); 4785 var videoCodecs = levels.map(function (level) { 4786 return level.videoCodec; 4787 }).filter(uniqueCodec); 4788 if (audioCodecs.length + videoCodecs.length === 0) { 4789 videoCodecs.push('avc1.42e01e'); 4790 } 4791 return new Promise(function (resolve, reject) { 4792 var attempt = function attempt(keySystems) { 4793 var keySystem = keySystems.shift(); 4794 _this.getMediaKeysPromise(keySystem, audioCodecs, videoCodecs).then(function (mediaKeys) { 4795 return resolve({ 4796 keySystem: keySystem, 4797 mediaKeys: mediaKeys 4798 }); 4799 }).catch(function (error) { 4800 if (keySystems.length) { 4801 attempt(keySystems); 4802 } else if (error instanceof EMEKeyError) { 4803 reject(error); 4804 } else { 4805 reject(new EMEKeyError({ 4806 type: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorTypes.KEY_SYSTEM_ERROR, 4807 details: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorDetails.KEY_SYSTEM_NO_ACCESS, 4808 error: error, 4809 fatal: true 4810 }, error.message)); 4811 } 4812 }); 4813 }; 4814 attempt(keySystemsToAttempt); 4815 }); 4816 }; 4817 _proto.requestMediaKeySystemAccess = function requestMediaKeySystemAccess(keySystem, supportedConfigurations) { 4818 var requestMediaKeySystemAccessFunc = this.config.requestMediaKeySystemAccessFunc; 4819 if (!(typeof requestMediaKeySystemAccessFunc === 'function')) { 4820 var errMessage = "Configured requestMediaKeySystemAccess is not a function " + requestMediaKeySystemAccessFunc; 4821 if (_utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_3__.requestMediaKeySystemAccess === null && self.location.protocol === 'http:') { 4822 errMessage = "navigator.requestMediaKeySystemAccess is not available over insecure protocol " + location.protocol; 4823 } 4824 return Promise.reject(new Error(errMessage)); 4825 } 4826 return requestMediaKeySystemAccessFunc(keySystem, supportedConfigurations); 4827 }; 4828 _proto.getMediaKeysPromise = function getMediaKeysPromise(keySystem, audioCodecs, videoCodecs) { 4829 var _this2 = this; 4830 // This can throw, but is caught in event handler callpath 4831 var mediaKeySystemConfigs = (0,_utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_3__.getSupportedMediaKeySystemConfigurations)(keySystem, audioCodecs, videoCodecs, this.config.drmSystemOptions); 4832 var keySystemAccessPromises = this.keySystemAccessPromises[keySystem]; 4833 var keySystemAccess = keySystemAccessPromises === null || keySystemAccessPromises === void 0 ? void 0 : keySystemAccessPromises.keySystemAccess; 4834 if (!keySystemAccess) { 4835 this.log("Requesting encrypted media \"" + keySystem + "\" key-system access with config: " + JSON.stringify(mediaKeySystemConfigs)); 4836 keySystemAccess = this.requestMediaKeySystemAccess(keySystem, mediaKeySystemConfigs); 4837 var _keySystemAccessPromises = this.keySystemAccessPromises[keySystem] = { 4838 keySystemAccess: keySystemAccess 4839 }; 4840 keySystemAccess.catch(function (error) { 4841 _this2.log("Failed to obtain access to key-system \"" + keySystem + "\": " + error); 4842 }); 4843 return keySystemAccess.then(function (mediaKeySystemAccess) { 4844 _this2.log("Access for key-system \"" + mediaKeySystemAccess.keySystem + "\" obtained"); 4845 var certificateRequest = _this2.fetchServerCertificate(keySystem); 4846 _this2.log("Create media-keys for \"" + keySystem + "\""); 4847 _keySystemAccessPromises.mediaKeys = mediaKeySystemAccess.createMediaKeys().then(function (mediaKeys) { 4848 _this2.log("Media-keys created for \"" + keySystem + "\""); 4849 return certificateRequest.then(function (certificate) { 4850 if (certificate) { 4851 return _this2.setMediaKeysServerCertificate(mediaKeys, keySystem, certificate); 4852 } 4853 return mediaKeys; 4854 }); 4855 }); 4856 _keySystemAccessPromises.mediaKeys.catch(function (error) { 4857 _this2.error("Failed to create media-keys for \"" + keySystem + "\"}: " + error); 4858 }); 4859 return _keySystemAccessPromises.mediaKeys; 4860 }); 4861 } 4862 return keySystemAccess.then(function () { 4863 return keySystemAccessPromises.mediaKeys; 4864 }); 4865 }; 4866 _proto.createMediaKeySessionContext = function createMediaKeySessionContext(_ref) { 4867 var decryptdata = _ref.decryptdata, 4868 keySystem = _ref.keySystem, 4869 mediaKeys = _ref.mediaKeys; 4870 console.assert(!!mediaKeys, 'mediaKeys is defined'); 4871 this.log("Creating key-system session \"" + keySystem + "\" keyId: " + _utils_hex__WEBPACK_IMPORTED_MODULE_7__["default"].hexDump(decryptdata.keyId || [])); 4872 var mediaKeysSession = mediaKeys.createSession(); 4873 var mediaKeySessionContext = { 4874 decryptdata: decryptdata, 4875 keySystem: keySystem, 4876 mediaKeys: mediaKeys, 4877 mediaKeysSession: mediaKeysSession, 4878 keyStatus: 'status-pending' 4879 }; 4880 this.mediaKeySessions.push(mediaKeySessionContext); 4881 return mediaKeySessionContext; 4882 }; 4883 _proto.renewKeySession = function renewKeySession(mediaKeySessionContext) { 4884 var decryptdata = mediaKeySessionContext.decryptdata; 4885 if (decryptdata.pssh) { 4886 var keySessionContext = this.createMediaKeySessionContext(mediaKeySessionContext); 4887 var _keyId = this.getKeyIdString(decryptdata); 4888 var scheme = 'cenc'; 4889 this.keyIdToKeySessionPromise[_keyId] = this.generateRequestWithPreferredKeySession(keySessionContext, scheme, decryptdata.pssh, 'expired'); 4890 } else { 4891 this.warn("Could not renew expired session. Missing pssh initData."); 4892 } 4893 this.removeSession(mediaKeySessionContext); 4894 }; 4895 _proto.getKeyIdString = function getKeyIdString(decryptdata) { 4896 if (!decryptdata) { 4897 throw new Error('Could not read keyId of undefined decryptdata'); 4898 } 4899 if (decryptdata.keyId === null) { 4900 throw new Error('keyId is null'); 4901 } 4902 return _utils_hex__WEBPACK_IMPORTED_MODULE_7__["default"].hexDump(decryptdata.keyId); 4903 }; 4904 _proto.updateKeySession = function updateKeySession(mediaKeySessionContext, data) { 4905 var _mediaKeySessionConte; 4906 var keySession = mediaKeySessionContext.mediaKeysSession; 4907 this.log("Updating key-session \"" + keySession.sessionId + "\" for keyID " + _utils_hex__WEBPACK_IMPORTED_MODULE_7__["default"].hexDump(((_mediaKeySessionConte = mediaKeySessionContext.decryptdata) === null || _mediaKeySessionConte === void 0 ? void 0 : _mediaKeySessionConte.keyId) || []) + "\n }
4907 (data length: " + (data ? data.byteLength : data) + ")"); 4908 return keySession.update(data); 4909 }; 4910 _proto.selectKeySystemFormat = function selectKeySystemFormat(frag) { 4911 var keyFormats = Object.keys(frag.levelkeys || {}); 4912 if (!this.keyFormatPromise) { 4913 this.log("Selecting key-system from fragment (sn: " + frag.sn + " " + frag.type + ": " + frag.level + ") key formats " + keyFormats.join(', ')); 4914 this.keyFormatPromise = this.getKeyFormatPromise(keyFormats); 4915 } 4916 return this.keyFormatPromise; 4917 }; 4918 _proto.getKeyFormatPromise = function getKeyFormatPromise(keyFormats) { 4919 var _this3 = this; 4920 return new Promise(function (resolve, reject) { 4921 var keySystemsInConfig = (0,_utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_3__.getKeySystemsForConfig)(_this3.config); 4922 var keySystemsToAttempt = keyFormats.map(_utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_3__.keySystemFormatToKeySystemDomain).filter(function (value) { 4923 return !!value && keySystemsInConfig.indexOf(value) !== -1; 4924 }); 4925 return _this3.getKeySystemSelectionPromise(keySystemsToAttempt).then(function (_ref2) { 4926 var keySystem = _ref2.keySystem; 4927 var keySystemFormat = (0,_utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_3__.keySystemDomainToKeySystemFormat)(keySystem); 4928 if (keySystemFormat) { 4929 resolve(keySystemFormat); 4930 } else { 4931 reject(new Error("Unable to find format for key-system \"" + keySystem + "\"")); 4932 } 4933 }).catch(reject); 4934 }); 4935 }; 4936 _proto.loadKey = function loadKey(data) { 4937 var _this4 = this; 4938 var decryptdata = data.keyInfo.decryptdata; 4939 var keyId = this.getKeyIdString(decryptdata); 4940 var keyDetails = "(keyId: " + keyId + " format: \"" + decryptdata.keyFormat + "\" method: " + decryptdata.method + " uri: " + decryptdata.uri + ")"; 4941 this.log("Starting session for key " + keyDetails); 4942 var keySessionContextPromise = this.keyIdToKeySessionPromise[keyId]; 4943 if (!keySessionContextPromise) { 4944 keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] = this.getKeySystemForKeyPromise(decryptdata).then(function (_ref3) { 4945 var keySystem = _ref3.keySystem, 4946 mediaKeys = _ref3.mediaKeys; 4947 _this4.throwIfDestroyed(); 4948 _this4.log("Handle encrypted media sn: " + data.frag.sn + " " + data.frag.type + ": " + data.frag.level + " using key " + keyDetails); 4949 return _this4.attemptSetMediaKeys(keySystem, mediaKeys).then(function () { 4950 _this4.throwIfDestroyed(); 4951 var keySessionContext = _this4.createMediaKeySessionContext({ 4952 keySystem: keySystem, 4953 mediaKeys: mediaKeys, 4954 decryptdata: decryptdata 4955 }); 4956 var scheme = 'cenc'; 4957 return _this4.generateRequestWithPreferredKeySession(keySessionContext, scheme, decryptdata.pssh, 'playlist-key'); 4958 }); 4959 }); 4960 keySessionContextPromise.catch(function (error) { 4961 return _this4.handleError(error); 4962 }); 4963 } 4964 return keySessionContextPromise; 4965 }; 4966 _proto.throwIfDestroyed = function throwIfDestroyed(message) { 4967 if (message === void 0) { 4968 message = 'Invalid state'; 4969 } 4970 if (!this.hls) { 4971 throw new Error('invalid state'); 4972 } 4973 }; 4974 _proto.handleError = function handleError(error) { 4975 if (!this.hls) { 4976 return; 4977 } 4978 this.error(error.message); 4979 if (error instanceof EMEKeyError) { 4980 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_0__.Events.ERROR, error.data); 4981 } else { 4982 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_0__.Events.ERROR, { 4983 type: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorTypes.KEY_SYSTEM_ERROR, 4984 details: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorDetails.KEY_SYSTEM_NO_KEYS, 4985 error: error, 4986 fatal: true 4987 }); 4988 } 4989 }; 4990 _proto.getKeySystemForKeyPromise = function getKeySystemForKeyPromise(decryptdata) { 4991 var keyId = this.getKeyIdString(decryptdata); 4992 var mediaKeySessionContext = this.keyIdToKeySessionPromise[keyId]; 4993 if (!mediaKeySessionContext) { 4994 var keySystem = (0,_utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_3__.keySystemFormatToKeySystemDomain)(decryptdata.keyFormat); 4995 var keySystemsToAttempt = keySystem ? [keySystem] : (0,_utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_3__.getKeySystemsForConfig)(this.config); 4996 return this.attemptKeySystemAccess(keySystemsToAttempt); 4997 } 4998 return mediaKeySessionContext; 4999 }; 5000 _proto.getKeySystemSelectionPromise = function getKeySystemSelectionPromise(keySystemsToAttempt) { 5001 if (!keySystemsToAttempt.length) { 5002 keySystemsToAttempt = (0,_utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_3__.getKeySystemsForConfig)(this.config); 5003 } 5004 if (keySystemsToAttempt.length === 0) { 5005 throw new EMEKeyError({ 5006 type: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorTypes.KEY_SYSTEM_ERROR, 5007 details: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorDetails.KEY_SYSTEM_NO_CONFIGURED_LICENSE, 5008 fatal: true 5009 }, "Missing key-system license configuration options " + JSON.stringify({ 5010 drmSystems: this.config.drmSystems 5011 })); 5012 } 5013 return this.attemptKeySystemAccess(keySystemsToAttempt); 5014 }; 5015 _proto._onMediaEncrypted = function _onMediaEncrypted(event) { 5016 var _this5 = this; 5017 var initDataType = event.initDataType, 5018 initData = event.initData; 5019 this.debug("\"" + event.type + "\" event: init data type: \"" + initDataType + "\""); 5020 5021 // Ignore event when initData is null 5022 if (initData === null) { 5023 return; 5024 } 5025 var keyId; 5026 var keySystemDomain; 5027 if (initDataType === 'sinf' && this.config.drmSystems[_utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_3__.KeySystems.FAIRPLAY]) { 5028 // Match sinf keyId to playlist skd://keyId= 5029 var json = (0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_8__.bin2str)(new Uint8Array(initData));
5030 try { 5031 var sinf = (0,_utils_numeric_encoding_utils__WEBPACK_IMPORTED_MODULE_5__.base64Decode)(JSON.parse(json).sinf); 5032 var tenc = (0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_8__.parseSinf)(new Uint8Array(sinf)); 5033 if (!tenc) { 5034 return; 5035 } 5036 keyId = tenc.subarray(8, 24); 5037 keySystemDomain = _utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_3__.KeySystems.FAIRPLAY; 5038 } catch (error) { 5039 this.warn('Failed to parse sinf "encrypted" event message initData'); 5040 return; 5041 } 5042 } else { 5043 // Support clear-lead key-session creation (otherwise depend on playlist keys) 5044 var psshInfo = (0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_8__.parsePssh)(initData); 5045 if (psshInfo === null) { 5046 return; 5047 } 5048 if (psshInfo.version === 0 && psshInfo.systemId === _utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_3__.KeySystemIds.WIDEVINE && psshInfo.data) { 5049 keyId = psshInfo.data.subarray(8, 24); 5050 } 5051 keySystemDomain = (0,_utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_3__.keySystemIdToKeySystemDomain)(psshInfo.systemId); 5052 } 5053 if (!keySystemDomain || !keyId) { 5054 return; 5055 } 5056 var keyIdHex = _utils_hex__WEBPACK_IMPORTED_MODULE_7__["default"].hexDump(keyId); 5057 var keyIdToKeySessionPromise = this.keyIdToKeySessionPromise, 5058 mediaKeySessions = this.mediaKeySessions; 5059 var keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex]; 5060 var _loop = function _loop(i) { 5061 // Match playlist key 5062 var keyContext = mediaKeySessions[i]; 5063 var decryptdata = keyContext.decryptdata; 5064 if (decryptdata.pssh || !decryptdata.keyId) { 5065 return "continue"; 5066 } 5067 var oldKeyIdHex = _utils_hex__WEBPACK_IMPORTED_MODULE_7__["default"].hexDump(decryptdata.keyId); 5068 if (keyIdHex === oldKeyIdHex || decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1) { 5069 keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex]; 5070 delete keyIdToKeySessionPromise[oldKeyIdHex]; 5071 decryptdata.pssh = new Uint8Array(initData); 5072 decryptdata.keyId = keyId; 5073 keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = keySessionContextPromise.then(function () { 5074 return _this5.generateRequestWithPreferredKeySession(keyContext, initDataType, initData, 'encrypted-event-key-match'); 5075 }); 5076 return "break"; 5077 } 5078 }; 5079 for (var i = 0; i < mediaKeySessions.length; i++) { 5080 var _ret = _loop(i); 5081 if (_ret === "continue") continue; 5082 if (_ret === "break") break; 5083 } 5084 if (!keySessionContextPromise) { 5085 // Clear-lead key (not encountered in playlist) 5086 keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = this.getKeySystemSelectionPromise([keySystemDomain]).then(function (_ref4) { 5087 var _keySystemToKeySystem; 5088 var keySystem = _ref4.keySystem, 5089 mediaKeys = _ref4.mediaKeys; 5090 _this5.throwIfDestroyed(); 5091 var decryptdata = new _loader_level_key__WEBPACK_IMPORTED_MODULE_6__.LevelKey('ISO-23001-7', keyIdHex, (_keySystemToKeySystem = (0,_utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_3__.keySystemDomainToKeySystemFormat)(keySystem)) != null ? _keySystemToKeySystem : ''); 5092 decryptdata.pssh = new Uint8Array(initData); 5093 decryptdata.keyId = keyId; 5094 return _this5.attemptSetMediaKeys(keySystem, mediaKeys).then(function () { 5095 _this5.throwIfDestroyed(); 5096 var keySessionContext = _this5.createMediaKeySessionContext({ 5097 decryptdata: decryptdata, 5098 keySystem: keySystem, 5099 mediaKeys: mediaKeys 5100 }); 5101 return _this5.generateRequestWithPreferredKeySession(keySessionContext, initDataType, initData, 'encrypted-event-no-match'); 5102 }); 5103 }); 5104 } 5105 keySessionContextPromise.catch(function (error) { 5106 return _this5.handleError(error); 5107 }); 5108 }; 5109 _proto._onWaitingForKey = function _onWaitingForKey(event) { 5110 this.log("\"" + event.type + "\" event"); 5111 }; 5112 _proto.attemptSetMediaKeys = function attemptSetMediaKeys(keySystem, mediaKeys) { 5113 var _this6 = this; 5114 var queue = this.setMediaKeysQueue.slice(); 5115 this.log("Setting media-keys for \"" + keySystem + "\""); 5116 // Only one setMediaKeys() can run at one time, and multiple setMediaKeys() operations 5117 // can be queued for execution for multiple key sessions. 5118 var setMediaKeysPromise = Promise.all(queue).then(function () { 5119 if (!_this6.media) { 5120 throw new Error('Attempted to set mediaKeys without media element attached'); 5121 } 5122 return _this6.media.setMediaKeys(mediaKeys); 5123 }); 5124 this.setMediaKeysQueue.push(setMediaKeysPromise); 5125 return setMediaKeysPromise.then(function () { 5126 _this6.log("Media-keys set for \"" + keySystem + "\""); 5127 queue.push(setMediaKeysPromise); 5128 _this6.setMediaKeysQueue = _this6.setMediaKeysQueue.filter(function (p) { 5129 return queue.indexOf(p) === -1; 5130 }); 5131 }); 5132 }; 5133 _proto.generateRequestWithPreferredKeySession = function generateRequestWithPreferredKeySession(context, initDataType, initData, reason) { 5134 var _this$config$drmSyste, 5135 _this$config$drmSyste2, 5136 _this7 = this; 5137 var generateRequestFilter = (_this$config$drmSyste = this.config.drmSystems) === null || _this$config$drmSyste === void 0 ? void 0 : (_this$config$drmSyste2 = _this$config$drmSyste[context.keySystem]) === null || _this$config$drmSyste2 === void 0 ? void 0 : _this$config$drmSyste2.generateRequest; 5138 if (generateRequestFilter) {
5139 try { 5140 var mappedInitData = generateRequestFilter.call(this.hls, initDataType, initData, context); 5141 if (!mappedInitData) { 5142 throw new Error('Invalid response from configured generateRequest filter'); 5143 } 5144 initDataType = mappedInitData.initDataType; 5145 initData = context.decryptdata.pssh = mappedInitData.initData ? new Uint8Array(mappedInitData.initData) : null; 5146 } catch (error) { 5147 var _this$hls; 5148 this.warn(error.message); 5149 if ((_this$hls = this.hls) !== null && _this$hls !== void 0 && _this$hls.config.debug) { 5150 throw error; 5151 } 5152 } 5153 } 5154 if (initData === null) { 5155 this.log("Skipping key-session request for \"" + reason + "\" (no initData)"); 5156 return Promise.resolve(context); 5157 } 5158 var keyId = this.getKeyIdString(context.decryptdata); 5159 this.log("Generating key-session request for \"" + reason + "\": " + keyId + " (init data type: " + initDataType + " length: " + (initData ? initData.byteLength : null) + ")"); 5160 var licenseStatus = new (eventemitter3__WEBPACK_IMPORTED_MODULE_9___default())(); 5161 context.mediaKeysSession.onmessage = function (event) { 5162 var keySession = context.mediaKeysSession; 5163 if (!keySession) { 5164 licenseStatus.emit('error', new Error('invalid state')); 5165 return; 5166 } 5167 var messageType = event.messageType, 5168 message = event.message; 5169 _this7.log("\"" + messageType + "\" message event for session \"" + keySession.sessionId + "\" message size: " + message.byteLength); 5170 if (messageType === 'license-request' || messageType === 'license-renewal') { 5171 _this7.renewLicense(context, message).catch(function (error) { 5172 _this7.handleError(error); 5173 licenseStatus.emit('error', error); 5174 }); 5175 } else if (messageType === 'license-release') { 5176 if (context.keySystem === _utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_3__.KeySystems.FAIRPLAY) { 5177 _this7.updateKeySession(context, (0,_utils_keysystem_util__WEBPACK_IMPORTED_MODULE_4__.strToUtf8array)('acknowledged')); 5178 _this7.removeSession(context); 5179 } 5180 } else { 5181 _this7.warn("unhandled media key message type \"" + messageType + "\""); 5182 } 5183 }; 5184 context.mediaKeysSession.onkeystatuseschange = function (event) { 5185 var keySession = context.mediaKeysSession; 5186 if (!keySession) { 5187 licenseStatus.emit('error', new Error('invalid state')); 5188 return; 5189 } 5190 _this7.onKeyStatusChange(context); 5191 var keyStatus = context.keyStatus; 5192 licenseStatus.emit('keyStatus', keyStatus); 5193 if (keyStatus === 'expired') { 5194 _this7.warn(context.keySystem + " expired for key " + keyId); 5195 _this7.renewKeySession(context); 5196 } 5197 }; 5198 var keyUsablePromise = new Promise(function (resolve, reject) { 5199 licenseStatus.on('error', reject); 5200 licenseStatus.on('keyStatus', function (keyStatus) { 5201 if (keyStatus.startsWith('usable')) { 5202 resolve(); 5203 } else if (keyStatus === 'output-restricted') { 5204 reject(new EMEKeyError({ 5205 type: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorTypes.KEY_SYSTEM_ERROR, 5206 details: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorDetails.KEY_SYSTEM_STATUS_OUTPUT_RESTRICTED, 5207 fatal: false 5208 }, 'HDCP level output restricted')); 5209 } else if (keyStatus === 'internal-error') { 5210 reject(new EMEKeyError({ 5211 type: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorTypes.KEY_SYSTEM_ERROR, 5212 details: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorDetails.KEY_SYSTEM_STATUS_INTERNAL_ERROR, 5213 fatal: true 5214 }, "key status changed to \"" + keyStatus + "\"")); 5215 } else if (keyStatus === 'expired') { 5216 reject(new Error('key expired while generating request')); 5217 } else { 5218 _this7.warn("unhandled key status change \"" + keyStatus + "\""); 5219 } 5220 }); 5221 }); 5222 return context.mediaKeysSession.generateRequest(initDataType, initData).then(function () { 5223 var _context$mediaKeysSes; 5224 _this7.log("Request generated for key-session \"" + ((_context$mediaKeysSes = context.mediaKeysSession) === null || _context$mediaKeysSes === void 0 ? void 0 : _context$mediaKeysSes.sessionId) + "\" keyId: " + keyId); 5225 }).catch(function (error) { 5226 throw new EMEKeyError({ 5227 type: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorTypes.KEY_SYSTEM_ERROR, 5228 details: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorDetails.KEY_SYSTEM_NO_SESSION, 5229 error: error, 5230 fatal: false 5231 }, "Error generating key-session request: " + error); 5232 }).then(function () { 5233 return keyUsablePromise; 5234 }).catch(function (error) { 5235 licenseStatus.removeAllListeners(); 5236 _this7.removeSession(context); 5237 throw error; 5238 }).then(function () { 5239 licenseStatus.removeAllListeners(); 5240 return context; 5241 }); 5242 }; 5243 _proto.onKeyStatusChange = function onKeyStatusChange(mediaKeySessionContext) { 5244 var _this8 = this;
5245 mediaKeySessionContext.mediaKeysSession.keyStatuses.forEach(function (status, keyId) { 5246 _this8.log("key status change \"" + status + "\" for keyStatuses keyId: " + _utils_hex__WEBPACK_IMPORTED_MODULE_7__["default"].hexDump('buffer' in keyId ? new Uint8Array(keyId.buffer, keyId.byteOffset, keyId.byteLength) : new Uint8Array(keyId)) + " session keyId: " + _utils_hex__WEBPACK_IMPORTED_MODULE_7__["default"].hexDump(new Uint8Array(mediaKeySessionContext.decryptdata.keyId || [])) + " uri: " + mediaKeySessionContext.decryptdata.uri); 5247 mediaKeySessionContext.keyStatus = status; 5248 }); 5249 }; 5250 _proto.fetchServerCertificate = function fetchServerCertificate(keySystem) { 5251 var _this9 = this; 5252 return new Promise(function (resolve, reject) { 5253 var url = _this9.getServerCertificateUrl(keySystem); 5254 if (!url) { 5255 return resolve(); 5256 } 5257 _this9.log("Fetching serverCertificate for \"" + keySystem + "\""); 5258 var xhr = new XMLHttpRequest(); 5259 xhr.open('GET', url, true); 5260 xhr.responseType = 'arraybuffer'; 5261 xhr.onreadystatechange = function () { 5262 if (xhr.readyState === XMLHttpRequest.DONE) { 5263 if (xhr.status === 200) { 5264 resolve(xhr.response); 5265 } else { 5266 reject(new EMEKeyError({ 5267 type: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorTypes.KEY_SYSTEM_ERROR, 5268 details: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED, 5269 fatal: true, 5270 networkDetails: xhr 5271 }, "\"" + keySystem + "\" certificate request XHR failed (" + url + "). Status: " + xhr.status + " (" + xhr.statusText + ")")); 5272 } 5273 } 5274 }; 5275 xhr.send(); 5276 }); 5277 }; 5278 _proto.setMediaKeysServerCertificate = function setMediaKeysServerCertificate(mediaKeys, keySystem, cert) { 5279 var _this10 = this; 5280 return new Promise(function (resolve, reject) { 5281 mediaKeys.setServerCertificate(cert).then(function (success) { 5282 _this10.log("setServerCertificate " + (success ? 'success' : 'not supported by CDM') + " (" + (cert === null || cert === void 0 ? void 0 : cert.byteLength) + ") on \"" + keySystem + "\""); 5283 resolve(mediaKeys); 5284 }).catch(function (error) { 5285 reject(new EMEKeyError({ 5286 type: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorTypes.KEY_SYSTEM_ERROR, 5287 details: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_UPDATE_FAILED, 5288 error: error, 5289 fatal: true 5290 }, error.message)); 5291 }); 5292 }); 5293 }; 5294 _proto.renewLicense = function renewLicense(context, keyMessage) { 5295 var _this11 = this; 5296 return this.requestLicense(context, new Uint8Array(keyMessage)).then(function (data) { 5297 return _this11.updateKeySession(context, new Uint8Array(data)).catch(function (error) { 5298 throw new EMEKeyError({ 5299 type: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorTypes.KEY_SYSTEM_ERROR, 5300 details: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorDetails.KEY_SYSTEM_SESSION_UPDATE_FAILED, 5301 error: error, 5302 fatal: true 5303 }, error.message); 5304 }); 5305 }); 5306 }; 5307 _proto.setupLicenseXHR = function setupLicenseXHR(xhr, url, keysListItem, licenseChallenge) { 5308 var _this12 = this; 5309 var licenseXhrSetup = this.config.licenseXhrSetup; 5310 if (!licenseXhrSetup) { 5311 xhr.open('POST', url, true); 5312 return Promise.resolve({ 5313 xhr: xhr, 5314 licenseChallenge: licenseChallenge 5315 }); 5316 } 5317 return Promise.resolve().then(function () { 5318 if (!keysListItem.decryptdata) { 5319 throw new Error('Key removed'); 5320 } 5321 return licenseXhrSetup.call(_this12.hls, xhr, url, keysListItem, licenseChallenge); 5322 }).catch(function (error) { 5323 if (!keysListItem.decryptdata) { 5324 // Key session removed. Cancel license request. 5325 throw error; 5326 } 5327 // let's try to open before running setup 5328 xhr.open('POST', url, true); 5329 return licenseXhrSetup.call(_this12.hls, xhr, url, keysListItem, licenseChallenge); 5330 }).then(function (licenseXhrSetupResult) { 5331 // if licenseXhrSetup did not yet call open, let's do it now 5332 if (!xhr.readyState) { 5333 xhr.open('POST', url, true); 5334 } 5335 var finalLicenseChallenge = licenseXhrSetupResult ? licenseXhrSetupResult : licenseChallenge; 5336 return { 5337 xhr: xhr, 5338 licenseChallenge: finalLicenseChallenge 5339 }; 5340 }); 5341 }; 5342 _proto.requestLicense = function requestLicense(keySessionContext, licenseChallenge) { 5343 var _this13 = this; 5344 return new Promise(function (resolve, reject) { 5345 var url = _this13.getLicenseServerUrl(keySessionContext.keySystem); 5346 _this13.log("Sending license request to URL: " + url); 5347 var xhr = new XMLHttpRequest(); 5348 xhr.responseType = 'arraybuffer'; 5349 xhr.onreadystatechange = function () { 5350 if (!_this13.hls || !keySessionContext.mediaKeysSession) { 5351 return reject(new Error('invalid state')); 5352 } 5353 if (xhr.readyState === 4) { 5354 if (xhr.status === 200) { 5355 _this13._requestLicenseFailureCount = 0; 5356 var data = xhr.response;
5357 _this13.log("License received " + (data instanceof ArrayBuffer ? data.byteLength : data)); 5358 var licenseResponseCallback = _this13.config.licenseResponseCallback; 5359 if (licenseResponseCallback) { 5360 try { 5361 data = licenseResponseCallback.call(_this13.hls, xhr, url, keySessionContext); 5362 } catch (error) { 5363 _this13.error(error); 5364 } 5365 } 5366 resolve(data); 5367 } else { 5368 _this13._requestLicenseFailureCount++; 5369 if (_this13._requestLicenseFailureCount > MAX_LICENSE_REQUEST_FAILURES || xhr.status >= 400 && xhr.status < 500) { 5370 reject(new EMEKeyError({ 5371 type: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorTypes.KEY_SYSTEM_ERROR, 5372 details: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED, 5373 fatal: true, 5374 networkDetails: xhr 5375 }, "License Request XHR failed (" + url + "). Status: " + xhr.status + " (" + xhr.statusText + ")")); 5376 } else { 5377 var attemptsLeft = MAX_LICENSE_REQUEST_FAILURES - _this13._requestLicenseFailureCount + 1; 5378 _this13.warn("Retrying license request, " + attemptsLeft + " attempts left"); 5379 _this13.requestLicense(keySessionContext, licenseChallenge).then(resolve, reject); 5380 } 5381 } 5382 } 5383 }; 5384 if (keySessionContext.licenseXhr && keySessionContext.licenseXhr.readyState !== XMLHttpRequest.DONE) { 5385 keySessionContext.licenseXhr.abort(); 5386 } 5387 keySessionContext.licenseXhr = xhr; 5388 _this13.setupLicenseXHR(xhr, url, keySessionContext, licenseChallenge).then(function (_ref5) { 5389 var xhr = _ref5.xhr, 5390 licenseChallenge = _ref5.licenseChallenge; 5391 xhr.send(licenseChallenge); 5392 }); 5393 }); 5394 }; 5395 _proto.onMediaAttached = function onMediaAttached(event, data) { 5396 if (!this.config.emeEnabled) { 5397 return; 5398 } 5399 var media = data.media; 5400 5401 // keep reference of media 5402 this.media = media; 5403 media.addEventListener('encrypted', this.onMediaEncrypted); 5404 media.addEventListener('waitingforkey', this.onWaitingForKey); 5405 }; 5406 _proto.onMediaDetached = function onMediaDetached() { 5407 var _this14 = this; 5408 var media = this.media; 5409 var mediaKeysList = this.mediaKeySessions; 5410 if (media) { 5411 media.removeEventListener('encrypted', this.onMediaEncrypted); 5412 media.removeEventListener('waitingforkey', this.onWaitingForKey); 5413 this.media = null; 5414 } 5415 this._requestLicenseFailureCount = 0; 5416 this.setMediaKeysQueue = []; 5417 this.mediaKeySessions = []; 5418 this.keyIdToKeySessionPromise = {}; 5419 _loader_level_key__WEBPACK_IMPORTED_MODULE_6__.LevelKey.clearKeyUriToKeyIdMap(); 5420 5421 // Close all sessions and remove media keys from the video element. 5422 var keySessionCount = mediaKeysList.length; 5423 EMEController.CDMCleanupPromise = Promise.all(mediaKeysList.map(function (mediaKeySessionContext) { 5424 return _this14.removeSession(mediaKeySessionContext); 5425 }).concat(media === null || media === void 0 ? void 0 : media.setMediaKeys(null).catch(function (error) { 5426 _this14.log("Could not clear media keys: " + error + ". media.src: " + (media === null || media === void 0 ? void 0 : media.src)); 5427 }))).then(function () { 5428 if (keySessionCount) { 5429 _this14.log('finished closing key sessions and clearing media keys'); 5430 mediaKeysList.length = 0; 5431 } 5432 }).catch(function (error) { 5433 _this14.log("Could not close sessions and clear media keys: " + error + ". media.src: " + (media === null || media === void 0 ? void 0 : media.src)); 5434 }); 5435 }; 5436 _proto.onManifestLoaded = function onManifestLoaded(event, _ref6) { 5437 var sessionKeys = _ref6.sessionKeys; 5438 if (!sessionKeys || !this.config.emeEnabled) { 5439 return; 5440 } 5441 if (!this.keyFormatPromise) { 5442 var keyFormats = sessionKeys.reduce(function (formats, sessionKey) { 5443 if (formats.indexOf(sessionKey.keyFormat) === -1) { 5444 formats.push(sessionKey.keyFormat); 5445 } 5446 return formats; 5447 }, []); 5448 this.log("Selecting key-system from session-keys " + keyFormats.join(', ')); 5449 this.keyFormatPromise = this.getKeyFormatPromise(keyFormats); 5450 } 5451 }; 5452 _proto.removeSession = function removeSession(mediaKeySessionContext) { 5453 var _this15 = this; 5454 var mediaKeysSession = mediaKeySessionContext.mediaKeysSession, 5455 licenseXhr = mediaKeySessionContext.licenseXhr; 5456 if (mediaKeysSession) {
5457 this.log("Remove licenses and keys and close session " + mediaKeysSession.sessionId); 5458 mediaKeysSession.onmessage = null; 5459 mediaKeysSession.onkeystatuseschange = null; 5460 if (licenseXhr && licenseXhr.readyState !== XMLHttpRequest.DONE) { 5461 licenseXhr.abort(); 5462 } 5463 mediaKeySessionContext.mediaKeysSession = mediaKeySessionContext.decryptdata = mediaKeySessionContext.licenseXhr = undefined; 5464 var index = this.mediaKeySessions.indexOf(mediaKeySessionContext); 5465 if (index > -1) { 5466 this.mediaKeySessions.splice(index, 1); 5467 } 5468 return mediaKeysSession.remove().catch(function (error) { 5469 _this15.log("Could not remove session: " + error); 5470 }).then(function () { 5471 return mediaKeysSession.close(); 5472 }).catch(function (error) { 5473 _this15.log("Could not close session: " + error); 5474 }); 5475 } 5476 }; 5477 return EMEController; 5478}(); 5479EMEController.CDMCleanupPromise = void 0; 5480var EMEKeyError = /*#__PURE__*/function (_Error) { 5481 _inheritsLoose(EMEKeyError, _Error); 5482 function EMEKeyError(data, message) { 5483 var _this16; 5484 _this16 = _Error.call(this, message) || this; 5485 _this16.data = void 0; 5486 _this16.data = data; 5487 data.err = data.error; 5488 return _this16; 5489 } 5490 return EMEKeyError; 5491}( /*#__PURE__*/_wrapNativeSuper(Error)); 5492/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (EME
vendor: 163,055 bytes, lines 5492-9178
5492Controller); 5493 5494/***/ }), 5495 5496/***/ "./src/controller/fps-controller.ts": 5497/*!******************************************!*\ 5498 !*** ./src/controller/fps-controller.ts ***! 5499 \******************************************/ 5500/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 5501 5502"use strict"; 5503__webpack_require__.r(__webpack_exports__); 5504/* harmony export */ __webpack_require__.d(__webpack_exports__, { 5505/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 5506/* harmony export */ }); 5507/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 5508/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 5509 5510 5511var FPSController = /*#__PURE__*/function () { 5512 // stream controller must be provided as a dependency! 5513 5514 function FPSController(hls) { 5515 this.hls = void 0; 5516 this.isVideoPlaybackQualityAvailable = false; 5517 this.timer = void 0; 5518 this.media = null; 5519 this.lastTime = void 0; 5520 this.lastDroppedFrames = 0; 5521 this.lastDecodedFrames = 0; 5522 this.streamController = void 0; 5523 this.hls = hls; 5524 this.registerListeners(); 5525 } 5526 var _proto = FPSController.prototype; 5527 _proto.setStreamController = function setStreamController(streamController) { 5528 this.streamController = streamController; 5529 }; 5530 _proto.registerListeners = function registerListeners() { 5531 this.hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MEDIA_ATTACHING, this.onMediaAttaching, this); 5532 }; 5533 _proto.unregisterListeners = function unregisterListeners() { 5534 this.hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MEDIA_ATTACHING, this.onMediaAttaching); 5535 }; 5536 _proto.destroy = function destroy() { 5537 if (this.timer) { 5538 clearInterval(this.timer); 5539 } 5540 this.unregisterListeners(); 5541 this.isVideoPlaybackQualityAvailable = false; 5542 this.media = null; 5543 }; 5544 _proto.onMediaAttaching = function onMediaAttaching(event, data) { 5545 var config = this.hls.config; 5546 if (config.capLevelOnFPSDrop) { 5547 var media = data.media instanceof self.HTMLVideoElement ? data.media : null; 5548 this.media = media; 5549 if (media && typeof media.getVideoPlaybackQuality === 'function') { 5550 this.isVideoPlaybackQualityAvailable = true; 5551 } 5552 self.clearInterval(this.timer); 5553 this.timer = self.setInterval(this.checkFPSInterval.bind(this), config.fpsDroppedMonitoringPeriod); 5554 } 5555 }; 5556 _proto.checkFPS = function checkFPS(video, decodedFrames, droppedFrames) { 5557 var currentTime = performance.now(); 5558 if (decodedFrames) { 5559 if (this.lastTime) { 5560 var currentPeriod = currentTime - this.lastTime; 5561 var currentDropped = droppedFrames - this.lastDroppedFrames; 5562 var currentDecoded = decodedFrames - this.lastDecodedFrames; 5563 var droppedFPS = 1000 * currentDropped / currentPeriod; 5564 var hls = this.hls; 5565 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_0__.Events.FPS_DROP, { 5566 currentDropped: currentDropped, 5567 currentDecoded: currentDecoded, 5568 totalDroppedFrames: droppedFrames 5569 }); 5570 if (droppedFPS > 0) { 5571 // logger.log('checkFPS : droppedFPS/decodedFPS:' + droppedFPS/(1000 * currentDecoded / currentPeriod)); 5572 if (currentDropped > hls.config.fpsDroppedMonitoringThreshold * currentDecoded) { 5573 var currentLevel = hls.currentLevel; 5574 _utils_logger__WEBPACK_IMPORTED_MODULE_1__.logger.warn('drop FPS ratio greater than max allowed value for currentLevel: ' + currentLevel); 5575 if (currentLevel > 0 && (hls.autoLevelCapping === -1 || hls.autoLevelCapping >= currentLevel)) { 5576 currentLevel = currentLevel - 1; 5577 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_0__.Events.FPS_DROP_LEVEL_CAPPING, { 5578 level: currentLevel, 5579 droppedLevel: hls.currentLevel 5580 }); 5581 hls.autoLevelCapping = currentLevel; 5582 this.streamController.nextLevelSwitch(); 5583 } 5584 } 5585 } 5586 } 5587 this.lastTime = currentTime; 5588 this.lastDroppedFrames = droppedFrames; 5589 this.lastDecodedFrames = decodedFrames; 5590 } 5591 }; 5592 _proto.checkFPSInterval = function checkFPSInterval() { 5593 var video = this.media; 5594 if (video) { 5595 if (this.isVideoPlaybackQualityAvailable) { 5596 var videoPlaybackQuality = video.getVideoPlaybackQuality(); 5597 this.checkFPS(video, videoPlaybackQuality.totalVideoFrames, videoPlaybackQuality.droppedVideoFrames); 5598 } else { 5599 // HTMLVideoElement doesn't include the webkit types 5600 this.checkFPS(video, video.webkitDecodedFrameCount, video.webkitDroppedFrameCount); 5601 } 5602 } 5603 }; 5604 return FPSController; 5605}(); 5606/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FPSController); 5607 5608/***/ }), 5609 5610/***/ "./src/controller/fragment-finders.ts": 5611/*!********************************************!*\ 5612 !*** ./src/controller/fragment-finders.ts ***! 5613 \********************************************/ 5614/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 5615 5616"use strict"; 5617__webpack_require__.r(__webpack_exports__); 5618/* harmony export */ __webpack_require__.d(__webpack_exports__, { 5619/* harmony export */ "findFragWithCC": () => (/* binding */ findFragWithCC), 5620/* harmony export */ "findFragmentByPDT": () => (/* binding */ findFragmentByPDT), 5621/* harmony export */ "findFragmentByPTS": () => (/* binding */ findFragmentByPTS), 5622/* harmony export */ "fragmentWithinToleranceTest": () => (/* binding */ fragmentWithinToleranceTest), 5623/* harmony export */ "pdtWithinToleranceTest": () => (/* binding */ pdtWithinToleranceTest) 5624/* harmony export */ }); 5625/* harmony import */ var _home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.ts"); 5626/* harmony import */ var _utils_binary_search__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils/binary-search */ "./src/utils/binary-search.ts"); 5627 5628 5629/** 5630 * Returns first fragment whose endPdt value exceeds the given PDT. 5631 * @param {Array<Fragment>} fragments - The array of candidate fragments 5632 * @param {number|null} [PDTValue = null] - The PDT value which must be exceeded 5633 * @param {number} [maxFragLookUpTolerance = 0] - The amount of time that a fragment's start/end can be within in order to be considered contiguous 5634 * @returns {*|null} fragment - The best matching fragment 5635 */ 5636function findFragmentByPDT(fragments, PDTValue, maxFragLookUpTolerance) { 5637 if (PDTValue === null || !Array.isArray(fragments) || !fragments.length || !(0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(PDTValue)) { 5638 return null; 5639 } 5640 5641 // if less than start 5642 var startPDT = fragments[0].programDateTime; 5643 if (PDTValue < (startPDT || 0)) { 5644 return null; 5645 } 5646 var endPDT = fragments[fragments.length - 1].endProgramDateTime; 5647 if (PDTValue >= (endPDT || 0)) { 5648 return null; 5649 } 5650 maxFragLookUpTolerance = maxFragLookUpTolerance || 0; 5651 for (var seg = 0; seg < fragments.length; ++seg) { 5652 var frag = fragments[seg]; 5653 if (pdtWithinToleranceTest(PDTValue, maxFragLookUpTolerance, frag)) { 5654 return frag; 5655 } 5656 } 5657 return null; 5658} 5659 5660/** 5661 * Finds a fragment based on the SN of the previous fragment; or based on the needs of the current buffer. 5662 * This method compensates for small buffer gaps by applying a tolerance to the start of any candidate fragment, thus 5663 * breaking any traps which would cause the same fragment to be continuously selected within a small range. 5664 * @param {*} fragPrevious - The last frag successfully appended 5665 * @param {Array} fragments - The array of candidate fragments 5666 * @param {number} [bufferEnd = 0] - The end of the contiguous buffered range the playhead is currently within 5667 * @param {number} maxFragLookUpTolerance - The amount of time that a fragment's start/end can be within in order to be considered contiguous 5668 * @returns {*} foundFrag - The best matching fragment 5669 */ 5670function findFragmentByPTS(fragPrevious, fragments, bufferEnd, maxFragLookUpTolerance) { 5671 if (bufferEnd === void 0) { 5672 bufferEnd = 0; 5673 } 5674 if (maxFragLookUpTolerance === void 0) { 5675 maxFragLookUpTolerance = 0; 5676 } 5677 var fragNext = null; 5678 if (fragPrevious) { 5679 fragNext = fragments[fragPrevious.sn - fragments[0].sn + 1] || null; 5680 } else if (bufferEnd === 0 && fragments[0].start === 0) { 5681 fragNext = fragments[0]; 5682 } 5683 // Prefer the next fragment if it's within tolerance 5684 if (fragNext && fragmentWithinToleranceTest(bufferEnd, maxFragLookUpTolerance, fragNext) === 0) { 5685 return fragNext; 5686 } 5687 // We might be seeking past the tolerance so find the best match 5688 var foundFragment = _utils_binary_search__WEBPACK_IMPORTED_MODULE_1__["default"].search(fragments, fragmentWithinToleranceTest.bind(null, bufferEnd, maxFragLookUpTolerance)); 5689 if (foundFragment && (foundFragment !== fragPrevious || !fragNext)) { 5690 return foundFragment; 5691 } 5692 // If no match was found return the next fragment after fragPrevious, or null 5693 return fragNext; 5694} 5695 5696/** 5697 * The test function used by the findFragmentBySn's BinarySearch to look for the best match to the current buffer conditions. 5698 * @param {*} candidate - The fragment to test 5699 * @param {number} [bufferEnd = 0] - The end of the current buffered range the playhead is currently within 5700 * @param {number} [maxFragLookUpTolerance = 0] - The amount of time that a fragment's start can be within in order to be considered contiguous 5701 * @returns {number} - 0 if it matches, 1 if too low, -1 if too high 5702 */ 5703function fragmentWithinToleranceTest(bufferEnd, maxFragLookUpTolerance, candidate) { 5704 if (bufferEnd === void 0) { 5705 bufferEnd = 0; 5706 } 5707 if (maxFragLookUpTolerance === void 0) { 5708 maxFragLookUpTolerance = 0; 5709 } 5710 // eagerly accept an accurate match (no tolerance) 5711 if (candidate.start <= bufferEnd && candidate.start + candidate.duration > bufferEnd) { 5712 return 0; 5713 } 5714 // offset should be within fragment boundary - config.maxFragLookUpTolerance 5715 // this is to cope with situations like 5716 // bufferEnd = 9.991 5717 // frag[Ø] : [0,10] 5718 // frag[1] : [10,20] 5719 // bufferEnd is within frag[0] range ... although what we are expecting is to return frag[1] here 5720 // frag start frag start+duration 5721 // |-----------------------------| 5722 // <---> <---> 5723 // ...--------><-----------------------------><---------.... 5724 // previous frag matching fragment next frag 5725 // return -1 return 0 return 1 5726 // logger.log(`level/sn/start/end/bufEnd:${level}/${candidate.sn}/${candidate.start}/${(candidate.start+candidate.duration)}/${bufferEnd}`); 5727 // Set the lookup tolerance to be small enough to detect the current segment - ensures we don't skip over very small segments 5728 var candidateLookupTolerance = Math.min(maxFragLookUpTolerance, candidate.duration + (candidate.deltaPTS ? candidate.deltaPTS : 0)); 5729 if (candidate.start + candidate.duration - candidateLookupTolerance <= bufferEnd) { 5730 return 1; 5731 } else if (candidate.start - candidateLookupTolerance > bufferEnd && candidate.start) { 5732 // if maxFragLookUpTolerance will have negative value then don't return -1 for first element 5733 return -1; 5734 } 5735 return 0; 5736} 5737 5738/** 5739 * The test function used by the findFragmentByPdt's BinarySearch to look for the best match to the current buffer conditions. 5740 * This function tests the candidate's program date time values, as represented in Unix time 5741 * @param {*} candidate - The fragment to test 5742 * @param {number} [pdtBufferEnd = 0] - The Unix time representing the end of the current buffered range 5743 * @param {number} [maxFragLookUpTolerance = 0] - The amount of time that a fragment's start can be within in order to be considered contiguous 5744 * @returns {boolean} True if contiguous, false otherwise 5745 */ 5746function pdtWithinToleranceTest(pdtBufferEnd, maxFragLookUpTolerance, candidate) { 5747 var candidateLookupTolerance = Math.min(maxFragLookUpTolerance, candidate.duration + (candidate.deltaPTS ? candidate.deltaPTS : 0)) * 1000; 5748 5749 // endProgramDateTime can be null, default to zero 5750 var endProgramDateTime = candidate.endProgramDateTime || 0; 5751 return endProgramDateTime - candidateLookupTolerance > pdtBufferEnd; 5752} 5753function findFragWithCC(fragments, cc) { 5754 return _utils_binary_search__WEBPACK_IMPORTED_MODULE_1__["default"].search(fragments, function (candidate) { 5755 if (candidate.cc < cc) { 5756 return 1; 5757 } else if (candidate.cc > cc) { 5758 return -1; 5759 } else { 5760 return 0; 5761 } 5762 }); 5763} 5764 5765/***/ }), 5766 5767/***/ "./src/controller/fragment-tracker.ts": 5768/*!********************************************!*\ 5769 !*** ./src/controller/fragment-tracker.ts ***! 5770 \********************************************/ 5771/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 5772 5773"use strict"; 5774__webpack_require__.r(__webpack_exports__); 5775/* harmony export */ __webpack_require__.d(__webpack_exports__, { 5776/* harmony export */ "FragmentState": () => (/* binding */ FragmentState), 5777/* harmony export */ "FragmentTracker": () => (/* binding */ FragmentTracker) 5778/* harmony export */ }); 5779/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 5780/* harmony import */ var _types_loader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../types/loader */ "./src/types/loader.ts"); 5781 5782 5783var FragmentState; 5784(function (FragmentState) { 5785 FragmentState["NOT_LOADED"] = "NOT_LOADED"; 5786 FragmentState["APPENDING"] = "APPENDING"; 5787 FragmentState["PARTIAL"] = "PARTIAL"; 5788 FragmentState["OK"] = "OK"; 5789})(FragmentState || (FragmentState = {})); 5790var FragmentTracker = /*#__PURE__*/function () { 5791 function FragmentTracker(hls) { 5792 this.activeFragment = null; 5793 this.activeParts = null; 5794 this.endListFragments = Object.create(null); 5795 this.fragments = Object.create(null); 5796 this.timeRanges = Object.create(null); 5797 this.bufferPadding = 0.2; 5798 this.hls = void 0; 5799 this.hls = hls; 5800 this._registerListeners(); 5801 } 5802 var _proto = FragmentTracker.prototype; 5803 _proto._registerListeners = function _registerListeners() { 5804 var hls = this.hls; 5805 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.BUFFER_APPENDED, this.onBufferAppended, this); 5806 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.FRAG_BUFFERED, this.onFragBuffered, this); 5807 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.FRAG_LOADED, this.onFragLoaded, this); 5808 }; 5809 _proto._unregisterListeners = function _unregisterListeners() { 5810 var hls = this.hls; 5811 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.BUFFER_APPENDED, this.onBufferAppended, this); 5812 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.FRAG_BUFFERED, this.onFragBuffered, this); 5813 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.FRAG_LOADED, this.onFragLoaded, this); 5814 }; 5815 _proto.destroy = function destroy() { 5816 this._unregisterListeners(); 5817 // @ts-ignore 5818 this.fragments = 5819 // @ts-ignore 5820 this.endListFragments = this.timeRanges = this.activeFragment = this.activeParts = null; 5821 } 5822 5823 /** 5824 * Return a Fragment with an appended range that matches the position and levelType. 5825 * If not found any Fragment, return null 5826 */; 5827 _proto.getAppendedFrag = function getAppendedFrag(position, levelType) { 5828 if (levelType === _types_loader__WEBPACK_IMPORTED_MODULE_1__.PlaylistLevelType.MAIN) { 5829 var activeFragment = this.activeFragment, 5830 activeParts = this.activeParts; 5831 if (!activeFragment) { 5832 return null; 5833 } 5834 if (activeParts) { 5835 for (var i = activeParts.length; i--;) { 5836 var activePart = activeParts[i]; 5837 var appendedPTS = activePart ? activePart.end : activeFragment.appendedPTS; 5838 if (activePart.start <= position && appendedPTS !== undefined && position <= appendedPTS) { 5839 // 9 is a magic number. remove parts from lookup after a match but keep some short seeks back. 5840 if (i > 9) { 5841 this.activeParts = activeParts.slice(i - 9); 5842 } 5843 return activePart; 5844 } 5845 } 5846 } else if (activeFragment.start <= position && activeFragment.appendedPTS !== undefined && position <= activeFragment.appendedPTS) { 5847 return activeFragment; 5848 } 5849 } 5850 return this.getBufferedFrag(position, levelType); 5851 } 5852 5853 /** 5854 * Return a buffered Fragment that matches the position and levelType. 5855 * A buffered Fragment is one whose loading, parsing and appending is done (completed or "partial" meaning aborted). 5856 * If not found any Fragment, return null 5857 */; 5858 _proto.getBufferedFrag = function getBufferedFrag(position, levelType) { 5859 var fragments = this.fragments; 5860 var keys = Object.keys(fragments); 5861 for (var i = keys.length; i--;) { 5862 var fragmentEntity = fragments[keys[i]]; 5863 if ((fragmentEntity === null || fragmentEntity === void 0 ? void 0 : fragmentEntity.body.type) === levelType && fragmentEntity.buffered) { 5864 var frag = fragmentEntity.body; 5865 if (frag.start <= position && position <= frag.end) { 5866 return frag; 5867 } 5868 } 5869 } 5870 return null; 5871 } 5872 5873 /** 5874 * Partial fragments effected by coded frame eviction will be removed 5875 * The browser will unload parts of the buffer to free up memory for new buffer data 5876 * Fragments will need to be reloaded when the buffer is freed up, removing partial fragments will allow them to reload(since there might be parts that are still playable) 5877 */; 5878 _proto.detectEvictedFragments = function detectEvictedFragments(elementaryStream, timeRange, playlistType) { 5879 var _this = this; 5880 if (this.timeRanges) { 5881 this.timeRanges[elementaryStream] = timeRange; 5882 } 5883 // Check if any flagged fragments have been unloaded 5884 Object.keys(this.fragments).forEach(function (key) { 5885 var fragmentEntity = _this.fragments[key]; 5886 if (!fragmentEntity) { 5887 return; 5888 } 5889 if (!fragmentEntity.buffered && !fragmentEntity.loaded) { 5890 if (fragmentEntity.body.type === playlistType) { 5891 _this.removeFragment(fragmentEntity.body); 5892 } 5893 return; 5894 } 5895 var esData = fragmentEntity.range[elementaryStream]; 5896 if (!esData) { 5897 return; 5898 } 5899 esData.time.some(function (time) { 5900 var isNotBuffered = !_this.isTimeBuffered(time.startPTS, time.endPTS, timeRange); 5901 if (isNotBuffered) { 5902 // Unregister partial fragment as it needs to load again to be reused 5903 _this.removeFragment(fragmentEntity.body); 5904 } 5905 return isNotBuffered; 5906 }); 5907 }); 5908 } 5909 5910 /** 5911 * Checks if the fragment passed in is loaded in the buffer properly 5912 * Partially loaded fragments will be registered as a partial fragment 5913 */; 5914 _proto.detectPartialFragments = function detectPartialFragments(data) { 5915 var _this2 = this; 5916 var timeRanges = this.timeRanges; 5917 var frag = data.frag, 5918 part = data.part; 5919 if (!timeRanges || frag.sn === 'initSegment') { 5920 return; 5921 } 5922 var fragKey = getFragmentKey(frag); 5923 var fragmentEntity = this.fragments[fragKey]; 5924 if (!fragmentEntity) { 5925 return; 5926 } 5927 Object.keys(timeRanges).forEach(function (elementaryStream) { 5928 var streamInfo = frag.elementaryStreams[elementaryStream]; 5929 if (!streamInfo) { 5930 return; 5931 } 5932 var timeRange = timeRanges[elementaryStream]; 5933 var partial = part !== null || streamInfo.partial === true; 5934 fragmentEntity.range[elementaryStream] = _this2.getBufferedTimes(frag, part, partial, timeRange); 5935 }); 5936 fragmentEntity.loaded = null; 5937 if (Object.keys(fragmentEntity.range).length) { 5938 fragmentEntity.buffered = true; 5939 if (fragmentEntity.body.endList) { 5940 this.endListFragments[fragmentEntity.body.type] = fragmentEntity; 5941 } 5942 } else { 5943 // remove fragment if nothing was appended 5944 this.removeFragment(fragmentEntity.body); 5945 } 5946 }; 5947 _proto.fragBuffered = function fragBuffered(frag) { 5948 var fragKey = getFragmentKey(frag); 5949 var fragmentEntity = this.fragments[fragKey]; 5950 if (fragmentEntity) { 5951 fragmentEntity.loaded = null; 5952 fragmentEntity.buffered = true; 5953 } 5954 }; 5955 _proto.getBufferedTimes = function getBufferedTimes(fragment, part, partial, timeRange) { 5956 var buffered = { 5957 time: [], 5958 partial: partial 5959 }; 5960 var startPTS = part ? part.start : fragment.start; 5961 var endPTS = part ? part.end : fragment.end; 5962 var minEndPTS = fragment.minEndPTS || endPTS; 5963 var maxStartPTS = fragment.maxStartPTS || startPTS; 5964 for (var i = 0; i < timeRange.length; i++) { 5965 var startTime = timeRange.start(i) - this.bufferPadding; 5966 var endTime = timeRange.end(i) + this.bufferPadding; 5967 if (maxStartPTS >= startTime && minEndPTS <= endTime) { 5968 // Fragment is entirely contained in buffer 5969 // No need to check the other timeRange times since it's completely playable 5970 buffered.time.push({ 5971 startPTS: Math.max(startPTS, timeRange.start(i)), 5972 endPTS: Math.min(endPTS, timeRange.end(i)) 5973 }); 5974 break; 5975 } else if (startPTS < endTime && endPTS > startTime) { 5976 buffered.partial = true; 5977 // Check for intersection with buffer 5978 // Get playable sections of the fragment 5979 buffered.time.push({ 5980 startPTS: Math.max(startPTS, timeRange.start(i)), 5981 endPTS: Math.min(endPTS, timeRange.end(i)) 5982 }); 5983 } else if (endPTS <= startTime) { 5984 // No need to check the rest of the timeRange as it is in order 5985 break; 5986 } 5987 } 5988 return buffered; 5989 } 5990 5991 /** 5992 * Gets the partial fragment for a certain time 5993 */; 5994 _proto.getPartialFragment = function getPartialFragment(time) { 5995 var bestFragment = null; 5996 var timePadding; 5997 var startTime; 5998 var endTime; 5999 var bestOverlap = 0; 6000 var bufferPadding = this.bufferPadding, 6001 fragments = this.fragments; 6002 Object.keys(fragments).forEach(function (key) { 6003 var fragmentEntity = fragments[key]; 6004 if (!fragmentEntity) { 6005 return; 6006 } 6007 if (isPartial(fragmentEntity)) { 6008 startTime = fragmentEntity.body.start - bufferPadding; 6009 endTime = fragmentEntity.body.end + bufferPadding; 6010 if (time >= startTime && time <= endTime) { 6011 // Use the fragment that has the most padding from start and end time 6012 timePadding = Math.min(time - startTime, endTime - time); 6013 if (bestOverlap <= timePadding) { 6014 bestFragment = fragmentEntity.body; 6015 bestOverlap = timePadding; 6016 } 6017 } 6018 } 6019 }); 6020 return bestFragment; 6021 }; 6022 _proto.isEndListAppended = function isEndListAppended(type) { 6023 var lastFragmentEntity = this.endListFragments[type]; 6024 return lastFragmentEntity !== undefined && (lastFragmentEntity.buffered || isPartial(lastFragmentEntity)); 6025 }; 6026 _proto.getState = function getState(fragment) { 6027 var fragKey = getFragmentKey(fragment); 6028 var fragmentEntity = this.fragments[fragKey]; 6029 if (fragmentEntity) { 6030 if (!fragmentEntity.buffered) { 6031 return FragmentState.APPENDING; 6032 } else if (isPartial(fragmentEntity)) { 6033 return FragmentState.PARTIAL; 6034 } else { 6035 return FragmentState.OK; 6036 } 6037 } 6038 return FragmentState.NOT_LOADED; 6039 }; 6040 _proto.isTimeBuffered = function isTimeBuffered(startPTS, endPTS, timeRange) { 6041 var startTime; 6042 var endTime; 6043 for (var i = 0; i < timeRange.length; i++) { 6044 startTime = timeRange.start(i) - this.bufferPadding; 6045 endTime = timeRange.end(i) + this.bufferPadding; 6046 if (startPTS >= startTime && endPTS <= endTime) { 6047 return true; 6048 } 6049 if (endPTS <= startTime) { 6050 // No need to check the rest of the timeRange as it is in order 6051 return false; 6052 } 6053 } 6054 return false; 6055 }; 6056 _proto.onFragLoaded = function onFragLoaded(event, data) { 6057 var frag = data.frag, 6058 part = data.part; 6059 // don't track initsegment (for which sn is not a number) 6060 // don't track frags used for bitrateTest, they're irrelevant. 6061 // don't track parts for memory efficiency 6062 if (frag.sn === 'initSegment' || frag.bitrateTest || part) { 6063 return; 6064 } 6065 var fragKey = getFragmentKey(frag); 6066 this.fragments[fragKey] = { 6067 body: frag, 6068 loaded: data, 6069 buffered: false, 6070 range: Object.create(null) 6071 }; 6072 }; 6073 _proto.onBufferAppended = function onBufferAppended(event, data) { 6074 var _this3 = this; 6075 var frag = data.frag, 6076 part = data.part, 6077 timeRanges = data.timeRanges; 6078 if (frag.type === _types_loader__WEBPACK_IMPORTED_MODULE_1__.PlaylistLevelType.MAIN) { 6079 if (this.activeFragment !== frag) { 6080 this.activeFragment = frag; 6081 frag.appendedPTS = undefined; 6082 } 6083 if (part) { 6084 var activeParts = this.activeParts; 6085 if (!activeParts) { 6086 this.activeParts = activeParts = []; 6087 } 6088 activeParts.push(part); 6089 } else { 6090 this.activeParts = null; 6091 } 6092 } 6093 // Store the latest timeRanges loaded in the buffer 6094 this.timeRanges = timeRanges; 6095 Object.keys(timeRanges).forEach(function (elementaryStream) { 6096 var timeRange = timeRanges[elementaryStream]; 6097 _this3.detectEvictedFragments(elementaryStream, timeRange); 6098 if (!part && frag.type === _types_loader__WEBPACK_IMPORTED_MODULE_1__.PlaylistLevelType.MAIN) { 6099 var streamInfo = frag.elementaryStreams[elementaryStream]; 6100 if (!streamInfo) { 6101 return; 6102 } 6103 for (var i = 0; i < timeRange.length; i++) { 6104 var rangeEnd = timeRange.end(i); 6105 if (rangeEnd <= streamInfo.endPTS && rangeEnd > streamInfo.startPTS) { 6106 frag.appendedPTS = Math.max(rangeEnd, frag.appendedPTS || 0); 6107 } else { 6108 frag.appendedPTS = streamInfo.endPTS; 6109 } 6110 } 6111 } 6112 }); 6113 }; 6114 _proto.onFragBuffered = function onFragBuffered(event, data) { 6115 this.detectPartialFragments(data); 6116 }; 6117 _proto.hasFragment = function hasFragment(fragment) { 6118 var fragKey = getFragmentKey(fragment); 6119 return !!this.fragments[fragKey]; 6120 }; 6121 _proto.removeFragmentsInRange = function removeFragmentsInRange(start, end, playlistType) { 6122 var _this4 = this; 6123 Object.keys(this.fragments).forEach(function (key) { 6124 var fragmentEntity = _this4.fragments[key]; 6125 if (!fragmentEntity) { 6126 return; 6127 } 6128 if (fragmentEntity.buffered) { 6129 var frag = fragmentEntity.body; 6130 if (frag.type === playlistType && frag.start < end && frag.end > start) { 6131 _this4.removeFragment(frag); 6132 } 6133 } 6134 }); 6135 }; 6136 _proto.removeFragment = function removeFragment(fragment) { 6137 var fragKey = getFragmentKey(fragment); 6138 fragment.stats.loaded = 0; 6139 fragment.clearElementaryStreamInfo(); 6140 fragment.appendedPTS = undefined; 6141 delete this.fragments[fragKey]; 6142 if (fragment.endList) { 6143 delete this.endListFragments[fragment.type]; 6144 } 6145 }; 6146 _proto.removeAllFragments = function removeAllFragments() { 6147 this.fragments = Object.create(null); 6148 this.endListFragments = Object.create(null); 6149 this.activeFragment = null; 6150 this.activeParts = null; 6151 }; 6152 return FragmentTracker; 6153}(); 6154function isPartial(fragmentEntity) { 6155 var _fragmentEntity$range, _fragmentEntity$range2; 6156 return fragmentEntity.buffered && (((_fragmentEntity$range = fragmentEntity.range.video) === null || _fragmentEntity$range === void 0 ? void 0 : _fragmentEntity$range.partial) || ((_fragmentEntity$range2 = fragmentEntity.range.audio) === null || _fragmentEntity$range2 === void 0 ? void 0 : _fragmentEntity$range2.partial)); 6157} 6158function getFragmentKey(fragment) { 6159 return fragment.type + "_" + fragment.level + "_" + fragment.urlId + "_" + fragment.sn; 6160} 6161 6162/***/ }), 6163 6164/***/ "./src/controller/gap-controller.ts": 6165/*!******************************************!*\ 6166 !*** ./src/controller/gap-controller.ts ***! 6167 \******************************************/ 6168/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 6169 6170"use strict"; 6171__webpack_require__.r(__webpack_exports__); 6172/* harmony export */ __webpack_require__.d(__webpack_exports__, { 6173/* harmony export */ "MAX_START_GAP_JUMP": () => (/* binding */ MAX_START_GAP_JUMP), 6174/* harmony export */ "SKIP_BUFFER_HOLE_STEP_SECONDS": () => (/* binding */ SKIP_BUFFER_HOLE_STEP_SECONDS), 6175/* harmony export */ "SKIP_BUFFER_RANGE_START": () => (/* binding */ SKIP_BUFFER_RANGE_START), 6176/* harmony export */ "STALL_MINIMUM_DURATION_MS": () => (/* binding */ STALL_MINIMUM_DURATION_MS), 6177/* harmony export */ "default": () => (/* binding */ GapController) 6178/* harmony export */ }); 6179/* harmony import */ var _utils_buffer_helper__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils/buffer-helper */ "./src/utils/buffer-helper.ts"); 6180/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../errors */ "./src/errors.ts"); 6181/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 6182/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 6183 6184 6185 6186 6187var STALL_MINIMUM_DURATION_MS = 250; 6188var MAX_START_GAP_JUMP = 2.0; 6189var SKIP_BUFFER_HOLE_STEP_SECONDS = 0.1; 6190var SKIP_BUFFER_RANGE_START = 0.05; 6191var GapController = /*#__PURE__*/function () { 6192 function GapController(config, media, fragmentTracker, hls) { 6193 this.config = void 0; 6194 this.media = null; 6195 this.fragmentTracker = void 0; 6196 this.hls = void 0; 6197 this.nudgeRetry = 0; 6198 this.stallReported = false; 6199 this.stalled = null; 6200 this.moved = false; 6201 this.seeking = false; 6202 this.config = config; 6203 this.media = media; 6204 this.fragmentTracker = fragmentTracker; 6205 this.hls = hls; 6206 } 6207 var _proto = GapController.prototype; 6208 _proto.destroy = function destroy() { 6209 this.media = null; 6210 // @ts-ignore 6211 this.hls = this.fragmentTracker = null; 6212 } 6213 6214 /** 6215 * Checks if the playhead is stuck within a gap, and if so, attempts to free it. 6216 * A gap is an unbuffered range between two buffered ranges (or the start and the first buffered range). 6217 * 6218 * @param {number} lastCurrentTime Previously read playhead position 6219 */; 6220 _proto.poll = function poll(lastCurrentTime, activeFrag) { 6221 var config = this.config, 6222 media = this.media, 6223 stalled = this.stalled; 6224 if (media === null) { 6225 return; 6226 } 6227 var currentTime = media.currentTime, 6228 seeking = media.seeking; 6229 var seeked = this.seeking && !seeking; 6230 var beginSeek = !this.seeking && seeking; 6231 this.seeking = seeking; 6232 6233 // The playhead is moving, no-op 6234 if (currentTime !== lastCurrentTime) { 6235 this.moved = true; 6236 if (stalled !== null) { 6237 // The playhead is now moving, but was previously stalled 6238 if (this.stallReported) { 6239 var _stalledDuration = self.performance.now() - stalled; 6240 _utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger.warn("playback not stuck anymore @" + currentTime + ", after " + Math.round(_stalledDuration) + "ms"); 6241 this.stallReported = false; 6242 } 6243 this.stalled = null; 6244 this.nudgeRetry = 0; 6245 } 6246 return; 6247 } 6248 6249 // Clear stalled state when beginning or finishing seeking so that we don't report stalls coming out of a seek 6250 if (beginSeek || seeked) { 6251 this.stalled = null; 6252 } 6253 6254 // The playhead should not be moving 6255 if (media.paused && !seeking || media.ended || media.playbackRate === 0 || !_utils_buffer_helper__WEBPACK_IMPORTED_MODULE_0__.BufferHelper.getBuffered(media).length) { 6256 return; 6257 } 6258 var bufferInfo = _utils_buffer_helper__WEBPACK_IMPORTED_MODULE_0__.BufferHelper.bufferInfo(media, currentTime, 0); 6259 var isBuffered = bufferInfo.len > 0; 6260 var nextStart = bufferInfo.nextStart || 0; 6261 6262 // There is no playable buffer (seeked, waiting for buffer) 6263 if (!isBuffered && !nextStart) { 6264 return; 6265 } 6266 if (seeking) { 6267 // Waiting for seeking in a buffered range to complete 6268 var hasEnoughBuffer = bufferInfo.len > MAX_START_GAP_JUMP; 6269 // Next buffered range is too far ahead to jump to while still seeking 6270 var noBufferGap = !nextStart || activeFrag && activeFrag.start <= currentTime || nextStart - currentTime > MAX_START_GAP_JUMP && !this.fragmentTracker.getPartialFragment(currentTime); 6271 if (hasEnoughBuffer || noBufferGap) { 6272 return; 6273 } 6274 // Reset moved state when seeking to a point in or before a gap 6275 this.moved = false; 6276 } 6277 6278 // Skip start gaps if we haven't played, but the last poll detected the start of a stall 6279 // The addition poll gives the browser a chance to jump the gap for us 6280 if (!this.moved && this.stalled !== null) { 6281 var _level$details; 6282 // Jump start gaps within jump threshold 6283 var startJump = Math.max(nextStart, bufferInfo.start || 0) - currentTime; 6284 6285 // When joining a live stream with audio tracks, account for live playlist window sliding by allowing 6286 // a larger jump over start gaps caused by the audio-stream-controller buffering a start fragment 6287 // that begins over 1 target duration after the video start position. 6288 var level = this.hls.levels ? this.hls.levels[this.hls.currentLevel] : null; 6289 var isLive = level === null || level === void 0 ? void 0 : (_level$details = level.details) === null || _level$details === void 0 ? void 0 : _level$details.live; 6290 var maxStartGapJump = isLive ? level.details.targetduration * 2 : MAX_START_GAP_JUMP; 6291 if (startJump > 0 && startJump <= maxStartGapJump) { 6292 this._trySkipBufferHole(null); 6293 return; 6294 } 6295 } 6296 6297 // Start tracking stall time 6298 var tnow = self.performance.now(); 6299 if (stalled === null) { 6300 this.stalled = tnow; 6301 return; 6302 } 6303 var stalledDuration = tnow - stalled; 6304 if (!seeking && stalledDuration >= STALL_MINIMUM_DURATION_MS) { 6305 // Report stalling after trying to fix 6306 this._reportStall(bufferInfo); 6307 if (!this.media) { 6308 return; 6309 } 6310 } 6311 var bufferedWithHoles = _utils_buffer_helper__WEBPACK_IMPORTED_MODULE_0__.BufferHelper.bufferInfo(media, currentTime, config.maxBufferHole); 6312 this._tryFixBufferStall(bufferedWithHoles, stalledDuration); 6313 } 6314 6315 /** 6316 * Detects and attempts to fix known buffer stalling issues. 6317 * @param bufferInfo - The properties of the current buffer. 6318 * @param stalledDurationMs - The amount of time Hls.js has been stalling for. 6319 * @private 6320 */; 6321 _proto._tryFixBufferStall = function _tryFixBufferStall(bufferInfo, stalledDurationMs) { 6322 var config = this.config, 6323 fragmentTracker = this.fragmentTracker, 6324 media = this.media; 6325 if (media === null) { 6326 return; 6327 } 6328 var currentTime = media.currentTime; 6329 var partial = fragmentTracker.getPartialFragment(currentTime); 6330 if (partial) { 6331 // Try to skip over the buffer hole caused by a partial fragment 6332 // This method isn't limited by the size of the gap between buffered ranges 6333 var targetTime = this._trySkipBufferHole(partial); 6334 // we return here in this case, meaning 6335 // the branch below only executes when we don't handle a partial fragment 6336 if (targetTime || !this.media) { 6337 return; 6338 } 6339 } 6340 6341 // if we haven't had to skip over a buffer hole of a partial fragment 6342 // we may just have to "nudge" the playlist as the browser decoding/rendering engine 6343 // needs to cross some sort of threshold covering all source-buffers content 6344 // to start playing properly. 6345 if (bufferInfo.len > config.maxBufferHole && stalledDurationMs > config.highBufferWatchdogPeriod * 1000) { 6346 _utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger.warn('Trying to nudge playhead over buffer-hole'); 6347 // Try to nudge currentTime over a buffer hole if we've been stalling for the configured amount of seconds 6348 // We only try to jump the hole if it's under the configured size 6349 // Reset stalled so to rearm watchdog timer 6350 this.stalled = null; 6351 this._tryNudgeBuffer(); 6352 } 6353 } 6354 6355 /** 6356 * Triggers a BUFFER_STALLED_ERROR event, but only once per stall period. 6357 * @param bufferLen - The playhead distance from the end of the current buffer segment. 6358 * @private 6359 */; 6360 _proto._reportStall = function _reportStall(bufferInfo) { 6361 var hls = this.hls, 6362 media = this.media, 6363 stallReported = this.stallReported; 6364 if (!stallReported && media) { 6365 // Report stalled error once 6366 this.stallReported = true; 6367 _utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger.warn("Playback stalling at @" + media.currentTime + " due to low buffer (" + JSON.stringify(bufferInfo) + ")"); 6368 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_2__.Events.ERROR, { 6369 type: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorTypes.MEDIA_ERROR, 6370 details: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorDetails.BUFFER_STALLED_ERROR, 6371 fatal: false, 6372 buffer: bufferInfo.len 6373 }); 6374 } 6375 } 6376 6377 /** 6378 * Attempts to fix buffer stalls by jumping over known gaps caused by partial fragments 6379 * @param partial - The partial fragment found at the current time (where playback is stalling). 6380 * @private 6381 */; 6382 _proto._trySkipBufferHole = function _trySkipBufferHole(partial) { 6383 var config = this.config, 6384 hls = this.hls, 6385 media = this.media; 6386 if (media === null) { 6387 return 0; 6388 } 6389 var currentTime = media.currentTime; 6390 var lastEndTime = 0; 6391 // Check if currentTime is between unbuffered regions of partial fragments 6392 var buffered = _utils_buffer_helper__WEBPACK_IMPORTED_MODULE_0__.BufferHelper.getBuffered(media); 6393 for (var i = 0; i < buffered.length; i++) { 6394 var startTime = buffered.start(i); 6395 if (currentTime + config.maxBufferHole >= lastEndTime && currentTime < startTime) { 6396 var targetTime = Math.max(startTime + SKIP_BUFFER_RANGE_START, media.currentTime + SKIP_BUFFER_HOLE_STEP_SECONDS); 6397 _utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger.warn("skipping hole, adjusting currentTime from " + currentTime + " to " + targetTime); 6398 this.moved = true; 6399 this.stalled = null; 6400 media.currentTime = targetTime; 6401 if (partial) { 6402 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_2__.Events.ERROR, { 6403 type: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorTypes.MEDIA_ERROR, 6404 details: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorDetails.BUFFER_SEEK_OVER_HOLE, 6405 fatal: false, 6406 reason: "fragment loaded with buffer holes, seeking from " + currentTime + " to " + targetTime, 6407 frag: partial 6408 }); 6409 } 6410 return targetTime; 6411 } 6412 lastEndTime = buffered.end(i); 6413 } 6414 return 0; 6415 } 6416 6417 /** 6418 * Attempts to fix buffer stalls by advancing the mediaElement's current time by a small amount. 6419 * @private 6420 */; 6421 _proto._tryNudgeBuffer = function _tryNudgeBuffer() { 6422 var config = this.config, 6423 hls = this.hls, 6424 media = this.media, 6425 nudgeRetry = this.nudgeRetry; 6426 if (media === null) { 6427 return; 6428 } 6429 var currentTime = media.currentTime; 6430 this.nudgeRetry++; 6431 if (nudgeRetry < config.nudgeMaxRetry) { 6432 var targetTime = currentTime + (nudgeRetry + 1) * config.nudgeOffset; 6433 // playback stalled in buffered area ... let's nudge currentTime to try to overcome this 6434 _utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger.warn("Nudging 'currentTime' from " + currentTime + " to " + targetTime); 6435 media.currentTime = targetTime; 6436 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_2__.Events.ERROR, { 6437 type: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorTypes.MEDIA_ERROR, 6438 details: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorDetails.BUFFER_NUDGE_ON_STALL, 6439 fatal: false 6440 }); 6441 } else { 6442 _utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger.error("Playhead still not moving while enough data buffered @" + currentTime + " after " + config.nudgeMaxRetry + " nudges"); 6443 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_2__.Events.ERROR, { 6444 type: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorTypes.MEDIA_ERROR, 6445 details: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorDetails.BUFFER_STALLED_ERROR, 6446 fatal: true 6447 }); 6448 } 6449 }; 6450 return GapController; 6451}(); 6452 6453 6454/***/ }), 6455 6456/***/ "./src/controller/id3-track-controller.ts": 6457/*!************************************************!*\ 6458 !*** ./src/controller/id3-track-controller.ts ***! 6459 \************************************************/ 6460/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 6461 6462"use strict"; 6463__webpack_require__.r(__webpack_exports__); 6464/* harmony export */ __webpack_require__.d(__webpack_exports__, { 6465/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 6466/* harmony export */ }); 6467/* harmony import */ var _home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.ts"); 6468/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 6469/* harmony import */ var _utils_texttrack_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils/texttrack-utils */ "./src/utils/texttrack-utils.ts"); 6470/* harmony import */ var _demux_id3__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../demux/id3 */ "./src/demux/id3.ts"); 6471/* harmony import */ var _loader_date_range__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../loader/date-range */ "./src/loader/date-range.ts"); 6472/* harmony import */ var _types_demuxer__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../types/demuxer */ "./src/types/demuxer.ts"); 6473 6474 6475 6476 6477 6478 6479var MIN_CUE_DURATION = 0.25; 6480function getCueClass() { 6481 // Attempt to recreate Safari functionality by creating 6482 // WebKitDataCue objects when available and store the decoded 6483 // ID3 data in the value property of the cue 6484 return self.WebKitDataCue || self.VTTCue || self.TextTrackCue; 6485} 6486 6487// VTTCue latest draft allows an infinite duration, fallback 6488// to MAX_VALUE if necessary 6489var MAX_CUE_ENDTIME = function () { 6490 var Cue = getCueClass(); 6491 try { 6492 new Cue(0, Number.POSITIVE_INFINITY, ''); 6493 } catch (e) { 6494 return Number.MAX_VALUE; 6495 } 6496 return Number.POSITIVE_INFINITY; 6497}(); 6498function dateRangeDateToTimelineSeconds(date, offset) { 6499 return date.getTime() / 1000 - offset; 6500} 6501function hexToArrayBuffer(str) { 6502 return Uint8Array.from(str.replace(/^0x/, '').replace(/([\da-fA-F]{2}) ?/g, '0x$1 ').replace(/ +$/, '').split(' ')).buffer; 6503} 6504var ID3TrackController = /*#__PURE__*/function () { 6505 function ID3TrackController(hls) { 6506 this.hls = void 0; 6507 this.id3Track = null; 6508 this.media = null; 6509 this.dateRangeCuesAppended = {}; 6510 this.hls = hls; 6511 this._registerListeners(); 6512 } 6513 var _proto = ID3TrackController.prototype; 6514 _proto.destroy = function destroy() { 6515 this._unregisterListeners(); 6516 this.id3Track = null; 6517 this.media = null; 6518 this.dateRangeCuesAppended = {}; 6519 // @ts-ignore 6520 this.hls = null; 6521 }; 6522 _proto._registerListeners = function _registerListeners() { 6523 var hls = this.hls; 6524 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MEDIA_ATTACHED, this.onMediaAttached, this); 6525 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MEDIA_DETACHING, this.onMediaDetaching, this); 6526 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MANIFEST_LOADING, this.onManifestLoading, this); 6527 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.FRAG_PARSING_METADATA, this.onFragParsingMetadata, this); 6528 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.BUFFER_FLUSHING, this.onBufferFlushing, this); 6529 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.LEVEL_UPDATED, this.onLevelUpdated, this); 6530 }; 6531 _proto._unregisterListeners = function _unregisterListeners() { 6532 var hls = this.hls; 6533 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MEDIA_ATTACHED, this.onMediaAttached, this); 6534 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MEDIA_DETACHING, this.onMediaDetaching, this); 6535 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MANIFEST_LOADING, this.onManifestLoading, this); 6536 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.FRAG_PARSING_METADATA, this.onFragParsingMetadata, this); 6537 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.BUFFER_FLUSHING, this.onBufferFlushing, this); 6538 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.LEVEL_UPDATED, this.onLevelUpdated, this); 6539 } 6540 6541 // Add ID3 metatadata text track. 6542 ; 6543 _proto.onMediaAttached = function onMediaAttached(event, data) { 6544 this.media = data.media; 6545 }; 6546 _proto.onMediaDetaching = function onMediaDetaching() { 6547 if (!this.id3Track) { 6548 return; 6549 } 6550 (0,_utils_texttrack_utils__WEBPACK_IMPORTED_MODULE_2__.clearCurrentCues)(this.id3Track); 6551 this.id3Track = null; 6552 this.media = null; 6553 this.dateRangeCuesAppended = {}; 6554 }; 6555 _proto.onManifestLoading = function onManifestLoading() { 6556 this.dateRangeCuesAppended = {}; 6557 }; 6558 _proto.createTrack = function createTrack(media) { 6559 var track = this.getID3Track(media.textTracks); 6560 track.mode = 'hidden'; 6561 return track; 6562 }; 6563 _proto.getID3Track = function getID3Track(textTracks) { 6564 if (!this.media) { 6565 return; 6566 } 6567 for (var i = 0; i < textTracks.length; i++) { 6568 var textTrack = textTracks[i]; 6569 if (textTrack.kind === 'metadata' && textTrack.label === 'id3') { 6570 // send 'addtrack' when reusing the textTrack for metadata, 6571 // same as what we do for captions 6572 (0,_utils_texttrack_utils__WEBPACK_IMPORTED_MODULE_2__.sendAddTrackEvent)(textTrack, this.media); 6573 return textTrack; 6574 } 6575 } 6576 return this.media.addTextTrack('metadata', 'id3'); 6577 }; 6578 _proto.onFragParsingMetadata = function onFragParsingMetadata(event, data) { 6579 if (!this.media) { 6580 return; 6581 } 6582 var _this$hls$config = this.hls.config, 6583 enableEmsgMetadataCues = _this$hls$config.enableEmsgMetadataCues, 6584 enableID3MetadataCues = _this$hls$config.enableID3MetadataCues; 6585 if (!enableEmsgMetadataCues && !enableID3MetadataCues) { 6586 return; 6587 } 6588 var samples = data.samples; 6589 6590 // create track dynamically 6591 if (!this.id3Track) { 6592 this.id3Track = this.createTrack(this.media); 6593 } 6594 var Cue = getCueClass(); 6595 for (var i = 0; i < samples.length; i++) { 6596 var type = samples[i].type; 6597 if (type === _types_demuxer__WEBPACK_IMPORTED_MODULE_5__.MetadataSchema.emsg && !enableEmsgMetadataCues || !enableID3MetadataCues) { 6598 continue; 6599 } 6600 var frames = _demux_id3__WEBPACK_IMPORTED_MODULE_3__.getID3Frames(samples[i].data); 6601 if (frames) { 6602 var startTime = samples[i].pts; 6603 var endTime = startTime + samples[i].duration; 6604 if (endTime > MAX_CUE_ENDTIME) { 6605 endTime = MAX_CUE_ENDTIME; 6606 } 6607 var timeDiff = endTime - startTime; 6608 if (timeDiff <= 0) { 6609 endTime = startTime + MIN_CUE_DURATION; 6610 } 6611 for (var j = 0; j < frames.length; j++) { 6612 var frame = frames[j]; 6613 // Safari doesn't put the timestamp frame in the TextTrack 6614 if (!_demux_id3__WEBPACK_IMPORTED_MODULE_3__.isTimeStampFrame(frame)) { 6615 // add a bounds to any unbounded cues 6616 this.updateId3CueEnds(startTime); 6617 var cue = new Cue(startTime, endTime, ''); 6618 cue.value = frame; 6619 if (type) { 6620 cue.type = type; 6621 } 6622 this.id3Track.addCue(cue); 6623 } 6624 } 6625 } 6626 } 6627 }; 6628 _proto.updateId3CueEnds = function updateId3CueEnds(startTime) { 6629 var _this$id3Track; 6630 var cues = (_this$id3Track = this.id3Track) === null || _this$id3Track === void 0 ? void 0 : _this$id3Track.cues; 6631 if (cues) { 6632 for (var i = cues.length; i--;) { 6633 var cue = cues[i]; 6634 if (cue.startTime < startTime && cue.endTime === MAX_CUE_ENDTIME) { 6635 cue.endTime = startTime; 6636 } 6637 } 6638 } 6639 }; 6640 _proto.onBufferFlushing = function onBufferFlushing(event, _ref) { 6641 var startOffset = _ref.startOffset, 6642 endOffset = _ref.endOffset, 6643 type = _ref.type; 6644 var id3Track = this.id3Track, 6645 hls = this.hls; 6646 if (!hls) { 6647 return; 6648 } 6649 var _hls$config = hls.config, 6650 enableEmsgMetadataCues = _hls$config.enableEmsgMetadataCues, 6651 enableID3MetadataCues = _hls$config.enableID3MetadataCues; 6652 if (id3Track && (enableEmsgMetadataCues || enableID3MetadataCues)) { 6653 var predicate; 6654 if (type === 'audio') { 6655 predicate = function predicate(cue) { 6656 return cue.type === _types_demuxer__WEBPACK_IMPORTED_MODULE_5__.MetadataSchema.audioId3 && enableID3MetadataCues; 6657 }; 6658 } else if (type === 'video') { 6659 predicate = function predicate(cue) { 6660 return cue.type === _types_demuxer__WEBPACK_IMPORTED_MODULE_5__.MetadataSchema.emsg && enableEmsgMetadataCues; 6661 }; 6662 } else { 6663 predicate = function predicate(cue) { 6664 return cue.type === _types_demuxer__WEBPACK_IMPORTED_MODULE_5__.MetadataSchema.audioId3 && enableID3MetadataCues || cue.type === _types_demuxer__WEBPACK_IMPORTED_MODULE_5__.MetadataSchema.emsg && enableEmsgMetadataCues; 6665 }; 6666 } 6667 (0,_utils_texttrack_utils__WEBPACK_IMPORTED_MODULE_2__.removeCuesInRange)(id3Track, startOffset, endOffset, predicate); 6668 } 6669 }; 6670 _proto.onLevelUpdated = function onLevelUpdated(event, _ref2) { 6671 var _this = this; 6672 var details = _ref2.details; 6673 if (!this.media || !details.hasProgramDateTime || !this.hls.config.enableDateRangeMetadataCues) { 6674 return; 6675 } 6676 var dateRangeCuesAppended = this.dateRangeCuesAppended, 6677 id3Track = this.id3Track; 6678 var dateRanges = details.dateRanges; 6679 var ids = Object.keys(dateRanges); 6680 // Remove cues from track not found in details.dateRanges 6681 if (id3Track) { 6682 var idsToRemove = Object.keys(dateRangeCuesAppended).filter(function (id) { 6683 return !ids.includes(id); 6684 }); 6685 var _loop = function _loop(i) { 6686 var id = idsToRemove[i]; 6687 Object.keys(dateRangeCuesAppended[id].cues).forEach(function (key) { 6688 id3Track.removeCue(dateRangeCuesAppended[id].cues[key]); 6689 }); 6690 delete dateRangeCuesAppended[id]; 6691 }; 6692 for (var i = idsToRemove.length; i--;) { 6693 _loop(i); 6694 } 6695 } 6696 // Exit if the playlist does not have Date Ranges or does not have Program Date Time 6697 var lastFragment = details.fragments[details.fragments.length - 1]; 6698 if (ids.length === 0 || !(0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(lastFragment === null || lastFragment === void 0 ? void 0 : lastFragment.programDateTime)) { 6699 return; 6700 } 6701 if (!this.id3Track) { 6702 this.id3Track = this.createTrack(this.media); 6703 } 6704 var dateTimeOffset = lastFragment.programDateTime / 1000 - lastFragment.start; 6705 var Cue = getCueClass(); 6706 var _loop2 = function _loop2(_i) { 6707 var id = ids[_i]; 6708 var dateRange = dateRanges[id]; 6709 var appendedDateRangeCues = dateRangeCuesAppended[id]; 6710 var cues = (appendedDateRangeCues === null || appendedDateRangeCues === void 0 ? void 0 : appendedDateRangeCues.cues) || {}; 6711 var durationKnown = (appendedDateRangeCues === null || appendedDateRangeCues === void 0 ? void 0 : appendedDateRangeCues.durationKnown) || false; 6712 var startTime = dateRangeDateToTimelineSeconds(dateRange.startDate, dateTimeOffset); 6713 var endTime = MAX_CUE_ENDTIME; 6714 var endDate = dateRange.endDate; 6715 if (endDate) { 6716 endTime = dateRangeDateToTimelineSeconds(endDate, dateTimeOffset); 6717 durationKnown = true; 6718 } else if (dateRange.endOnNext && !durationKnown) { 6719 var nextDateRangeWithSameClass = ids.reduce(function (filterMapArray, id) { 6720 var candidate = dateRanges[id]; 6721 if (candidate.class === dateRange.class && candidate.id !== id && candidate.startDate > dateRange.startDate) { 6722 filterMapArray.push(candidate); 6723 } 6724 return filterMapArray; 6725 }, []).sort(function (a, b) { 6726 return a.startDate.getTime() - b.startDate.getTime(); 6727 })[0]; 6728 if (nextDateRangeWithSameClass) { 6729 endTime = dateRangeDateToTimelineSeconds(nextDateRangeWithSameClass.startDate, dateTimeOffset); 6730 durationKnown = true; 6731 } 6732 } 6733 var attributes = Object.keys(dateRange.attr); 6734 for (var j = 0; j < attributes.length; j++) { 6735 var key = attributes[j]; 6736 if (key === _loader_date_range__WEBPACK_IMPORTED_MODULE_4__.DateRangeAttribute.ID || key === _loader_date_range__WEBPACK_IMPORTED_MODULE_4__.DateRangeAttribute.CLASS || key === _loader_date_range__WEBPACK_IMPORTED_MODULE_4__.DateRangeAttribute.START_DATE || key === _loader_date_range__WEBPACK_IMPORTED_MODULE_4__.DateRangeAttribute.DURATION || key === _loader_date_range__WEBPACK_IMPORTED_MODULE_4__.DateRangeAttribute.END_DATE || key === _loader_date_range__WEBPACK_IMPORTED_MODULE_4__.DateRangeAttribute.END_ON_NEXT) { 6737 continue; 6738 } 6739 var cue = cues[key]; 6740 if (cue) { 6741 if (durationKnown && !appendedDateRangeCues.durationKnown) { 6742 cue.endTime = endTime; 6743 } 6744 } else { 6745 var data = dateRange.attr[key]; 6746 cue = new Cue(startTime, endTime, ''); 6747 if (key === _loader_date_range__WEBPACK_IMPORTED_MODULE_4__.DateRangeAttribute.SCTE35_OUT || key === _loader_date_range__WEBPACK_IMPORTED_MODULE_4__.DateRangeAttribute.SCTE35_IN) { 6748 data = hexToArrayBuffer(data); 6749 } 6750 cue.value = { 6751 key: key, 6752 data: data 6753 }; 6754 cue.type = _types_demuxer__WEBPACK_IMPORTED_MODULE_5__.MetadataSchema.dateRange; 6755 _this.id3Track.addCue(cue); 6756 cues[key] = cue; 6757 } 6758 } 6759 dateRangeCuesAppended[id] = { 6760 cues: cues, 6761 dateRange: dateRange, 6762 durationKnown: durationKnown 6763 }; 6764 }; 6765 for (var _i = 0; _i < ids.length; _i++) { 6766 _loop2(_i); 6767 } 6768 }; 6769 return ID3TrackController; 6770}(); 6771/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ID3TrackController); 6772 6773/***/ }), 6774 6775/***/ "./src/controller/latency-controller.ts": 6776/*!**********************************************!*\ 6777 !*** ./src/controller/latency-controller.ts ***! 6778 \**********************************************/ 6779/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 6780 6781"use strict"; 6782__webpack_require__.r(__webpack_exports__); 6783/* harmony export */ __webpack_require__.d(__webpack_exports__, { 6784/* harmony export */ "default": () => (/* binding */ LatencyController) 6785/* harmony export */ }); 6786/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../errors */ "./src/errors.ts"); 6787/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 6788/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 6789function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } 6790function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } 6791function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } 6792function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } 6793 6794 6795 6796var LatencyController = /*#__PURE__*/function () { 6797 function LatencyController(hls) { 6798 var _this = this; 6799 this.hls = void 0; 6800 this.config = void 0; 6801 this.media = null; 6802 this.levelDetails = null; 6803 this.currentTime = 0; 6804 this.stallCount = 0; 6805 this._latency = null; 6806 this.timeupdateHandler = function () { 6807 return _this.timeupdate(); 6808 }; 6809 this.hls = hls; 6810 this.config = hls.config; 6811 this.registerListeners(); 6812 } 6813 var _proto = LatencyController.prototype; 6814 _proto.destroy = function destroy() { 6815 this.unregisterListeners(); 6816 this.onMediaDetaching(); 6817 this.levelDetails = null; 6818 // @ts-ignore 6819 this.hls = this.timeupdateHandler = null; 6820 }; 6821 _proto.registerListeners = function registerListeners() { 6822 this.hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MEDIA_ATTACHED, this.onMediaAttached, this); 6823 this.hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MEDIA_DETACHING, this.onMediaDetaching, this); 6824 this.hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MANIFEST_LOADING, this.onManifestLoading, this); 6825 this.hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.LEVEL_UPDATED, this.onLevelUpdated, this); 6826 this.hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.ERROR, this.onError, this); 6827 }; 6828 _proto.unregisterListeners = function unregisterListeners() { 6829 this.hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MEDIA_ATTACHED, this.onMediaAttached); 6830 this.hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MEDIA_DETACHING, this.onMediaDetaching); 6831 this.hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MANIFEST_LOADING, this.onManifestLoading); 6832 this.hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.LEVEL_UPDATED, this.onLevelUpdated); 6833 this.hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.ERROR, this.onError); 6834 }; 6835 _proto.onMediaAttached = function onMediaAttached(event, data) { 6836 this.media = data.media; 6837 this.media.addEventListener('timeupdate', this.timeupdateHandler); 6838 }; 6839 _proto.onMediaDetaching = function onMediaDetaching() { 6840 if (this.media) { 6841 this.media.removeEventListener('timeupdate', this.timeupdateHandler); 6842 this.media = null; 6843 } 6844 }; 6845 _proto.onManifestLoading = function onManifestLoading() { 6846 this.levelDetails = null; 6847 this._latency = null; 6848 this.stallCount = 0; 6849 }; 6850 _proto.onLevelUpdated = function onLevelUpdated(event, _ref) { 6851 var details = _ref.details; 6852 this.levelDetails = details; 6853 if (details.advanced) { 6854 this.timeupdate(); 6855 } 6856 if (!details.live && this.media) { 6857 this.media.removeEventListener('timeupdate', this.timeupdateHandler); 6858 } 6859 }; 6860 _proto.onError = function onError(event, data) { 6861 if (data.details !== _errors__WEBPACK_IMPORTED_MODULE_0__.ErrorDetails.BUFFER_STALLED_ERROR) { 6862 return; 6863 } 6864 this.stallCount++; 6865 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.warn('[playback-rate-controller]: Stall detected, adjusting target latency'); 6866 }; 6867 _proto.timeupdate = function timeupdate() { 6868 var media = this.media, 6869 levelDetails = this.levelDetails; 6870 if (!media || !levelDetails) { 6871 return; 6872 } 6873 this.currentTime = media.currentTime; 6874 var latency = this.computeLatency(); 6875 if (latency === null) { 6876 return; 6877 } 6878 this._latency = latency; 6879 6880 // Adapt playbackRate to meet target latency in low-latency mode 6881 var _this$config = this.config, 6882 lowLatencyMode = _this$config.lowLatencyMode, 6883 maxLiveSyncPlaybackRate = _this$config.maxLiveSyncPlaybackRate; 6884 if (!lowLatencyMode || maxLiveSyncPlaybackRate === 1) { 6885 return; 6886 } 6887 var targetLatency = this.targetLatency; 6888 if (targetLatency === null) { 6889 return; 6890 } 6891 var distanceFromTarget = latency - targetLatency; 6892 // Only adjust playbackRate when within one target duration of targetLatency 6893 // and more than one second from under-buffering. 6894 // Playback further than one target duration from target can be considered DVR playback. 6895 var liveMinLatencyDuration = Math.min(this.maxLatency, targetLatency + levelDetails.targetduration); 6896 var inLiveRange = distanceFromTarget < liveMinLatencyDuration; 6897 if (levelDetails.live && inLiveRange && distanceFromTarget > 0.05 && this.forwardBufferLength > 1) { 6898 var max = Math.min(2, Math.max(1.0, maxLiveSyncPlaybackRate)); 6899 var rate = Math.round(2 / (1 + Math.exp(-0.75 * distanceFromTarget - this.edgeStalled)) * 20) / 20; 6900 media.playbackRate = Math.min(max, Math.max(1, rate)); 6901 } else if (media.playbackRate !== 1 && media.playbackRate !== 0) { 6902 media.playbackRate = 1; 6903 } 6904 }; 6905 _proto.estimateLiveEdge = function estimateLiveEdge() { 6906 var levelDetails = this.levelDetails; 6907 if (levelDetails === null) { 6908 return null; 6909 } 6910 return levelDetails.edge + levelDetails.age; 6911 }; 6912 _proto.computeLatency = function computeLatency() { 6913 var liveEdge = this.estimateLiveEdge(); 6914 if (liveEdge === null) { 6915 return null; 6916 } 6917 return liveEdge - this.currentTime; 6918 }; 6919 _createClass(LatencyController, [{ 6920 key: "latency", 6921 get: function get() { 6922 return this._latency || 0; 6923 } 6924 }, { 6925 key: "maxLatency", 6926 get: function get() { 6927 var config = this.config, 6928 levelDetails = this.levelDetails; 6929 if (config.liveMaxLatencyDuration !== undefined) { 6930 return config.liveMaxLatencyDuration; 6931 } 6932 return levelDetails ? config.liveMaxLatencyDurationCount * levelDetails.targetduration : 0; 6933 } 6934 }, { 6935 key: "targetLatency", 6936 get: function get() { 6937 var levelDetails = this.levelDetails; 6938 if (levelDetails === null) { 6939 return null; 6940 } 6941 var holdBack = levelDetails.holdBack, 6942 partHoldBack = levelDetails.partHoldBack, 6943 targetduration = levelDetails.targetduration; 6944 var _this$config2 = this.config, 6945 liveSyncDuration = _this$config2.liveSyncDuration, 6946 liveSyncDurationCount = _this$config2.liveSyncDurationCount, 6947 lowLatencyMode = _this$config2.lowLatencyMode; 6948 var userConfig = this.hls.userConfig; 6949 var targetLatency = lowLatencyMode ? partHoldBack || holdBack : holdBack; 6950 if (userConfig.liveSyncDuration || userConfig.liveSyncDurationCount || targetLatency === 0) { 6951 targetLatency = liveSyncDuration !== undefined ? liveSyncDuration : liveSyncDurationCount * targetduration; 6952 } 6953 var maxLiveSyncOnStallIncrease = targetduration; 6954 var liveSyncOnStallIncrease = 1.0; 6955 return targetLatency + Math.min(this.stallCount * liveSyncOnStallIncrease, maxLiveSyncOnStallIncrease); 6956 } 6957 }, { 6958 key: "liveSyncPosition", 6959 get: function get() { 6960 var liveEdge = this.estimateLiveEdge(); 6961 var targetLatency = this.targetLatency; 6962 var levelDetails = this.levelDetails; 6963 if (liveEdge === null || targetLatency === null || levelDetails === null) { 6964 return null; 6965 } 6966 var edge = levelDetails.edge; 6967 var syncPosition = liveEdge - targetLatency - this.edgeStalled; 6968 var min = edge - levelDetails.totalduration; 6969 var max = edge - (this.config.lowLatencyMode && levelDetails.partTarget || levelDetails.targetduration); 6970 return Math.min(Math.max(min, syncPosition), max); 6971 } 6972 }, { 6973 key: "drift", 6974 get: function get() { 6975 var levelDetails = this.levelDetails; 6976 if (levelDetails === null) { 6977 return 1; 6978 } 6979 return levelDetails.drift; 6980 } 6981 }, { 6982 key: "edgeStalled", 6983 get: function get() { 6984 var levelDetails = this.levelDetails; 6985 if (levelDetails === null) { 6986 return 0; 6987 } 6988 var maxLevelUpdateAge = (this.config.lowLatencyMode && levelDetails.partTarget || levelDetails.targetduration) * 3; 6989 return Math.max(levelDetails.age - maxLevelUpdateAge, 0); 6990 } 6991 }, { 6992 key: "forwardBufferLength", 6993 get: function get() { 6994 var media = this.media, 6995 levelDetails = this.levelDetails; 6996 if (!media || !levelDetails) { 6997 return 0; 6998 } 6999 var bufferedRanges = media.buffered.length; 7000 return (bufferedRanges ? media.buffered.end(bufferedRanges - 1) : levelDetails.edge) - this.currentTime; 7001 } 7002 }]); 7003 return LatencyController; 7004}(); 7005 7006 7007/***/ }), 7008 7009/***/ "./src/controller/level-controller.ts": 7010/*!********************************************!*\ 7011 !*** ./src/controller/level-controller.ts ***! 7012 \********************************************/ 7013/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 7014 7015"use strict"; 7016__webpack_require__.r(__webpack_exports__); 7017/* harmony export */ __webpack_require__.d(__webpack_exports__, { 7018/* harmony export */ "default": () => (/* binding */ LevelController) 7019/* harmony export */ }); 7020/* harmony import */ var _types_level__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../types/level */ "./src/types/level.ts"); 7021/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 7022/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../errors */ "./src/errors.ts"); 7023/* harmony import */ var _utils_codecs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils/codecs */ "./src/utils/codecs.ts"); 7024/* harmony import */ var _level_helper__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./level-helper */ "./src/controller/level-helper.ts"); 7025/* harmony import */ var _base_playlist_controller__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./base-playlist-controller */ "./src/controller/base-playlist-controller.ts"); 7026/* harmony import */ var _types_loader__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../types/loader */ "./src/types/loader.ts"); 7027function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } 7028function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } 7029function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } 7030function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } 7031function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } 7032function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); } 7033function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } 7034/* 7035 * Level Controller 7036 */ 7037 7038 7039 7040 7041 7042 7043 7044 7045var chromeOrFirefox = /chrome|firefox/.test(navigator.userAgent.toLowerCase()); 7046var LevelController = /*#__PURE__*/function (_BasePlaylistControll) { 7047 _inheritsLoose(LevelController, _BasePlaylistControll); 7048 function LevelController(hls) { 7049 var _this; 7050 _this = _BasePlaylistControll.call(this, hls, '[level-controller]') || this; 7051 _this._levels = []; 7052 _this._firstLevel = -1; 7053 _this._startLevel = void 0; 7054 _this.currentLevelIndex = -1; 7055 _this.manualLevelIndex = -1; 7056 _this.onParsedComplete = void 0; 7057 _this._registerListeners(); 7058 return _this; 7059 } 7060 var _proto = LevelController.prototype; 7061 _proto._registerListeners = function _registerListeners() { 7062 var hls = this.hls; 7063 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MANIFEST_LOADED, this.onManifestLoaded, this); 7064 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.LEVEL_LOADED, this.onLevelLoaded, this); 7065 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this); 7066 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.FRAG_LOADED, this.onFragLoaded, this); 7067 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.ERROR, this.onError, this); 7068 }; 7069 _proto._unregisterListeners = function _unregisterListeners() { 7070 var hls = this.hls; 7071 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MANIFEST_LOADED, this.onManifestLoaded, this); 7072 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.LEVEL_LOADED, this.onLevelLoaded, this); 7073 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this); 7074 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.FRAG_LOADED, this.onFragLoaded, this); 7075 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.ERROR, this.onError, this); 7076 }; 7077 _proto.destroy = function destroy() { 7078 this._unregisterListeners(); 7079 this.manualLevelIndex = -1; 7080 this._levels.length = 0; 7081 _BasePlaylistControll.prototype.destroy.call(this); 7082 }; 7083 _proto.startLoad = function startLoad() { 7084 var levels = this._levels; 7085 7086 // clean up live level details to force reload them, and reset load errors 7087 levels.forEach(function (level) { 7088 level.loadError = 0; 7089 }); 7090 _BasePlaylistControll.prototype.startLoad.call(this); 7091 }; 7092 _proto.onManifestLoaded = function onManifestLoaded(event, data) { 7093 var levels = []; 7094 var audioTracks = []; 7095 var subtitleTracks = []; 7096 var bitrateStart; 7097 var levelSet = {}; 7098 var levelFromSet; 7099 var resolutionFound = false; 7100 var videoCodecFound = false; 7101 var audioCodecFound = false; 7102 7103 // regroup redundant levels together 7104 data.levels.forEach(function (levelParsed) { 7105 var attributes = levelParsed.attrs; 7106 resolutionFound = resolutionFound || !!(levelParsed.width && levelParsed.height); 7107 videoCodecFound = videoCodecFound || !!levelParsed.videoCodec; 7108 audioCodecFound = audioCodecFound || !!levelParsed.audioCodec; 7109 7110 // erase audio codec info if browser does not support mp4a.40.34. 7111 // demuxer will autodetect codec and fallback to mpeg/audio 7112 if (chromeOrFirefox && levelParsed.audioCodec && levelParsed.audioCodec.indexOf('mp4a.40.34') !== -1) { 7113 levelParsed.audioCodec = undefined; 7114 } 7115 var levelKey = levelParsed.bitrate + "-" + levelParsed.attrs.RESOLUTION + "-" + levelParsed.attrs.CODECS; 7116 levelFromSet = levelSet[levelKey]; 7117 if (!levelFromSet) { 7118 levelFromSet = new _types_level__WEBPACK_IMPORTED_MODULE_0__.Level(levelParsed); 7119 levelSet[levelKey] = levelFromSet; 7120 levels.push(levelFromSet); 7121 } else { 7122 levelFromSet.url.push(levelParsed.url); 7123 } 7124 if (attributes) { 7125 if (attributes.AUDIO) { 7126 (0,_level_helper__WEBPACK_IMPORTED_MODULE_4__.addGroupId)(levelFromSet, 'audio', attributes.AUDIO); 7127 } 7128 if (attributes.SUBTITLES) { 7129 (0,_level_helper__WEBPACK_IMPORTED_MODULE_4__.addGroupId)(levelFromSet, 'text', attributes.SUBTITLES); 7130 } 7131 } 7132 }); 7133 7134 // remove audio-only level if we also have levels with video codecs or RESOLUTION signalled 7135 if ((resolutionFound || videoCodecFound) && audioCodecFound) { 7136 levels = levels.filter(function (_ref) { 7137 var videoCodec = _ref.videoCodec, 7138 width = _ref.width, 7139 height = _ref.height; 7140 return !!videoCodec || !!(width && height); 7141 }); 7142 } 7143 7144 // only keep levels with supported audio/video codecs 7145 levels = levels.filter(function (_ref2) { 7146 var audioCodec = _ref2.audioCodec, 7147 videoCodec = _ref2.videoCodec; 7148 return (!audioCodec || (0,_utils_codecs__WEBPACK_IMPORTED_MODULE_3__.isCodecSupportedInMp4)(audioCodec, 'audio')) && (!videoCodec || (0,_utils_codecs__WEBPACK_IMPORTED_MODULE_3__.isCodecSupportedInMp4)(videoCodec, 'video')); 7149 }); 7150 if (data.audioTracks) { 7151 audioTracks = data.audioTracks.filter(function (track) { 7152 return !track.audioCodec || (0,_utils_codecs__WEBPACK_IMPORTED_MODULE_3__.isCodecSupportedInMp4)(track.audioCodec, 'audio'); 7153 }); 7154 // Assign ids after filtering as array indices by group-id 7155 (0,_level_helper__WEBPACK_IMPORTED_MODULE_4__.assignTrackIdsByGroup)(audioTracks); 7156 } 7157 if (data.subtitles) { 7158 subtitleTracks = data.subtitles; 7159 (0,_level_helper__WEBPACK_IMPORTED_MODULE_4__.assignTrackIdsByGroup)(subtitleTracks); 7160 } 7161 if (levels.length > 0) { 7162 // start bitrate is the first bitrate of the manifest 7163 bitrateStart = levels[0].bitrate; 7164 // sort levels from lowest to highest 7165 levels.sort(function (a, b) { 7166 if (a.attrs['HDCP-LEVEL'] !== b.attrs['HDCP-LEVEL']) { 7167 return (a.attrs['HDCP-LEVEL'] || '') > (b.attrs['HDCP-LEVEL'] || '') ? 1 : -1; 7168 } 7169 if (a.bitrate !== b.bitrate) { 7170 return a.bitrate - b.bitrate; 7171 } 7172 if (a.attrs.SCORE !== b.attrs.SCORE) { 7173 return a.attrs.decimalFloatingPoint('SCORE') - b.attrs.decimalFloatingPoint('SCORE'); 7174 } 7175 if (resolutionFound && a.height !== b.height) { 7176 return a.height - b.height; 7177 } 7178 return 0; 7179 }); 7180 this._levels = levels; 7181 // find index of first level in sorted levels 7182 for (var i = 0; i < levels.length; i++) { 7183 if (levels[i].bitrate === bitrateStart) { 7184 this._firstLevel = i; 7185 this.log("manifest loaded, " + levels.length + " level(s) found, first bitrate: " + bitrateStart); 7186 break; 7187 } 7188 } 7189 7190 // Audio is only alternate if manifest include a URI along with the audio group tag, 7191 // and this is not an audio-only stream where levels contain audio-only 7192 var audioOnly = audioCodecFound && !videoCodecFound; 7193 var edata = { 7194 levels: levels, 7195 audioTracks: audioTracks, 7196 subtitleTracks: subtitleTracks, 7197 sessionData: data.sessionData, 7198 sessionKeys: data.sessionKeys, 7199 firstLevel: this._firstLevel, 7200 stats: data.stats, 7201 audio: audioCodecFound, 7202 video: videoCodecFound, 7203 altAudio: !audioOnly && audioTracks.some(function (t) { 7204 return !!t.url; 7205 }) 7206 }; 7207 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MANIFEST_PARSED, edata); 7208 7209 // Initiate loading after all controllers have received MANIFEST_PARSED 7210 if (this.hls.config.autoStartLoad || this.hls.forceStartLoad) { 7211 this.hls.startLoad(this.hls.config.startPosition); 7212 } 7213 } else { 7214 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.ERROR, { 7215 type: _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorTypes.MEDIA_ERROR, 7216 details: _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorDetails.MANIFEST_INCOMPATIBLE_CODECS_ERROR, 7217 fatal: true, 7218 url: data.url, 7219 reason: 'no level with compatible codecs found in manifest' 7220 }); 7221 } 7222 }; 7223 _proto.onError = function onError(event, data) { 7224 var _data$frag, _data$level; 7225 _BasePlaylistControll.prototype.onError.call(this, event, data); 7226 if (data.fatal) { 7227 return; 7228 } 7229 7230 // Switch to redundant level when track fails to load 7231 var context = data.context; 7232 var level = this._levels[this.currentLevelIndex]; 7233 if (context && (context.type === _types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistContextType.AUDIO_TRACK && level.audioGroupIds && context.groupId === level.audioGroupIds[level.urlId] || context.type === _types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistContextType.SUBTITLE_TRACK && level.textGroupIds && context.groupId === level.textGroupIds[level.urlId])) { 7234 this.redundantFailover(this.currentLevelIndex); 7235 return; 7236 } 7237 var levelError = false; 7238 var levelSwitch = true; 7239 var levelIndex; 7240 7241 // try to recover not fatal errors 7242 switch (data.details) { 7243 case _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorDetails.FRAG_LOAD_ERROR: 7244 case _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorDetails.FRAG_LOAD_TIMEOUT: 7245 case _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorDetails.KEY_LOAD_ERROR: 7246 case _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorDetails.KEY_LOAD_TIMEOUT: 7247 if (data.frag) { 7248 // Share fragment error count accross media options (main, audio, subs) 7249 // This allows for level based rendition switching when media option assets fail 7250 var variantLevelIndex = data.frag.type === _types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistLevelType.MAIN ? data.frag.level : this.currentLevelIndex; 7251 var _level = this._levels[variantLevelIndex]; 7252 // Set levelIndex when we're out of fragment retries 7253 if (_level) { 7254 _level.fragmentError++; 7255 if (_level.fragmentError > this.hls.config.fragLoadingMaxRetry) { 7256 levelIndex = variantLevelIndex; 7257 } 7258 } else { 7259 levelIndex = variantLevelIndex; 7260 } 7261 } 7262 break; 7263 case _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorDetails.KEY_SYSTEM_STATUS_OUTPUT_RESTRICTED: 7264 { 7265 var restrictedHdcpLevel = level.attrs['HDCP-LEVEL']; 7266 if (restrictedHdcpLevel) { 7267 this.hls.maxHdcpLevel = _types_level__WEBPACK_IMPORTED_MODULE_0__.HdcpLevels[_types_level__WEBPACK_IMPORTED_MODULE_0__.HdcpLevels.indexOf(restrictedHdcpLevel) - 1]; 7268 this.warn("Restricting playback to HDCP-LEVEL of \"" + this.hls.maxHdcpLevel + "\" or lower"); 7269 } 7270 } 7271 // eslint-disable-next-line no-fallthrough 7272 case _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorDetails.FRAG_PARSING_ERROR: 7273 case _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorDetails.KEY_SYSTEM_NO_SESSION: 7274 levelIndex = ((_data$frag = data.frag) === null || _data$frag === void 0 ? void 0 : _data$frag.type) === _types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistLevelType.MAIN ? data.frag.level : this.currentLevelIndex; 7275 // Do not retry level. Escalate to fatal if switching levels fails. 7276 data.levelRetry = false; 7277 break; 7278 case _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorDetails.LEVEL_LOAD_ERROR: 7279 case _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorDetails.LEVEL_LOAD_TIMEOUT: 7280 // Do not perform level switch if an error occurred using delivery directives 7281 // Attempt to reload level without directives first 7282 if (context) { 7283 if (context.deliveryDirectives) { 7284 levelSwitch = false; 7285 } 7286 levelIndex = context.level; 7287 } 7288 levelError = true; 7289 break; 7290 case _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorDetails.REMUX_ALLOC_ERROR: 7291 levelIndex = (_data$level = data.level) != null ? _data$level : this.currentLevelIndex; 7292 levelError = true; 7293 break; 7294 } 7295 if (levelIndex !== undefined) { 7296 this.recoverLevel(data, levelIndex, levelError, levelSwitch); 7297 } 7298 } 7299 7300 /** 7301 * Switch to a redundant stream if any available. 7302 * If redundant stream is not available, emergency switch down if ABR mode is enabled. 7303 */; 7304 _proto.recoverLevel = function recoverLevel(errorEvent, levelIndex, levelError, levelSwitch) { 7305 var errorDetails = errorEvent.details; 7306 var level = this._levels[levelIndex]; 7307 level.loadError++; 7308 if (levelError) { 7309 var retrying = this.retryLoadingOrFail(errorEvent); 7310 if (retrying) { 7311 // boolean used to inform stream controller not to switch back to IDLE on non fatal error 7312 errorEvent.levelRetry = true; 7313 } else { 7314 this.currentLevelIndex = -1; 7315 return; 7316 } 7317 } 7318 if (levelSwitch) { 7319 var redundantLevels = level.url.length; 7320 // Try redundant fail-over until level.loadError reaches redundantLevels 7321 if (redundantLevels > 1 && level.loadError < redundantLevels) { 7322 errorEvent.levelRetry = true; 7323 this.redundantFailover(levelIndex); 7324 } else if (this.manualLevelIndex === -1) { 7325 // Search for next level to retry 7326 var nextLevel = -1; 7327 var levels = this._levels; 7328 for (var i = levels.length; i--;) { 7329 var candidate = (i + this.currentLevelIndex) % levels.length; 7330 if (candidate !== this.currentLevelIndex && levels[candidate].loadError === 0) { 7331 nextLevel = candidate; 7332 break; 7333 } 7334 } 7335 if (nextLevel > -1 && this.currentLevelIndex !== nextLevel) { 7336 this.warn(errorDetails + ": switch to " + nextLevel); 7337 errorEvent.levelRetry = true; 7338 this.hls.nextAutoLevel = nextLevel; 7339 } else if (errorEvent.levelRetry === false) { 7340 // No levels to switch to and no more retries 7341 errorEvent.fatal = true; 7342 } 7343 } 7344 } 7345 }; 7346 _proto.redundantFailover = function redundantFailover(levelIndex) { 7347 var level = this._levels[levelIndex]; 7348 var redundantLevels = level.url.length; 7349 if (redundantLevels > 1) { 7350 // Update the url id of all levels so that we stay on the same set of variants when level switching 7351 var newUrlId = (level.urlId + 1) % redundantLevels; 7352 this.warn("Switching to redundant URL-id " + newUrlId); 7353 this._levels.forEach(function (level) { 7354 level.urlId = newUrlId; 7355 }); 7356 this.level = levelIndex; 7357 } 7358 } 7359 7360 // reset errors on the successful load of a fragment 7361 ; 7362 _proto.onFragLoaded = function onFragLoaded(event, _ref3) { 7363 var frag = _ref3.frag; 7364 if (frag !== undefined && frag.type === _types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistLevelType.MAIN) { 7365 var level = this._levels[frag.level]; 7366 if (level !== undefined) { 7367 level.fragmentError = 0; 7368 level.loadError = 0; 7369 } 7370 } 7371 }; 7372 _proto.onLevelLoaded = function onLevelLoaded(event, data) { 7373 var _data$deliveryDirecti2; 7374 var level = data.level, 7375 details = data.details; 7376 var curLevel = this._levels[level]; 7377 if (!curLevel) { 7378 var _data$deliveryDirecti; 7379 this.warn("Invalid level index " + level); 7380 if ((_data$deliveryDirecti = data.deliveryDirectives) !== null && _data$deliveryDirecti !== void 0 && _data$deliveryDirecti.skip) { 7381 details.deltaUpdateFailed = true; 7382 } 7383 return; 7384 } 7385 7386 // only process level loaded events matching with expected level 7387 if (level === this.currentLevelIndex) { 7388 // reset level load error counter on successful level loaded only if there is no issues with fragments 7389 if (curLevel.fragmentError === 0) { 7390 curLevel.loadError = 0; 7391 this.retryCount = 0; 7392 } 7393 this.playlistLoaded(level, data, curLevel.details); 7394 } else if ((_data$deliveryDirecti2 = data.deliveryDirectives) !== null && _data$deliveryDirecti2 !== void 0 && _data$deliveryDirecti2.skip) { 7395 // received a delta playlist update that cannot be merged 7396 details.deltaUpdateFailed = true; 7397 } 7398 }; 7399 _proto.onAudioTrackSwitched = function onAudioTrackSwitched(event, data) { 7400 var currentLevel = this.hls.levels[this.currentLevelIndex]; 7401 if (!currentLevel) { 7402 return; 7403 } 7404 if (currentLevel.audioGroupIds) { 7405 var urlId = -1; 7406 var audioGroupId = this.hls.audioTracks[data.id].groupId; 7407 for (var i = 0; i < currentLevel.audioGroupIds.length; i++) { 7408 if (currentLevel.audioGroupIds[i] === audioGroupId) { 7409 urlId = i; 7410 break; 7411 } 7412 } 7413 if (urlId !== currentLevel.urlId) { 7414 currentLevel.urlId = urlId; 7415 this.startLoad(); 7416 } 7417 } 7418 }; 7419 _proto.loadPlaylist = function loadPlaylist(hlsUrlParameters) { 7420 _BasePlaylistControll.prototype.loadPlaylist.call(this); 7421 var level = this.currentLevelIndex; 7422 var currentLevel = this._levels[level]; 7423 if (this.canLoad && currentLevel && currentLevel.url.length > 0) { 7424 var id = currentLevel.urlId; 7425 var url = currentLevel.url[id]; 7426 if (hlsUrlParameters) { 7427 try { 7428 url = hlsUrlParameters.addDirectives(url); 7429 } catch (error) { 7430 this.warn("Could not construct new URL with HLS Delivery Directives: " + error); 7431 } 7432 } 7433 this.log("Attempt loading level index " + level + ((hlsUrlParameters === null || hlsUrlParameters === void 0 ? void 0 : hlsUrlParameters.msn) !== undefined ? ' at sn ' + hlsUrlParameters.msn + ' part ' + hlsUrlParameters.part : '') + " with URL-id " + id + " " + url); 7434 7435 // console.log('Current audio track group ID:', this.hls.audioTracks[this.hls.audioTrack].groupId); 7436 // console.log('New video quality level audio group id:', levelObject.attrs.AUDIO, level); 7437 this.clearTimer(); 7438 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.LEVEL_LOADING, { 7439 url: url, 7440 level: level, 7441 id: id, 7442 deliveryDirectives: hlsUrlParameters || null 7443 }); 7444 } 7445 }; 7446 _proto.removeLevel = function removeLevel(levelIndex, urlId) { 7447 var filterLevelAndGroupByIdIndex = function filterLevelAndGroupByIdIndex(url, id) { 7448 return id !== urlId; 7449 }; 7450 var levels = this._levels.filter(function (level, index) { 7451 if (index !== levelIndex) { 7452 return true; 7453 } 7454 if (level.url.length > 1 && urlId !== undefined) { 7455 level.url = level.url.filter(filterLevelAndGroupByIdIndex); 7456 if (level.audioGroupIds) { 7457 level.audioGroupIds = level.audioGroupIds.filter(filterLevelAndGroupByIdIndex); 7458 } 7459 if (level.textGroupIds) { 7460 level.textGroupIds = level.textGroupIds.filter(filterLevelAndGroupByIdIndex); 7461 } 7462 level.urlId = 0; 7463 return true; 7464 } 7465 return false; 7466 }).map(function (level, index) { 7467 var details = level.details; 7468 if (details !== null && details !== void 0 && details.fragments) { 7469 details.fragments.forEach(function (fragment) { 7470 fragment.level = index; 7471 }); 7472 } 7473 return level; 7474 }); 7475 this._levels = levels; 7476 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.LEVELS_UPDATED, { 7477 levels: levels 7478 }); 7479 }; 7480 _createClass(LevelController, [{ 7481 key: "levels", 7482 get: function get() { 7483 if (this._levels.length === 0) { 7484 return null; 7485 } 7486 return this._levels; 7487 } 7488 }, { 7489 key: "level", 7490 get: function get() { 7491 return this.currentLevelIndex; 7492 }, 7493 set: function set(newLevel) { 7494 var _levels$newLevel; 7495 var levels = this._levels; 7496 if (levels.length === 0) { 7497 return; 7498 } 7499 if (this.currentLevelIndex === newLevel && (_levels$newLevel = levels[newLevel]) !== null && _levels$newLevel !== void 0 && _levels$newLevel.details) { 7500 return; 7501 } 7502 // check if level idx is valid 7503 if (newLevel < 0 || newLevel >= levels.length) { 7504 // invalid level id given, trigger error 7505 var fatal = newLevel < 0; 7506 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.ERROR, { 7507 type: _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorTypes.OTHER_ERROR, 7508 details: _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorDetails.LEVEL_SWITCH_ERROR, 7509 level: newLevel, 7510 fatal: fatal, 7511 reason: 'invalid level idx' 7512 }); 7513 if (fatal) { 7514 return; 7515 } 7516 newLevel = Math.min(newLevel, levels.length - 1); 7517 } 7518 7519 // stopping live reloading timer if any 7520 this.clearTimer(); 7521 var lastLevelIndex = this.currentLevelIndex; 7522 var lastLevel = levels[lastLevelIndex]; 7523 var level = levels[newLevel]; 7524 this.log("switching to level " + newLevel + " from " + lastLevelIndex); 7525 this.currentLevelIndex = newLevel; 7526 var levelSwitchingData = _extends({}, level, { 7527 level: newLevel, 7528 maxBitrate: level.maxBitrate, 7529 uri: level.uri, 7530 urlId: level.urlId 7531 }); 7532 // @ts-ignore 7533 delete levelSwitchingData._urlId; 7534 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.LEVEL_SWITCHING, levelSwitchingData); 7535 // check if we need to load playlist for this level 7536 var levelDetails = level.details; 7537 if (!levelDetails || levelDetails.live) { 7538 // level not retrieved yet, or live playlist we need to (re)load it 7539 var hlsUrlParameters = this.switchParams(level.uri, lastLevel === null || lastLevel === void 0 ? void 0 : lastLevel.details); 7540 this.loadPlaylist(hlsUrlParameters); 7541 } 7542 } 7543 }, { 7544 key: "manualLevel", 7545 get: function get() { 7546 return this.manualLevelIndex; 7547 }, 7548 set: function set(newLevel) { 7549 this.manualLevelIndex = newLevel; 7550 if (this._startLevel === undefined) { 7551 this._startLevel = newLevel; 7552 } 7553 if (newLevel !== -1) { 7554 this.level = newLevel; 7555 } 7556 } 7557 }, { 7558 key: "firstLevel", 7559 get: function get() { 7560 return this._firstLevel; 7561 }, 7562 set: function set(newLevel) { 7563 this._firstLevel = newLevel; 7564 } 7565 }, { 7566 key: "startLevel", 7567 get: function get() { 7568 // hls.startLevel takes precedence over config.startLevel 7569 // if none of these values are defined, fallback on this._firstLevel (first quality level appearing in variant manifest) 7570 if (this._startLevel === undefined) { 7571 var configStartLevel = this.hls.config.startLevel; 7572 if (configStartLevel !== undefined) { 7573 return configStartLevel; 7574 } else { 7575 return this._firstLevel; 7576 } 7577 } else { 7578 return this._startLevel; 7579 } 7580 }, 7581 set: function set(newLevel) { 7582 this._startLevel = newLevel; 7583 } 7584 }, { 7585 key: "nextLoadLevel", 7586 get: function get() { 7587 if (this.manualLevelIndex !== -1) { 7588 return this.manualLevelIndex; 7589 } else { 7590 return this.hls.nextAutoLevel; 7591 } 7592 }, 7593 set: function set(nextLevel) { 7594 this.level = nextLevel; 7595 if (this.manualLevelIndex === -1) { 7596 this.hls.nextAutoLevel = nextLevel; 7597 } 7598 } 7599 }]); 7600 return LevelController; 7601}(_base_playlist_controller__WEBPACK_IMPORTED_MODULE_5__["default"]); 7602 7603 7604/***/ }), 7605 7606/***/ "./src/controller/level-helper.ts": 7607/*!****************************************!*\ 7608 !*** ./src/controller/level-helper.ts ***! 7609 \****************************************/ 7610/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 7611 7612"use strict"; 7613__webpack_require__.r(__webpack_exports__); 7614/* harmony export */ __webpack_require__.d(__webpack_exports__, { 7615/* harmony export */ "addGroupId": () => (/* binding */ addGroupId), 7616/* harmony export */ "addSliding": () => (/* binding */ addSliding), 7617/* harmony export */ "adjustSliding": () => (/* binding */ adjustSliding), 7618/* harmony export */ "assignTrackIdsByGroup": () => (/* binding */ assignTrackIdsByGroup), 7619/* harmony export */ "computeReloadInterval": () => (/* binding */ computeReloadInterval), 7620/* harmony export */ "getFragmentWithSN": () => (/* binding */ getFragmentWithSN), 7621/* harmony export */ "getPartWith": () => (/* binding */ getPartWith), 7622/* harmony export */ "mapFragmentIntersection": () => (/* binding */ mapFragmentIntersection), 7623/* harmony export */ "mapPartIntersection": () => (/* binding */ mapPartIntersection), 7624/* harmony export */ "mergeDetails": () => (/* binding */ mergeDetails), 7625/* harmony export */ "updateFragPTSDTS": () => (/* binding */ updateFragPTSDTS), 7626/* harmony export */ "updatePTS": () => (/* binding */ updatePTS) 7627/* harmony export */ }); 7628/* harmony import */ var _home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.ts"); 7629/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 7630/* harmony import */ var _loader_date_range__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../loader/date-range */ "./src/loader/date-range.ts"); 7631 7632 7633 7634 7635 7636function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } 7637/** 7638 * @module LevelHelper 7639 * Providing methods dealing with playlist sliding and drift 7640 * */ 7641 7642 7643 7644function addGroupId(level, type, id) { 7645 switch (type) { 7646 case 'audio': 7647 if (!level.audioGroupIds) { 7648 level.audioGroupIds = []; 7649 } 7650 level.audioGroupIds.push(id); 7651 break; 7652 case 'text': 7653 if (!level.textGroupIds) { 7654 level.textGroupIds = []; 7655 } 7656 level.textGroupIds.push(id); 7657 break; 7658 } 7659} 7660function assignTrackIdsByGroup(tracks) { 7661 var groups = {}; 7662 tracks.forEach(function (track) { 7663 var groupId = track.groupId || ''; 7664 track.id = groups[groupId] = groups[groupId] || 0; 7665 groups[groupId]++; 7666 }); 7667} 7668function updatePTS(fragments, fromIdx, toIdx) { 7669 var fragFrom = fragments[fromIdx]; 7670 var fragTo = fragments[toIdx]; 7671 updateFromToPTS(fragFrom, fragTo); 7672} 7673function updateFromToPTS(fragFrom, fragTo) { 7674 var fragToPTS = fragTo.startPTS; 7675 // if we know startPTS[toIdx] 7676 if ((0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(fragToPTS)) { 7677 // update fragment duration. 7678 // it helps to fix drifts between playlist reported duration and fragment real duration 7679 var duration = 0; 7680 var frag; 7681 if (fragTo.sn > fragFrom.sn) { 7682 duration = fragToPTS - fragFrom.start; 7683 frag = fragFrom; 7684 } else { 7685 duration = fragFrom.start - fragToPTS; 7686 frag = fragTo; 7687 } 7688 // TODO? Drift can go either way, or the playlist could be completely accurate 7689 // console.assert(duration > 0, 7690 // `duration of ${duration} computed for frag ${frag.sn}, level ${frag.level}, there should be some duration drift between playlist and fragment!`); 7691 if (frag.duration !== duration) { 7692 frag.duration = duration; 7693 } 7694 // we dont know startPTS[toIdx] 7695 } else if (fragTo.sn > fragFrom.sn) { 7696 var contiguous = fragFrom.cc === fragTo.cc; 7697 // TODO: With part-loading end/durations we need to confirm the whole fragment is loaded before using (or setting) minEndPTS 7698 if (contiguous && fragFrom.minEndPTS) { 7699 fragTo.start = fragFrom.start + (fragFrom.minEndPTS - fragFrom.start); 7700 } else { 7701 fragTo.start = fragFrom.start + fragFrom.duration; 7702 } 7703 } else { 7704 fragTo.start = Math.max(fragFrom.start - fragTo.duration, 0); 7705 } 7706} 7707function updateFragPTSDTS(details, frag, startPTS, endPTS, startDTS, endDTS) { 7708 var parsedMediaDuration = endPTS - startPTS; 7709 if (parsedMediaDuration <= 0) { 7710 _utils_logger__WEBPACK_IMPORTED_MODULE_1__.logger.warn('Fragment should have a positive duration', frag); 7711 endPTS = startPTS + frag.duration; 7712 endDTS = startDTS + frag.duration; 7713 } 7714 var maxStartPTS = startPTS; 7715 var minEndPTS = endPTS; 7716 var fragStartPts = frag.startPTS; 7717 var fragEndPts = frag.endPTS; 7718 if ((0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(fragStartPts)) { 7719 // delta PTS between audio and video 7720 var deltaPTS = Math.abs(fragStartPts - startPTS); 7721 if (!(0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(frag.deltaPTS)) { 7722 frag.deltaPTS = deltaPTS; 7723 } else { 7724 frag.deltaPTS = Math.max(deltaPTS, frag.deltaPTS); 7725 } 7726 maxStartPTS = Math.max(startPTS, fragStartPts); 7727 startPTS = Math.min(startPTS, fragStartPts); 7728 startDTS = Math.min(startDTS, frag.startDTS); 7729 minEndPTS = Math.min(endPTS, fragEndPts); 7730 endPTS = Math.max(endPTS, fragEndPts); 7731 endDTS = Math.max(endDTS, frag.endDTS); 7732 } 7733 frag.duration = endPTS - startPTS; 7734 var drift = startPTS - frag.start; 7735 frag.start = frag.startPTS = startPTS; 7736 frag.maxStartPTS = maxStartPTS; 7737 frag.startDTS = startDTS; 7738 frag.endPTS = endPTS; 7739 frag.minEndPTS = minEndPTS; 7740 frag.endDTS = endDTS; 7741 var sn = frag.sn; // 'initSegment' 7742 // exit if sn out of range 7743 if (!details || sn < details.startSN || sn > details.endSN) { 7744 return 0; 7745 } 7746 var i; 7747 var fragIdx = sn - details.startSN; 7748 var fragments = details.fragments; 7749 // update frag reference in fragments array 7750 // rationale is that fragments array might not contain this frag object. 7751 // this will happen if playlist has been refreshed between frag loading and call to updateFragPTSDTS() 7752 // if we don't update frag, we won't be able to propagate PTS info on the playlist 7753 // resulting in invalid sliding computation 7754 fragments[fragIdx] = frag; 7755 // adjust fragment PTS/duration from seqnum-1 to frag 0 7756 for (i = fragIdx; i > 0; i--) { 7757 updateFromToPTS(fragments[i], fragments[i - 1]); 7758 } 7759 7760 // adjust fragment PTS/duration from seqnum to last frag 7761 for (i = fragIdx; i < fragments.length - 1; i++) { 7762 updateFromToPTS(fragments[i], fragments[i + 1]); 7763 } 7764 if (details.fragmentHint) { 7765 updateFromToPTS(fragments[fragments.length - 1], details.fragmentHint); 7766 } 7767 details.PTSKnown = details.alignedSliding = true; 7768 return drift; 7769} 7770function mergeDetails(oldDetails, newDetails) { 7771 // Track the last initSegment processed. Initialize it to the last one on the timeline. 7772 var currentInitSegment = null; 7773 var oldFragments = oldDetails.fragments; 7774 for (var i = oldFragments.length - 1; i >= 0; i--) { 7775 var oldInit = oldFragments[i].initSegment; 7776 if (oldInit) { 7777 currentInitSegment = oldInit; 7778 break; 7779 } 7780 } 7781 if (oldDetails.fragmentHint) { 7782 // prevent PTS and duration from being adjusted on the next hint 7783 delete oldDetails.fragmentHint.endPTS; 7784 } 7785 // check if old/new playlists have fragments in common 7786 // loop through overlapping SN and update startPTS , cc, and duration if any found 7787 var ccOffset = 0; 7788 var PTSFrag; 7789 mapFragmentIntersection(oldDetails, newDetails, function (oldFrag, newFrag) { 7790 if (oldFrag.relurl) { 7791 // Do not compare CC if the old fragment has no url. This is a level.fragmentHint used by LL-HLS parts. 7792 // It maybe be off by 1 if it was created before any parts or discontinuity tags were appended to the end 7793 // of the playlist. 7794 ccOffset = oldFrag.cc - newFrag.cc; 7795 } 7796 if ((0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(oldFrag.startPTS) && (0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(oldFrag.endPTS)) { 7797 newFrag.start = newFrag.startPTS = oldFrag.startPTS; 7798 newFrag.startDTS = oldFrag.startDTS; 7799 newFrag.appendedPTS = oldFrag.appendedPTS; 7800 newFrag.maxStartPTS = oldFrag.maxStartPTS; 7801 newFrag.endPTS = oldFrag.endPTS; 7802 newFrag.endDTS = oldFrag.endDTS; 7803 newFrag.minEndPTS = oldFrag.minEndPTS; 7804 newFrag.duration = oldFrag.endPTS - oldFrag.startPTS; 7805 if (newFrag.duration) { 7806 PTSFrag = newFrag; 7807 } 7808 7809 // PTS is known when any segment has startPTS and endPTS 7810 newDetails.PTSKnown = newDetails.alignedSliding = true; 7811 } 7812 newFrag.elementaryStreams = oldFrag.elementaryStreams; 7813 newFrag.loader = oldFrag.loader; 7814 newFrag.stats = oldFrag.stats; 7815 newFrag.urlId = oldFrag.urlId; 7816 if (oldFrag.initSegment) { 7817 newFrag.initSegment = oldFrag.initSegment; 7818 currentInitSegment = oldFrag.initSegment; 7819 } 7820 }); 7821 if (currentInitSegment) { 7822 var fragmentsToCheck = newDetails.fragmentHint ? newDetails.fragments.concat(newDetails.fragmentHint) : newDetails.fragments; 7823 fragmentsToCheck.forEach(function (frag) { 7824 var _currentInitSegment; 7825 if (!frag.initSegment || frag.initSegment.relurl === ((_currentInitSegment = currentInitSegment) === null || _currentInitSegment === void 0 ? void 0 : _currentInitSegment.relurl)) { 7826 frag.initSegment = currentInitSegment; 7827 } 7828 }); 7829 } 7830 if (newDetails.skippedSegments) { 7831 newDetails.deltaUpdateFailed = newDetails.fragments.some(function (frag) { 7832 return !frag; 7833 }); 7834 if (newDetails.deltaUpdateFailed) { 7835 _utils_logger__WEBPACK_IMPORTED_MODULE_1__.logger.warn('[level-helper] Previous playlist missing segments skipped in delta playlist'); 7836 for (var _i = newDetails.skippedSegments; _i--;) { 7837 newDetails.fragments.shift(); 7838 } 7839 newDetails.startSN = newDetails.fragments[0].sn; 7840 newDetails.startCC = newDetails.fragments[0].cc; 7841 } else if (newDetails.canSkipDateRanges) { 7842 newDetails.dateRanges = mergeDateRanges(oldDetails.dateRanges, newDetails.dateRanges, newDetails.recentlyRemovedDateranges); 7843 } 7844 } 7845 var newFragments = newDetails.fragments; 7846 if (ccOffset) { 7847 _utils_logger__WEBPACK_IMPORTED_MODULE_1__.logger.warn('discontinuity sliding from playlist, take drift into account'); 7848 for (var _i2 = 0; _i2 < newFragments.length; _i2++) { 7849 newFragments[_i2].cc += ccOffset; 7850 } 7851 } 7852 if (newDetails.skippedSegments) { 7853 newDetails.startCC = newDetails.fragments[0].cc; 7854 } 7855 7856 // Merge parts 7857 mapPartIntersection(oldDetails.partList, newDetails.partList, function (oldPart, newPart) { 7858 newPart.elementaryStreams = oldPart.elementaryStreams; 7859 newPart.stats = oldPart.stats; 7860 }); 7861 7862 // if at least one fragment contains PTS info, recompute PTS information for all fragments 7863 if (PTSFrag) { 7864 updateFragPTSDTS(newDetails, PTSFrag, PTSFrag.startPTS, PTSFrag.endPTS, PTSFrag.startDTS, PTSFrag.endDTS); 7865 } else { 7866 // ensure that delta is within oldFragments range 7867 // also adjust sliding in case delta is 0 (we could have old=[50-60] and new=old=[50-61]) 7868 // in that case we also need to adjust start offset of all fragments 7869 adjustSliding(oldDetails, newDetails); 7870 } 7871 if (newFragments.length) { 7872 newDetails.totalduration = newDetails.edge - newFragments[0].start; 7873 } 7874 newDetails.driftStartTime = oldDetails.driftStartTime; 7875 newDetails.driftStart = oldDetails.driftStart; 7876 var advancedDateTime = newDetails.advancedDateTime; 7877 if (newDetails.advanced && advancedDateTime) { 7878 var edge = newDetails.edge; 7879 if (!newDetails.driftStart) { 7880 newDetails.driftStartTime = advancedDateTime; 7881 newDetails.driftStart = edge; 7882 } 7883 newDetails.driftEndTime = advancedDateTime; 7884 newDetails.driftEnd = edge; 7885 } else { 7886 newDetails.driftEndTime = oldDetails.driftEndTime; 7887 newDetails.driftEnd = oldDetails.driftEnd; 7888 newDetails.advancedDateTime = oldDetails.advancedDateTime; 7889 } 7890} 7891function mergeDateRanges(oldDateRanges, deltaDateRanges, recentlyRemovedDateranges) { 7892 var dateRanges = _extends({}, oldDateRanges); 7893 if (recentlyRemovedDateranges) { 7894 recentlyRemovedDateranges.forEach(function (id) { 7895 delete dateRanges[id]; 7896 }); 7897 } 7898 Object.keys(deltaDateRanges).forEach(function (id) { 7899 var dateRange = new _loader_date_range__WEBPACK_IMPORTED_MODULE_2__.DateRange(deltaDateRanges[id].attr, dateRanges[id]); 7900 if (dateRange.isValid) { 7901 dateRanges[id] = dateRange; 7902 } else { 7903 _utils_logger__WEBPACK_IMPORTED_MODULE_1__.logger.warn("Ignoring invalid Playlist Delta Update DATERANGE tag: \"" + JSON.stringify(deltaDateRanges[id].attr) + "\""); 7904 } 7905 }); 7906 return dateRanges; 7907} 7908function mapPartIntersection(oldParts, newParts, intersectionFn) { 7909 if (oldParts && newParts) { 7910 var delta = 0; 7911 for (var i = 0, len = oldParts.length; i <= len; i++) { 7912 var _oldPart = oldParts[i]; 7913 var _newPart = newParts[i + delta]; 7914 if (_oldPart && _newPart && _oldPart.index === _newPart.index && _oldPart.fragment.sn === _newPart.fragment.sn) { 7915 intersectionFn(_oldPart, _newPart); 7916 } else { 7917 delta--; 7918 } 7919 } 7920 } 7921} 7922function mapFragmentIntersection(oldDetails, newDetails, intersectionFn) { 7923 var skippedSegments = newDetails.skippedSegments; 7924 var start = Math.max(oldDetails.startSN, newDetails.startSN) - newDetails.startSN; 7925 var end = (oldDetails.fragmentHint ? 1 : 0) + (skippedSegments ? newDetails.endSN : Math.min(oldDetails.endSN, newDetails.endSN)) - newDetails.startSN; 7926 var delta = newDetails.startSN - oldDetails.startSN; 7927 var newFrags = newDetails.fragmentHint ? newDetails.fragments.concat(newDetails.fragmentHint) : newDetails.fragments; 7928 var oldFrags = oldDetails.fragmentHint ? oldDetails.fragments.concat(oldDetails.fragmentHint) : oldDetails.fragments; 7929 for (var i = start; i <= end; i++) { 7930 var _oldFrag = oldFrags[delta + i]; 7931 var _newFrag = newFrags[i]; 7932 if (skippedSegments && !_newFrag && i < skippedSegments) { 7933 // Fill in skipped segments in delta playlist 7934 _newFrag = newDetails.fragments[i] = _oldFrag; 7935 } 7936 if (_oldFrag && _newFrag) { 7937 intersectionFn(_oldFrag, _newFrag); 7938 } 7939 } 7940} 7941function adjustSliding(oldDetails, newDetails) { 7942 var delta = newDetails.startSN + newDetails.skippedSegments - oldDetails.startSN; 7943 var oldFragments = oldDetails.fragments; 7944 if (delta < 0 || delta >= oldFragments.length) { 7945 return; 7946 } 7947 addSliding(newDetails, oldFragments[delta].start); 7948} 7949function addSliding(details, start) { 7950 if (start) { 7951 var fragments = details.fragments; 7952 for (var i = details.skippedSegments; i < fragments.length; i++) { 7953 fragments[i].start += start; 7954 } 7955 if (details.fragmentHint) { 7956 details.fragmentHint.start += start; 7957 } 7958 } 7959} 7960function computeReloadInterval(newDetails, distanceToLiveEdgeMs) { 7961 if (distanceToLiveEdgeMs === void 0) { 7962 distanceToLiveEdgeMs = Infinity; 7963 } 7964 var reloadInterval = 1000 * newDetails.targetduration; 7965 if (newDetails.updated) { 7966 // Use last segment duration when shorter than target duration and near live edge 7967 var fragments = newDetails.fragments; 7968 var liveEdgeMaxTargetDurations = 4; 7969 if (fragments.length && reloadInterval * liveEdgeMaxTargetDurations > distanceToLiveEdgeMs) { 7970 var lastSegmentDuration = fragments[fragments.length - 1].duration * 1000; 7971 if (lastSegmentDuration < reloadInterval) { 7972 reloadInterval = lastSegmentDuration; 7973 } 7974 } 7975 } else { 7976 // estimate = 'miss half average'; 7977 // follow HLS Spec, If the client reloads a Playlist file and finds that it has not 7978 // changed then it MUST wait for a period of one-half the target 7979 // duration before retrying. 7980 reloadInterval /= 2; 7981 } 7982 return Math.round(reloadInterval); 7983} 7984function getFragmentWithSN(level, sn, fragCurrent) { 7985 if (!level || !level.details) { 7986 return null; 7987 } 7988 var levelDetails = level.details; 7989 var fragment = levelDetails.fragments[sn - levelDetails.startSN]; 7990 if (fragment) { 7991 return fragment; 7992 } 7993 fragment = levelDetails.fragmentHint; 7994 if (fragment && fragment.sn === sn) { 7995 return fragment; 7996 } 7997 if (sn < levelDetails.startSN && fragCurrent && fragCurrent.sn === sn) { 7998 return fragCurrent; 7999 } 8000 return null; 8001} 8002function getPartWith(level, sn, partIndex) { 8003 if (!level || !level.details) { 8004 return null; 8005 } 8006 var partList = level.details.partList; 8007 if (partList) { 8008 for (var i = partList.length; i--;) { 8009 var part = partList[i]; 8010 if (part.index === partIndex && part.fragment.sn === sn) { 8011 return part; 8012 } 8013 } 8014 } 8015 return null; 8016} 8017 8018/***/ }), 8019 8020/***/ "./src/controller/stream-controller.ts": 8021/*!*********************************************!*\ 8022 !*** ./src/controller/stream-controller.ts ***! 8023 \*********************************************/ 8024/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 8025 8026"use strict"; 8027__webpack_require__.r(__webpack_exports__); 8028/* harmony export */ __webpack_require__.d(__webpack_exports__, { 8029/* harmony export */ "default": () => (/* binding */ StreamController) 8030/* harmony export */ }); 8031/* harmony import */ var _home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.ts"); 8032/* harmony import */ var _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./base-stream-controller */ "./src/controller/base-stream-controller.ts"); 8033/* harmony import */ var _is_supported__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../is-supported */ "./src/is-supported.ts"); 8034/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 8035/* harmony import */ var _utils_buffer_helper__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../utils/buffer-helper */ "./src/utils/buffer-helper.ts"); 8036/* harmony import */ var _fragment_tracker__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./fragment-tracker */ "./src/controller/fragment-tracker.ts"); 8037/* harmony import */ var _types_loader__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../types/loader */ "./src/types/loader.ts"); 8038/* harmony import */ var _loader_fragment__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../loader/fragment */ "./src/loader/fragment.ts"); 8039/* harmony import */ var _demux_transmuxer_interface__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../demux/transmuxer-interface */ "./src/demux/transmuxer-interface.ts"); 8040/* harmony import */ var _types_transmuxer__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../types/transmuxer */ "./src/types/transmuxer.ts"); 8041/* harmony import */ var _gap_controller__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./gap-controller */ "./src/controller/gap-controller.ts"); 8042/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../errors */ "./src/errors.ts"); 8043 8044 8045 8046 8047function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } 8048function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } 8049function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } 8050function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } 8051function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); } 8052function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } 8053 8054 8055 8056 8057 8058 8059 8060 8061 8062 8063 8064var TICK_INTERVAL = 100; // how often to tick in ms 8065var StreamController = /*#__PURE__*/function (_BaseStreamController) { 8066 _inheritsLoose(StreamController, _BaseStreamController); 8067 function StreamController(hls, fragmentTracker, keyLoader) { 8068 var _this; 8069 _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '[stream-controller]') || this; 8070 _this.audioCodecSwap = false; 8071 _this.gapController = null; 8072 _this.level = -1; 8073 _this._forceStartLoad = false; 8074 _this.altAudio = false; 8075 _this.audioOnly = false; 8076 _this.fragPlaying = null; 8077 _this.onvplaying = null; 8078 _this.onvseeked = null; 8079 _this.fragLastKbps = 0; 8080 _this.couldBacktrack = false; 8081 _this.backtrackFragment = null; 8082 _this.audioCodecSwitch = false; 8083 _this.videoBuffer = null; 8084 _this._registerListeners(); 8085 return _this; 8086 } 8087 var _proto = StreamController.prototype; 8088 _proto._registerListeners = function _registerListeners() { 8089 var hls = this.hls; 8090 hls.on(_events__WEBPACK_IMPORTED_MODULE_3__.Events.MEDIA_ATTACHED, this.onMediaAttached, this); 8091 hls.on(_events__WEBPACK_IMPORTED_MODULE_3__.Events.MEDIA_DETACHING, this.onMediaDetaching, this); 8092 hls.on(_events__WEBPACK_IMPORTED_MODULE_3__.Events.MANIFEST_LOADING, this.onManifestLoading, this); 8093 hls.on(_events__WEBPACK_IMPORTED_MODULE_3__.Events.MANIFEST_PARSED, this.onManifestParsed, this); 8094 hls.on(_events__WEBPACK_IMPORTED_MODULE_3__.Events.LEVEL_LOADING, this.onLevelLoading, this); 8095 hls.on(_events__WEBPACK_IMPORTED_MODULE_3__.Events.LEVEL_LOADED, this.onLevelLoaded, this); 8096 hls.on(_events__WEBPACK_IMPORTED_MODULE_3__.Events.FRAG_LOAD_EMERGENCY_ABORTED, this.onFragLoadEmergencyAborted, this); 8097 hls.on(_events__WEBPACK_IMPORTED_MODULE_3__.Events.ERROR, this.onError, this); 8098 hls.on(_events__WEBPACK_IMPORTED_MODULE_3__.Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this); 8099 hls.on(_events__WEBPACK_IMPORTED_MODULE_3__.Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this); 8100 hls.on(_events__WEBPACK_IMPORTED_MODULE_3__.Events.BUFFER_CREATED, this.onBufferCreated, this); 8101 hls.on(_events__WEBPACK_IMPORTED_MODULE_3__.Events.BUFFER_FLUSHED, this.onBufferFlushed, this); 8102 hls.on(_events__WEBPACK_IMPORTED_MODULE_3__.Events.LEVELS_UPDATED, this.onLevelsUpdated, this); 8103 hls.on(_events__WEBPACK_IMPORTED_MODULE_3__.Events.FRAG_BUFFERED, this.onFragBuffered, this); 8104 }; 8105 _proto._unregisterListeners = function _unregisterListeners() { 8106 var hls = this.hls; 8107 hls.off(_events__WEBPACK_IMPORTED_MODULE_3__.Events.MEDIA_ATTACHED, this.onMediaAttached, this); 8108 hls.off(_events__WEBPACK_IMPORTED_MODULE_3__.Events.MEDIA_DETACHING, this.onMediaDetaching, this); 8109 hls.off(_events__WEBPACK_IMPORTED_MODULE_3__.Events.MANIFEST_LOADING, this.onManifestLoading, this); 8110 hls.off(_events__WEBPACK_IMPORTED_MODULE_3__.Events.MANIFEST_PARSED, this.onManifestParsed, this); 8111 hls.off(_events__WEBPACK_IMPORTED_MODULE_3__.Events.LEVEL_LOADED, this.onLevelLoaded, this); 8112 hls.off(_events__WEBPACK_IMPORTED_MODULE_3__.Events.FRAG_LOAD_EMERGENCY_ABORTED, this.onFragLoadEmergencyAborted, this); 8113 hls.off(_events__WEBPACK_IMPORTED_MODULE_3__.Events.ERROR, this.onError, this); 8114 hls.off(_events__WEBPACK_IMPORTED_MODULE_3__.Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this); 8115 hls.off(_events__WEBPACK_IMPORTED_MODULE_3__.Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this); 8116 hls.off(_events__WEBPACK_IMPORTED_MODULE_3__.Events.BUFFER_CREATED, this.onBufferCreated, this); 8117 hls.off(_events__WEBPACK_IMPORTED_MODULE_3__.Events.BUFFER_FLUSHED, this.onBufferFlushed, this); 8118 hls.off(_events__WEBPACK_IMPORTED_MODULE_3__.Events.LEVELS_UPDATED, this.onLevelsUpdated, this); 8119 hls.off(_events__WEBPACK_IMPORTED_MODULE_3__.Events.FRAG_BUFFERED, this.onFragBuffered, this); 8120 }; 8121 _proto.onHandlerDestroying = function onHandlerDestroying() { 8122 this._unregisterListeners(); 8123 this.onMediaDetaching(); 8124 }; 8125 _proto.startLoad = function startLoad(startPosition) { 8126 if (this.levels) { 8127 var lastCurrentTime = this.lastCurrentTime, 8128 hls = this.hls; 8129 this.stopLoad(); 8130 this.setInterval(TICK_INTERVAL); 8131 this.level = -1; 8132 this.fragLoadError = 0; 8133 if (!this.startFragRequested) { 8134 // determine load level 8135 var startLevel = hls.startLevel; 8136 if (startLevel === -1) { 8137 if (hls.config.testBandwidth && this.levels.length > 1) { 8138 // -1 : guess start Level by doing a bitrate test by loading first fragment of lowest quality level 8139 startLevel = 0; 8140 this.bitrateTest = true; 8141 } else { 8142 startLevel = hls.nextAutoLevel; 8143 } 8144 } 8145 // set new level to playlist loader : this will trigger start level load 8146 // hls.nextLoadLevel remains until it is set to a new value or until a new frag is successfully loaded 8147 this.level = hls.nextLoadLevel = startLevel; 8148 this.loadedmetadata = false; 8149 } 8150 // if startPosition undefined but lastCurrentTime set, set startPosition to last currentTime 8151 if (lastCurrentTime > 0 && startPosition === -1) { 8152 this.log("Override startPosition with lastCurrentTime @" + lastCurrentTime.toFixed(3)); 8153 startPosition = lastCurrentTime; 8154 } 8155 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.IDLE; 8156 this.nextLoadPosition = this.startPosition = this.lastCurrentTime = startPosition; 8157 this.tick(); 8158 } else { 8159 this._forceStartLoad = true; 8160 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.STOPPED; 8161 } 8162 }; 8163 _proto.stopLoad = function stopLoad() { 8164 this._forceStartLoad = false; 8165 _BaseStreamController.prototype.stopLoad.call(this); 8166 }; 8167 _proto.doTick = function doTick() { 8168 switch (this.state) { 8169 case _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.IDLE: 8170 this.doTickIdle(); 8171 break; 8172 case _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.WAITING_LEVEL: 8173 { 8174 var _levels$level; 8175 var levels = this.levels, 8176 level = this.level; 8177 var details = levels === null || levels === void 0 ? void 0 : (_levels$level = levels[level]) === null || _levels$level === void 0 ? void 0 : _levels$level.details; 8178 if (details && (!details.live || this.levelLastLoaded === this.level)) { 8179 if (this.waitForCdnTuneIn(details)) { 8180 break; 8181 } 8182 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.IDLE; 8183 break; 8184 } 8185 break; 8186 } 8187 case _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.FRAG_LOADING_WAITING_RETRY: 8188 { 8189 var _this$media; 8190 var now = self.performance.now(); 8191 var retryDate = this.retryDate; 8192 // if current time is gt than retryDate, or if media seeking let's switch to IDLE state to retry loading 8193 if (!retryDate || now >= retryDate || (_this$media = this.media) !== null && _this$media !== void 0 && _this$media.seeking) { 8194 this.log('retryDate reached, switch back to IDLE state'); 8195 this.resetStartWhenNotLoaded(this.level); 8196 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.IDLE; 8197 } 8198 } 8199 break; 8200 default: 8201 break; 8202 } 8203 // check buffer 8204 // check/update current fragment 8205 this.onTickEnd(); 8206 }; 8207 _proto.onTickEnd = function onTickEnd() { 8208 _BaseStreamController.prototype.onTickEnd.call(this); 8209 this.checkBuffer(); 8210 this.checkFragmentChanged(); 8211 }; 8212 _proto.doTickIdle = function doTickIdle() { 8213 var hls = this.hls, 8214 levelLastLoaded = this.levelLastLoaded, 8215 levels = this.levels, 8216 media = this.media; 8217 var config = hls.config, 8218 level = hls.nextLoadLevel; 8219 8220 // if start level not parsed yet OR 8221 // if video not attached AND start fragment already requested OR start frag prefetch not enabled 8222 // exit loop, as we either need more info (level not parsed) or we need media to be attached to load new fragment 8223 if (levelLastLoaded === null || !media && (this.startFragRequested || !config.startFragPrefetch)) { 8224 return; 8225 } 8226 8227 // If the "main" level is audio-only but we are loading an alternate track in the same group, do not load anything 8228 if (this.altAudio && this.audioOnly) { 8229 return; 8230 } 8231 if (!levels || !levels[level]) { 8232 return; 8233 } 8234 var levelInfo = levels[level]; 8235 8236 // if buffer length is less than maxBufLen try to load a new fragment 8237 8238 var bufferInfo = this.getMainFwdBufferInfo(); 8239 if (bufferInfo === null) { 8240 return; 8241 } 8242 var lastDetails = this.getLevelDetails(); 8243 if (lastDetails && this._streamEnded(bufferInfo, lastDetails)) { 8244 var data = {}; 8245 if (this.altAudio) { 8246 data.type = 'video'; 8247 } 8248 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_3__.Events.BUFFER_EOS, data); 8249 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.ENDED; 8250 return; 8251 } 8252 8253 // set next load level : this will trigger a playlist load if needed 8254 this.level = hls.nextLoadLevel = level; 8255 var levelDetails = levelInfo.details; 8256 // if level info not retrieved yet, switch state and wait for level retrieval 8257 // if live playlist, ensure that new playlist has been refreshed to avoid loading/try to load 8258 // a useless and outdated fragment (that might even introduce load error if it is already out of the live playlist) 8259 if (!levelDetails || this.state === _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.WAITING_LEVEL || levelDetails.live && this.levelLastLoaded !== level) { 8260 this.level = level; 8261 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.WAITING_LEVEL; 8262 return; 8263 } 8264 var bufferLen = bufferInfo.len; 8265 8266 // compute max Buffer Length that we could get from this load level, based on level bitrate. don't buffer more than 60 MB and more than 30s 8267 var maxBufLen = this.getMaxBufferLength(levelInfo.maxBitrate); 8268 8269 // Stay idle if we are still with buffer margins 8270 if (bufferLen >= maxBufLen) { 8271 return; 8272 } 8273 if (this.backtrackFragment && this.backtrackFragment.start > bufferInfo.end) { 8274 this.backtrackFragment = null; 8275 } 8276 var targetBufferTime = this.backtrackFragment ? this.backtrackFragment.start : bufferInfo.end; 8277 var frag = this.getNextFragment(targetBufferTime, levelDetails); 8278 // Avoid backtracking by loading an earlier segment in streams with segments that do not start with a key frame (flagged by `couldBacktrack`) 8279 if (this.couldBacktrack && !this.fragPrevious && frag && frag.sn !== 'initSegment' && this.fragmentTracker.getState(frag) !== _fragment_tracker__WEBPACK_IMPORTED_MODULE_5__.FragmentState.OK) { 8280 var _this$backtrackFragme; 8281 var backtrackSn = ((_this$backtrackFragme = this.backtrackFragment) != null ? _this$backtrackFragme : frag).sn; 8282 var fragIdx = backtrackSn - levelDetails.startSN; 8283 var backtrackFrag = levelDetails.fragments[fragIdx - 1]; 8284 if (backtrackFrag && frag.cc === backtrackFrag.cc) { 8285 frag = backtrackFrag; 8286 this.fragmentTracker.removeFragment(backtrackFrag); 8287 } 8288 } else if (this.backtrackFragment && bufferInfo.len) { 8289 this.backtrackFragment = null; 8290 } 8291 // Avoid loop loading by using nextLoadPosition set for backtracking 8292 if (frag && this.fragmentTracker.getState(frag) === _fragment_tracker__WEBPACK_IMPORTED_MODULE_5__.FragmentState.OK && this.nextLoadPosition > targetBufferTime) { 8293 // Cleanup the fragment tracker before trying to find the next unbuffered fragment 8294 var type = this.audioOnly && !this.altAudio ? _loader_fragment__WEBPACK_IMPORTED_MODULE_7__.ElementaryStreamTypes.AUDIO : _loader_fragment__WEBPACK_IMPORTED_MODULE_7__.ElementaryStreamTypes.VIDEO; 8295 var mediaBuffer = (type === _loader_fragment__WEBPACK_IMPORTED_MODULE_7__.ElementaryStreamTypes.VIDEO ? this.videoBuffer : this.mediaBuffer) || this.media; 8296 if (mediaBuffer) { 8297 this.afterBufferFlushed(mediaBuffer, type, _types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistLevelType.MAIN); 8298 } 8299 frag = this.getNextFragment(this.nextLoadPosition, levelDetails); 8300 } 8301 if (!frag) { 8302 return; 8303 } 8304 if (frag.initSegment && !frag.initSegment.data && !this.bitrateTest) { 8305 frag = frag.initSegment; 8306 } 8307 this.loadFragment(frag, levelDetails, targetBufferTime); 8308 }; 8309 _proto.loadFragment = function loadFragment(frag, levelDetails, targetBufferTime) { 8310 var _this$media2; 8311 // Check if fragment is not loaded 8312 var fragState = this.fragmentTracker.getState(frag); 8313 this.fragCurrent = frag; 8314 if (fragState === _fragment_tracker__WEBPACK_IMPORTED_MODULE_5__.FragmentState.NOT_LOADED) { 8315 if (frag.sn === 'initSegment') { 8316 this._loadInitSegment(frag, levelDetails); 8317 } else if (this.bitrateTest) { 8318 this.log("Fragment " + frag.sn + " of level " + frag.level + " is being downloaded to test bitrate and will not be buffered"); 8319 this._loadBitrateTestFrag(frag, levelDetails); 8320 } else { 8321 this.startFragRequested = true; 8322 _BaseStreamController.prototype.loadFragment.call(this, frag, levelDetails, targetBufferTime); 8323 } 8324 } else if (fragState === _fragment_tracker__WEBPACK_IMPORTED_MODULE_5__.FragmentState.APPENDING) { 8325 // Lower the buffer size and try again 8326 if (this.reduceMaxBufferLength(frag.duration)) { 8327 this.fragmentTracker.removeFragment(frag); 8328 } 8329 } else if (((_this$media2 = this.media) === null || _this$media2 === void 0 ? void 0 : _this$media2.buffered.length) === 0) { 8330 // Stop gap for bad tracker / buffer flush behavior 8331 this.fragmentTracker.removeAllFragments(); 8332 } 8333 }; 8334 _proto.getAppendedFrag = function getAppendedFrag(position) { 8335 var fragOrPart = this.fragmentTracker.getAppendedFrag(position, _types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistLevelType.MAIN); 8336 if (fragOrPart && 'fragment' in fragOrPart) { 8337 return fragOrPart.fragment; 8338 } 8339 return fragOrPart; 8340 }; 8341 _proto.getBufferedFrag = function getBufferedFrag(position) { 8342 return this.fragmentTracker.getBufferedFrag(position, _types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistLevelType.MAIN); 8343 }; 8344 _proto.followingBufferedFrag = function followingBufferedFrag(frag) { 8345 if (frag) { 8346 // try to get range of next fragment (500ms after this range) 8347 return this.getBufferedFrag(frag.end + 0.5); 8348 } 8349 return null; 8350 } 8351 8352 /* 8353 on immediate level switch : 8354 - pause playback if playing 8355 - cancel any pending load request 8356 - and trigger a buffer flush 8357 */; 8358 _proto.immediateLevelSwitch = function immediateLevelSwitch() { 8359 this.abortCurrentFrag(); 8360 this.flushMainBuffer(0, Number.POSITIVE_INFINITY); 8361 } 8362 8363 /** 8364 * try to switch ASAP without breaking video playback: 8365 * in order to ensure smooth but quick level switching, 8366 * we need to find the next flushable buffer range 8367 * we should take into account new segment fetch time 8368 */; 8369 _proto.nextLevelSwitch = function nextLevelSwitch() { 8370 var levels = this.levels, 8371 media = this.media; 8372 // ensure that media is defined and that metadata are available (to retrieve currentTime) 8373 if (media !== null && media !== void 0 && media.readyState) { 8374 var fetchdelay; 8375 var fragPlayingCurrent = this.getAppendedFrag(media.currentTime); 8376 if (fragPlayingCurrent && fragPlayingCurrent.start > 1) { 8377 // flush buffer preceding current fragment (flush until current fragment start offset) 8378 // minus 1s to avoid video freezing, that could happen if we flush keyframe of current video ... 8379 this.flushMainBuffer(0, fragPlayingCurrent.start - 1); 8380 } 8381 if (!media.paused && levels) { 8382 // add a safety delay of 1s 8383 var nextLevelId = this.hls.nextLoadLevel; 8384 var nextLevel = levels[nextLevelId]; 8385 var fragLastKbps = this.fragLastKbps; 8386 if (fragLastKbps && this.fragCurrent) { 8387 fetchdelay = this.fragCurrent.duration * nextLevel.maxBitrate / (1000 * fragLastKbps) + 1; 8388 } else { 8389 fetchdelay = 0; 8390 } 8391 } else { 8392 fetchdelay = 0; 8393 } 8394 // this.log('fetchdelay:'+fetchdelay); 8395 // find buffer range that will be reached once new fragment will be fetched 8396 var bufferedFrag = this.getBufferedFrag(media.currentTime + fetchdelay); 8397 if (bufferedFrag) { 8398 // we can flush buffer range following this one without stalling playback 8399 var nextBufferedFrag = this.followingBufferedFrag(bufferedFrag); 8400 if (nextBufferedFrag) { 8401 // if we are here, we can also cancel any loading/demuxing in progress, as they are useless 8402 this.abortCurrentFrag(); 8403 // start flush position is in next buffered frag. Leave some padding for non-independent segments and smoother playback. 8404 var maxStart = nextBufferedFrag.maxStartPTS ? nextBufferedFrag.maxStartPTS : nextBufferedFrag.start; 8405 var fragDuration = nextBufferedFrag.duration; 8406 var startPts = Math.max(bufferedFrag.end, maxStart + Math.min(Math.max(fragDuration - this.config.maxFragLookUpTolerance, fragDuration * 0.5), fragDuration * 0.75)); 8407 this.flushMainBuffer(startPts, Number.POSITIVE_INFINITY); 8408 } 8409 } 8410 } 8411 }; 8412 _proto.abortCurrentFrag = function abortCurrentFrag() { 8413 var fragCurrent = this.fragCurrent; 8414 this.fragCurrent = null; 8415 this.backtrackFragment = null; 8416 if (fragCurrent) { 8417 fragCurrent.abortRequests(); 8418 } 8419 switch (this.state) { 8420 case _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.KEY_LOADING: 8421 case _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.FRAG_LOADING: 8422 case _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.FRAG_LOADING_WAITING_RETRY: 8423 case _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.PARSING: 8424 case _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.PARSED: 8425 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.IDLE; 8426 break; 8427 } 8428 this.nextLoadPosition = this.getLoadPosition(); 8429 }; 8430 _proto.flushMainBuffer = function flushMainBuffer(startOffset, endOffset) { 8431 _BaseStreamController.prototype.flushMainBuffer.call(this, startOffset, endOffset, this.altAudio ? 'video' : null); 8432 }; 8433 _proto.onMediaAttached = function onMediaAttached(event, data) { 8434 _BaseStreamController.prototype.onMediaAttached.call(this, event, data); 8435 var media = data.media; 8436 this.onvplaying = this.onMediaPlaying.bind(this); 8437 this.onvseeked = this.onMediaSeeked.bind(this); 8438 media.addEventListener('playing', this.onvplaying); 8439 media.addEventListener('seeked', this.onvseeked); 8440 this.gapController = new _gap_controller__WEBPACK_IMPORTED_MODULE_10__["default"](this.config, media, this.fragmentTracker, this.hls); 8441 }; 8442 _proto.onMediaDetaching = function onMediaDetaching() { 8443 var media = this.media; 8444 if (media && this.onvplaying && this.onvseeked) { 8445 media.removeEventListener('playing', this.onvplaying); 8446 media.removeEventListener('seeked', this.onvseeked); 8447 this.onvplaying = this.onvseeked = null; 8448 this.videoBuffer = null; 8449 } 8450 this.fragPlaying = null; 8451 if (this.gapController) { 8452 this.gapController.destroy(); 8453 this.gapController = null; 8454 } 8455 _BaseStreamController.prototype.onMediaDetaching.call(this); 8456 }; 8457 _proto.onMediaPlaying = function onMediaPlaying() { 8458 // tick to speed up FRAG_CHANGED triggering 8459 this.tick(); 8460 }; 8461 _proto.onMediaSeeked = function onMediaSeeked() { 8462 var media = this.media; 8463 var currentTime = media ? media.currentTime : null; 8464 if ((0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(currentTime)) { 8465 this.log("Media seeked to " + currentTime.toFixed(3)); 8466 } 8467 8468 // tick to speed up FRAG_CHANGED triggering 8469 this.tick(); 8470 }; 8471 _proto.onManifestLoading = function onManifestLoading() { 8472 // reset buffer on manifest loading 8473 this.log('Trigger BUFFER_RESET'); 8474 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_3__.Events.BUFFER_RESET, undefined); 8475 this.fragmentTracker.removeAllFragments(); 8476 this.couldBacktrack = false; 8477 this.startPosition = this.lastCurrentTime = 0; 8478 this.fragPlaying = null; 8479 this.backtrackFragment = null; 8480 }; 8481 _proto.onManifestParsed = function onManifestParsed(event, data) { 8482 var aac = false; 8483 var heaac = false; 8484 var codec; 8485 data.levels.forEach(function (level) { 8486 // detect if we have different kind of audio codecs used amongst playlists 8487 codec = level.audioCodec; 8488 if (codec) { 8489 if (codec.indexOf('mp4a.40.2') !== -1) { 8490 aac = true; 8491 } 8492 if (codec.indexOf('mp4a.40.5') !== -1) { 8493 heaac = true; 8494 } 8495 } 8496 }); 8497 this.audioCodecSwitch = aac && heaac && !(0,_is_supported__WEBPACK_IMPORTED_MODULE_2__.changeTypeSupported)(); 8498 if (this.audioCodecSwitch) { 8499 this.log('Both AAC/HE-AAC audio found in levels; declaring level codec as HE-AAC'); 8500 } 8501 this.levels = data.levels; 8502 this.startFragRequested = false; 8503 }; 8504 _proto.onLevelLoading = function onLevelLoading(event, data) { 8505 var levels = this.levels; 8506 if (!levels || this.state !== _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.IDLE) { 8507 return; 8508 } 8509 var level = levels[data.level]; 8510 if (!level.details || level.details.live && this.levelLastLoaded !== data.level || this.waitForCdnTuneIn(level.details)) { 8511 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.WAITING_LEVEL; 8512 } 8513 }; 8514 _proto.onLevelLoaded = function onLevelLoaded(event, data) { 8515 var _curLevel$details; 8516 var levels = this.levels; 8517 var newLevelId = data.level; 8518 var newDetails = data.details; 8519 var duration = newDetails.totalduration; 8520 if (!levels) { 8521 this.warn("Levels were reset while loading level " + newLevelId); 8522 return; 8523 } 8524 this.log("Level " + newLevelId + " loaded [" + newDetails.startSN + "," + newDetails.endSN + "], cc [" + newDetails.startCC + ", " + newDetails.endCC + "] duration:" + duration); 8525 var fragCurrent = this.fragCurrent; 8526 if (fragCurrent && (this.state === _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.FRAG_LOADING || this.state === _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.FRAG_LOADING_WAITING_RETRY)) { 8527 if (fragCurrent.level !== data.level && fragCurrent.loader) { 8528 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.IDLE; 8529 this.backtrackFragment = null; 8530 fragCurrent.abortRequests(); 8531 } 8532 } 8533 var curLevel = levels[newLevelId]; 8534 var sliding = 0; 8535 if (newDetails.live || (_curLevel$details = curLevel.details) !== null && _curLevel$details !== void 0 && _curLevel$details.live) { 8536 if (!newDetails.fragments[0]) { 8537 newDetails.deltaUpdateFailed = true; 8538 } 8539 if (newDetails.deltaUpdateFailed) { 8540 return; 8541 } 8542 sliding = this.alignPlaylists(newDetails, curLevel.details); 8543 } 8544 // override level info 8545 curLevel.details = newDetails; 8546 this.levelLastLoaded = newLevelId; 8547 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_3__.Events.LEVEL_UPDATED, { 8548 details: newDetails, 8549 level: newLevelId 8550 }); 8551 8552 // only switch back to IDLE state if we were waiting for level to start downloading a new fragment 8553 if (this.state === _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.WAITING_LEVEL) { 8554 if (this.waitForCdnTuneIn(newDetails)) { 8555 // Wait for Low-Latency CDN Tune-in 8556 return; 8557 } 8558 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.IDLE; 8559 } 8560 if (!this.startFragRequested) { 8561 this.setStartPosition(newDetails, sliding); 8562 } else if (newDetails.live) { 8563 this.synchronizeToLiveEdge(newDetails); 8564 } 8565 8566 // trigger handler right now 8567 this.tick(); 8568 }; 8569 _proto._handleFragmentLoadProgress = function _handleFragmentLoadProgress(data) { 8570 var _frag$initSegment; 8571 var frag = data.frag, 8572 part = data.part, 8573 payload = data.payload; 8574 var levels = this.levels; 8575 if (!levels) { 8576 this.warn("Levels were reset while fragment load was in progress. Fragment " + frag.sn + " of level " + frag.level + " will not be buffered"); 8577 return; 8578 } 8579 var currentLevel = levels[frag.level]; 8580 var details = currentLevel.details; 8581 if (!details) { 8582 this.warn("Dropping fragment " + frag.sn + " of level " + frag.level + " after level details were reset"); 8583 return; 8584 } 8585 var videoCodec = currentLevel.videoCodec; 8586 8587 // time Offset is accurate if level PTS is known, or if playlist is not sliding (not live) 8588 var accurateTimeOffset = details.PTSKnown || !details.live; 8589 var initSegmentData = (_frag$initSegment = frag.initSegment) === null || _frag$initSegment === void 0 ? void 0 : _frag$initSegment.data; 8590 var audioCodec = this._getAudioCodec(currentLevel); 8591 8592 // transmux the MPEG-TS data to ISO-BMFF segments 8593 // this.log(`Transmuxing ${frag.sn} of [${details.startSN} ,${details.endSN}],level ${frag.level}, cc ${frag.cc}`); 8594 var transmuxer = this.transmuxer = this.transmuxer || new _demux_transmuxer_interface__WEBPACK_IMPORTED_MODULE_8__["default"](this.hls, _types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistLevelType.MAIN, this._handleTransmuxComplete.bind(this), this._handleTransmuxerFlush.bind(this)); 8595 var partIndex = part ? part.index : -1; 8596 var partial = partIndex !== -1; 8597 var chunkMeta = new _types_transmuxer__WEBPACK_IMPORTED_MODULE_9__.ChunkMetadata(frag.level, frag.sn, frag.stats.chunkCount, payload.byteLength, partIndex, partial); 8598 var initPTS = this.initPTS[frag.cc]; 8599 transmuxer.push(payload, initSegmentData, audioCodec, videoCodec, frag, part, details.totalduration, accurateTimeOffset, chunkMeta, initPTS); 8600 }; 8601 _proto.onAudioTrackSwitching = function onAudioTrackSwitching(event, data) { 8602 // if any URL found on new audio track, it is an alternate audio track 8603 var fromAltAudio = this.altAudio; 8604 var altAudio = !!data.url; 8605 var trackId = data.id; 8606 // if we switch on main audio, ensure that main fragment scheduling is synced with media.buffered 8607 // don't do anything if we switch to alt audio: audio stream controller is handling it. 8608 // we will just have to change buffer scheduling on audioTrackSwitched 8609 if (!altAudio) { 8610 if (this.mediaBuffer !== this.media) { 8611 this.log('Switching on main audio, use media.buffered to schedule main fragment loading'); 8612 this.mediaBuffer = this.media; 8613 var fragCurrent = this.fragCurrent; 8614 // we need to refill audio buffer from main: cancel any frag loading to speed up audio switch 8615 if (fragCurrent) { 8616 this.log('Switching to main audio track, cancel main fragment load'); 8617 fragCurrent.abortRequests(); 8618 } 8619 // destroy transmuxer to force init segment generation (following audio switch) 8620 this.resetTransmuxer(); 8621 // switch to IDLE state to load new fragment 8622 this.resetLoadingState(); 8623 } else if (this.audioOnly) { 8624 // Reset audio transmuxer so when switching back to main audio we're not still appending where we left off 8625 this.resetTransmuxer(); 8626 } 8627 var hls = this.hls; 8628 // If switching from alt to main audio, flush all audio and trigger track switched 8629 if (fromAltAudio) { 8630 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_3__.Events.BUFFER_FLUSHING, { 8631 startOffset: 0, 8632 endOffset: Number.POSITIVE_INFINITY, 8633 type: 'audio' 8634 }); 8635 } 8636 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_3__.Events.AUDIO_TRACK_SWITCHED, { 8637 id: trackId 8638 }); 8639 } 8640 }; 8641 _proto.onAudioTrackSwitched = function onAudioTrackSwitched(event, data) { 8642 var trackId = data.id; 8643 var altAudio = !!this.hls.audioTracks[trackId].url; 8644 if (altAudio) { 8645 var videoBuffer = this.videoBuffer; 8646 // if we switched on alternate audio, ensure that main fragment scheduling is synced with video sourcebuffer buffered 8647 if (videoBuffer && this.mediaBuffer !== videoBuffer) { 8648 this.log('Switching on alternate audio, use video.buffered to schedule main fragment loading'); 8649 this.mediaBuffer = videoBuffer; 8650 } 8651 } 8652 this.altAudio = altAudio; 8653 this.tick(); 8654 }; 8655 _proto.onBufferCreated = function onBufferCreated(event, data) { 8656 var tracks = data.tracks; 8657 var mediaTrack; 8658 var name; 8659 var alternate = false; 8660 for (var type in tracks) { 8661 var track = tracks[type]; 8662 if (track.id === 'main') { 8663 name = type; 8664 mediaTrack = track; 8665 // keep video source buffer reference 8666 if (type === 'video') { 8667 var videoTrack = tracks[type]; 8668 if (videoTrack) { 8669 this.videoBuffer = videoTrack.buffer; 8670 } 8671 } 8672 } else { 8673 alternate = true; 8674 } 8675 } 8676 if (alternate && mediaTrack) { 8677 this.log("Alternate track found, use " + name + ".buffered to schedule main fragment loading"); 8678 this.mediaBuffer = mediaTrack.buffer; 8679 } else { 8680 this.mediaBuffer = this.media; 8681 } 8682 }; 8683 _proto.onFragBuffered = function onFragBuffered(event, data) { 8684 var frag = data.frag, 8685 part = data.part; 8686 if (frag && frag.type !== _types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistLevelType.MAIN) { 8687 return; 8688 } 8689 if (this.fragContextChanged(frag)) { 8690 // If a level switch was requested while a fragment was buffering, it will emit the FRAG_BUFFERED event upon completion 8691 // Avoid setting state back to IDLE, since that will interfere with a level switch 8692 this.warn("Fragment " + frag.sn + (part ? ' p: ' + part.index : '') + " of level " + frag.level + " finished buffering, but was aborted. state: " + this.state); 8693 if (this.state === _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.PARSED) { 8694 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.IDLE; 8695 } 8696 return; 8697 } 8698 var stats = part ? part.stats : frag.stats; 8699 this.fragLastKbps = Math.round(8 * stats.total / (stats.buffering.end - stats.loading.first)); 8700 if (frag.sn !== 'initSegment') { 8701 this.fragPrevious = frag; 8702 } 8703 this.fragBufferedComplete(frag, part); 8704 }; 8705 _proto.onError = function onError(event, data) { 8706 if (data.type === _errors__WEBPACK_IMPORTED_MODULE_11__.ErrorTypes.KEY_SYSTEM_ERROR) { 8707 this.onFragmentOrKeyLoadError(_types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistLevelType.MAIN, data); 8708 return; 8709 } 8710 switch (data.details) { 8711 case _errors__WEBPACK_IMPORTED_MODULE_11__.ErrorDetails.FRAG_LOAD_ERROR: 8712 case _errors__WEBPACK_IMPORTED_MODULE_11__.ErrorDetails.FRAG_LOAD_TIMEOUT: 8713 case _errors__WEBPACK_IMPORTED_MODULE_11__.ErrorDetails.FRAG_PARSING_ERROR: 8714 case _errors__WEBPACK_IMPORTED_MODULE_11__.ErrorDetails.KEY_LOAD_ERROR: 8715 case _errors__WEBPACK_IMPORTED_MODULE_11__.ErrorDetails.KEY_LOAD_TIMEOUT: 8716 this.onFragmentOrKeyLoadError(_types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistLevelType.MAIN, data); 8717 break; 8718 case _errors__WEBPACK_IMPORTED_MODULE_11__.ErrorDetails.LEVEL_LOAD_ERROR: 8719 case _errors__WEBPACK_IMPORTED_MODULE_11__.ErrorDetails.LEVEL_LOAD_TIMEOUT: 8720 if (this.state !== _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.ERROR) { 8721 if (data.fatal) { 8722 // if fatal error, stop processing 8723 this.warn("" + data.details); 8724 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.ERROR; 8725 } else { 8726 // in case of non fatal error while loading level, if level controller is not retrying to load level , switch back to IDLE 8727 if (!data.levelRetry && this.state === _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.WAITING_LEVEL) { 8728 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.IDLE; 8729 } 8730 } 8731 } 8732 break; 8733 case _errors__WEBPACK_IMPORTED_MODULE_11__.ErrorDetails.BUFFER_FULL_ERROR: 8734 // if in appending state 8735 if (data.parent === 'main' && (this.state === _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.PARSING || this.state === _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.PARSED)) { 8736 var flushBuffer = true; 8737 var bufferedInfo = this.getFwdBufferInfo(this.media, _types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistLevelType.MAIN); 8738 // 0.5 : tolerance needed as some browsers stalls playback before reaching buffered end 8739 // reduce max buf len if current position is buffered 8740 if (bufferedInfo && bufferedInfo.len > 0.5) { 8741 flushBuffer = !this.reduceMaxBufferLength(bufferedInfo.len); 8742 } 8743 if (flushBuffer) { 8744 // current position is not buffered, but browser is still complaining about buffer full error 8745 // this happens on IE/Edge, refer to https://github.com/video-dev/hls.js/pull/708 8746 // in that case flush the whole buffer to recover 8747 this.warn('buffer full error also media.currentTime is not buffered, flush main'); 8748 // flush main buffer 8749 this.immediateLevelSwitch(); 8750 } 8751 this.resetLoadingState(); 8752 } 8753 break; 8754 default: 8755 break; 8756 } 8757 } 8758 8759 // Checks the health of the buffer and attempts to resolve playback stalls. 8760 ; 8761 _proto.checkBuffer = function checkBuffer() { 8762 var media = this.media, 8763 gapController = this.gapController; 8764 if (!media || !gapController || !media.readyState) { 8765 // Exit early if we don't have media or if the media hasn't buffered anything yet (readyState 0) 8766 return; 8767 } 8768 if (this.loadedmetadata || !_utils_buffer_helper__WEBPACK_IMPORTED_MODULE_4__.BufferHelper.getBuffered(media).length) { 8769 // Resolve gaps using the main buffer, whose ranges are the intersections of the A/V sourcebuffers 8770 var activeFrag = this.state !== _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.IDLE ? this.fragCurrent : null; 8771 gapController.poll(this.lastCurrentTime, activeFrag); 8772 } 8773 this.lastCurrentTime = media.currentTime; 8774 }; 8775 _proto.onFragLoadEmergencyAborted = function onFragLoadEmergencyAborted() { 8776 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.IDLE; 8777 // if loadedmetadata is not set, it means that we are emergency switch down on first frag 8778 // in that case, reset startFragRequested flag 8779 if (!this.loadedmetadata) { 8780 this.startFragRequested = false; 8781 this.nextLoadPosition = this.startPosition; 8782 } 8783 this.tickImmediate(); 8784 }; 8785 _proto.onBufferFlushed = function onBufferFlushed(event, _ref) { 8786 var type = _ref.type; 8787 if (type !== _loader_fragment__WEBPACK_IMPORTED_MODULE_7__.ElementaryStreamTypes.AUDIO || this.audioOnly && !this.altAudio) { 8788 var mediaBuffer = (type === _loader_fragment__WEBPACK_IMPORTED_MODULE_7__.ElementaryStreamTypes.VIDEO ? this.videoBuffer : this.mediaBuffer) || this.media; 8789 this.afterBufferFlushed(mediaBuffer, type, _types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistLevelType.MAIN); 8790 } 8791 }; 8792 _proto.onLevelsUpdated = function onLevelsUpdated(event, data) { 8793 this.levels = data.levels; 8794 }; 8795 _proto.swapAudioCodec = function swapAudioCodec() { 8796 this.audioCodecSwap = !this.audioCodecSwap; 8797 } 8798 8799 /** 8800 * Seeks to the set startPosition if not equal to the mediaElement's current time. 8801 */; 8802 _proto.seekToStartPos = function seekToStartPos() { 8803 var media = this.media; 8804 if (!media) { 8805 return; 8806 } 8807 var currentTime = media.currentTime; 8808 var startPosition = this.startPosition; 8809 // only adjust currentTime if different from startPosition or if startPosition not buffered 8810 // at that stage, there should be only one buffered range, as we reach that code after first fragment has been buffered 8811 if (startPosition >= 0 && currentTime < startPosition) { 8812 if (media.seeking) { 8813 this.log("could not seek to " + startPosition + ", already seeking at " + currentTime); 8814 return; 8815 } 8816 var buffered = _utils_buffer_helper__WEBPACK_IMPORTED_MODULE_4__.BufferHelper.getBuffered(media); 8817 var bufferStart = buffered.length ? buffered.start(0) : 0; 8818 var delta = bufferStart - startPosition; 8819 if (delta > 0 && (delta < this.config.maxBufferHole || delta < this.config.maxFragLookUpTolerance)) { 8820 this.log("adjusting start position by " + delta + " to match buffer start"); 8821 startPosition += delta; 8822 this.startPosition = startPosition; 8823 } 8824 this.log("seek to target start position " + startPosition + " from current time " + currentTime); 8825 media.currentTime = startPosition; 8826 } 8827 }; 8828 _proto._getAudioCodec = function _getAudioCodec(currentLevel) { 8829 var audioCodec = this.config.defaultAudioCodec || currentLevel.audioCodec; 8830 if (this.audioCodecSwap && audioCodec) { 8831 this.log('Swapping audio codec'); 8832 if (audioCodec.indexOf('mp4a.40.5') !== -1) { 8833 audioCodec = 'mp4a.40.2'; 8834 } else { 8835 audioCodec = 'mp4a.40.5'; 8836 } 8837 } 8838 return audioCodec; 8839 }; 8840 _proto._loadBitrateTestFrag = function _loadBitrateTestFrag(frag, levelDetails) { 8841 var _this2 = this; 8842 frag.bitrateTest = true; 8843 this._doFragLoad(frag, levelDetails).then(function (data) { 8844 var hls = _this2.hls; 8845 if (!data || _this2.fragContextChanged(frag)) { 8846 return; 8847 } 8848 _this2.fragLoadError = 0; 8849 _this2.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.IDLE; 8850 _this2.startFragRequested = false; 8851 _this2.bitrateTest = false; 8852 var stats = frag.stats; 8853 // Bitrate tests fragments are neither parsed nor buffered 8854 stats.parsing.start = stats.parsing.end = stats.buffering.start = stats.buffering.end = self.performance.now(); 8855 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_3__.Events.FRAG_LOADED, data); 8856 frag.bitrateTest = false; 8857 }); 8858 }; 8859 _proto._handleTransmuxComplete = function _handleTransmuxComplete(transmuxResult) { 8860 var _id3$samples; 8861 var id = 'main'; 8862 var hls = this.hls; 8863 var remuxResult = transmuxResult.remuxResult, 8864 chunkMeta = transmuxResult.chunkMeta; 8865 var context = this.getCurrentContext(chunkMeta); 8866 if (!context) { 8867 this.warn("The loading context changed while buffering fragment " + chunkMeta.sn + " of level " + chunkMeta.level + ". This chunk will not be buffered."); 8868 this.resetStartWhenNotLoaded(chunkMeta.level); 8869 return; 8870 } 8871 var frag = context.frag, 8872 part = context.part, 8873 level = context.level; 8874 var video = remuxResult.video, 8875 text = remuxResult.text, 8876 id3 = remuxResult.id3, 8877 initSegment = remuxResult.initSegment; 8878 var details = level.details; 8879 // The audio-stream-controller handles audio buffering if Hls.js is playing an alternate audio track 8880 var audio = this.altAudio ? undefined : remuxResult.audio; 8881 8882 // Check if the current fragment has been aborted. We check this by first seeing if we're still playing the current level. 8883 // If we are, subsequently check if the currently loading fragment (fragCurrent) has changed. 8884 if (this.fragContextChanged(frag)) { 8885 return; 8886 } 8887 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.PARSING; 8888 if (initSegment) { 8889 if (initSegment.tracks) { 8890 this._bufferInitSegment(level, initSegment.tracks, frag, chunkMeta); 8891 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_3__.Events.FRAG_PARSING_INIT_SEGMENT, { 8892 frag: frag, 8893 id: id, 8894 tracks: initSegment.tracks 8895 }); 8896 } 8897 8898 // This would be nice if Number.isFinite acted as a typeguard, but it doesn't. See: https://github.com/Microsoft/TypeScript/issues/10038 8899 var initPTS = initSegment.initPTS; 8900 var timescale = initSegment.timescale; 8901 if ((0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(initPTS)) { 8902 this.initPTS[frag.cc] = initPTS; 8903 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_3__.Events.INIT_PTS_FOUND, { 8904 frag: frag, 8905 id: id, 8906 initPTS: initPTS, 8907 timescale: timescale 8908 }); 8909 } 8910 } 8911 8912 // Avoid buffering if backtracking this fragment 8913 if (video && remuxResult.independent !== false) { 8914 if (details) { 8915 var startPTS = video.startPTS, 8916 endPTS = video.endPTS, 8917 startDTS = video.startDTS, 8918 endDTS = video.endDTS; 8919 if (part) { 8920 part.elementaryStreams[video.type] = { 8921 startPTS: startPTS, 8922 endPTS: endPTS, 8923 startDTS: startDTS, 8924 endDTS: endDTS 8925 }; 8926 } else { 8927 if (video.firstKeyFrame && video.independent && chunkMeta.id === 1) { 8928 this.couldBacktrack = true; 8929 } 8930 if (video.dropped && video.independent) { 8931 // Backtrack if dropped frames create a gap after currentTime 8932 8933 var bufferInfo = this.getMainFwdBufferInfo(); 8934 var targetBufferTime = (bufferInfo ? bufferInfo.end : this.getLoadPosition()) + this.config.maxBufferHole; 8935 var startTime = video.firstKeyFramePTS ? video.firstKeyFramePTS : startPTS; 8936 if (targetBufferTime < startTime - this.config.maxBufferHole) { 8937 this.backtrack(frag); 8938 return; 8939 } 8940 // Set video stream start to fragment start so that truncated samples do not distort the timeline, and mark it partial 8941 frag.setElementaryStreamInfo(video.type, frag.start, endPTS, frag.start, endDTS, true); 8942 } 8943 } 8944 frag.setElementaryStreamInfo(video.type, startPTS, endPTS, startDTS, endDTS); 8945 if (this.backtrackFragment) { 8946 this.backtrackFragment = frag; 8947 } 8948 this.bufferFragmentData(video, frag, part, chunkMeta); 8949 } 8950 } else if (remuxResult.independent === false) { 8951 this.backtrack(frag); 8952 return; 8953 } 8954 if (audio) { 8955 var _startPTS = audio.startPTS, 8956 _endPTS = audio.endPTS, 8957 _startDTS = audio.startDTS, 8958 _endDTS = audio.endDTS; 8959 if (part) { 8960 part.elementaryStreams[_loader_fragment__WEBPACK_IMPORTED_MODULE_7__.ElementaryStreamTypes.AUDIO] = { 8961 startPTS: _startPTS, 8962 endPTS: _endPTS, 8963 startDTS: _startDTS, 8964 endDTS: _endDTS 8965 }; 8966 } 8967 frag.setElementaryStreamInfo(_loader_fragment__WEBPACK_IMPORTED_MODULE_7__.ElementaryStreamTypes.AUDIO, _startPTS, _endPTS, _startDTS, _endDTS); 8968 this.bufferFragmentData(audio, frag, part, chunkMeta); 8969 } 8970 if (details && id3 !== null && id3 !== void 0 && (_id3$samples = id3.samples) !== null && _id3$samples !== void 0 && _id3$samples.length) { 8971 var emittedID3 = { 8972 id: id, 8973 frag: frag, 8974 details: details, 8975 samples: id3.samples 8976 }; 8977 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_3__.Events.FRAG_PARSING_METADATA, emittedID3); 8978 } 8979 if (details && text) { 8980 var emittedText = { 8981 id: id, 8982 frag: frag, 8983 details: details, 8984 samples: text.samples 8985 }; 8986 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_3__.Events.FRAG_PARSING_USERDATA, emittedText); 8987 } 8988 }; 8989 _proto._bufferInitSegment = function _bufferInitSegment(currentLevel, tracks, frag, chunkMeta) { 8990 var _this3 = this; 8991 if (this.state !== _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.PARSING) { 8992 return; 8993 } 8994 this.audioOnly = !!tracks.audio && !tracks.video; 8995 8996 // if audio track is expected to come from audio stream controller, discard any coming from main 8997 if (this.altAudio && !this.audioOnly) { 8998 delete tracks.audio; 8999 } 9000 // include levelCodec in audio and video tracks 9001 var audio = tracks.audio, 9002 video = tracks.video, 9003 audiovideo = tracks.audiovideo; 9004 if (audio) { 9005 var audioCodec = currentLevel.audioCodec; 9006 var ua = navigator.userAgent.toLowerCase(); 9007 if (this.audioCodecSwitch) { 9008 if (audioCodec) { 9009 if (audioCodec.indexOf('mp4a.40.5') !== -1) { 9010 audioCodec = 'mp4a.40.2'; 9011 } else { 9012 audioCodec = 'mp4a.40.5'; 9013 } 9014 } 9015 // In the case that AAC and HE-AAC audio codecs are signalled in manifest, 9016 // force HE-AAC, as it seems that most browsers prefers it. 9017 // don't force HE-AAC if mono stream, or in Firefox 9018 if (audio.metadata.channelCount !== 1 && ua.indexOf('firefox') === -1) { 9019 audioCodec = 'mp4a.40.5'; 9020 } 9021 } 9022 // HE-AAC is broken on Android, always signal audio codec as AAC even if variant manifest states otherwise 9023 if (ua.indexOf('android') !== -1 && audio.container !== 'audio/mpeg') { 9024 // Exclude mpeg audio 9025 audioCodec = 'mp4a.40.2'; 9026 this.log("Android: force audio codec to " + audioCodec); 9027 } 9028 if (currentLevel.audioCodec && currentLevel.audioCodec !== audioCodec) { 9029 this.log("Swapping manifest audio codec \"" + currentLevel.audioCodec + "\" for \"" + audioCodec + "\""); 9030 } 9031 audio.levelCodec = audioCodec; 9032 audio.id = 'main'; 9033 this.log("Init audio buffer, container:" + audio.container + ", codecs[selected/level/parsed]=[" + (audioCodec || '') + "/" + (currentLevel.audioCodec || '') + "/" + audio.codec + "]"); 9034 } 9035 if (video) { 9036 video.levelCodec = currentLevel.videoCodec; 9037 video.id = 'main'; 9038 this.log("Init video buffer, container:" + video.container + ", codecs[level/parsed]=[" + (currentLevel.videoCodec || '') + "/" + video.codec + "]"); 9039 } 9040 if (audiovideo) { 9041 this.log("Init audiovideo buffer, container:" + audiovideo.container + ", codecs[level/parsed]=[" + (currentLevel.attrs.CODECS || '') + "/" + audiovideo.codec + "]"); 9042 } 9043 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_3__.Events.BUFFER_CODECS, tracks); 9044 // loop through tracks that are going to be provided to bufferController 9045 Object.keys(tracks).forEach(function (trackName) { 9046 var track = tracks[trackName]; 9047 var initSegment = track.initSegment; 9048 if (initSegment !== null && initSegment !== void 0 && initSegment.byteLength) { 9049 _this3.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_3__.Events.BUFFER_APPENDING, { 9050 type: trackName, 9051 data: initSegment, 9052 frag: frag, 9053 part: null, 9054 chunkMeta: chunkMeta, 9055 parent: frag.type 9056 }); 9057 } 9058 }); 9059 // trigger handler right now 9060 this.tick(); 9061 }; 9062 _proto.getMainFwdBufferInfo = function getMainFwdBufferInfo() { 9063 return this.getFwdBufferInfo(this.mediaBuffer ? this.mediaBuffer : this.media, _types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistLevelType.MAIN); 9064 }; 9065 _proto.backtrack = function backtrack(frag) { 9066 this.couldBacktrack = true; 9067 // Causes findFragments to backtrack through fragments to find the keyframe 9068 this.backtrackFragment = frag; 9069 this.resetTransmuxer(); 9070 this.flushBufferGap(frag); 9071 this.fragmentTracker.removeFragment(frag); 9072 this.fragPrevious = null; 9073 this.nextLoadPosition = frag.start; 9074 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_1__.State.IDLE; 9075 }; 9076 _proto.checkFragmentChanged = function checkFragmentChanged() { 9077 var video = this.media; 9078 var fragPlayingCurrent = null; 9079 if (video && video.readyState > 1 && video.seeking === false) { 9080 var currentTime = video.currentTime; 9081 /* if video element is in seeked state, currentTime can only increase. 9082 (assuming that playback rate is positive ...) 9083 As sometimes currentTime jumps back to zero after a 9084 media decode error, check this, to avoid seeking back to 9085 wrong position after a media decode error 9086 */ 9087 9088 if (_utils_buffer_helper__WEBPACK_IMPORTED_MODULE_4__.BufferHelper.isBuffered(video, currentTime)) { 9089 fragPlayingCurrent = this.getAppendedFrag(currentTime); 9090 } else if (_utils_buffer_helper__WEBPACK_IMPORTED_MODULE_4__.BufferHelper.isBuffered(video, currentTime + 0.1)) { 9091 /* ensure that FRAG_CHANGED event is triggered at startup, 9092 when first video frame is displayed and playback is paused. 9093 add a tolerance of 100ms, in case current position is not buffered, 9094 check if current pos+100ms is buffered and use that buffer range 9095 for FRAG_CHANGED event reporting */ 9096 fragPlayingCurrent = this.getAppendedFrag(currentTime + 0.1); 9097 } 9098 if (fragPlayingCurrent) { 9099 this.backtrackFragment = null; 9100 var fragPlaying = this.fragPlaying; 9101 var fragCurrentLevel = fragPlayingCurrent.level; 9102 if (!fragPlaying || fragPlayingCurrent.sn !== fragPlaying.sn || fragPlaying.level !== fragCurrentLevel || fragPlayingCurrent.urlId !== fragPlaying.urlId) { 9103 this.fragPlaying = fragPlayingCurrent; 9104 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_3__.Events.FRAG_CHANGED, { 9105 frag: fragPlayingCurrent 9106 }); 9107 if (!fragPlaying || fragPlaying.level !== fragCurrentLevel) { 9108 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_3__.Events.LEVEL_SWITCHED, { 9109 level: fragCurrentLevel 9110 }); 9111 } 9112 } 9113 } 9114 } 9115 }; 9116 _createClass(StreamController, [{ 9117 key: "nextLevel", 9118 get: function get() { 9119 var frag = this.nextBufferedFrag; 9120 if (frag) { 9121 return frag.level; 9122 } 9123 return -1; 9124 } 9125 }, { 9126 key: "currentFrag", 9127 get: function get() { 9128 var media = this.media; 9129 if (media) { 9130 return this.fragPlaying || this.getAppendedFrag(media.currentTime); 9131 } 9132 return null; 9133 } 9134 }, { 9135 key: "currentProgramDateTime", 9136 get: function get() { 9137 var media = this.media; 9138 if (media) { 9139 var currentTime = media.currentTime; 9140 var frag = this.currentFrag; 9141 if (frag && (0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(currentTime) && (0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(frag.programDateTime)) { 9142 var epocMs = frag.programDateTime + (currentTime - frag.start) * 1000; 9143 return new Date(epocMs); 9144 } 9145 } 9146 return null; 9147 } 9148 }, { 9149 key: "currentLevel", 9150 get: function get() { 9151 var frag = this.currentFrag; 9152 if (frag) { 9153 return frag.level; 9154 } 9155 return -1; 9156 } 9157 }, { 9158 key: "nextBufferedFrag", 9159 get: function get() { 9160 var frag = this.currentFrag; 9161 if (frag) { 9162 return this.followingBufferedFrag(frag); 9163 } 9164 return null; 9165 } 9166 }, { 9167 key: "forceStartLoad", 9168 get: function get() { 9169 return this._forceStartLoad; 9170 } 9171 }]); 9172 return StreamController; 9173}(_base_stream_controller__WEBPACK_IMPORTED_MODULE_1__["default"]); 9174 9175 9176/***/ }), 9177 9178/***/ "./src/c
vendor: 4,349 bytes, lines 9178-9234
9178ontroller/subtitle-stream-controller.ts": 9179/*!******************************************************!*\ 9180 !*** ./src/controller/subtitle-stream-controller.ts ***! 9181 \******************************************************/ 9182/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 9183 9184"use strict"; 9185__webpack_require__.r(__webpack_exports__); 9186/* harmony export */ __webpack_require__.d(__webpack_exports__, { 9187/* harmony export */ "SubtitleStreamController": () => (/* binding */ SubtitleStreamController) 9188/* harmony export */ }); 9189/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 9190/* harmony import */ var _utils_buffer_helper__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils/buffer-helper */ "./src/utils/buffer-helper.ts"); 9191/* harmony import */ var _fragment_finders__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./fragment-finders */ "./src/controller/fragment-finders.ts"); 9192/* harmony import */ var _utils_discontinuities__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils/discontinuities */ "./src/utils/discontinuities.ts"); 9193/* harmony import */ var _level_helper__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./level-helper */ "./src/controller/level-helper.ts"); 9194/* harmony import */ var _fragment_tracker__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./fragment-tracker */ "./src/controller/fragment-tracker.ts"); 9195/* harmony import */ var _base_stream_controller__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./base-stream-controller */ "./src/controller/base-stream-controller.ts"); 9196/* harmony import */ var _types_loader__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../types/loader */ "./src/types/loader.ts"); 9197/* harmony import */ var _types_level__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../types/level */ "./src/types/level.ts"); 9198function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } 9199function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } 9200function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } 9201function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } 9202function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); } 9203function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } 9204 9205 9206 9207 9208 9209 9210 9211 9212 9213var TICK_INTERVAL = 500; // how often to tick in ms 9214 9215var SubtitleStreamController = /*#__PURE__*/function (_BaseStreamController) { 9216 _inheritsLoose(SubtitleStreamController, _BaseStreamController); 9217 function SubtitleStreamController(hls, fragmentTracker, keyLoader) { 9218 var _this; 9219 _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '[subtitle-stream-controller]') || this; 9220 _this.levels = []; 9221 _this.currentTrackId = -1; 9222 _this.tracksBuffered = []; 9223 _this.mainDetails = null; 9224 _this._registerListeners(); 9225 return _this; 9226 } 9227 var _proto = SubtitleStreamController.prototype; 9228 _proto.onHandlerDestroying = function onHandlerDestroying() { 9229 this._unregisterListeners(); 9230 this.mainDetails = null; 9231 }; 9232 _proto._registerListeners = function _registerListeners() { 9233 var hls = this.hls; 9234 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MEDIA_ATTA
vendor: 4,371 bytes, lines 9234-9317
9234CHED, this.onMediaAttached, this); 9235 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MEDIA_DETACHING, this.onMediaDetaching, this); 9236 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MANIFEST_LOADING, this.onManifestLoading, this); 9237 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.LEVEL_LOADED, this.onLevelLoaded, this); 9238 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.ERROR, this.onError, this); 9239 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this); 9240 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this); 9241 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this); 9242 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.SUBTITLE_FRAG_PROCESSED, this.onSubtitleFragProcessed, this); 9243 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.BUFFER_FLUSHING, this.onBufferFlushing, this); 9244 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.FRAG_BUFFERED, this.onFragBuffered, this); 9245 }; 9246 _proto._unregisterListeners = function _unregisterListeners() { 9247 var hls = this.hls; 9248 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MEDIA_ATTACHED, this.onMediaAttached, this); 9249 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MEDIA_DETACHING, this.onMediaDetaching, this); 9250 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MANIFEST_LOADING, this.onManifestLoading, this); 9251 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.LEVEL_LOADED, this.onLevelLoaded, this); 9252 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.ERROR, this.onError, this); 9253 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this); 9254 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this); 9255 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this); 9256 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.SUBTITLE_FRAG_PROCESSED, this.onSubtitleFragProcessed, this); 9257 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.BUFFER_FLUSHING, this.onBufferFlushing, this); 9258 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.FRAG_BUFFERED, this.onFragBuffered, this); 9259 }; 9260 _proto.startLoad = function startLoad(startPosition) { 9261 this.stopLoad(); 9262 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_6__.State.IDLE; 9263 this.setInterval(TICK_INTERVAL); 9264 this.nextLoadPosition = this.startPosition = this.lastCurrentTime = startPosition; 9265 this.tick(); 9266 }; 9267 _proto.onManifestLoading = function onManifestLoading() { 9268 this.mainDetails = null; 9269 this.fragmentTracker.removeAllFragments(); 9270 }; 9271 _proto.onLevelLoaded = function onLevelLoaded(event, data) { 9272 this.mainDetails = data.details; 9273 }; 9274 _proto.onSubtitleFragProcessed = function onSubtitleFragProcessed(event, data) { 9275 var frag = data.frag, 9276 success = data.success; 9277 this.fragPrevious = frag; 9278 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_6__.State.IDLE; 9279 if (!success) { 9280 return; 9281 } 9282 var buffered = this.tracksBuffered[this.currentTrackId]; 9283 if (!buffered) { 9284 return; 9285 } 9286 9287 // Create/update a buffered array matching the interface used by BufferHelper.bufferedInfo 9288 // so we can re-use the logic used to detect how much has been buffered 9289 var timeRange; 9290 var fragStart = frag.start; 9291 for (var i = 0; i < buffered.length; i++) { 9292 if (fragStart >= buffered[i].start && fragStart <= buffered[i].end) { 9293 timeRange = buffered[i]; 9294 break; 9295 } 9296 } 9297 var fragEnd = frag.start + frag.duration; 9298 if (timeRange) { 9299 timeRange.end = fragEnd; 9300 } else { 9301 timeRange = { 9302 start: fragStart, 9303 end: fragEnd 9304 }; 9305 buffered.push(timeRange); 9306 } 9307 this.fragmentTracker.fragBuffered(frag); 9308 }; 9309 _proto.onBufferFlushing = function onBufferFlushing(event, data) { 9310 var startOffset = data.startOffset, 9311 endOffset = data.endOffset; 9312 if (startOffset === 0 && endOffset !== Number.POSITIVE_INFINITY) { 9313 var currentTrackId = this.currentTrackId, 9314 levels = this.levels; 9315 if (!levels.length || !levels[currentTrackId] || !levels[currentTrackId].details) { 9316 return; 9317 }
9318 var trackDetails = levels[currentTrackId].details; 9319 var targetDuration = trackDetails.targetduration; 9320 var endOffsetSubtitles = endOffset - targetDuration; 9321 if (endOffsetSubtitles <= 0) { 9322 return; 9323 } 9324 data.endOffsetSubtitles = Math.max(0, endOffsetSubtitles); 9325 this.tracksBuffered.forEach(function (buffered) { 9326 for (var i = 0; i < buffered.length;) { 9327 if (buffered[i].end <= endOffsetSubtitles) { 9328 buffered.shift(); 9329 continue; 9330 } else if (buffered[i].start < endOffsetSubtitles) { 9331 buffered[i].start = endOffsetSubtitles; 9332 } else { 9333 break; 9334 } 9335 i++; 9336 } 9337 }); 9338 this.fragmentTracker.removeFragmentsInRange(startOffset, endOffsetSubtitles, _types_loader__WEBPACK_IMPORTED_MODULE_7__.PlaylistLevelType.SUBTITLE); 9339 } 9340 }; 9341 _proto.onFragBuffered = function onFragBuffered(event, data) { 9342 if (!this.loadedmetadata && data.frag.type === _types_loader__WEBPACK_IMPORTED_MODULE_7__.PlaylistLevelType.MAIN) { 9343 var _this$media; 9344 if ((_this$media = this.media) !== null && _this$media !== void 0 && _this$media.buffered.length) { 9345 this.loadedmetadata = true; 9346 } 9347 } 9348 } 9349 9350 // If something goes wrong, proceed to next frag, if we were processing one. 9351 ; 9352 _proto.onError = function onError(event, data) { 9353 var frag = data.frag; 9354 // don't handle error not related to subtitle fragment 9355 if (!frag || frag.type !== _types_loader__WEBPACK_IMPORTED_MODULE_7__.PlaylistLevelType.SUBTITLE) { 9356 return; 9357 } 9358 if (this.fragCurrent) { 9359 this.fragCurrent.abortRequests(); 9360 } 9361 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_6__.State.IDLE; 9362 } 9363 9364 // Got all new subtitle levels. 9365 ; 9366 _proto.onSubtitleTracksUpdated = function onSubtitleTracksUpdated(event, _ref) { 9367 var _this2 = this; 9368 var subtitleTracks = _ref.subtitleTracks; 9369 this.tracksBuffered = []; 9370 this.levels = subtitleTracks.map(function (mediaPlaylist) { 9371 return new _types_level__WEBPACK_IMPORTED_MODULE_8__.Level(mediaPlaylist); 9372 }); 9373 this.fragmentTracker.removeAllFragments(); 9374 this.fragPrevious = null; 9375 this.levels.forEach(function (level) { 9376 _this2.tracksBuffered[level.id] = []; 9377 }); 9378 this.mediaBuffer = null; 9379 }; 9380 _proto.onSubtitleTrackSwitch = function onSubtitleTrackSwitch(event, data) { 9381 this.currentTrackId = data.id; 9382 if (!this.levels.length || this.currentTrackId === -1) { 9383 this.clearInterval(); 9384 return; 9385 } 9386 9387 // Check if track has the necessary details to load fragments 9388 var currentTrack = this.levels[this.currentTrackId]; 9389 if (currentTrack !== null && currentTrack !== void 0 && currentTrack.details) { 9390 this.mediaBuffer = this.mediaBufferTimeRanges; 9391 } else { 9392 this.mediaBuffer = null; 9393 } 9394 if (currentTrack) { 9395 this.setInterval(TICK_INTERVAL); 9396 } 9397 } 9398 9399 // Got a new set of subtitle fragments. 9400 ; 9401 _proto.onSubtitleTrackLoaded = function onSubtitleTrackLoaded(event, data) { 9402 var _track$details; 9403 var newDetails = data.details, 9404 trackId = data.id; 9405 var currentTrackId = this.currentTrackId, 9406 levels = this.levels; 9407 if (!levels.length) { 9408 return; 9409 } 9410 var track = levels[currentTrackId]; 9411 if (trackId >= levels.length || trackId !== currentTrackId || !track) { 9412 return; 9413 } 9414 this.mediaBuffer = this.mediaBufferTimeRanges; 9415 var sliding = 0; 9416 if (newDetails.live || (_track$details = track.details) !== null && _track$details !== void 0 && _track$details.live) { 9417 var mainDetails = this.mainDetails; 9418 if (newDetails.deltaUpdateFailed || !mainDetails) { 9419 return; 9420 } 9421 var mainSlidingStartFragment = mainDetails.fragments[0]; 9422 if (!track.details) { 9423 if (newDetails.hasProgramDateTime && mainDetails.hasProgramDateTime) { 9424 (0,_utils_discontinuities__WEBPACK_IMPORTED_MODULE_3__.alignMediaPlaylistByPDT)(newDetails, mainDetails); 9425 sliding = newDetails.fragments[0].start; 9426 } else if (mainSlidingStartFragment) { 9427 // line up live playlist with main so that fragments in range are loaded 9428 sliding = mainSlidingStartFragment.start; 9429 (0,_level_helper__WEBPACK_IMPORTED_MODULE_4__.addSliding)(newDetails, sliding); 9430 } 9431 } else { 9432 sliding = this.alignPlaylists(newDetails, track.details); 9433 if (sliding === 0 && mainSlidingStartFragment) { 9434 // realign with main when there is no overlap with last refresh 9435 sliding = mainSlidingStartFragment.start; 9436 (0,_level_helper__WEBPACK_IMPORTED_MODULE_4__.addSliding)(newDetails, sliding); 9437 } 9438 } 9439 } 9440 track.details = newDetails; 9441 this.levelLastLoaded = trackId; 9442 if (!this.startFragRequested && (this.mainDetails || !newDetails.live)) { 9443 this.setStartPosition(track.details, sliding); 9444 } 9445 9446 // trigger handler right now 9447 this.tick(); 9448 9449 // If playlist is misaligned because of bad PDT or drift, delete details to resync with main on reload 9450 if (newDetails.live && !this.fragCurrent && this.media && this.state === _base_stream_controller__WEBPACK_IMPORTED_MODULE_6__.State.IDLE) { 9451 var foundFrag = (0,_fragment_finders__WEBPACK_IMPORTED_MODULE_2__.findFragmentByPTS)(null, newDetails.fragments, this.media.currentTime, 0); 9452 if (!foundFrag) { 9453 this.warn('Subtitle playlist not aligned with playback'); 9454 track.details = undefined; 9455 } 9456 } 9457 }; 9458 _proto._handleFragmentLoadComplete = function _handleFragmentLoadComplete(fragLoadedData) { 9459 var _this3 = this; 9460 var frag = fragLoadedData.frag, 9461 payload = fragLoadedData.payload; 9462 var decryptData = frag.decryptdata; 9463 var hls = this.hls; 9464 if (this.fragContextChanged(frag)) { 9465 return; 9466 } 9467 // check to see if the payload needs to be decrypted 9468 if (payload && payload.byteLength > 0 && decryptData && decryptData.key && decryptData.iv && decryptData.method === 'AES-128') { 9469 var startTime = performance.now(); 9470 // decrypt the subtitles
9471 this.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer).then(function (decryptedData) { 9472 var endTime = performance.now(); 9473 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_0__.Events.FRAG_DECRYPTED, { 9474 frag: frag, 9475 payload: decryptedData, 9476 stats: { 9477 tstart: startTime, 9478 tdecrypt: endTime 9479 } 9480 }); 9481 }).catch(function (err) { 9482 _this3.warn(err.name + ": " + err.message); 9483 _this3.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_6__.State.IDLE; 9484 }); 9485 } 9486 }; 9487 _proto.doTick = function doTick() { 9488 if (!this.media) { 9489 this.state = _base_stream_controller__WEBPACK_IMPORTED_MODULE_6__.State.IDLE; 9490 return; 9491 } 9492 if (this.state === _base_stream_controller__WEBPACK_IMPORTED_MODULE_6__.State.IDLE) { 9493 var currentTrackId = this.currentTrackId, 9494 levels = this.levels; 9495 if (!levels.length || !levels[currentTrackId] || !levels[currentTrackId].details) { 9496 return; 9497 } 9498 9499 // Expand range of subs loaded by one target-duration in either direction to make up for misaligned playlists 9500 var trackDetails = levels[currentTrackId].details; 9501 var targetDuration = trackDetails.targetduration; 9502 var config = this.config; 9503 var currentTime = this.getLoadPosition(); 9504 var bufferedInfo = _utils_buffer_helper__WEBPACK_IMPORTED_MODULE_1__.BufferHelper.bufferedInfo(this.tracksBuffered[this.currentTrackId] || [], currentTime - targetDuration, config.maxBufferHole); 9505 var targetBufferTime = bufferedInfo.end, 9506 bufferLen = bufferedInfo.len; 9507 var mainBufferInfo = this.getFwdBufferInfo(this.media, _types_loader__WEBPACK_IMPORTED_MODULE_7__.PlaylistLevelType.MAIN); 9508 var maxBufLen = this.getMaxBufferLength(mainBufferInfo === null || mainBufferInfo === void 0 ? void 0 : mainBufferInfo.len) + targetDuration; 9509 if (bufferLen > maxBufLen) { 9510 return; 9511 } 9512 console.assert(trackDetails, 'Subtitle track details are defined on idle subtitle stream controller tick'); 9513 var fragments = trackDetails.fragments; 9514 var fragLen = fragments.length; 9515 var end = trackDetails.edge; 9516 var foundFrag = null; 9517 var fragPrevious = this.fragPrevious; 9518 if (targetBufferTime < end) { 9519 var maxFragLookUpTolerance = config.maxFragLookUpTolerance; 9520 foundFrag = (0,_fragment_finders__WEBPACK_IMPORTED_MODULE_2__.findFragmentByPTS)(fragPrevious, fragments, Math.max(fragments[0].start, targetBufferTime), maxFragLookUpTolerance); 9521 if (!foundFrag && fragPrevious && fragPrevious.start < fragments[0].start) { 9522 foundFrag = fragments[0]; 9523 } 9524 } else { 9525 foundFrag = fragments[fragLen - 1]; 9526 } 9527 if (!foundFrag) { 9528 return; 9529 } 9530 foundFrag = this.mapToInitFragWhenRequired(foundFrag); 9531 if (this.fragmentTracker.getState(foundFrag) === _fragment_tracker__WEBPACK_IMPORTED_MODULE_5__.FragmentState.NOT_LOADED) { 9532 // only load if fragment is not loaded 9533 this.loadFragment(foundFrag, trackDetails, targetBufferTime); 9534 } 9535 } 9536 }; 9537 _proto.getMaxBufferLength = function getMaxBufferLength(mainBufferLength) { 9538 var maxConfigBuffer = _BaseStreamController.prototype.getMaxBufferLength.call(this); 9539 if (!mainBufferLength) { 9540 return maxConfigBuffer; 9541 } 9542 return Math.max(maxConfigBuffer, mainBufferLength); 9543 }; 9544 _proto.loadFragment = function loadFragment(frag, levelDetails, targetBufferTime) { 9545 this.fragCurrent = frag; 9546 if (frag.sn === 'initSegment') { 9547 this._loadInitSegment(frag, levelDetails); 9548 } else { 9549 this.startFragRequested = true; 9550 _BaseStreamController.prototype.loadFragment.call(this, frag, levelDetails, targetBufferTime); 9551 } 9552 }; 9553 _createClass(SubtitleStreamController, [{ 9554 key: "mediaBufferTimeRanges", 9555 get: function get() { 9556 return new BufferableInstance(this.tracksBuffered[this.currentTrackId] || []); 9557 } 9558 }]); 9559 return SubtitleStreamController; 9560}(_base_stream_controller__WEBPACK_IMPORTED_MODULE_6__["default"]); 9561var BufferableInstance = function BufferableInstance(timeranges) { 9562 this.buffered = void 0; 9563 var getRange = function getRange(name, index, length) { 9564 index = index >>> 0; 9565 if (index > length - 1) {
9566 throw new DOMException("Failed to execute '" + name + "' on 'TimeRanges': The index provided (" + index + ") is greater than the maximum bound (" + length + ")"); 9567 } 9568 return timeranges[index][name]; 9569 }; 9570 this.buffered = { 9571 get length() { 9572 return timeranges.length; 9573 }, 9574 end: function end(index) { 9575 return getRange('end', index, timeranges.length); 9576 }, 9577 start: function start(index) { 9578 return getRange('start', index, timeranges.length); 9579 } 9580 }; 9581}; 9582 9583/***/ }), 9584
vendor: 4,861 bytes, lines 9585-9655
9585/***/ "./src/controller/subtitle-track-controller.ts": 9586/*!*****************************************************!*\ 9587 !*** ./src/controller/subtitle-track-controller.ts ***! 9588 \*****************************************************/ 9589/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 9590 9591"use strict"; 9592__webpack_require__.r(__webpack_exports__); 9593/* harmony export */ __webpack_require__.d(__webpack_exports__, { 9594/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 9595/* harmony export */ }); 9596/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 9597/* harmony import */ var _utils_texttrack_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils/texttrack-utils */ "./src/utils/texttrack-utils.ts"); 9598/* harmony import */ var _base_playlist_controller__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./base-playlist-controller */ "./src/controller/base-playlist-controller.ts"); 9599/* harmony import */ var _types_loader__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../types/loader */ "./src/types/loader.ts"); 9600function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } 9601function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } 9602function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } 9603function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } 9604function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); } 9605function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } 9606 9607 9608 9609 9610var SubtitleTrackController = /*#__PURE__*/function (_BasePlaylistControll) { 9611 _inheritsLoose(SubtitleTrackController, _BasePlaylistControll); 9612 function SubtitleTrackController(hls) { 9613 var _this; 9614 _this = _BasePlaylistControll.call(this, hls, '[subtitle-track-controller]') || this; 9615 _this.media = null; 9616 _this.tracks = []; 9617 _this.groupId = null; 9618 _this.tracksInGroup = []; 9619 _this.trackId = -1; 9620 _this.selectDefaultTrack = true; 9621 _this.queuedDefaultTrack = -1; 9622 _this.trackChangeListener = function () { 9623 return _this.onTextTracksChanged(); 9624 }; 9625 _this.asyncPollTrackChange = function () { 9626 return _this.pollTrackChange(0); 9627 }; 9628 _this.useTextTrackPolling = false; 9629 _this.subtitlePollingInterval = -1; 9630 _this._subtitleDisplay = true; 9631 _this.registerListeners(); 9632 return _this; 9633 } 9634 var _proto = SubtitleTrackController.prototype; 9635 _proto.destroy = function destroy() { 9636 this.unregisterListeners(); 9637 this.tracks.length = 0; 9638 this.tracksInGroup.length = 0; 9639 this.trackChangeListener = this.asyncPollTrackChange = null; 9640 _BasePlaylistControll.prototype.destroy.call(this); 9641 }; 9642 _proto.registerListeners = function registerListeners() { 9643 var hls = this.hls; 9644 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MEDIA_ATTACHED, this.onMediaAttached, this); 9645 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MEDIA_DETACHING, this.onMediaDetaching, this); 9646 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MANIFEST_LOADING, this.onManifestLoading, this); 9647 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MANIFEST_PARSED, this.onManifestParsed, this); 9648 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.LEVEL_LOADING, this.onLevelLoading, this); 9649 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.LEVEL_SWITCHING, this.onLevelSwitching, this); 9650 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this); 9651 hls.on(_events__WEBPACK_IMPORTED_MODULE_0__.Events.ERROR, this.onError, this); 9652 }; 9653 _proto.unregisterListeners = function unregisterListeners() { 9654 var hls = this.hls; 9655 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MEDIA_ATTA
9655CHED, this.onMediaAttached, this); 9656 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MEDIA_DETACHING, this.onMediaDetaching, this); 9657 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MANIFEST_LOADING, this.onManifestLoading, this); 9658 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.MANIFEST_PARSED, this.onManifestParsed, this); 9659 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.LEVEL_LOADING, this.onLevelLoading, this); 9660 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.LEVEL_SWITCHING, this.onLevelSwitching, this); 9661 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this); 9662 hls.off(_events__WEBPACK_IMPORTED_MODULE_0__.Events.ERROR, this.onError, this); 9663 } 9664 9665 // Listen for subtitle track change, then extract the current track ID. 9666 ; 9667 _proto.onMediaAttached = function onMediaAttached(event, data) { 9668 this.media = data.media; 9669 if (!this.media) { 9670 return; 9671 } 9672 if (this.queuedDefaultTrack > -1) { 9673 this.subtitleTrack = this.queuedDefaultTrack; 9674 this.queuedDefaultTrack = -1; 9675 } 9676 this.useTextTrackPolling = !(this.media.textTracks && 'onchange' in this.media.textTracks); 9677 if (this.useTextTrackPolling) { 9678 this.pollTrackChange(500); 9679 } else { 9680 this.media.textTracks.addEventListener('change', this.asyncPollTrackChange); 9681 } 9682 }; 9683 _proto.pollTrackChange = function pollTrackChange(timeout) { 9684 self.clearInterval(this.subtitlePollingInterval); 9685 this.subtitlePollingInterval = self.setInterval(this.trackChangeListener, timeout); 9686 }; 9687 _proto.onMediaDetaching = function onMediaDetaching() { 9688 if (!this.media) { 9689 return; 9690 } 9691 self.clearInterval(this.subtitlePollingInterval); 9692 if (!this.useTextTrackPolling) { 9693 this.media.textTracks.removeEventListener('change', this.asyncPollTrackChange); 9694 } 9695 if (this.trackId > -1) { 9696 this.queuedDefaultTrack = this.trackId; 9697 } 9698 var textTracks = filterSubtitleTracks(this.media.textTracks); 9699 // Clear loaded cues on media detachment from tracks 9700 textTracks.forEach(function (track) { 9701 (0,_utils_texttrack_utils__WEBPACK_IMPORTED_MODULE_1__.clearCurrentCues)(track); 9702 }); 9703 // Disable all subtitle tracks before detachment so when reattached only tracks in that content are enabled. 9704 this.subtitleTrack = -1; 9705 this.media = null; 9706 }; 9707 _proto.onManifestLoading = function onManifestLoading() { 9708 this.tracks = []; 9709 this.groupId = null; 9710 this.tracksInGroup = []; 9711 this.trackId = -1; 9712 this.selectDefaultTrack = true; 9713 } 9714 9715 // Fired whenever a new manifest is loaded. 9716 ; 9717 _proto.onManifestParsed = function onManifestParsed(event, data) { 9718 this.tracks = data.subtitleTracks; 9719 }; 9720 _proto.onSubtitleTrackLoaded = function onSubtitleTrackLoaded(event, data) { 9721 var id = data.id, 9722 details = data.details; 9723 var trackId = this.trackId; 9724 var currentTrack = this.tracksInGroup[trackId]; 9725 if (!currentTrack) { 9726 this.warn("Invalid subtitle track id " + id); 9727 return; 9728 } 9729 var curDetails = currentTrack.details; 9730 currentTrack.details = data.details; 9731 this.log("subtitle track " + id + " loaded [" + details.startSN + "-" + details.endSN + "]"); 9732 if (id === this.trackId) { 9733 this.retryCount = 0; 9734 this.playlistLoaded(id, data, curDetails); 9735 } 9736 }; 9737 _proto.onLevelLoading = function onLevelLoading(event, data) { 9738 this.switchLevel(data.level); 9739 }; 9740 _proto.onLevelSwitching = function onLevelSwitching(event, data) { 9741 this.switchLevel(data.level); 9742 }; 9743 _proto.switchLevel = function switchLevel(levelIndex) { 9744 var levelInfo = this.hls.levels[levelIndex]; 9745 if (!(levelInfo !== null && levelInfo !== void 0 && levelInfo.textGroupIds)) { 9746 return; 9747 } 9748 var textGroupId = levelInfo.textGroupIds[levelInfo.urlId]; 9749 if (this.groupId !== textGroupId) { 9750 var lastTrack = this.tracksInGroup ? this.tracksInGroup[this.trackId] : undefined; 9751 var subtitleTracks = this.tracks.filter(function (track) { 9752 return !textGroupId || track.groupId === textGroupId; 9753 }); 9754 this.tracksInGroup = subtitleTracks; 9755 var initialTrackId = this.findTrackId(lastTrack === null || lastTrack === void 0 ? void 0 : lastTrack.name) || this.findTrackId(); 9756 this.groupId = textGroupId;
9757 var subtitleTracksUpdated = { 9758 subtitleTracks: subtitleTracks 9759 }; 9760 this.log("Updating subtitle tracks, " + subtitleTracks.length + " track(s) found in \"" + textGroupId + "\" group-id"); 9761 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_0__.Events.SUBTITLE_TRACKS_UPDATED, subtitleTracksUpdated); 9762 if (initialTrackId !== -1) { 9763 this.setSubtitleTrack(initialTrackId, lastTrack); 9764 } 9765 } 9766 }; 9767 _proto.findTrackId = function findTrackId(name) { 9768 var textTracks = this.tracksInGroup; 9769 for (var i = 0; i < textTracks.length; i++) { 9770 var track = textTracks[i]; 9771 if (!this.selectDefaultTrack || track.default) { 9772 if (!name || name === track.name) { 9773 return track.id; 9774 } 9775 } 9776 } 9777 return -1; 9778 }; 9779 _proto.onError = function onError(event, data) { 9780 _BasePlaylistControll.prototype.onError.call(this, event, data); 9781 if (data.fatal || !data.context) { 9782 return; 9783 } 9784 if (data.context.type === _types_loader__WEBPACK_IMPORTED_MODULE_3__.PlaylistContextType.SUBTITLE_TRACK && data.context.id === this.trackId && data.context.groupId === this.groupId) { 9785 this.retryLoadingOrFail(data); 9786 } 9787 } 9788 9789 /** get alternate subtitle tracks list from playlist **/; 9790 _proto.loadPlaylist = function loadPlaylist(hlsUrlParameters) { 9791 _BasePlaylistControll.prototype.loadPlaylist.call(this); 9792 var currentTrack = this.tracksInGroup[this.trackId]; 9793 if (this.shouldLoadTrack(currentTrack)) { 9794 var id = currentTrack.id; 9795 var groupId = currentTrack.groupId; 9796 var url = currentTrack.url; 9797 if (hlsUrlParameters) { 9798 try { 9799 url = hlsUrlParameters.addDirectives(url); 9800 } catch (error) { 9801 this.warn("Could not construct new URL with HLS Delivery Directives: " + error); 9802 } 9803 } 9804 this.log("Loading subtitle playlist for id " + id); 9805 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_0__.Events.SUBTITLE_TRACK_LOADING, { 9806 url: url, 9807 id: id, 9808 groupId: groupId, 9809 deliveryDirectives: hlsUrlParameters || null 9810 }); 9811 } 9812 } 9813 9814 /** 9815 * Disables the old subtitleTrack and sets current mode on the next subtitleTrack. 9816 * This operates on the DOM textTracks. 9817 * A value of -1 will disable all subtitle tracks. 9818 */; 9819 _proto.toggleTrackModes = function toggleTrackModes(newId) { 9820 var _this2 = this; 9821 var media = this.media, 9822 trackId = this.trackId; 9823 if (!media) { 9824 return; 9825 } 9826 var textTracks = filterSubtitleTracks(media.textTracks); 9827 var groupTracks = textTracks.filter(function (track) { 9828 return track.groupId === _this2.groupId; 9829 }); 9830 if (newId === -1) {
9831 [].slice.call(textTracks).forEach(function (track) { 9832 track.mode = 'disabled'; 9833 }); 9834 } else { 9835 var oldTrack = groupTracks[trackId]; 9836 if (oldTrack) { 9837 oldTrack.mode = 'disabled'; 9838 } 9839 } 9840 var nextTrack = groupTracks[newId]; 9841 if (nextTrack) { 9842 nextTrack.mode = this.subtitleDisplay ? 'showing' : 'hidden'; 9843 } 9844 } 9845 9846 /** 9847 * This method is responsible for validating the subtitle index and periodically reloading if live. 9848 * Dispatches the SUBTITLE_TRACK_SWITCH event, which instructs the subtitle-stream-controller to load the selected track. 9849 */; 9850 _proto.setSubtitleTrack = function setSubtitleTrack(newId, lastTrack) { 9851 var _tracks$newId; 9852 var tracks = this.tracksInGroup; 9853 9854 // setting this.subtitleTrack will trigger internal logic 9855 // if media has not been attached yet, it will fail 9856 // we keep a reference to the default track id 9857 // and we'll set subtitleTrack when onMediaAttached is triggered 9858 if (!this.media) { 9859 this.queuedDefaultTrack = newId; 9860 return; 9861 } 9862 if (this.trackId !== newId) { 9863 this.toggleTrackModes(newId); 9864 } 9865 9866 // exit if track id as already set or invalid 9867 if (this.trackId === newId && (newId === -1 || (_tracks$newId = tracks[newId]) !== null && _tracks$newId !== void 0 && _tracks$newId.details) || newId < -1 || newId >= tracks.length) { 9868 return; 9869 } 9870 9871 // stopping live reloading timer if any 9872 this.clearTimer(); 9873 var track = tracks[newId]; 9874 this.log("Switching to subtitle track " + newId); 9875 this.trackId = newId; 9876 if (track) { 9877 var id = track.id, 9878 _track$groupId = track.groupId, 9879 groupId = _track$groupId === void 0 ? '' : _track$groupId, 9880 name = track.name, 9881 type = track.type, 9882 url = track.url; 9883 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_0__.Events.SUBTITLE_TRACK_SWITCH, { 9884 id: id, 9885 groupId: groupId, 9886 name: name, 9887 type: type, 9888 url: url 9889 }); 9890 var hlsUrlParameters = this.switchParams(track.url, lastTrack === null || lastTrack === void 0 ? void 0 : lastTrack.details); 9891 this.loadPlaylist(hlsUrlParameters); 9892 } else { 9893 // switch to -1 9894 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_0__.Events.SUBTITLE_TRACK_SWITCH, { 9895 id: newId 9896 }); 9897 } 9898 }; 9899 _proto.onTextTracksChanged = function onTextTracksChanged() { 9900 if (!this.useTextTrackPolling) { 9901 self.clearInterval(this.subtitlePollingInterval); 9902 } 9903 // Media is undefined when switching streams via loadSource() 9904 if (!this.media || !this.hls.config.renderTextTracksNatively) { 9905 return; 9906 } 9907 var trackId = -1; 9908 var tracks = filterSubtitleTracks(this.media.textTracks); 9909 for (var id = 0; id < tracks.length; id++) { 9910 if (tracks[id].mode === 'hidden') { 9911 // Do not break in case there is a following track with showing. 9912 trackId = id; 9913 } else if (tracks[id].mode === 'showing') { 9914 trackId = id; 9915 break; 9916 } 9917 } 9918 9919 // Setting current subtitleTrack will invoke code. 9920 if (this.subtitleTrack !== trackId) { 9921 this.subtitleTrack = trackId; 9922 } 9923 }; 9924 _createClass(SubtitleTrackController, [{ 9925 key: "subtitleDisplay", 9926 get: function get() { 9927 return this._subtitleDisplay; 9928 }, 9929 set: function set(value) { 9930 this._subtitleDisplay = value; 9931 if (this.trackId > -1) { 9932 this.toggleTrackModes(this.trackId); 9933 } 9934 } 9935 }, { 9936 key: "subtitleTracks", 9937 get: function get() { 9938 return this.tracksInGroup; 9939 } 9940 9941 /** get/set index of the selected subtitle track (based on index in subtitle track lists) **/ 9942 }, { 9943 key: "subtitleTrack", 9944 get: function get() { 9945 return this.trackId; 9946 }, 9947 set: function set(newId) { 9948 this.selectDefaultTrack = false; 9949 var lastTrack = this.tracksInGroup ? this.tracksInGroup[this.trackId] : undefined; 9950 this.setSubtitleTrack(newId, lastTrack); 9951 } 9952 }]); 9953 return SubtitleTrackController; 9954}(_base_playlist_controller__WEBPACK_IMPORTED_MODULE_2__["default"]); 9955function filterSubtitleTracks(textTrackList) { 9956 var tracks = []; 9957 for (var i = 0; i < textTrackList.length; i++) { 9958 var track = textTrackList[i]; 9959 // Edge adds a track without a label; we don't want to use it 9960 if (track.kind === 'subtitles' && track.label) { 9961 tracks.push(textTrackList[i]); 9962 } 9963 } 9964 return tracks; 9965} 9966/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SubtitleTrackController); 9967 9968/***/ }), 9969
9970/***/ "./src/controller/timeline-controller.ts": 9971/*!***********************************************!*\ 9972 !*** ./src/controller/timeline-controller.ts ***! 9973 \***********************************************/ 9974/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 9975 9976"use strict"; 9977__webpack_require__.r(__webpack_exports__); 9978/* harmony export */ __webpack_require__.d(__webpack_exports__, { 9979/* harmony export */ "TimelineController": () => (/* binding */ TimelineController) 9980/* harmony export */ }); 9981/* harmony import */ var _home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.ts"); 9982/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 9983/* harmony import */ var _utils_cea_608_parser__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils/cea-608-parser */ "./src/utils/cea-608-parser.ts"); 9984/* harmony import */ var _utils_output_filter__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils/output-filter */ "./src/utils/output-filter.ts"); 9985/* harmony import */ var _utils_webvtt_parser__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../utils/webvtt-parser */ "./src/utils/webvtt-parser.ts"); 9986/* harmony import */ var _utils_texttrack_utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../utils/texttrack-utils */ "./src/utils/texttrack-utils.ts"); 9987/* harmony import */ var _utils_imsc1_ttml_parser__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../utils/imsc1-ttml-parser */ "./src/utils/imsc1-ttml-parser.ts"); 9988/* harmony import */ var _utils_mp4_tools__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../utils/mp4-tools */ "./src/utils/mp4-tools.ts"); 9989/* harmony import */ var _types_loader__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../types/loader */ "./src/types/loader.ts"); 9990/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 9991 9992 9993 9994 9995 9996 9997 9998 9999 10000 10001 10002var TimelineController = /*#__PURE__*/function () { 10003 function TimelineController(hls) { 10004 this.hls = void 0; 10005 this.media = null; 10006 this.config = void 0; 10007 this.enabled = true; 10008 this.Cues = void 0; 10009 this.textTracks = []; 10010 this.tracks = []; 10011 this.initPTS = []; 10012 this.timescale = []; 10013 this.unparsedVttFrags = []; 10014 this.captionsTracks = {}; 10015 this.nonNativeCaptionsTracks = {}; 10016 this.cea608Parser1 = void 0; 10017 this.cea608Parser2 = void 0; 10018 this.lastSn = -1; 10019 this.lastPartIndex = -1; 10020 this.prevCC = -1; 10021 this.vttCCs = newVTTCCs(); 10022 this.captionsProperties = void 0; 10023 this.hls = hls; 10024 this.config = hls.config; 10025 this.Cues = hls.config.cueHandler; 10026 this.captionsProperties = { 10027 textTrack1: { 10028 label: this.config.captionsTextTrack1Label, 10029 languageCode: this.config.captionsTextTrack1LanguageCode 10030 }, 10031 textTrack2: { 10032 label: this.config.captionsTextTrack2Label, 10033 languageCode: this.config.captionsTextTrack2LanguageCode 10034 }, 10035 textTrack3: { 10036 label: this.config.captionsTextTrack3Label, 10037 languageCode: this.config.captionsTextTrack3LanguageCode 10038 }, 10039 textTrack4: { 10040 label: this.config.captionsTextTrack4Label, 10041 languageCode: this.config.captionsTextTrack4LanguageCode 10042 } 10043 }; 10044 if (this.config.enableCEA708Captions) { 10045 var channel1 = new _utils_output_filter__WEBPACK_IMPORTED_MODULE_3__["default"](this, 'textTrack1'); 10046 var channel2 = new _utils_output_filter__WEBPACK_IMPORTED_MODULE_3__["default"](this, 'textTrack2'); 10047 var channel3 = new _utils_output_filter__WEBPACK_IMPORTED_MODULE_3__["default"](this, 'textTrack3'); 10048 var channel4 = new _utils_output_filter__WEBPACK_IMPORTED_MODULE_3__["default"](this, 'textTrack4'); 10049 this.cea608Parser1 = new _utils_cea_608_parser__WEBPACK_IMPORTED_MODULE_2__["default"](1, channel1, channel2); 10050 this.cea608Parser2 = new _utils_cea_608_parser__WEBPACK_IMPORTED_MODULE_2__["default"](3, channel3, channel4); 10051 } 10052 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MEDIA_ATTA
vendor: 4,434 bytes, lines 10052-10131
10052CHING, this.onMediaAttaching, this); 10053 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MEDIA_DETACHING, this.onMediaDetaching, this); 10054 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MANIFEST_LOADING, this.onManifestLoading, this); 10055 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MANIFEST_LOADED, this.onManifestLoaded, this); 10056 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this); 10057 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.FRAG_LOADING, this.onFragLoading, this); 10058 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.FRAG_LOADED, this.onFragLoaded, this); 10059 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.FRAG_PARSING_USERDATA, this.onFragParsingUserdata, this); 10060 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.FRAG_DECRYPTED, this.onFragDecrypted, this); 10061 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.INIT_PTS_FOUND, this.onInitPtsFound, this); 10062 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.SUBTITLE_TRACKS_CLEARED, this.onSubtitleTracksCleared, this); 10063 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.BUFFER_FLUSHING, this.onBufferFlushing, this); 10064 } 10065 var _proto = TimelineController.prototype; 10066 _proto.destroy = function destroy() { 10067 var hls = this.hls; 10068 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MEDIA_ATTACHING, this.onMediaAttaching, this); 10069 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MEDIA_DETACHING, this.onMediaDetaching, this); 10070 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MANIFEST_LOADING, this.onManifestLoading, this); 10071 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MANIFEST_LOADED, this.onManifestLoaded, this); 10072 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this); 10073 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.FRAG_LOADING, this.onFragLoading, this); 10074 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.FRAG_LOADED, this.onFragLoaded, this); 10075 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.FRAG_PARSING_USERDATA, this.onFragParsingUserdata, this); 10076 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.FRAG_DECRYPTED, this.onFragDecrypted, this); 10077 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.INIT_PTS_FOUND, this.onInitPtsFound, this); 10078 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.SUBTITLE_TRACKS_CLEARED, this.onSubtitleTracksCleared, this); 10079 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.BUFFER_FLUSHING, this.onBufferFlushing, this); 10080 // @ts-ignore 10081 this.hls = this.config = this.cea608Parser1 = this.cea608Parser2 = null; 10082 }; 10083 _proto.addCues = function addCues(trackName, startTime, endTime, screen, cueRanges) { 10084 // skip cues which overlap more than 50% with previously parsed time ranges 10085 var merged = false; 10086 for (var i = cueRanges.length; i--;) { 10087 var cueRange = cueRanges[i]; 10088 var overlap = intersection(cueRange[0], cueRange[1], startTime, endTime); 10089 if (overlap >= 0) { 10090 cueRange[0] = Math.min(cueRange[0], startTime); 10091 cueRange[1] = Math.max(cueRange[1], endTime); 10092 merged = true; 10093 if (overlap / (endTime - startTime) > 0.5) { 10094 return; 10095 } 10096 } 10097 } 10098 if (!merged) { 10099 cueRanges.push([startTime, endTime]); 10100 } 10101 if (this.config.renderTextTracksNatively) { 10102 var track = this.captionsTracks[trackName]; 10103 this.Cues.newCue(track, startTime, endTime, screen); 10104 } else { 10105 var cues = this.Cues.newCue(null, startTime, endTime, screen); 10106 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.CUES_PARSED, { 10107 type: 'captions', 10108 cues: cues, 10109 track: trackName 10110 }); 10111 } 10112 } 10113 10114 // Triggered when an initial PTS is found; used for synchronisation of WebVTT. 10115 ; 10116 _proto.onInitPtsFound = function onInitPtsFound(event, _ref) { 10117 var _this = this; 10118 var frag = _ref.frag, 10119 id = _ref.id, 10120 initPTS = _ref.initPTS, 10121 timescale = _ref.timescale; 10122 var unparsedVttFrags = this.unparsedVttFrags; 10123 if (id === 'main') { 10124 this.initPTS[frag.cc] = initPTS; 10125 this.timescale[frag.cc] = timescale; 10126 } 10127 10128 // Due to asynchronous processing, initial PTS may arrive later than the first VTT fragments are loaded. 10129 // Parse any unparsed fragments upon receiving the initial PTS. 10130 if (unparsedVttFrags.length) { 10131 this.unparsedVttFrags = [];
10132 unparsedVttFrags.forEach(function (frag) { 10133 _this.onFragLoaded(_events__WEBPACK_IMPORTED_MODULE_1__.Events.FRAG_LOADED, frag); 10134 }); 10135 } 10136 }; 10137 _proto.getExistingTrack = function getExistingTrack(trackName) { 10138 var media = this.media; 10139 if (media) { 10140 for (var i = 0; i < media.textTracks.length; i++) { 10141 var textTrack = media.textTracks[i]; 10142 if (textTrack[trackName]) { 10143 return textTrack; 10144 } 10145 } 10146 } 10147 return null; 10148 }; 10149 _proto.createCaptionsTrack = function createCaptionsTrack(trackName) { 10150 if (this.config.renderTextTracksNatively) { 10151 this.createNativeTrack(trackName); 10152 } else { 10153 this.createNonNativeTrack(trackName); 10154 } 10155 }; 10156 _proto.createNativeTrack = function createNativeTrack(trackName) { 10157 if (this.captionsTracks[trackName]) { 10158 return; 10159 } 10160 var captionsProperties = this.captionsProperties, 10161 captionsTracks = this.captionsTracks, 10162 media = this.media; 10163 var _captionsProperties$t = captionsProperties[trackName], 10164 label = _captionsProperties$t.label, 10165 languageCode = _captionsProperties$t.languageCode; 10166 // Enable reuse of existing text track. 10167 var existingTrack = this.getExistingTrack(trackName); 10168 if (!existingTrack) { 10169 var textTrack = this.createTextTrack('captions', label, languageCode); 10170 if (textTrack) { 10171 // Set a special property on the track so we know it's managed by Hls.js 10172 textTrack[trackName] = true; 10173 captionsTracks[trackName] = textTrack; 10174 } 10175 } else { 10176 captionsTracks[trackName] = existingTrack; 10177 (0,_utils_texttrack_utils__WEBPACK_IMPORTED_MODULE_5__.clearCurrentCues)(captionsTracks[trackName]); 10178 (0,_utils_texttrack_utils__WEBPACK_IMPORTED_MODULE_5__.sendAddTrackEvent)(captionsTracks[trackName], media); 10179 } 10180 }; 10181 _proto.createNonNativeTrack = function createNonNativeTrack(trackName) { 10182 if (this.nonNativeCaptionsTracks[trackName]) { 10183 return; 10184 } 10185 // Create a list of a single track for the provider to consume 10186 var trackProperties = this.captionsProperties[trackName]; 10187 if (!trackProperties) { 10188 return; 10189 } 10190 var label = trackProperties.label; 10191 var track = { 10192 _id: trackName, 10193 label: label, 10194 kind: 'captions', 10195 default: trackProperties.media ? !!trackProperties.media.default : false, 10196 closedCaptions: trackProperties.media 10197 }; 10198 this.nonNativeCaptionsTracks[trackName] = track; 10199 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.NON_NATIVE_TEXT_TRACKS_FOUND, { 10200 tracks: [track] 10201 }); 10202 }; 10203 _proto.createTextTrack = function createTextTrack(kind, label, lang) { 10204 var media = this.media; 10205 if (!media) { 10206 return; 10207 } 10208 return media.addTextTrack(kind, label, lang); 10209 }; 10210 _proto.onMediaAttaching = function onMediaAttaching(event, data) { 10211 this.media = data.media; 10212 this._cleanTracks(); 10213 }; 10214 _proto.onMediaDetaching = function onMediaDetaching() { 10215 var captionsTracks = this.captionsTracks;
10216 Object.keys(captionsTracks).forEach(function (trackName) { 10217 (0,_utils_texttrack_utils__WEBPACK_IMPORTED_MODULE_5__.clearCurrentCues)(captionsTracks[trackName]); 10218 delete captionsTracks[trackName]; 10219 }); 10220 this.nonNativeCaptionsTracks = {}; 10221 }; 10222 _proto.onManifestLoading = function onManifestLoading() { 10223 this.lastSn = -1; // Detect discontinuity in fragment parsing 10224 this.lastPartIndex = -1; 10225 this.prevCC = -1; 10226 this.vttCCs = newVTTCCs(); // Detect discontinuity in subtitle manifests 10227 this._cleanTracks(); 10228 this.tracks = []; 10229 this.captionsTracks = {}; 10230 this.nonNativeCaptionsTracks = {}; 10231 this.textTracks = []; 10232 this.unparsedVttFrags = this.unparsedVttFrags || []; 10233 this.initPTS = []; 10234 this.timescale = []; 10235 if (this.cea608Parser1 && this.cea608Parser2) { 10236 this.cea608Parser1.reset(); 10237 this.cea608Parser2.reset(); 10238 } 10239 }; 10240 _proto._cleanTracks = function _cleanTracks() { 10241 // clear outdated subtitles 10242 var media = this.media; 10243 if (!media) { 10244 return; 10245 } 10246 var textTracks = media.textTracks; 10247 if (textTracks) { 10248 for (var i = 0; i < textTracks.length; i++) { 10249 (0,_utils_texttrack_utils__WEBPACK_IMPORTED_MODULE_5__.clearCurrentCues)(textTracks[i]); 10250 } 10251 } 10252 }; 10253 _proto.onSubtitleTracksUpdated = function onSubtitleTracksUpdated(event, data) { 10254 var _this2 = this; 10255 this.textTracks = []; 10256 var tracks = data.subtitleTracks || []; 10257 var hasIMSC1 = tracks.some(function (track) { 10258 return track.textCodec === _utils_imsc1_ttml_parser__WEBPACK_IMPORTED_MODULE_6__.IMSC1_CODEC; 10259 }); 10260 if (this.config.enableWebVTT || hasIMSC1 && this.config.enableIMSC1) { 10261 var sameTracks = this.tracks && tracks && this.tracks.length === tracks.length; 10262 this.tracks = tracks || []; 10263 if (this.config.renderTextTracksNatively) { 10264 var inUseTracks = this.media ? this.media.textTracks : []; 10265 this.tracks.forEach(function (track, index) { 10266 var textTrack; 10267 if (index < inUseTracks.length) { 10268 var inUseTrack = null; 10269 for (var i = 0; i < inUseTracks.length; i++) { 10270 if (canReuseVttTextTrack(inUseTracks[i], track)) { 10271 inUseTrack = inUseTracks[i]; 10272 break; 10273 } 10274 } 10275 10276 // Reuse tracks with the same label, but do not reuse 608/708 tracks 10277 if (inUseTrack) { 10278 textTrack = inUseTrack; 10279 } 10280 } 10281 if (textTrack) { 10282 (0,_utils_texttrack_utils__WEBPACK_IMPORTED_MODULE_5__.clearCurrentCues)(textTrack); 10283 } else { 10284 var textTrackKind = _this2._captionsOrSubtitlesFromCharacteristics(track); 10285 textTrack = _this2.createTextTrack(textTrackKind, track.name, track.lang); 10286 if (textTrack) { 10287 textTrack.mode = 'disabled'; 10288 } 10289 } 10290 if (textTrack) { 10291 textTrack.groupId = track.groupId; 10292 _this2.textTracks.push(textTrack); 10293 } 10294 }); 10295 } else if (!sameTracks && this.tracks && this.tracks.length) { 10296 // Create a list of tracks for the provider to consume 10297 var tracksList = this.tracks.map(function (track) { 10298 return { 10299 label: track.name, 10300 kind: track.type.toLowerCase(), 10301 default: track.default, 10302 subtitleTrack: track 10303 }; 10304 }); 10305 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.NON_NATIVE_TEXT_TRACKS_FOUND, { 10306 tracks: tracksList 10307 }); 10308 } 10309 } 10310 }; 10311 _proto._captionsOrSubtitlesFromCharacteristics = function _captionsOrSubtitlesFromCharacteristics(track) { 10312 var _track$attrs; 10313 if ((_track$attrs = track.attrs) !== null && _track$attrs !== void 0 && _track$attrs.CHARACTERISTICS) { 10314 var transcribesSpokenDialog = /transcribes-spoken-dialog/gi.test(track.attrs.CHARACTERISTICS); 10315 var describesMusicAndSound = /describes-music-and-sound/gi.test(track.attrs.CHARACTERISTICS); 10316 if (transcribesSpokenDialog && describesMusicAndSound) { 10317 return 'captions'; 10318 } 10319 } 10320 return 'subtitles'; 10321 }; 10322 _proto.onManifestLoaded = function onManifestLoaded(event, data) { 10323 var _this3 = this; 10324 if (this.config.enableCEA708Captions && data.captions) { 10325 data.captions.forEach(function (captionsTrack) { 10326 var instreamIdMatch = /(?:CC|SERVICE)([1-4])/.exec(captionsTrack.instreamId); 10327 if (!instreamIdMatch) { 10328 return; 10329 } 10330 var trackName = "textTrack" + instreamIdMatch[1]; 10331 var trackProperties = _this3.captionsProperties[trackName]; 10332 if (!trackProperties) { 10333 return; 10334 } 10335 trackProperties.label = captionsTrack.name; 10336 if (captionsTrack.lang) { 10337 // optional attribute 10338 trackProperties.languageCode = captionsTrack.lang; 10339 } 10340 trackProperties.media = captionsTrack; 10341 }); 10342 } 10343 }; 10344 _proto.closedCaptionsForLevel = function closedCaptionsForLevel(frag) { 10345 var level = this.hls.levels[frag.level]; 10346 return level === null || level === void 0 ? void 0 : level.attrs['CLOSED-CAPTIONS']; 10347 }; 10348 _proto.onFragLoading = function onFragLoading(event, data) { 10349 var cea608Parser1 = this.cea608Parser1, 10350 cea608Parser2 = this.cea608Parser2, 10351 lastSn = this.lastSn, 10352 lastPartIndex = this.lastPartIndex; 10353 if (!this.enabled || !(cea608Parser1 && cea608Parser2)) { 10354 return; 10355 } 10356 // if this frag isn't contiguous, clear the parser so cues with bad start/end times aren't added to the textTrack 10357 if (data.frag.type === _types_loader__WEBPACK_IMPORTED_MODULE_8__.PlaylistLevelType.MAIN) { 10358 var _data$part$index, _data$part; 10359 var sn = data.frag.sn; 10360 var partIndex = (_data$part$index = data === null || data === void 0 ? void 0 : (_data$part = data.part) === null || _data$part === void 0 ? void 0 : _data$part.index) != null ? _data$part$index : -1; 10361 if (!(sn === lastSn + 1 || sn === lastSn && partIndex === lastPartIndex + 1)) { 10362 cea608Parser1.reset(); 10363 cea608Parser2.reset(); 10364 } 10365 this.lastSn = sn; 10366 this.lastPartIndex = partIndex; 10367 } 10368 }; 10369 _proto.onFragLoaded = function onFragLoaded(event, data) { 10370 var frag = data.frag, 10371 payload = data.payload; 10372 var initPTS = this.initPTS, 10373 unparsedVttFrags = this.unparsedVttFrags; 10374 if (frag.type === _types_loader__WEBPACK_IMPORTED_MODULE_8__.PlaylistLevelType.SUBTITLE) { 10375 // If fragment is subtitle type, parse as WebVTT. 10376 if (payload.byteLength) { 10377 // We need an initial synchronisation PTS. Store fragments as long as none has arrived. 10378 if (!(0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(initPTS[frag.cc])) { 10379 unparsedVttFrags.push(data); 10380 if (initPTS.length) { 10381 // finish unsuccessfully, otherwise the subtitle-stream-controller could be blocked from loading new frags. 10382 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.SUBTITLE_FRAG_PROCESSED, { 10383 success: false, 10384 frag: frag, 10385 error: new Error('Missing initial subtitle PTS') 10386 }); 10387 } 10388 return; 10389 } 10390 var decryptData = frag.decryptdata; 10391 // fragment after decryption has a stats object 10392 var decrypted = ('stats' in data); 10393 // If the subtitles are not encrypted, parse VTTs now. Otherwise, we need to wait. 10394 if (decryptData == null || !decryptData.encrypted || decrypted) { 10395 var trackPlaylistMedia = this.tracks[frag.level]; 10396 var vttCCs = this.vttCCs; 10397 if (!vttCCs[frag.cc]) { 10398 vttCCs[frag.cc] = { 10399 start: frag.start, 10400 prevCC: this.prevCC, 10401 new: true 10402 }; 10403 this.prevCC = frag.cc; 10404 } 10405 if (trackPlaylistMedia && trackPlaylistMedia.textCodec === _utils_imsc1_ttml_parser__WEBPACK_IMPORTED_MODULE_6__.IMSC1_CODEC) { 10406 this._parseIMSC1(frag, payload); 10407 } else { 10408 this._parseVTTs(frag, payload, vttCCs); 10409 } 10410 } 10411 } else { 10412 // In case there is no payload, finish unsuccessfully. 10413 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.SUBTITLE_FRAG_PROCESSED, { 10414 success: false, 10415 frag: frag,
10416 error: new Error('Empty subtitle payload') 10417 }); 10418 } 10419 } 10420 }; 10421 _proto._parseIMSC1 = function _parseIMSC1(frag, payload) { 10422 var _this4 = this; 10423 var hls = this.hls; 10424 (0,_utils_imsc1_ttml_parser__WEBPACK_IMPORTED_MODULE_6__.parseIMSC1)(payload, this.initPTS[frag.cc], this.timescale[frag.cc], function (cues) { 10425 _this4._appendCues(cues, frag.level); 10426 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.SUBTITLE_FRAG_PROCESSED, { 10427 success: true, 10428 frag: frag 10429 }); 10430 }, function (error) { 10431 _utils_logger__WEBPACK_IMPORTED_MODULE_9__.logger.log("Failed to parse IMSC1: " + error); 10432 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.SUBTITLE_FRAG_PROCESSED, { 10433 success: false, 10434 frag: frag, 10435 error: error 10436 }); 10437 }); 10438 }; 10439 _proto._parseVTTs = function _parseVTTs(frag, payload, vttCCs) { 10440 var _frag$initSegment, 10441 _this5 = this; 10442 var hls = this.hls; 10443 // Parse the WebVTT file contents. 10444 var payloadWebVTT = (_frag$initSegment = frag.initSegment) !== null && _frag$initSegment !== void 0 && _frag$initSegment.data ? (0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_7__.appendUint8Array)(frag.initSegment.data, new Uint8Array(payload)) : payload; 10445 (0,_utils_webvtt_parser__WEBPACK_IMPORTED_MODULE_4__.parseWebVTT)(payloadWebVTT, this.initPTS[frag.cc], this.timescale[frag.cc], vttCCs, frag.cc, frag.start, function (cues) { 10446 _this5._appendCues(cues, frag.level); 10447 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.SUBTITLE_FRAG_PROCESSED, { 10448 success: true, 10449 frag: frag 10450 }); 10451 }, function (error) { 10452 _this5._fallbackToIMSC1(frag, payload); 10453 // Something went wrong while parsing. Trigger event with success false. 10454 _utils_logger__WEBPACK_IMPORTED_MODULE_9__.logger.log("Failed to parse VTT cue: " + error); 10455 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.SUBTITLE_FRAG_PROCESSED, { 10456 success: false, 10457 frag: frag, 10458 error: error 10459 }); 10460 }); 10461 }; 10462 _proto._fallbackToIMSC1 = function _fallbackToIMSC1(frag, payload) { 10463 var _this6 = this; 10464 // If textCodec is unknown, try parsing as IMSC1. Set textCodec based on the result 10465 var trackPlaylistMedia = this.tracks[frag.level]; 10466 if (!trackPlaylistMedia.textCodec) { 10467 (0,_utils_imsc1_ttml_parser__WEBPACK_IMPORTED_MODULE_6__.parseIMSC1)(payload, this.initPTS[frag.cc], this.timescale[frag.cc], function () { 10468 trackPlaylistMedia.textCodec = _utils_imsc1_ttml_parser__WEBPACK_IMPORTED_MODULE_6__.IMSC1_CODEC; 10469 _this6._parseIMSC1(frag, payload); 10470 }, function () { 10471 trackPlaylistMedia.textCodec = 'wvtt'; 10472 }); 10473 } 10474 }; 10475 _proto._appendCues = function _appendCues(cues, fragLevel) { 10476 var hls = this.hls; 10477 if (this.config.renderTextTracksNatively) { 10478 var textTrack = this.textTracks[fragLevel]; 10479 // WebVTTParser.parse is an async method and if the currently selected text track mode is set to "disabled" 10480 // before parsing is done then don't try to access currentTrack.cues.getCueById as cues will be null 10481 // and trying to access getCueById method of cues will throw an exception 10482 // Because we check if the mode is disabled, we can force check `cues` below. They can't be null. 10483 if (!textTrack || textTrack.mode === 'disabled') { 10484 return; 10485 } 10486 cues.forEach(function (cue) { 10487 return (0,_utils_texttrack_utils__WEBPACK_IMPORTED_MODULE_5__.addCueToTrack)(textTrack, cue); 10488 }); 10489 } else { 10490 var currentTrack = this.tracks[fragLevel]; 10491 if (!currentTrack) { 10492 return; 10493 } 10494 var track = currentTrack.default ? 'default' : 'subtitles' + fragLevel; 10495 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.CUES_PARSED, { 10496 type: 'subtitles', 10497 cues: cues, 10498 track: track 10499 }); 10500 } 10501 }; 10502 _proto.onFragDecrypted = function onFragDecrypted(event, data) { 10503 var frag = data.frag; 10504 if (frag.type === _types_loader__WEBPACK_IMPORTED_MODULE_8__.PlaylistLevelType.SUBTITLE) { 10505 if (!(0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(this.initPTS[frag.cc])) { 10506 this.unparsedVttFrags.push(data); 10507 return; 10508 } 10509 this.onFragLoaded(_events__WEBPACK_IMPORTED_MODULE_1__.Events.FRAG_LOADED, data); 10510 } 10511 }; 10512 _proto.onSubtitleTracksCleared = function onSubtitleTracksCleared() { 10513 this.tracks = []; 10514 this.captionsTracks = {}; 10515 }; 10516 _proto.onFragParsingUserdata = function onFragParsingUserdata(event, data) { 10517 var cea608Parser1 = this.cea608Parser1, 10518 cea608Parser2 = this.cea608Parser2; 10519 if (!this.enabled || !(cea608Parser1 && cea608Parser2)) { 10520 return; 10521 } 10522 var frag = data.frag, 10523 samples = data.samples; 10524 if (frag.type === _types_loader__WEBPACK_IMPORTED_MODULE_8__.PlaylistLevelType.MAIN && this.closedCaptionsForLevel(frag) === 'NONE') { 10525 return; 10526 } 10527 // If the event contains captions (found in the bytes property), push all bytes into the parser immediately 10528 // It will create the proper timestamps based on the PTS value 10529 for (var i = 0; i < samples.length; i++) {
10530 var ccBytes = samples[i].bytes; 10531 if (ccBytes) { 10532 var ccdatas = this.extractCea608Data(ccBytes); 10533 cea608Parser1.addData(samples[i].pts, ccdatas[0]); 10534 cea608Parser2.addData(samples[i].pts, ccdatas[1]); 10535 } 10536 } 10537 }; 10538 _proto.onBufferFlushing = function onBufferFlushing(event, _ref2) { 10539 var startOffset = _ref2.startOffset, 10540 endOffset = _ref2.endOffset, 10541 endOffsetSubtitles = _ref2.endOffsetSubtitles, 10542 type = _ref2.type; 10543 var media = this.media; 10544 if (!media || media.currentTime < endOffset) { 10545 return; 10546 } 10547 // Clear 608 caption cues from the captions TextTracks when the video back buffer is flushed 10548 // Forward cues are never removed because we can loose streamed 608 content from recent fragments 10549 if (!type || type === 'video') { 10550 var captionsTracks = this.captionsTracks; 10551 Object.keys(captionsTracks).forEach(function (trackName) { 10552 return (0,_utils_texttrack_utils__WEBPACK_IMPORTED_MODULE_5__.removeCuesInRange)(captionsTracks[trackName], startOffset, endOffset); 10553 }); 10554 } 10555 if (this.config.renderTextTracksNatively) { 10556 // Clear VTT/IMSC1 subtitle cues from the subtitle TextTracks when the back buffer is flushed 10557 if (startOffset === 0 && endOffsetSubtitles !== undefined) { 10558 var textTracks = this.textTracks;
vendor: 1,509 bytes, lines 10559-10606
10559 Object.keys(textTracks).forEach(function (trackName) { 10560 return (0,_utils_texttrack_utils__WEBPACK_IMPORTED_MODULE_5__.removeCuesInRange)(textTracks[trackName], startOffset, endOffsetSubtitles); 10561 }); 10562 } 10563 } 10564 }; 10565 _proto.extractCea608Data = function extractCea608Data(byteArray) { 10566 var actualCCBytes = [[], []]; 10567 var count = byteArray[0] & 0x1f; 10568 var position = 2; 10569 for (var j = 0; j < count; j++) { 10570 var tmpByte = byteArray[position++]; 10571 var ccbyte1 = 0x7f & byteArray[position++]; 10572 var ccbyte2 = 0x7f & byteArray[position++]; 10573 if (ccbyte1 === 0 && ccbyte2 === 0) { 10574 continue; 10575 } 10576 var ccValid = (0x04 & tmpByte) !== 0; // Support all four channels 10577 if (ccValid) { 10578 var ccType = 0x03 & tmpByte; 10579 if (0x00 /* CEA608 field1*/ === ccType || 0x01 /* CEA608 field2*/ === ccType) { 10580 // Exclude CEA708 CC data. 10581 actualCCBytes[ccType].push(ccbyte1); 10582 actualCCBytes[ccType].push(ccbyte2); 10583 } 10584 } 10585 } 10586 return actualCCBytes; 10587 }; 10588 return TimelineController; 10589}(); 10590function canReuseVttTextTrack(inUseTrack, manifestTrack) { 10591 return inUseTrack && inUseTrack.label === manifestTrack.name && !(inUseTrack.textTrack1 || inUseTrack.textTrack2); 10592} 10593function intersection(x1, x2, y1, y2) { 10594 return Math.min(x2, y2) - Math.max(x1, y1); 10595} 10596function newVTTCCs() { 10597 return { 10598 ccOffset: 0, 10599 presentationOffset: 0, 10600 0: { 10601 start: 0, 10602 prevCC: -1, 10603 new: true 10604 } 10605 }; 10606}
vendor: 13,187 bytes, lines 10606-10967
10606 10607 10608/***/ }), 10609 10610/***/ "./src/crypt/aes-crypto.ts": 10611/*!*********************************!*\ 10612 !*** ./src/crypt/aes-crypto.ts ***! 10613 \*********************************/ 10614/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 10615 10616"use strict"; 10617__webpack_require__.r(__webpack_exports__); 10618/* harmony export */ __webpack_require__.d(__webpack_exports__, { 10619/* harmony export */ "default": () => (/* binding */ AESCrypto) 10620/* harmony export */ }); 10621var AESCrypto = /*#__PURE__*/function () { 10622 function AESCrypto(subtle, iv) { 10623 this.subtle = void 0; 10624 this.aesIV = void 0; 10625 this.subtle = subtle; 10626 this.aesIV = iv; 10627 } 10628 var _proto = AESCrypto.prototype; 10629 _proto.decrypt = function decrypt(data, key) { 10630 return this.subtle.decrypt({ 10631 name: 'AES-CBC', 10632 iv: this.aesIV 10633 }, key, data); 10634 }; 10635 return AESCrypto; 10636}(); 10637 10638 10639/***/ }), 10640 10641/***/ "./src/crypt/aes-decryptor.ts": 10642/*!************************************!*\ 10643 !*** ./src/crypt/aes-decryptor.ts ***! 10644 \************************************/ 10645/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 10646 10647"use strict"; 10648__webpack_require__.r(__webpack_exports__); 10649/* harmony export */ __webpack_require__.d(__webpack_exports__, { 10650/* harmony export */ "default": () => (/* binding */ AESDecryptor), 10651/* harmony export */ "removePadding": () => (/* binding */ removePadding) 10652/* harmony export */ }); 10653/* harmony import */ var _utils_typed_array__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils/typed-array */ "./src/utils/typed-array.ts"); 10654 10655 10656// PKCS7 10657function removePadding(array) { 10658 var outputBytes = array.byteLength; 10659 var paddingBytes = outputBytes && new DataView(array.buffer).getUint8(outputBytes - 1); 10660 if (paddingBytes) { 10661 return (0,_utils_typed_array__WEBPACK_IMPORTED_MODULE_0__.sliceUint8)(array, 0, outputBytes - paddingBytes); 10662 } 10663 return array; 10664} 10665var AESDecryptor = /*#__PURE__*/function () { 10666 function AESDecryptor() { 10667 this.rcon = [0x0, 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36]; 10668 this.subMix = [new Uint32Array(256), new Uint32Array(256), new Uint32Array(256), new Uint32Array(256)]; 10669 this.invSubMix = [new Uint32Array(256), new Uint32Array(256), new Uint32Array(256), new Uint32Array(256)]; 10670 this.sBox = new Uint32Array(256); 10671 this.invSBox = new Uint32Array(256); 10672 this.key = new Uint32Array(0); 10673 this.ksRows = 0; 10674 this.keySize = 0; 10675 this.keySchedule = void 0; 10676 this.invKeySchedule = void 0; 10677 this.initTable(); 10678 } 10679 10680 // Using view.getUint32() also swaps the byte order. 10681 var _proto = AESDecryptor.prototype; 10682 _proto.uint8ArrayToUint32Array_ = function uint8ArrayToUint32Array_(arrayBuffer) { 10683 var view = new DataView(arrayBuffer); 10684 var newArray = new Uint32Array(4); 10685 for (var i = 0; i < 4; i++) { 10686 newArray[i] = view.getUint32(i * 4); 10687 } 10688 return newArray; 10689 }; 10690 _proto.initTable = function initTable() { 10691 var sBox = this.sBox; 10692 var invSBox = this.invSBox; 10693 var subMix = this.subMix; 10694 var subMix0 = subMix[0]; 10695 var subMix1 = subMix[1]; 10696 var subMix2 = subMix[2]; 10697 var subMix3 = subMix[3]; 10698 var invSubMix = this.invSubMix; 10699 var invSubMix0 = invSubMix[0]; 10700 var invSubMix1 = invSubMix[1]; 10701 var invSubMix2 = invSubMix[2]; 10702 var invSubMix3 = invSubMix[3]; 10703 var d = new Uint32Array(256); 10704 var x = 0; 10705 var xi = 0; 10706 var i = 0; 10707 for (i = 0; i < 256; i++) { 10708 if (i < 128) { 10709 d[i] = i << 1; 10710 } else { 10711 d[i] = i << 1 ^ 0x11b; 10712 } 10713 } 10714 for (i = 0; i < 256; i++) { 10715 var sx = xi ^ xi << 1 ^ xi << 2 ^ xi << 3 ^ xi << 4; 10716 sx = sx >>> 8 ^ sx & 0xff ^ 0x63; 10717 sBox[x] = sx; 10718 invSBox[sx] = x; 10719 10720 // Compute multiplication 10721 var x2 = d[x]; 10722 var x4 = d[x2]; 10723 var x8 = d[x4]; 10724 10725 // Compute sub/invSub bytes, mix columns tables 10726 var t = d[sx] * 0x101 ^ sx * 0x1010100; 10727 subMix0[x] = t << 24 | t >>> 8; 10728 subMix1[x] = t << 16 | t >>> 16; 10729 subMix2[x] = t << 8 | t >>> 24; 10730 subMix3[x] = t; 10731 10732 // Compute inv sub bytes, inv mix columns tables 10733 t = x8 * 0x1010101 ^ x4 * 0x10001 ^ x2 * 0x101 ^ x * 0x1010100; 10734 invSubMix0[sx] = t << 24 | t >>> 8; 10735 invSubMix1[sx] = t << 16 | t >>> 16; 10736 invSubMix2[sx] = t << 8 | t >>> 24; 10737 invSubMix3[sx] = t; 10738 10739 // Compute next counter 10740 if (!x) { 10741 x = xi = 1; 10742 } else { 10743 x = x2 ^ d[d[d[x8 ^ x2]]]; 10744 xi ^= d[d[xi]]; 10745 } 10746 } 10747 }; 10748 _proto.expandKey = function expandKey(keyBuffer) { 10749 // convert keyBuffer to Uint32Array 10750 var key = this.uint8ArrayToUint32Array_(keyBuffer); 10751 var sameKey = true; 10752 var offset = 0; 10753 while (offset < key.length && sameKey) { 10754 sameKey = key[offset] === this.key[offset]; 10755 offset++; 10756 } 10757 if (sameKey) { 10758 return; 10759 } 10760 this.key = key; 10761 var keySize = this.keySize = key.length; 10762 if (keySize !== 4 && keySize !== 6 && keySize !== 8) { 10763 throw new Error('Invalid aes key size=' + keySize); 10764 } 10765 var ksRows = this.ksRows = (keySize + 6 + 1) * 4; 10766 var ksRow; 10767 var invKsRow; 10768 var keySchedule = this.keySchedule = new Uint32Array(ksRows); 10769 var invKeySchedule = this.invKeySchedule = new Uint32Array(ksRows); 10770 var sbox = this.sBox; 10771 var rcon = this.rcon; 10772 var invSubMix = this.invSubMix; 10773 var invSubMix0 = invSubMix[0]; 10774 var invSubMix1 = invSubMix[1]; 10775 var invSubMix2 = invSubMix[2]; 10776 var invSubMix3 = invSubMix[3]; 10777 var prev; 10778 var t; 10779 for (ksRow = 0; ksRow < ksRows; ksRow++) { 10780 if (ksRow < keySize) { 10781 prev = keySchedule[ksRow] = key[ksRow]; 10782 continue; 10783 } 10784 t = prev; 10785 if (ksRow % keySize === 0) { 10786 // Rot word 10787 t = t << 8 | t >>> 24; 10788 10789 // Sub word 10790 t = sbox[t >>> 24] << 24 | sbox[t >>> 16 & 0xff] << 16 | sbox[t >>> 8 & 0xff] << 8 | sbox[t & 0xff]; 10791 10792 // Mix Rcon 10793 t ^= rcon[ksRow / keySize | 0] << 24; 10794 } else if (keySize > 6 && ksRow % keySize === 4) { 10795 // Sub word 10796 t = sbox[t >>> 24] << 24 | sbox[t >>> 16 & 0xff] << 16 | sbox[t >>> 8 & 0xff] << 8 | sbox[t & 0xff]; 10797 } 10798 keySchedule[ksRow] = prev = (keySchedule[ksRow - keySize] ^ t) >>> 0; 10799 } 10800 for (invKsRow = 0; invKsRow < ksRows; invKsRow++) { 10801 ksRow = ksRows - invKsRow; 10802 if (invKsRow & 3) { 10803 t = keySchedule[ksRow]; 10804 } else { 10805 t = keySchedule[ksRow - 4]; 10806 } 10807 if (invKsRow < 4 || ksRow <= 4) { 10808 invKeySchedule[invKsRow] = t; 10809 } else { 10810 invKeySchedule[invKsRow] = invSubMix0[sbox[t >>> 24]] ^ invSubMix1[sbox[t >>> 16 & 0xff]] ^ invSubMix2[sbox[t >>> 8 & 0xff]] ^ invSubMix3[sbox[t & 0xff]]; 10811 } 10812 invKeySchedule[invKsRow] = invKeySchedule[invKsRow] >>> 0; 10813 } 10814 } 10815 10816 // Adding this as a method greatly improves performance. 10817 ; 10818 _proto.networkToHostOrderSwap = function networkToHostOrderSwap(word) { 10819 return word << 24 | (word & 0xff00) << 8 | (word & 0xff0000) >> 8 | word >>> 24; 10820 }; 10821 _proto.decrypt = function decrypt(inputArrayBuffer, offset, aesIV) { 10822 var nRounds = this.keySize + 6; 10823 var invKeySchedule = this.invKeySchedule; 10824 var invSBOX = this.invSBox; 10825 var invSubMix = this.invSubMix; 10826 var invSubMix0 = invSubMix[0]; 10827 var invSubMix1 = invSubMix[1]; 10828 var invSubMix2 = invSubMix[2]; 10829 var invSubMix3 = invSubMix[3]; 10830 var initVector = this.uint8ArrayToUint32Array_(aesIV); 10831 var initVector0 = initVector[0]; 10832 var initVector1 = initVector[1]; 10833 var initVector2 = initVector[2]; 10834 var initVector3 = initVector[3]; 10835 var inputInt32 = new Int32Array(inputArrayBuffer); 10836 var outputInt32 = new Int32Array(inputInt32.length); 10837 var t0, t1, t2, t3; 10838 var s0, s1, s2, s3; 10839 var inputWords0, inputWords1, inputWords2, inputWords3; 10840 var ksRow, i; 10841 var swapWord = this.networkToHostOrderSwap; 10842 while (offset < inputInt32.length) { 10843 inputWords0 = swapWord(inputInt32[offset]); 10844 inputWords1 = swapWord(inputInt32[offset + 1]); 10845 inputWords2 = swapWord(inputInt32[offset + 2]); 10846 inputWords3 = swapWord(inputInt32[offset + 3]); 10847 s0 = inputWords0 ^ invKeySchedule[0]; 10848 s1 = inputWords3 ^ invKeySchedule[1]; 10849 s2 = inputWords2 ^ invKeySchedule[2]; 10850 s3 = inputWords1 ^ invKeySchedule[3]; 10851 ksRow = 4; 10852 10853 // Iterate through the rounds of decryption 10854 for (i = 1; i < nRounds; i++) { 10855 t0 = invSubMix0[s0 >>> 24] ^ invSubMix1[s1 >> 16 & 0xff] ^ invSubMix2[s2 >> 8 & 0xff] ^ invSubMix3[s3 & 0xff] ^ invKeySchedule[ksRow]; 10856 t1 = invSubMix0[s1 >>> 24] ^ invSubMix1[s2 >> 16 & 0xff] ^ invSubMix2[s3 >> 8 & 0xff] ^ invSubMix3[s0 & 0xff] ^ invKeySchedule[ksRow + 1]; 10857 t2 = invSubMix0[s2 >>> 24] ^ invSubMix1[s3 >> 16 & 0xff] ^ invSubMix2[s0 >> 8 & 0xff] ^ invSubMix3[s1 & 0xff] ^ invKeySchedule[ksRow + 2]; 10858 t3 = invSubMix0[s3 >>> 24] ^ invSubMix1[s0 >> 16 & 0xff] ^ invSubMix2[s1 >> 8 & 0xff] ^ invSubMix3[s2 & 0xff] ^ invKeySchedule[ksRow + 3]; 10859 // Update state 10860 s0 = t0; 10861 s1 = t1; 10862 s2 = t2; 10863 s3 = t3; 10864 ksRow = ksRow + 4; 10865 } 10866 10867 // Shift rows, sub bytes, add round key 10868 t0 = invSBOX[s0 >>> 24] << 24 ^ invSBOX[s1 >> 16 & 0xff] << 16 ^ invSBOX[s2 >> 8 & 0xff] << 8 ^ invSBOX[s3 & 0xff] ^ invKeySchedule[ksRow]; 10869 t1 = invSBOX[s1 >>> 24] << 24 ^ invSBOX[s2 >> 16 & 0xff] << 16 ^ invSBOX[s3 >> 8 & 0xff] << 8 ^ invSBOX[s0 & 0xff] ^ invKeySchedule[ksRow + 1]; 10870 t2 = invSBOX[s2 >>> 24] << 24 ^ invSBOX[s3 >> 16 & 0xff] << 16 ^ invSBOX[s0 >> 8 & 0xff] << 8 ^ invSBOX[s1 & 0xff] ^ invKeySchedule[ksRow + 2]; 10871 t3 = invSBOX[s3 >>> 24] << 24 ^ invSBOX[s0 >> 16 & 0xff] << 16 ^ invSBOX[s1 >> 8 & 0xff] << 8 ^ invSBOX[s2 & 0xff] ^ invKeySchedule[ksRow + 3]; 10872 10873 // Write 10874 outputInt32[offset] = swapWord(t0 ^ initVector0); 10875 outputInt32[offset + 1] = swapWord(t3 ^ initVector1); 10876 outputInt32[offset + 2] = swapWord(t2 ^ initVector2); 10877 outputInt32[offset + 3] = swapWord(t1 ^ initVector3); 10878 10879 // reset initVector to last 4 unsigned int 10880 initVector0 = inputWords0; 10881 initVector1 = inputWords1; 10882 initVector2 = inputWords2; 10883 initVector3 = inputWords3; 10884 offset = offset + 4; 10885 } 10886 return outputInt32.buffer; 10887 }; 10888 return AESDecryptor; 10889}(); 10890 10891 10892/***/ }), 10893 10894/***/ "./src/crypt/decrypter.ts": 10895/*!********************************!*\ 10896 !*** ./src/crypt/decrypter.ts ***! 10897 \********************************/ 10898/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 10899 10900"use strict"; 10901__webpack_require__.r(__webpack_exports__); 10902/* harmony export */ __webpack_require__.d(__webpack_exports__, { 10903/* harmony export */ "default": () => (/* binding */ Decrypter) 10904/* harmony export */ }); 10905/* harmony import */ var _aes_crypto__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./aes-crypto */ "./src/crypt/aes-crypto.ts"); 10906/* harmony import */ var _fast_aes_key__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./fast-aes-key */ "./src/crypt/fast-aes-key.ts"); 10907/* harmony import */ var _aes_decryptor__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./aes-decryptor */ "./src/crypt/aes-decryptor.ts"); 10908/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 10909/* harmony import */ var _utils_mp4_tools__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../utils/mp4-tools */ "./src/utils/mp4-tools.ts"); 10910/* harmony import */ var _utils_typed_array__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../utils/typed-array */ "./src/utils/typed-array.ts"); 10911 10912 10913 10914 10915 10916 10917var CHUNK_SIZE = 16; // 16 bytes, 128 bits 10918var Decrypter = /*#__PURE__*/function () { 10919 function Decrypter(config, _temp) { 10920 var _ref = _temp === void 0 ? {} : _temp, 10921 _ref$removePKCS7Paddi = _ref.removePKCS7Padding, 10922 removePKCS7Padding = _ref$removePKCS7Paddi === void 0 ? true : _ref$removePKCS7Paddi; 10923 this.logEnabled = true; 10924 this.removePKCS7Padding = void 0; 10925 this.subtle = null; 10926 this.softwareDecrypter = null; 10927 this.key = null; 10928 this.fastAesKey = null; 10929 this.remainderData = null; 10930 this.currentIV = null; 10931 this.currentResult = null; 10932 this.useSoftware = void 0; 10933 this.useSoftware = config.enableSoftwareAES; 10934 this.removePKCS7Padding = removePKCS7Padding; 10935 // built in decryptor expects PKCS7 padding 10936 if (removePKCS7Padding) { 10937 try { 10938 var browserCrypto = self.crypto; 10939 if (browserCrypto) { 10940 this.subtle = browserCrypto.subtle || browserCrypto.webkitSubtle; 10941 } 10942 } catch (e) { 10943 /* no-op */ 10944 } 10945 } 10946 if (this.subtle === null) { 10947 this.useSoftware = true; 10948 } 10949 } 10950 var _proto = Decrypter.prototype; 10951 _proto.destroy = function destroy() { 10952 this.subtle = null; 10953 this.softwareDecrypter = null; 10954 this.key = null; 10955 this.fastAesKey = null; 10956 this.remainderData = null; 10957 this.currentIV = null; 10958 this.currentResult = null; 10959 }; 10960 _proto.isSync = function isSync() { 10961 return this.useSoftware; 10962 }; 10963 _proto.flush = function flush() { 10964 var currentResult = this.currentResult, 10965 remainderData = this.remainderData; 10966 if (!currentResult || remainderData) { 10967
10967_utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger.error("[softwareDecrypt] " + (remainderData ? 'overflow bytes: ' + remainderData.byteLength : 'no result'));
vendor: 112,563 bytes, lines 10967-13931
10967 10968 this.reset(); 10969 return null; 10970 } 10971 var data = new Uint8Array(currentResult); 10972 this.reset(); 10973 if (this.removePKCS7Padding) { 10974 return (0,_aes_decryptor__WEBPACK_IMPORTED_MODULE_2__.removePadding)(data); 10975 } 10976 return data; 10977 }; 10978 _proto.reset = function reset() { 10979 this.currentResult = null; 10980 this.currentIV = null; 10981 this.remainderData = null; 10982 if (this.softwareDecrypter) { 10983 this.softwareDecrypter = null; 10984 } 10985 }; 10986 _proto.decrypt = function decrypt(data, key, iv) { 10987 var _this = this; 10988 if (this.useSoftware) { 10989 return new Promise(function (resolve, reject) { 10990 _this.softwareDecrypt(new Uint8Array(data), key, iv); 10991 var decryptResult = _this.flush(); 10992 if (decryptResult) { 10993 resolve(decryptResult.buffer); 10994 } else { 10995 reject(new Error('[softwareDecrypt] Failed to decrypt data')); 10996 } 10997 }); 10998 } 10999 return this.webCryptoDecrypt(new Uint8Array(data), key, iv); 11000 } 11001 11002 // Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached 11003 // data is handled in the flush() call 11004 ; 11005 _proto.softwareDecrypt = function softwareDecrypt(data, key, iv) { 11006 var currentIV = this.currentIV, 11007 currentResult = this.currentResult, 11008 remainderData = this.remainderData; 11009 this.logOnce('JS AES decrypt'); 11010 // The output is staggered during progressive parsing - the current result is cached, and emitted on the next call 11011 // This is done in order to strip PKCS7 padding, which is found at the end of each segment. We only know we've reached 11012 // the end on flush(), but by that time we have already received all bytes for the segment. 11013 // Progressive decryption does not work with WebCrypto 11014 11015 if (remainderData) { 11016 data = (0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_4__.appendUint8Array)(remainderData, data); 11017 this.remainderData = null; 11018 } 11019 11020 // Byte length must be a multiple of 16 (AES-128 = 128 bit blocks = 16 bytes) 11021 var currentChunk = this.getValidChunk(data); 11022 if (!currentChunk.length) { 11023 return null; 11024 } 11025 if (currentIV) { 11026 iv = currentIV; 11027 } 11028 var softwareDecrypter = this.softwareDecrypter; 11029 if (!softwareDecrypter) { 11030 softwareDecrypter = this.softwareDecrypter = new _aes_decryptor__WEBPACK_IMPORTED_MODULE_2__["default"](); 11031 } 11032 softwareDecrypter.expandKey(key); 11033 var result = currentResult; 11034 this.currentResult = softwareDecrypter.decrypt(currentChunk.buffer, 0, iv); 11035 this.currentIV = (0,_utils_typed_array__WEBPACK_IMPORTED_MODULE_5__.sliceUint8)(currentChunk, -16).buffer; 11036 if (!result) { 11037 return null; 11038 } 11039 return result; 11040 }; 11041 _proto.webCryptoDecrypt = function webCryptoDecrypt(data, key, iv) { 11042 var _this2 = this; 11043 var subtle = this.subtle; 11044 if (this.key !== key || !this.fastAesKey) { 11045 this.key = key; 11046 this.fastAesKey = new _fast_aes_key__WEBPACK_IMPORTED_MODULE_1__["default"](subtle, key); 11047 } 11048 return this.fastAesKey.expandKey().then(function (aesKey) { 11049 // decrypt using web crypto 11050 if (!subtle) { 11051 return Promise.reject(new Error('web crypto not initialized')); 11052 } 11053 _this2.logOnce('WebCrypto AES decrypt'); 11054 var crypto = new _aes_crypto__WEBPACK_IMPORTED_MODULE_0__["default"](subtle, new Uint8Array(iv)); 11055 return crypto.decrypt(data.buffer, aesKey); 11056 }).catch(function (err) { 11057 _utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger.warn("[decrypter]: WebCrypto Error, disable WebCrypto API, " + err.name + ": " + err.message); 11058 return _this2.onWebCryptoError(data, key, iv); 11059 }); 11060 }; 11061 _proto.onWebCryptoError = function onWebCryptoError(data, key, iv) { 11062 this.useSoftware = true; 11063 this.logEnabled = true; 11064 this.softwareDecrypt(data, key, iv); 11065 var decryptResult = this.flush(); 11066 if (decryptResult) { 11067 return decryptResult.buffer; 11068 } 11069 throw new Error('WebCrypto and softwareDecrypt: failed to decrypt data'); 11070 }; 11071 _proto.getValidChunk = function getValidChunk(data) { 11072 var currentChunk = data; 11073 var splitPoint = data.length - data.length % CHUNK_SIZE; 11074 if (splitPoint !== data.length) { 11075 currentChunk = (0,_utils_typed_array__WEBPACK_IMPORTED_MODULE_5__.sliceUint8)(data, 0, splitPoint); 11076 this.remainderData = (0,_utils_typed_array__WEBPACK_IMPORTED_MODULE_5__.sliceUint8)(data, splitPoint); 11077 } 11078 return currentChunk; 11079 }; 11080 _proto.logOnce = function logOnce(msg) { 11081 if (!this.logEnabled) { 11082 return; 11083 } 11084 _utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger.log("[decrypter]: " + msg); 11085 this.logEnabled = false; 11086 }; 11087 return Decrypter; 11088}(); 11089 11090 11091/***/ }), 11092 11093/***/ "./src/crypt/fast-aes-key.ts": 11094/*!***********************************!*\ 11095 !*** ./src/crypt/fast-aes-key.ts ***! 11096 \***********************************/ 11097/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 11098 11099"use strict"; 11100__webpack_require__.r(__webpack_exports__); 11101/* harmony export */ __webpack_require__.d(__webpack_exports__, { 11102/* harmony export */ "default": () => (/* binding */ FastAESKey) 11103/* harmony export */ }); 11104var FastAESKey = /*#__PURE__*/function () { 11105 function FastAESKey(subtle, key) { 11106 this.subtle = void 0; 11107 this.key = void 0; 11108 this.subtle = subtle; 11109 this.key = key; 11110 } 11111 var _proto = FastAESKey.prototype; 11112 _proto.expandKey = function expandKey() { 11113 return this.subtle.importKey('raw', this.key, { 11114 name: 'AES-CBC' 11115 }, false, ['encrypt', 'decrypt']); 11116 }; 11117 return FastAESKey; 11118}(); 11119 11120 11121/***/ }), 11122 11123/***/ "./src/demux/aacdemuxer.ts": 11124/*!*********************************!*\ 11125 !*** ./src/demux/aacdemuxer.ts ***! 11126 \*********************************/ 11127/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 11128 11129"use strict"; 11130__webpack_require__.r(__webpack_exports__); 11131/* harmony export */ __webpack_require__.d(__webpack_exports__, { 11132/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 11133/* harmony export */ }); 11134/* harmony import */ var _base_audio_demuxer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./base-audio-demuxer */ "./src/demux/base-audio-demuxer.ts"); 11135/* harmony import */ var _adts__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./adts */ "./src/demux/adts.ts"); 11136/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 11137/* harmony import */ var _demux_id3__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../demux/id3 */ "./src/demux/id3.ts"); 11138function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); } 11139function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } 11140/** 11141 * AAC demuxer 11142 */ 11143 11144 11145 11146 11147var AACDemuxer = /*#__PURE__*/function (_BaseAudioDemuxer) { 11148 _inheritsLoose(AACDemuxer, _BaseAudioDemuxer); 11149 function AACDemuxer(observer, config) { 11150 var _this; 11151 _this = _BaseAudioDemuxer.call(this) || this; 11152 _this.observer = void 0; 11153 _this.config = void 0; 11154 _this.observer = observer; 11155 _this.config = config; 11156 return _this; 11157 } 11158 var _proto = AACDemuxer.prototype; 11159 _proto.resetInitSegment = function resetInitSegment(initSegment, audioCodec, videoCodec, trackDuration) { 11160 _BaseAudioDemuxer.prototype.resetInitSegment.call(this, initSegment, audioCodec, videoCodec, trackDuration); 11161 this._audioTrack = { 11162 container: 'audio/adts', 11163 type: 'audio', 11164 id: 2, 11165 pid: -1, 11166 sequenceNumber: 0, 11167 segmentCodec: 'aac', 11168 samples: [], 11169 manifestCodec: audioCodec, 11170 duration: trackDuration, 11171 inputTimeScale: 90000, 11172 dropped: 0 11173 }; 11174 } 11175 11176 // Source for probe info - https://wiki.multimedia.cx/index.php?title=ADTS 11177 ; 11178 AACDemuxer.probe = function probe(data) { 11179 if (!data) { 11180 return false; 11181 } 11182 11183 // Check for the ADTS sync word 11184 // Look for ADTS header | 1111 1111 | 1111 X00X | where X can be either 0 or 1 11185 // Layer bits (position 14 and 15) in header should be always 0 for ADTS 11186 // More info https://wiki.multimedia.cx/index.php?title=ADTS 11187 var id3Data = _demux_id3__WEBPACK_IMPORTED_MODULE_3__.getID3Data(data, 0) || []; 11188 var offset = id3Data.length; 11189 for (var length = data.length; offset < length; offset++) { 11190 if (_adts__WEBPACK_IMPORTED_MODULE_1__.probe(data, offset)) { 11191 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.log('ADTS sync word found !'); 11192 return true; 11193 } 11194 } 11195 return false; 11196 }; 11197 _proto.canParse = function canParse(data, offset) { 11198 return _adts__WEBPACK_IMPORTED_MODULE_1__.canParse(data, offset); 11199 }; 11200 _proto.appendFrame = function appendFrame(track, data, offset) { 11201 _adts__WEBPACK_IMPORTED_MODULE_1__.initTrackConfig(track, this.observer, data, offset, track.manifestCodec); 11202 var frame = _adts__WEBPACK_IMPORTED_MODULE_1__.appendFrame(track, data, offset, this.basePTS, this.frameIndex); 11203 if (frame && frame.missing === 0) { 11204 return frame; 11205 } 11206 }; 11207 return AACDemuxer; 11208}(_base_audio_demuxer__WEBPACK_IMPORTED_MODULE_0__["default"]); 11209/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AACDemuxer); 11210 11211/***/ }), 11212 11213/***/ "./src/demux/adts.ts": 11214/*!***************************!*\ 11215 !*** ./src/demux/adts.ts ***! 11216 \***************************/ 11217/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 11218 11219"use strict"; 11220__webpack_require__.r(__webpack_exports__); 11221/* harmony export */ __webpack_require__.d(__webpack_exports__, { 11222/* harmony export */ "appendFrame": () => (/* binding */ appendFrame), 11223/* harmony export */ "canGetFrameLength": () => (/* binding */ canGetFrameLength), 11224/* harmony export */ "canParse": () => (/* binding */ canParse), 11225/* harmony export */ "getAudioConfig": () => (/* binding */ getAudioConfig), 11226/* harmony export */ "getFrameDuration": () => (/* binding */ getFrameDuration), 11227/* harmony export */ "getFullFrameLength": () => (/* binding */ getFullFrameLength), 11228/* harmony export */ "getHeaderLength": () => (/* binding */ getHeaderLength), 11229/* harmony export */ "initTrackConfig": () => (/* binding */ initTrackConfig), 11230/* harmony export */ "isHeader": () => (/* binding */ isHeader), 11231/* harmony export */ "isHeaderPattern": () => (/* binding */ isHeaderPattern), 11232/* harmony export */ "parseFrameHeader": () => (/* binding */ parseFrameHeader), 11233/* harmony export */ "probe": () => (/* binding */ probe) 11234/* harmony export */ }); 11235/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 11236/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../errors */ "./src/errors.ts"); 11237/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 11238/** 11239 * ADTS parser helper 11240 * @link https://wiki.multimedia.cx/index.php?title=ADTS 11241 */ 11242 11243 11244 11245function getAudioConfig(observer, data, offset, audioCodec) { 11246 var adtsObjectType; 11247 var adtsExtensionSamplingIndex; 11248 var adtsChannelConfig; 11249 var config; 11250 var userAgent = navigator.userAgent.toLowerCase(); 11251 var manifestCodec = audioCodec; 11252 var adtsSamplingRates = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350]; 11253 // byte 2 11254 adtsObjectType = ((data[offset + 2] & 0xc0) >>> 6) + 1; 11255 var adtsSamplingIndex = (data[offset + 2] & 0x3c) >>> 2; 11256 if (adtsSamplingIndex > adtsSamplingRates.length - 1) { 11257 observer.trigger(_events__WEBPACK_IMPORTED_MODULE_2__.Events.ERROR, { 11258 type: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorTypes.MEDIA_ERROR, 11259 details: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorDetails.FRAG_PARSING_ERROR, 11260 fatal: true, 11261 reason: "invalid ADTS sampling index:" + adtsSamplingIndex 11262 }); 11263 return; 11264 } 11265 adtsChannelConfig = (data[offset + 2] & 0x01) << 2; 11266 // byte 3 11267 adtsChannelConfig |= (data[offset + 3] & 0xc0) >>> 6; 11268 _utils_logger__WEBPACK_IMPORTED_MODULE_0__.logger.log("manifest codec:" + audioCodec + ", ADTS type:" + adtsObjectType + ", samplingIndex:" + adtsSamplingIndex); 11269 // firefox: freq less than 24kHz = AAC SBR (HE-AAC) 11270 if (/firefox/i.test(userAgent)) { 11271 if (adtsSamplingIndex >= 6) { 11272 adtsObjectType = 5; 11273 config = new Array(4); 11274 // HE-AAC uses SBR (Spectral Band Replication) , high frequencies are constructed from low frequencies 11275 // there is a factor 2 between frame sample rate and output sample rate 11276 // multiply frequency by 2 (see table below, equivalent to substract 3) 11277 adtsExtensionSamplingIndex = adtsSamplingIndex - 3; 11278 } else { 11279 adtsObjectType = 2; 11280 config = new Array(2); 11281 adtsExtensionSamplingIndex = adtsSamplingIndex; 11282 } 11283 // Android : always use AAC 11284 } else if (userAgent.indexOf('android') !== -1) { 11285 adtsObjectType = 2; 11286 config = new Array(2); 11287 adtsExtensionSamplingIndex = adtsSamplingIndex; 11288 } else { 11289 /* for other browsers (Chrome/Vivaldi/Opera ...) 11290 always force audio type to be HE-AAC SBR, as some browsers do not support audio codec switch properly (like Chrome ...) 11291 */ 11292 adtsObjectType = 5; 11293 config = new Array(4); 11294 // if (manifest codec is HE-AAC or HE-AACv2) OR (manifest codec not specified AND frequency less than 24kHz) 11295 if (audioCodec && (audioCodec.indexOf('mp4a.40.29') !== -1 || audioCodec.indexOf('mp4a.40.5') !== -1) || !audioCodec && adtsSamplingIndex >= 6) { 11296 // HE-AAC uses SBR (Spectral Band Replication) , high frequencies are constructed from low frequencies 11297 // there is a factor 2 between frame sample rate and output sample rate 11298 // multiply frequency by 2 (see table below, equivalent to substract 3) 11299 adtsExtensionSamplingIndex = adtsSamplingIndex - 3; 11300 } else { 11301 // if (manifest codec is AAC) AND (frequency less than 24kHz AND nb channel is 1) OR (manifest codec not specified and mono audio) 11302 // Chrome fails to play back with low frequency AAC LC mono when initialized with HE-AAC. This is not a problem with stereo. 11303 if (audioCodec && audioCodec.indexOf('mp4a.40.2') !== -1 && (adtsSamplingIndex >= 6 && adtsChannelConfig === 1 || /vivaldi/i.test(userAgent)) || !audioCodec && adtsChannelConfig === 1) { 11304 adtsObjectType = 2; 11305 config = new Array(2); 11306 } 11307 adtsExtensionSamplingIndex = adtsSamplingIndex; 11308 } 11309 } 11310 /* refer to http://wiki.multimedia.cx/index.php?title=MPEG-4_Audio#Audio_Specific_Config 11311 ISO 14496-3 (AAC).pdf - Table 1.13 — Syntax of AudioSpecificConfig() 11312 Audio Profile / Audio Object Type 11313 0: Null 11314 1: AAC Main 11315 2: AAC LC (Low Complexity) 11316 3: AAC SSR (Scalable Sample Rate) 11317 4: AAC LTP (Long Term Prediction) 11318 5: SBR (Spectral Band Replication) 11319 6: AAC Scalable 11320 sampling freq 11321 0: 96000 Hz 11322 1: 88200 Hz 11323 2: 64000 Hz 11324 3: 48000 Hz 11325 4: 44100 Hz 11326 5: 32000 Hz 11327 6: 24000 Hz 11328 7: 22050 Hz 11329 8: 16000 Hz 11330 9: 12000 Hz 11331 10: 11025 Hz 11332 11: 8000 Hz 11333 12: 7350 Hz 11334 13: Reserved 11335 14: Reserved 11336 15: frequency is written explictly 11337 Channel Configurations 11338 These are the channel configurations: 11339 0: Defined in AOT Specifc Config 11340 1: 1 channel: front-center 11341 2: 2 channels: front-left, front-right 11342 */ 11343 // audioObjectType = profile => profile, the MPEG-4 Audio Object Type minus 1 11344 config[0] = adtsObjectType << 3; 11345 // samplingFrequencyIndex 11346 config[0] |= (adtsSamplingIndex & 0x0e) >> 1; 11347 config[1] |= (adtsSamplingIndex & 0x01) << 7; 11348 // channelConfiguration 11349 config[1] |= adtsChannelConfig << 3; 11350 if (adtsObjectType === 5) { 11351 // adtsExtensionSamplingIndex 11352 config[1] |= (adtsExtensionSamplingIndex & 0x0e) >> 1; 11353 config[2] = (adtsExtensionSamplingIndex & 0x01) << 7; 11354 // adtsObjectType (force to 2, chrome is checking that object type is less than 5 ??? 11355 // https://chromium.googlesource.com/chromium/src.git/+/master/media/formats/mp4/aac.cc 11356 config[2] |= 2 << 2; 11357 config[3] = 0; 11358 } 11359 return { 11360 config: config, 11361 samplerate: adtsSamplingRates[adtsSamplingIndex], 11362 channelCount: adtsChannelConfig, 11363 codec: 'mp4a.40.' + adtsObjectType, 11364 manifestCodec: manifestCodec 11365 }; 11366} 11367function isHeaderPattern(data, offset) { 11368 return data[offset] === 0xff && (data[offset + 1] & 0xf6) === 0xf0; 11369} 11370function getHeaderLength(data, offset) { 11371 return data[offset + 1] & 0x01 ? 7 : 9; 11372} 11373function getFullFrameLength(data, offset) { 11374 return (data[offset + 3] & 0x03) << 11 | data[offset + 4] << 3 | (data[offset + 5] & 0xe0) >>> 5; 11375} 11376function canGetFrameLength(data, offset) { 11377 return offset + 5 < data.length; 11378} 11379function isHeader(data, offset) { 11380 // Look for ADTS header | 1111 1111 | 1111 X00X | where X can be either 0 or 1 11381 // Layer bits (position 14 and 15) in header should be always 0 for ADTS 11382 // More info https://wiki.multimedia.cx/index.php?title=ADTS 11383 return offset + 1 < data.length && isHeaderPattern(data, offset); 11384} 11385function canParse(data, offset) { 11386 return canGetFrameLength(data, offset) && isHeaderPattern(data, offset) && getFullFrameLength(data, offset) <= data.length - offset; 11387} 11388function probe(data, offset) { 11389 // same as isHeader but we also check that ADTS frame follows last ADTS frame 11390 // or end of data is reached 11391 if (isHeader(data, offset)) { 11392 // ADTS header Length 11393 var headerLength = getHeaderLength(data, offset); 11394 if (offset + headerLength >= data.length) { 11395 return false; 11396 } 11397 // ADTS frame Length 11398 var frameLength = getFullFrameLength(data, offset); 11399 if (frameLength <= headerLength) { 11400 return false; 11401 } 11402 var newOffset = offset + frameLength; 11403 return newOffset === data.length || isHeader(data, newOffset); 11404 } 11405 return false; 11406} 11407function initTrackConfig(track, observer, data, offset, audioCodec) { 11408 if (!track.samplerate) { 11409 var config = getAudioConfig(observer, data, offset, audioCodec); 11410 if (!config) { 11411 return; 11412 } 11413 track.config = config.config; 11414 track.samplerate = config.samplerate; 11415 track.channelCount = config.channelCount; 11416 track.codec = config.codec; 11417 track.manifestCodec = config.manifestCodec; 11418 _utils_logger__WEBPACK_IMPORTED_MODULE_0__.logger.log("parsed codec:" + track.codec + ", rate:" + config.samplerate + ", channels:" + config.channelCount); 11419 } 11420} 11421function getFrameDuration(samplerate) { 11422 return 1024 * 90000 / samplerate; 11423} 11424function parseFrameHeader(data, offset) { 11425 // The protection skip bit tells us if we have 2 bytes of CRC data at the end of the ADTS header 11426 var headerLength = getHeaderLength(data, offset); 11427 if (offset + headerLength <= data.length) { 11428 // retrieve frame size 11429 var frameLength = getFullFrameLength(data, offset) - headerLength; 11430 if (frameLength > 0) { 11431 // logger.log(`AAC frame, offset/length/total/pts:${offset+headerLength}/${frameLength}/${data.byteLength}`); 11432 return { 11433 headerLength: headerLength, 11434 frameLength: frameLength 11435 }; 11436 } 11437 } 11438} 11439function appendFrame(track, data, offset, pts, frameIndex) { 11440 var frameDuration = getFrameDuration(track.samplerate); 11441 var stamp = pts + frameIndex * frameDuration; 11442 var header = parseFrameHeader(data, offset); 11443 var unit; 11444 if (header) { 11445 var frameLength = header.frameLength, 11446 headerLength = header.headerLength; 11447 var _length = headerLength + frameLength; 11448 var missing = Math.max(0, offset + _length - data.length); 11449 // logger.log(`AAC frame ${frameIndex}, pts:${stamp} length@offset/total: ${frameLength}@${offset+headerLength}/${data.byteLength} missing: ${missing}`); 11450 if (missing) { 11451 unit = new Uint8Array(_length - headerLength); 11452 unit.set(data.subarray(offset + headerLength, data.length), 0); 11453 } else { 11454 unit = data.subarray(offset + headerLength, offset + _length); 11455 } 11456 var _sample = { 11457 unit: unit, 11458 pts: stamp 11459 }; 11460 if (!missing) { 11461 track.samples.push(_sample); 11462 } 11463 return { 11464 sample: _sample, 11465 length: _length, 11466 missing: missing 11467 }; 11468 } 11469 // overflow incomplete header 11470 var length = data.length - offset; 11471 unit = new Uint8Array(length); 11472 unit.set(data.subarray(offset, data.length), 0); 11473 var sample = { 11474 unit: unit, 11475 pts: stamp 11476 }; 11477 return { 11478 sample: sample, 11479 length: length, 11480 missing: -1 11481 }; 11482} 11483 11484/***/ }), 11485 11486/***/ "./src/demux/base-audio-demuxer.ts": 11487/*!*****************************************!*\ 11488 !*** ./src/demux/base-audio-demuxer.ts ***! 11489 \*****************************************/ 11490/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 11491 11492"use strict"; 11493__webpack_require__.r(__webpack_exports__); 11494/* harmony export */ __webpack_require__.d(__webpack_exports__, { 11495/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__), 11496/* harmony export */ "initPTSFn": () => (/* binding */ initPTSFn) 11497/* harmony export */ }); 11498/* harmony import */ var _home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.ts"); 11499/* harmony import */ var _demux_id3__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../demux/id3 */ "./src/demux/id3.ts"); 11500/* harmony import */ var _types_demuxer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../types/demuxer */ "./src/types/demuxer.ts"); 11501/* harmony import */ var _dummy_demuxed_track__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./dummy-demuxed-track */ "./src/demux/dummy-demuxed-track.ts"); 11502/* harmony import */ var _utils_mp4_tools__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../utils/mp4-tools */ "./src/utils/mp4-tools.ts"); 11503/* harmony import */ var _utils_typed_array__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../utils/typed-array */ "./src/utils/typed-array.ts"); 11504 11505 11506 11507 11508 11509 11510 11511var BaseAudioDemuxer = /*#__PURE__*/function () { 11512 function BaseAudioDemuxer() { 11513 this._audioTrack = void 0; 11514 this._id3Track = void 0; 11515 this.frameIndex = 0; 11516 this.cachedData = null; 11517 this.basePTS = null; 11518 this.initPTS = null; 11519 this.lastPTS = null; 11520 } 11521 var _proto = BaseAudioDemuxer.prototype; 11522 _proto.resetInitSegment = function resetInitSegment(initSegment, audioCodec, videoCodec, trackDuration) { 11523 this._id3Track = { 11524 type: 'id3', 11525 id: 3, 11526 pid: -1, 11527 inputTimeScale: 90000, 11528 sequenceNumber: 0, 11529 samples: [], 11530 dropped: 0 11531 }; 11532 }; 11533 _proto.resetTimeStamp = function resetTimeStamp(deaultTimestamp) { 11534 this.initPTS = deaultTimestamp; 11535 this.resetContiguity(); 11536 }; 11537 _proto.resetContiguity = function resetContiguity() { 11538 this.basePTS = null; 11539 this.lastPTS = null; 11540 this.frameIndex = 0; 11541 }; 11542 _proto.canParse = function canParse(data, offset) { 11543 return false; 11544 }; 11545 _proto.appendFrame = function appendFrame(track, data, offset) {} 11546 11547 // feed incoming data to the front of the parsing pipeline 11548 ; 11549 _proto.demux = function demux(data, timeOffset) { 11550 if (this.cachedData) { 11551 data = (0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_4__.appendUint8Array)(this.cachedData, data); 11552 this.cachedData = null; 11553 } 11554 var id3Data = _demux_id3__WEBPACK_IMPORTED_MODULE_1__.getID3Data(data, 0); 11555 var offset = id3Data ? id3Data.length : 0; 11556 var lastDataIndex; 11557 var track = this._audioTrack; 11558 var id3Track = this._id3Track; 11559 var timestamp = id3Data ? _demux_id3__WEBPACK_IMPORTED_MODULE_1__.getTimeStamp(id3Data) : undefined; 11560 var length = data.length; 11561 if (this.basePTS === null || this.frameIndex === 0 && (0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(timestamp)) { 11562 this.basePTS = initPTSFn(timestamp, timeOffset, this.initPTS); 11563 this.lastPTS = this.basePTS; 11564 } 11565 if (this.lastPTS === null) { 11566 this.lastPTS = this.basePTS; 11567 } 11568 11569 // more expressive than alternative: id3Data?.length 11570 if (id3Data && id3Data.length > 0) { 11571 id3Track.samples.push({ 11572 pts: this.lastPTS, 11573 dts: this.lastPTS, 11574 data: id3Data, 11575 type: _types_demuxer__WEBPACK_IMPORTED_MODULE_2__.MetadataSchema.audioId3, 11576 duration: Number.POSITIVE_INFINITY 11577 }); 11578 } 11579 while (offset < length) { 11580 if (this.canParse(data, offset)) { 11581 var frame = this.appendFrame(track, data, offset); 11582 if (frame) { 11583 this.frameIndex++; 11584 this.lastPTS = frame.sample.pts; 11585 offset += frame.length; 11586 lastDataIndex = offset; 11587 } else { 11588 offset = length; 11589 } 11590 } else if (_demux_id3__WEBPACK_IMPORTED_MODULE_1__.canParse(data, offset)) { 11591 // after a ID3.canParse, a call to ID3.getID3Data *should* always returns some data 11592 id3Data = _demux_id3__WEBPACK_IMPORTED_MODULE_1__.getID3Data(data, offset); 11593 id3Track.samples.push({ 11594 pts: this.lastPTS, 11595 dts: this.lastPTS, 11596 data: id3Data, 11597 type: _types_demuxer__WEBPACK_IMPORTED_MODULE_2__.MetadataSchema.audioId3, 11598 duration: Number.POSITIVE_INFINITY 11599 }); 11600 offset += id3Data.length; 11601 lastDataIndex = offset; 11602 } else { 11603 offset++; 11604 } 11605 if (offset === length && lastDataIndex !== length) { 11606 var partialData = (0,_utils_typed_array__WEBPACK_IMPORTED_MODULE_5__.sliceUint8)(data, lastDataIndex); 11607 if (this.cachedData) { 11608 this.cachedData = (0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_4__.appendUint8Array)(this.cachedData, partialData); 11609 } else { 11610 this.cachedData = partialData; 11611 } 11612 } 11613 } 11614 return { 11615 audioTrack: track, 11616 videoTrack: (0,_dummy_demuxed_track__WEBPACK_IMPORTED_MODULE_3__.dummyTrack)(), 11617 id3Track: id3Track, 11618 textTrack: (0,_dummy_demuxed_track__WEBPACK_IMPORTED_MODULE_3__.dummyTrack)() 11619 }; 11620 }; 11621 _proto.demuxSampleAes = function demuxSampleAes(data, keyData, timeOffset) { 11622 return Promise.reject(new Error("[" + this + "] This demuxer does not support Sample-AES decryption")); 11623 }; 11624 _proto.flush = function flush(timeOffset) { 11625 // Parse cache in case of remaining frames. 11626 var cachedData = this.cachedData; 11627 if (cachedData) { 11628 this.cachedData = null; 11629 this.demux(cachedData, 0); 11630 } 11631 return { 11632 audioTrack: this._audioTrack, 11633 videoTrack: (0,_dummy_demuxed_track__WEBPACK_IMPORTED_MODULE_3__.dummyTrack)(), 11634 id3Track: this._id3Track, 11635 textTrack: (0,_dummy_demuxed_track__WEBPACK_IMPORTED_MODULE_3__.dummyTrack)() 11636 }; 11637 }; 11638 _proto.destroy = function destroy() {}; 11639 return BaseAudioDemuxer; 11640}(); 11641/** 11642 * Initialize PTS 11643 * <p> 11644 * use timestamp unless it is undefined, NaN or Infinity 11645 * </p> 11646 */ 11647var initPTSFn = function initPTSFn(timestamp, timeOffset, initPTS) { 11648 if ((0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(timestamp)) { 11649 return timestamp * 90; 11650 } 11651 return timeOffset * 90000 + (initPTS || 0); 11652}; 11653/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BaseAudioDemuxer); 11654 11655/***/ }), 11656 11657/***/ "./src/demux/chunk-cache.ts": 11658/*!**********************************!*\ 11659 !*** ./src/demux/chunk-cache.ts ***! 11660 \**********************************/ 11661/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 11662 11663"use strict"; 11664__webpack_require__.r(__webpack_exports__); 11665/* harmony export */ __webpack_require__.d(__webpack_exports__, { 11666/* harmony export */ "default": () => (/* binding */ ChunkCache) 11667/* harmony export */ }); 11668var ChunkCache = /*#__PURE__*/function () { 11669 function ChunkCache() { 11670 this.chunks = []; 11671 this.dataLength = 0; 11672 } 11673 var _proto = ChunkCache.prototype; 11674 _proto.push = function push(chunk) { 11675 this.chunks.push(chunk); 11676 this.dataLength += chunk.length; 11677 }; 11678 _proto.flush = function flush() { 11679 var chunks = this.chunks, 11680 dataLength = this.dataLength; 11681 var result; 11682 if (!chunks.length) { 11683 return new Uint8Array(0); 11684 } else if (chunks.length === 1) { 11685 result = chunks[0]; 11686 } else { 11687 result = concatUint8Arrays(chunks, dataLength); 11688 } 11689 this.reset(); 11690 return result; 11691 }; 11692 _proto.reset = function reset() { 11693 this.chunks.length = 0; 11694 this.dataLength = 0; 11695 }; 11696 return ChunkCache; 11697}(); 11698 11699function concatUint8Arrays(chunks, dataLength) { 11700 var result = new Uint8Array(dataLength); 11701 var offset = 0; 11702 for (var i = 0; i < chunks.length; i++) { 11703 var chunk = chunks[i]; 11704 result.set(chunk, offset); 11705 offset += chunk.length; 11706 } 11707 return result; 11708} 11709 11710/***/ }), 11711 11712/***/ "./src/demux/dummy-demuxed-track.ts": 11713/*!******************************************!*\ 11714 !*** ./src/demux/dummy-demuxed-track.ts ***! 11715 \******************************************/ 11716/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 11717 11718"use strict"; 11719__webpack_require__.r(__webpack_exports__); 11720/* harmony export */ __webpack_require__.d(__webpack_exports__, { 11721/* harmony export */ "dummyTrack": () => (/* binding */ dummyTrack) 11722/* harmony export */ }); 11723function dummyTrack(type, inputTimeScale) { 11724 if (type === void 0) { 11725 type = ''; 11726 } 11727 if (inputTimeScale === void 0) { 11728 inputTimeScale = 90000; 11729 } 11730 return { 11731 type: type, 11732 id: -1, 11733 pid: -1, 11734 inputTimeScale: inputTimeScale, 11735 sequenceNumber: -1, 11736 samples: [], 11737 dropped: 0 11738 }; 11739} 11740 11741/***/ }), 11742 11743/***/ "./src/demux/exp-golomb.ts": 11744/*!*********************************!*\ 11745 !*** ./src/demux/exp-golomb.ts ***! 11746 \*********************************/ 11747/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 11748 11749"use strict"; 11750__webpack_require__.r(__webpack_exports__); 11751/* harmony export */ __webpack_require__.d(__webpack_exports__, { 11752/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 11753/* harmony export */ }); 11754/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 11755/** 11756 * Parser for exponential Golomb codes, a variable-bitwidth number encoding scheme used by h264. 11757 */ 11758 11759 11760var ExpGolomb = /*#__PURE__*/function () { 11761 function ExpGolomb(data) { 11762 this.data = void 0; 11763 this.bytesAvailable = void 0; 11764 this.word = void 0; 11765 this.bitsAvailable = void 0; 11766 this.data = data; 11767 // the number of bytes left to examine in this.data 11768 this.bytesAvailable = data.byteLength; 11769 // the current word being examined 11770 this.word = 0; // :uint 11771 // the number of bits left to examine in the current word 11772 this.bitsAvailable = 0; // :uint 11773 } 11774 11775 // ():void 11776 var _proto = ExpGolomb.prototype; 11777 _proto.loadWord = function loadWord() { 11778 var data = this.data; 11779 var bytesAvailable = this.bytesAvailable; 11780 var position = data.byteLength - bytesAvailable; 11781 var workingBytes = new Uint8Array(4); 11782 var availableBytes = Math.min(4, bytesAvailable); 11783 if (availableBytes === 0) { 11784 throw new Error('no bytes available'); 11785 } 11786 workingBytes.set(data.subarray(position, position + availableBytes)); 11787 this.word = new DataView(workingBytes.buffer).getUint32(0); 11788 // track the amount of this.data that has been processed 11789 this.bitsAvailable = availableBytes * 8; 11790 this.bytesAvailable -= availableBytes; 11791 } 11792 11793 // (count:int):void 11794 ; 11795 _proto.skipBits = function skipBits(count) { 11796 var skipBytes; // :int 11797 count = Math.min(count, this.bytesAvailable * 8 + this.bitsAvailable); 11798 if (this.bitsAvailable > count) { 11799 this.word <<= count; 11800 this.bitsAvailable -= count; 11801 } else { 11802 count -= this.bitsAvailable; 11803 skipBytes = count >> 3; 11804 count -= skipBytes << 3; 11805 this.bytesAvailable -= skipBytes; 11806 this.loadWord(); 11807 this.word <<= count; 11808 this.bitsAvailable -= count; 11809 } 11810 } 11811 11812 // (size:int):uint 11813 ; 11814 _proto.readBits = function readBits(size) { 11815 var bits = Math.min(this.bitsAvailable, size); // :uint 11816 var valu = this.word >>> 32 - bits; // :uint 11817 if (size > 32) { 11818 _utils_logger__WEBPACK_IMPORTED_MODULE_0__.logger.error('Cannot read more than 32 bits at a time'); 11819 } 11820 this.bitsAvailable -= bits; 11821 if (this.bitsAvailable > 0) { 11822 this.word <<= bits; 11823 } else if (this.bytesAvailable > 0) { 11824 this.loadWord(); 11825 } else { 11826 throw new Error('no bits available'); 11827 } 11828 bits = size - bits; 11829 if (bits > 0 && this.bitsAvailable) { 11830 return valu << bits | this.readBits(bits); 11831 } else { 11832 return valu; 11833 } 11834 } 11835 11836 // ():uint 11837 ; 11838 _proto.skipLZ = function skipLZ() { 11839 var leadingZeroCount; // :uint 11840 for (leadingZeroCount = 0; leadingZeroCount < this.bitsAvailable; ++leadingZeroCount) { 11841 if ((this.word & 0x80000000 >>> leadingZeroCount) !== 0) { 11842 // the first bit of working word is 1 11843 this.word <<= leadingZeroCount; 11844 this.bitsAvailable -= leadingZeroCount; 11845 return leadingZeroCount; 11846 } 11847 } 11848 // we exhausted word and still have not found a 1 11849 this.loadWord(); 11850 return leadingZeroCount + this.skipLZ(); 11851 } 11852 11853 // ():void 11854 ; 11855 _proto.skipUEG = function skipUEG() { 11856 this.skipBits(1 + this.skipLZ()); 11857 } 11858 11859 // ():void 11860 ; 11861 _proto.skipEG = function skipEG() { 11862 this.skipBits(1 + this.skipLZ()); 11863 } 11864 11865 // ():uint 11866 ; 11867 _proto.readUEG = function readUEG() { 11868 var clz = this.skipLZ(); // :uint 11869 return this.readBits(clz + 1) - 1; 11870 } 11871 11872 // ():int 11873 ; 11874 _proto.readEG = function readEG() { 11875 var valu = this.readUEG(); // :int 11876 if (0x01 & valu) { 11877 // the number is odd if the low order bit is set 11878 return 1 + valu >>> 1; // add 1 to make it even, and divide by 2 11879 } else { 11880 return -1 * (valu >>> 1); // divide by two then make it negative 11881 } 11882 } 11883 11884 // Some convenience functions 11885 // :Boolean 11886 ; 11887 _proto.readBoolean = function readBoolean() { 11888 return this.readBits(1) === 1; 11889 } 11890 11891 // ():int 11892 ; 11893 _proto.readUByte = function readUByte() { 11894 return this.readBits(8); 11895 } 11896 11897 // ():int 11898 ; 11899 _proto.readUShort = function readUShort() { 11900 return this.readBits(16); 11901 } 11902 11903 // ():int 11904 ; 11905 _proto.readUInt = function readUInt() { 11906 return this.readBits(32); 11907 } 11908 11909 /** 11910 * Advance the ExpGolomb decoder past a scaling list. The scaling 11911 * list is optionally transmitted as part of a sequence parameter 11912 * set and is not relevant to transmuxing. 11913 * @param count the number of entries in this scaling list 11914 * @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1 11915 */; 11916 _proto.skipScalingList = function skipScalingList(count) { 11917 var lastScale = 8; 11918 var nextScale = 8; 11919 var deltaScale; 11920 for (var j = 0; j < count; j++) { 11921 if (nextScale !== 0) { 11922 deltaScale = this.readEG(); 11923 nextScale = (lastScale + deltaScale + 256) % 256; 11924 } 11925 lastScale = nextScale === 0 ? lastScale : nextScale; 11926 } 11927 } 11928 11929 /** 11930 * Read a sequence parameter set and return some interesting video 11931 * properties. A sequence parameter set is the H264 metadata that 11932 * describes the properties of upcoming video frames. 11933 * @param data {Uint8Array} the bytes of a sequence parameter set 11934 * @return {object} an object with configuration parsed from the 11935 * sequence parameter set, including the dimensions of the 11936 * associated video frames. 11937 */; 11938 _proto.readSPS = function readSPS() { 11939 var frameCropLeftOffset = 0; 11940 var frameCropRightOffset = 0; 11941 var frameCropTopOffset = 0; 11942 var frameCropBottomOffset = 0; 11943 var numRefFramesInPicOrderCntCycle; 11944 var scalingListCount; 11945 var i; 11946 var readUByte = this.readUByte.bind(this); 11947 var readBits = this.readBits.bind(this); 11948 var readUEG = this.readUEG.bind(this); 11949 var readBoolean = this.readBoolean.bind(this); 11950 var skipBits = this.skipBits.bind(this); 11951 var skipEG = this.skipEG.bind(this); 11952 var skipUEG = this.skipUEG.bind(this); 11953 var skipScalingList = this.skipScalingList.bind(this); 11954 readUByte(); 11955 var profileIdc = readUByte(); // profile_idc 11956 readBits(5); // profileCompat constraint_set[0-4]_flag, u(5) 11957 skipBits(3); // reserved_zero_3bits u(3), 11958 readUByte(); // level_idc u(8) 11959 skipUEG(); // seq_parameter_set_id 11960 // some profiles have more optional data we don't need 11961 if (profileIdc === 100 || profileIdc === 110 || profileIdc === 122 || profileIdc === 244 || profileIdc === 44 || profileIdc === 83 || profileIdc === 86 || profileIdc === 118 || profileIdc === 128) { 11962 var chromaFormatIdc = readUEG(); 11963 if (chromaFormatIdc === 3) { 11964 skipBits(1); 11965 } // separate_colour_plane_flag 11966 11967 skipUEG(); // bit_depth_luma_minus8 11968 skipUEG(); // bit_depth_chroma_minus8 11969 skipBits(1); // qpprime_y_zero_transform_bypass_flag 11970 if (readBoolean()) { 11971 // seq_scaling_matrix_present_flag 11972 scalingListCount = chromaFormatIdc !== 3 ? 8 : 12; 11973 for (i = 0; i < scalingListCount; i++) { 11974 if (readBoolean()) { 11975 // seq_scaling_list_present_flag[ i ] 11976 if (i < 6) { 11977 skipScalingList(16); 11978 } else { 11979 skipScalingList(64); 11980 } 11981 } 11982 } 11983 } 11984 } 11985 skipUEG(); // log2_max_frame_num_minus4 11986 var picOrderCntType = readUEG(); 11987 if (picOrderCntType === 0) { 11988 readUEG(); // log2_max_pic_order_cnt_lsb_minus4 11989 } else if (picOrderCntType === 1) { 11990 skipBits(1); // delta_pic_order_always_zero_flag 11991 skipEG(); // offset_for_non_ref_pic 11992 skipEG(); // offset_for_top_to_bottom_field 11993 numRefFramesInPicOrderCntCycle = readUEG(); 11994 for (i = 0; i < numRefFramesInPicOrderCntCycle; i++) { 11995 skipEG(); 11996 } // offset_for_ref_frame[ i ] 11997 } 11998 11999 skipUEG(); // max_num_ref_frames 12000 skipBits(1); // gaps_in_frame_num_value_allowed_flag 12001 var picWidthInMbsMinus1 = readUEG(); 12002 var picHeightInMapUnitsMinus1 = readUEG(); 12003 var frameMbsOnlyFlag = readBits(1); 12004 if (frameMbsOnlyFlag === 0) { 12005 skipBits(1); 12006 } // mb_adaptive_frame_field_flag 12007 12008 skipBits(1); // direct_8x8_inference_flag 12009 if (readBoolean()) { 12010 // frame_cropping_flag 12011 frameCropLeftOffset = readUEG(); 12012 frameCropRightOffset = readUEG(); 12013 frameCropTopOffset = readUEG(); 12014 frameCropBottomOffset = readUEG(); 12015 } 12016 var pixelRatio = [1, 1]; 12017 if (readBoolean()) { 12018 // vui_parameters_present_flag 12019 if (readBoolean()) { 12020 // aspect_ratio_info_present_flag 12021 var aspectRatioIdc = readUByte(); 12022 switch (aspectRatioIdc) { 12023 case 1: 12024 pixelRatio = [1, 1]; 12025 break; 12026 case 2: 12027 pixelRatio = [12, 11]; 12028 break; 12029 case 3: 12030 pixelRatio = [10, 11]; 12031 break; 12032 case 4: 12033 pixelRatio = [16, 11]; 12034 break; 12035 case 5: 12036 pixelRatio = [40, 33]; 12037 break; 12038 case 6: 12039 pixelRatio = [24, 11]; 12040 break; 12041 case 7: 12042 pixelRatio = [20, 11]; 12043 break; 12044 case 8: 12045 pixelRatio = [32, 11]; 12046 break; 12047 case 9: 12048 pixelRatio = [80, 33]; 12049 break; 12050 case 10: 12051 pixelRatio = [18, 11]; 12052 break; 12053 case 11: 12054 pixelRatio = [15, 11]; 12055 break; 12056 case 12: 12057 pixelRatio = [64, 33]; 12058 break; 12059 case 13: 12060 pixelRatio = [160, 99]; 12061 break; 12062 case 14: 12063 pixelRatio = [4, 3]; 12064 break; 12065 case 15: 12066 pixelRatio = [3, 2]; 12067 break; 12068 case 16: 12069 pixelRatio = [2, 1]; 12070 break; 12071 case 255: 12072 { 12073 pixelRatio = [readUByte() << 8 | readUByte(), readUByte() << 8 | readUByte()]; 12074 break; 12075 } 12076 } 12077 } 12078 } 12079 return { 12080 width: Math.ceil((picWidthInMbsMinus1 + 1) * 16 - frameCropLeftOffset * 2 - frameCropRightOffset * 2), 12081 height: (2 - frameMbsOnlyFlag) * (picHeightInMapUnitsMinus1 + 1) * 16 - (frameMbsOnlyFlag ? 2 : 4) * (frameCropTopOffset + frameCropBottomOffset), 12082 pixelRatio: pixelRatio 12083 }; 12084 }; 12085 _proto.readSliceType = function readSliceType() { 12086 // skip NALu type 12087 this.readUByte(); 12088 // discard first_mb_in_slice 12089 this.readUEG(); 12090 // return slice_type 12091 return this.readUEG(); 12092 }; 12093 return ExpGolomb; 12094}(); 12095/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ExpGolomb); 12096 12097/***/ }), 12098 12099/***/ "./src/demux/id3.ts": 12100/*!**************************!*\ 12101 !*** ./src/demux/id3.ts ***! 12102 \**************************/ 12103/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 12104 12105"use strict"; 12106__webpack_require__.r(__webpack_exports__); 12107/* harmony export */ __webpack_require__.d(__webpack_exports__, { 12108/* harmony export */ "canParse": () => (/* binding */ canParse), 12109/* harmony export */ "decodeFrame": () => (/* binding */ decodeFrame), 12110/* harmony export */ "getID3Data": () => (/* binding */ getID3Data), 12111/* harmony export */ "getID3Frames": () => (/* binding */ getID3Frames), 12112/* harmony export */ "getTimeStamp": () => (/* binding */ getTimeStamp), 12113/* harmony export */ "isFooter": () => (/* binding */ isFooter), 12114/* harmony export */ "isHeader": () => (/* binding */ isHeader), 12115/* harmony export */ "isTimeStampFrame": () => (/* binding */ isTimeStampFrame), 12116/* harmony export */ "testables": () => (/* binding */ testables), 12117/* harmony export */ "utf8ArrayToStr": () => (/* binding */ utf8ArrayToStr) 12118/* harmony export */ }); 12119// breaking up those two types in order to clarify what is happening in the decoding path. 12120 12121/** 12122 * Returns true if an ID3 header can be found at offset in data 12123 * @param {Uint8Array} data - The data to search in 12124 * @param {number} offset - The offset at which to start searching 12125 * @return {boolean} - True if an ID3 header is found 12126 */ 12127var isHeader = function isHeader(data, offset) { 12128 /* 12129 * http://id3.org/id3v2.3.0 12130 * [0] = 'I' 12131 * [1] = 'D' 12132 * [2] = '3' 12133 * [3,4] = {Version} 12134 * [5] = {Flags} 12135 * [6-9] = {ID3 Size} 12136 * 12137 * An ID3v2 tag can be detected with the following pattern: 12138 * $49 44 33 yy yy xx zz zz zz zz 12139 * Where yy is less than $FF, xx is the 'flags' byte and zz is less than $80 12140 */ 12141 if (offset + 10 <= data.length) { 12142 // look for 'ID3' identifier 12143 if (data[offset] === 0x49 && data[offset + 1] === 0x44 && data[offset + 2] === 0x33) { 12144 // check version is within range 12145 if (data[offset + 3] < 0xff && data[offset + 4] < 0xff) { 12146 // check size is within range 12147 if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) { 12148 return true; 12149 } 12150 } 12151 } 12152 } 12153 return false; 12154}; 12155 12156/** 12157 * Returns true if an ID3 footer can be found at offset in data 12158 * @param {Uint8Array} data - The data to search in 12159 * @param {number} offset - The offset at which to start searching 12160 * @return {boolean} - True if an ID3 footer is found 12161 */ 12162var isFooter = function isFooter(data, offset) { 12163 /* 12164 * The footer is a copy of the header, but with a different identifier 12165 */ 12166 if (offset + 10 <= data.length) { 12167 // look for '3DI' identifier 12168 if (data[offset] === 0x33 && data[offset + 1] === 0x44 && data[offset + 2] === 0x49) { 12169 // check version is within range 12170 if (data[offset + 3] < 0xff && data[offset + 4] < 0xff) { 12171 // check size is within range 12172 if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) { 12173 return true; 12174 } 12175 } 12176 } 12177 } 12178 return false; 12179}; 12180 12181/** 12182 * Returns any adjacent ID3 tags found in data starting at offset, as one block of data 12183 * @param {Uint8Array} data - The data to search in 12184 * @param {number} offset - The offset at which to start searching 12185 * @return {Uint8Array | undefined} - The block of data containing any ID3 tags found 12186 * or *undefined* if no header is found at the starting offset 12187 */ 12188var getID3Data = function getID3Data(data, offset) { 12189 var front = offset; 12190 var length = 0; 12191 while (isHeader(data, offset)) { 12192 // ID3 header is 10 bytes 12193 length += 10; 12194 var size = readSize(data, offset + 6); 12195 length += size; 12196 if (isFooter(data, offset + 10)) { 12197 // ID3 footer is 10 bytes 12198 length += 10; 12199 } 12200 offset += length; 12201 } 12202 if (length > 0) { 12203 return data.subarray(front, front + length); 12204 } 12205 return undefined; 12206}; 12207var readSize = function readSize(data, offset) { 12208 var size = 0; 12209 size = (data[offset] & 0x7f) << 21; 12210 size |= (data[offset + 1] & 0x7f) << 14; 12211 size |= (data[offset + 2] & 0x7f) << 7; 12212 size |= data[offset + 3] & 0x7f; 12213 return size; 12214}; 12215var canParse = function canParse(data, offset) { 12216 return isHeader(data, offset) && readSize(data, offset + 6) + 10 <= data.length - offset; 12217}; 12218 12219/** 12220 * Searches for the Elementary Stream timestamp found in the ID3 data chunk 12221 * @param {Uint8Array} data - Block of data containing one or more ID3 tags 12222 * @return {number | undefined} - The timestamp 12223 */ 12224var getTimeStamp = function getTimeStamp(data) { 12225 var frames = getID3Frames(data); 12226 for (var i = 0; i < frames.length; i++) { 12227 var frame = frames[i]; 12228 if (isTimeStampFrame(frame)) { 12229 return readTimeStamp(frame); 12230 } 12231 } 12232 return undefined; 12233}; 12234 12235/** 12236 * Returns true if the ID3 frame is an Elementary Stream timestamp frame 12237 * @param {ID3 frame} frame 12238 */ 12239var isTimeStampFrame = function isTimeStampFrame(frame) { 12240 return frame && frame.key === 'PRIV' && frame.info === 'com.apple.streaming.transportStreamTimestamp'; 12241}; 12242var getFrameData = function getFrameData(data) { 12243 /* 12244 Frame ID $xx xx xx xx (four characters) 12245 Size $xx xx xx xx 12246 Flags $xx xx 12247 */ 12248 var type = String.fromCharCode(data[0], data[1], data[2], data[3]); 12249 var size = readSize(data, 4); 12250 12251 // skip frame id, size, and flags 12252 var offset = 10; 12253 return { 12254 type: type, 12255 size: size, 12256 data: data.subarray(offset, offset + size) 12257 }; 12258}; 12259 12260/** 12261 * Returns an array of ID3 frames found in all the ID3 tags in the id3Data 12262 * @param {Uint8Array} id3Data - The ID3 data containing one or more ID3 tags 12263 * @return {ID3.Frame[]} - Array of ID3 frame objects 12264 */ 12265var getID3Frames = function getID3Frames(id3Data) { 12266 var offset = 0; 12267 var frames = []; 12268 while (isHeader(id3Data, offset)) { 12269 var size = readSize(id3Data, offset + 6); 12270 // skip past ID3 header 12271 offset += 10; 12272 var end = offset + size; 12273 // loop through frames in the ID3 tag 12274 while (offset + 8 < end) { 12275 var frameData = getFrameData(id3Data.subarray(offset)); 12276 var frame = decodeFrame(frameData); 12277 if (frame) { 12278 frames.push(frame); 12279 } 12280 12281 // skip frame header and frame data 12282 offset += frameData.size + 10; 12283 } 12284 if (isFooter(id3Data, offset)) { 12285 offset += 10; 12286 } 12287 } 12288 return frames; 12289}; 12290var decodeFrame = function decodeFrame(frame) { 12291 if (frame.type === 'PRIV') { 12292 return decodePrivFrame(frame); 12293 } else if (frame.type[0] === 'W') { 12294 return decodeURLFrame(frame); 12295 } 12296 return decodeTextFrame(frame); 12297}; 12298var decodePrivFrame = function decodePrivFrame(frame) { 12299 /* 12300 Format: <text string>\0<binary data> 12301 */ 12302 if (frame.size < 2) { 12303 return undefined; 12304 } 12305 var owner = utf8ArrayToStr(frame.data, true); 12306 var privateData = new Uint8Array(frame.data.subarray(owner.length + 1)); 12307 return { 12308 key: frame.type, 12309 info: owner, 12310 data: privateData.buffer 12311 }; 12312}; 12313var decodeTextFrame = function decodeTextFrame(frame) { 12314 if (frame.size < 2) { 12315 return undefined; 12316 } 12317 if (frame.type === 'TXXX') { 12318 /* 12319 Format: 12320 [0] = {Text Encoding} 12321 [1-?] = {Description}\0{Value} 12322 */ 12323 var index = 1; 12324 var description = utf8ArrayToStr(frame.data.subarray(index), true); 12325 index += description.length + 1; 12326 var value = utf8ArrayToStr(frame.data.subarray(index)); 12327 return { 12328 key: frame.type, 12329 info: description, 12330 data: value 12331 }; 12332 } 12333 /* 12334 Format: 12335 [0] = {Text Encoding} 12336 [1-?] = {Value} 12337 */ 12338 var text = utf8ArrayToStr(frame.data.subarray(1)); 12339 return { 12340 key: frame.type, 12341 data: text 12342 }; 12343}; 12344var decodeURLFrame = function decodeURLFrame(frame) { 12345 if (frame.type === 'WXXX') { 12346 /* 12347 Format: 12348 [0] = {Text Encoding} 12349 [1-?] = {Description}\0{URL} 12350 */ 12351 if (frame.size < 2) { 12352 return undefined; 12353 } 12354 var index = 1; 12355 var description = utf8ArrayToStr(frame.data.subarray(index), true); 12356 index += description.length + 1; 12357 var value = utf8ArrayToStr(frame.data.subarray(index)); 12358 return { 12359 key: frame.type, 12360 info: description, 12361 data: value 12362 }; 12363 } 12364 /* 12365 Format: 12366 [0-?] = {URL} 12367 */ 12368 var url = utf8ArrayToStr(frame.data); 12369 return { 12370 key: frame.type, 12371 data: url 12372 }; 12373}; 12374var readTimeStamp = function readTimeStamp(timeStampFrame) { 12375 if (timeStampFrame.data.byteLength === 8) { 12376 var data = new Uint8Array(timeStampFrame.data); 12377 // timestamp is 33 bit expressed as a big-endian eight-octet number, 12378 // with the upper 31 bits set to zero. 12379 var pts33Bit = data[3] & 0x1; 12380 var timestamp = (data[4] << 23) + (data[5] << 15) + (data[6] << 7) + data[7]; 12381 timestamp /= 45; 12382 if (pts33Bit) { 12383 timestamp += 47721858.84; 12384 } // 2^32 / 90 12385 12386 return Math.round(timestamp); 12387 } 12388 return undefined; 12389}; 12390 12391// http://stackoverflow.com/questions/8936984/uint8array-to-string-in-javascript/22373197 12392// http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt 12393/* utf.js - UTF-8 <=> UTF-16 convertion 12394 * 12395 * Copyright (C) 1999 Masanao Izumo <[email protected]> 12396 * Version: 1.0 12397 * LastModified: Dec 25 1999 12398 * This library is free. You can redistribute it and/or modify it. 12399 */ 12400var utf8ArrayToStr = function utf8ArrayToStr(array, exitOnNull) { 12401 if (exitOnNull === void 0) { 12402 exitOnNull = false; 12403 } 12404 var decoder = getTextDecoder(); 12405 if (decoder) { 12406 var decoded = decoder.decode(array); 12407 if (exitOnNull) { 12408 // grab up to the first null 12409 var idx = decoded.indexOf('\0'); 12410 return idx !== -1 ? decoded.substring(0, idx) : decoded; 12411 } 12412 12413 // remove any null characters 12414 return decoded.replace(/\0/g, ''); 12415 } 12416 var len = array.length; 12417 var c; 12418 var char2; 12419 var char3; 12420 var out = ''; 12421 var i = 0; 12422 while (i < len) { 12423 c = array[i++]; 12424 if (c === 0x00 && exitOnNull) { 12425 return out; 12426 } else if (c === 0x00 || c === 0x03) { 12427 // If the character is 3 (END_OF_TEXT) or 0 (NULL) then skip it 12428 continue; 12429 } 12430 switch (c >> 4) { 12431 case 0: 12432 case 1: 12433 case 2: 12434 case 3: 12435 case 4: 12436 case 5: 12437 case 6: 12438 case 7: 12439 // 0xxxxxxx 12440 out += String.fromCharCode(c); 12441 break; 12442 case 12: 12443 case 13: 12444 // 110x xxxx 10xx xxxx 12445 char2 = array[i++]; 12446 out += String.fromCharCode((c & 0x1f) << 6 | char2 & 0x3f); 12447 break; 12448 case 14: 12449 // 1110 xxxx 10xx xxxx 10xx xxxx 12450 char2 = array[i++]; 12451 char3 = array[i++]; 12452 out += String.fromCharCode((c & 0x0f) << 12 | (char2 & 0x3f) << 6 | (char3 & 0x3f) << 0); 12453 break; 12454 default: 12455 } 12456 } 12457 return out; 12458}; 12459var testables = { 12460 decodeTextFrame: decodeTextFrame 12461}; 12462var decoder; 12463function getTextDecoder() { 12464 if (!decoder && typeof self.TextDecoder !== 'undefined') { 12465 decoder = new self.TextDecoder('utf-8'); 12466 } 12467 return decoder; 12468} 12469 12470/***/ }), 12471 12472/***/ "./src/demux/mp3demuxer.ts": 12473/*!*********************************!*\ 12474 !*** ./src/demux/mp3demuxer.ts ***! 12475 \*********************************/ 12476/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 12477 12478"use strict"; 12479__webpack_require__.r(__webpack_exports__); 12480/* harmony export */ __webpack_require__.d(__webpack_exports__, { 12481/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 12482/* harmony export */ }); 12483/* harmony import */ var _base_audio_demuxer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./base-audio-demuxer */ "./src/demux/base-audio-demuxer.ts"); 12484/* harmony import */ var _demux_id3__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../demux/id3 */ "./src/demux/id3.ts"); 12485/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 12486/* harmony import */ var _mpegaudio__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./mpegaudio */ "./src/demux/mpegaudio.ts"); 12487function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); } 12488function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } 12489/** 12490 * MP3 demuxer 12491 */ 12492 12493 12494 12495 12496var MP3Demuxer = /*#__PURE__*/function (_BaseAudioDemuxer) { 12497 _inheritsLoose(MP3Demuxer, _BaseAudioDemuxer); 12498 function MP3Demuxer() { 12499 return _BaseAudioDemuxer.apply(this, arguments) || this; 12500 } 12501 var _proto = MP3Demuxer.prototype; 12502 _proto.resetInitSegment = function resetInitSegment(initSegment, audioCodec, videoCodec, trackDuration) { 12503 _BaseAudioDemuxer.prototype.resetInitSegment.call(this, initSegment, audioCodec, videoCodec, trackDuration); 12504 this._audioTrack = { 12505 container: 'audio/mpeg', 12506 type: 'audio', 12507 id: 2, 12508 pid: -1, 12509 sequenceNumber: 0, 12510 segmentCodec: 'mp3', 12511 samples: [], 12512 manifestCodec: audioCodec, 12513 duration: trackDuration, 12514 inputTimeScale: 90000, 12515 dropped: 0 12516 }; 12517 }; 12518 MP3Demuxer.probe = function probe(data) { 12519 if (!data) { 12520 return false; 12521 } 12522 12523 // check if data contains ID3 timestamp and MPEG sync word 12524 // Look for MPEG header | 1111 1111 | 111X XYZX | where X can be either 0 or 1 and Y or Z should be 1 12525 // Layer bits (position 14 and 15) in header should be always different from 0 (Layer I or Layer II or Layer III) 12526 // More info http://www.mp3-tech.org/programmer/frame_header.html 12527 var id3Data = _demux_id3__WEBPACK_IMPORTED_MODULE_1__.getID3Data(data, 0) || []; 12528 var offset = id3Data.length; 12529 for (var length = data.length; offset < length; offset++) { 12530 if (_mpegaudio__WEBPACK_IMPORTED_MODULE_3__.probe(data, offset)) { 12531 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.log('MPEG Audio sync word found !'); 12532 return true; 12533 } 12534 } 12535 return false; 12536 }; 12537 _proto.canParse = function canParse(data, offset) { 12538 return _mpegaudio__WEBPACK_IMPORTED_MODULE_3__.canParse(data, offset); 12539 }; 12540 _proto.appendFrame = function appendFrame(track, data, offset) { 12541 if (this.basePTS === null) { 12542 return; 12543 } 12544 return _mpegaudio__WEBPACK_IMPORTED_MODULE_3__.appendFrame(track, data, offset, this.basePTS, this.frameIndex); 12545 }; 12546 return MP3Demuxer; 12547}(_base_audio_demuxer__WEBPACK_IMPORTED_MODULE_0__["default"]); 12548/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (MP3Demuxer); 12549 12550/***/ }), 12551 12552/***/ "./src/demux/mp4demuxer.ts": 12553/*!*********************************!*\ 12554 !*** ./src/demux/mp4demuxer.ts ***! 12555 \*********************************/ 12556/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 12557 12558"use strict"; 12559__webpack_require__.r(__webpack_exports__); 12560/* harmony export */ __webpack_require__.d(__webpack_exports__, { 12561/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 12562/* harmony export */ }); 12563/* harmony import */ var _home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.ts"); 12564/* harmony import */ var _types_demuxer__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../types/demuxer */ "./src/types/demuxer.ts"); 12565/* harmony import */ var _utils_mp4_tools__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils/mp4-tools */ "./src/utils/mp4-tools.ts"); 12566/* harmony import */ var _dummy_demuxed_track__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./dummy-demuxed-track */ "./src/demux/dummy-demuxed-track.ts"); 12567 12568/** 12569 * MP4 demuxer 12570 */ 12571 12572 12573 12574var emsgSchemePattern = /\/emsg[-/]ID3/i; 12575var MP4Demuxer = /*#__PURE__*/function () { 12576 function MP4Demuxer(observer, config) { 12577 this.remainderData = null; 12578 this.timeOffset = 0; 12579 this.config = void 0; 12580 this.videoTrack = void 0; 12581 this.audioTrack = void 0; 12582 this.id3Track = void 0; 12583 this.txtTrack = void 0; 12584 this.config = config; 12585 } 12586 var _proto = MP4Demuxer.prototype; 12587 _proto.resetTimeStamp = function resetTimeStamp() {}; 12588 _proto.resetInitSegment = function resetInitSegment(initSegment, audioCodec, videoCodec, trackDuration) { 12589 var videoTrack = this.videoTrack = (0,_dummy_demuxed_track__WEBPACK_IMPORTED_MODULE_3__.dummyTrack)('video', 1); 12590 var audioTrack = this.audioTrack = (0,_dummy_demuxed_track__WEBPACK_IMPORTED_MODULE_3__.dummyTrack)('audio', 1); 12591 var captionTrack = this.txtTrack = (0,_dummy_demuxed_track__WEBPACK_IMPORTED_MODULE_3__.dummyTrack)('text', 1); 12592 this.id3Track = (0,_dummy_demuxed_track__WEBPACK_IMPORTED_MODULE_3__.dummyTrack)('id3', 1); 12593 this.timeOffset = 0; 12594 if (!initSegment || !initSegment.byteLength) { 12595 return; 12596 } 12597 var initData = (0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_2__.parseInitSegment)(initSegment); 12598 if (initData.video) { 12599 var _initData$video = initData.video, 12600 id = _initData$video.id, 12601 timescale = _initData$video.timescale, 12602 codec = _initData$video.codec; 12603 videoTrack.id = id; 12604 videoTrack.timescale = captionTrack.timescale = timescale; 12605 videoTrack.codec = codec; 12606 } 12607 if (initData.audio) { 12608 var _initData$audio = initData.audio, 12609 _id = _initData$audio.id, 12610 _timescale = _initData$audio.timescale, 12611 _codec = _initData$audio.codec; 12612 audioTrack.id = _id; 12613 audioTrack.timescale = _timescale; 12614 audioTrack.codec = _codec; 12615 } 12616 captionTrack.id = _utils_mp4_tools__WEBPACK_IMPORTED_MODULE_2__.RemuxerTrackIdConfig.text; 12617 videoTrack.sampleDuration = 0; 12618 videoTrack.duration = audioTrack.duration = trackDuration; 12619 }; 12620 _proto.resetContiguity = function resetContiguity() {}; 12621 MP4Demuxer.probe = function probe(data) { 12622 // ensure we find a moof box in the first 16 kB 12623 data = data.length > 16384 ? data.subarray(0, 16384) : data; 12624 return (0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_2__.findBox)(data, ['moof']).length > 0; 12625 }; 12626 _proto.demux = function demux(data, timeOffset) { 12627 this.timeOffset = timeOffset; 12628 // Load all data into the avc track. The CMAF remuxer will look for the data in the samples object; the rest of the fields do not matter 12629 var videoSamples = data; 12630 var videoTrack = this.videoTrack; 12631 var textTrack = this.txtTrack; 12632 if (this.config.progressive) { 12633 // Split the bytestream into two ranges: one encompassing all data up until the start of the last moof, and everything else. 12634 // This is done to guarantee that we're sending valid data to MSE - when demuxing progressively, we have no guarantee 12635 // that the fetch loader gives us flush moof+mdat pairs. If we push jagged data to MSE, it will throw an exception. 12636 if (this.remainderData) { 12637 videoSamples = (0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_2__.appendUint8Array)(this.remainderData, data); 12638 } 12639 var segmentedData = (0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_2__.segmentValidRange)(videoSamples); 12640 this.remainderData = segmentedData.remainder; 12641 videoTrack.samples = segmentedData.valid || new Uint8Array(); 12642 } else { 12643 videoTrack.samples = videoSamples; 12644 } 12645 var id3Track = this.extractID3Track(videoTrack, timeOffset); 12646 textTrack.samples = (0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_2__.parseSamples)(timeOffset, videoTrack); 12647 return { 12648 videoTrack: videoTrack, 12649 audioTrack: this.audioTrack, 12650 id3Track: id3Track, 12651 textTrack: this.txtTrack 12652 }; 12653 }; 12654 _proto.flush = function flush() { 12655 var timeOffset = this.timeOffset; 12656 var videoTrack = this.videoTrack; 12657 var textTrack = this.txtTrack; 12658 videoTrack.samples = this.remainderData || new Uint8Array(); 12659 this.remainderData = null; 12660 var id3Track = this.extractID3Track(videoTrack, this.timeOffset); 12661 textTrack.samples = (0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_2__.parseSamples)(timeOffset, videoTrack); 12662 return { 12663 videoTrack: videoTrack, 12664 audioTrack: (0,_dummy_demuxed_track__WEBPACK_IMPORTED_MODULE_3__.dummyTrack)(), 12665 id3Track: id3Track, 12666 textTrack: (0,_dummy_demuxed_track__WEBPACK_IMPORTED_MODULE_3__.dummyTrack)() 12667 }; 12668 }; 12669 _proto.extractID3Track = function extractID3Track(videoTrack, timeOffset) { 12670 var id3Track = this.id3Track; 12671 if (videoTrack.samples.length) { 12672 var emsgs = (0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_2__.findBox)(videoTrack.samples, ['emsg']); 12673 if (emsgs) { 12674 emsgs.forEach(function (data) { 12675 var emsgInfo = (0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_2__.parseEmsg)(data); 12676 if (emsgSchemePattern.test(emsgInfo.schemeIdUri)) { 12677 var pts = (0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(emsgInfo.presentationTime) ? emsgInfo.presentationTime / emsgInfo.timeScale : timeOffset + emsgInfo.presentationTimeDelta / emsgInfo.timeScale; 12678 var duration = emsgInfo.eventDuration === 0xffffffff ? Number.POSITIVE_INFINITY : emsgInfo.eventDuration / emsgInfo.timeScale; 12679 // Safari takes anything <= 0.001 seconds and maps it to Infinity 12680 if (duration <= 0.001) { 12681 duration = Number.POSITIVE_INFINITY; 12682 } 12683 var payload = emsgInfo.payload; 12684 id3Track.samples.push({ 12685 data: payload, 12686 len: payload.byteLength, 12687 dts: pts, 12688 pts: pts, 12689 type: _types_demuxer__WEBPACK_IMPORTED_MODULE_1__.MetadataSchema.emsg, 12690 duration: duration 12691 }); 12692 } 12693 }); 12694 } 12695 } 12696 return id3Track; 12697 }; 12698 _proto.demuxSampleAes = function demuxSampleAes(data, keyData, timeOffset) { 12699 return Promise.reject(new Error('The MP4 demuxer does not support SAMPLE-AES decryption')); 12700 }; 12701 _proto.destroy = function destroy() {}; 12702 return MP4Demuxer; 12703}(); 12704/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (MP4Demuxer); 12705 12706/***/ }), 12707 12708/***/ "./src/demux/mpegaudio.ts": 12709/*!********************************!*\ 12710 !*** ./src/demux/mpegaudio.ts ***! 12711 \********************************/ 12712/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 12713 12714"use strict"; 12715__webpack_require__.r(__webpack_exports__); 12716/* harmony export */ __webpack_require__.d(__webpack_exports__, { 12717/* harmony export */ "appendFrame": () => (/* binding */ appendFrame), 12718/* harmony export */ "canParse": () => (/* binding */ canParse), 12719/* harmony export */ "isHeader": () => (/* binding */ isHeader), 12720/* harmony export */ "isHeaderPattern": () => (/* binding */ isHeaderPattern), 12721/* harmony export */ "parseHeader": () => (/* binding */ parseHeader), 12722/* harmony export */ "probe": () => (/* binding */ probe) 12723/* harmony export */ }); 12724/** 12725 * MPEG parser helper 12726 */ 12727 12728var chromeVersion = null; 12729var BitratesMap = [32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160]; 12730var SamplingRateMap = [44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000]; 12731var SamplesCoefficients = [ 12732// MPEG 2.5 12733[0, 12734// Reserved 1273572, 12736// Layer3 12737144, 12738// Layer2 1273912 // Layer1 12740], 12741// Reserved 12742[0, 12743// Reserved 127440, 12745// Layer3 127460, 12747// Layer2 127480 // Layer1 12749], 12750// MPEG 2 12751[0, 12752// Reserved 1275372, 12754// Layer3 12755144, 12756// Layer2 1275712 // Layer1 12758], 12759// MPEG 1 12760[0, 12761// Reserved 12762144, 12763// Layer3 12764144, 12765// Layer2 1276612 // Layer1 12767]]; 12768 12769var BytesInSlot = [0, 12770// Reserved 127711, 12772// Layer3 127731, 12774// Layer2 127754 // Layer1 12776]; 12777 12778function appendFrame(track, data, offset, pts, frameIndex) { 12779 // Using http://www.datavoyage.com/mpgscript/mpeghdr.htm as a reference 12780 if (offset + 24 > data.length) { 12781 return; 12782 } 12783 var header = parseHeader(data, offset); 12784 if (header && offset + header.frameLength <= data.length) { 12785 var frameDuration = header.samplesPerFrame * 90000 / header.sampleRate; 12786 var stamp = pts + frameIndex * frameDuration; 12787 var sample = { 12788 unit: data.subarray(offset, offset + header.frameLength), 12789 pts: stamp, 12790 dts: stamp 12791 }; 12792 track.config = []; 12793 track.channelCount = header.channelCount; 12794 track.samplerate = header.sampleRate; 12795 track.samples.push(sample); 12796 return { 12797 sample: sample, 12798 length: header.frameLength, 12799 missing: 0 12800 }; 12801 } 12802} 12803function parseHeader(data, offset) { 12804 var mpegVersion = data[offset + 1] >> 3 & 3; 12805 var mpegLayer = data[offset + 1] >> 1 & 3; 12806 var bitRateIndex = data[offset + 2] >> 4 & 15; 12807 var sampleRateIndex = data[offset + 2] >> 2 & 3; 12808 if (mpegVersion !== 1 && bitRateIndex !== 0 && bitRateIndex !== 15 && sampleRateIndex !== 3) { 12809 var paddingBit = data[offset + 2] >> 1 & 1; 12810 var channelMode = data[offset + 3] >> 6; 12811 var columnInBitrates = mpegVersion === 3 ? 3 - mpegLayer : mpegLayer === 3 ? 3 : 4; 12812 var bitRate = BitratesMap[columnInBitrates * 14 + bitRateIndex - 1] * 1000; 12813 var columnInSampleRates = mpegVersion === 3 ? 0 : mpegVersion === 2 ? 1 : 2; 12814 var sampleRate = SamplingRateMap[columnInSampleRates * 3 + sampleRateIndex]; 12815 var channelCount = channelMode === 3 ? 1 : 2; // If bits of channel mode are `11` then it is a single channel (Mono) 12816 var sampleCoefficient = SamplesCoefficients[mpegVersion][mpegLayer]; 12817 var bytesInSlot = BytesInSlot[mpegLayer]; 12818 var samplesPerFrame = sampleCoefficient * 8 * bytesInSlot; 12819 var frameLength = Math.floor(sampleCoefficient * bitRate / sampleRate + paddingBit) * bytesInSlot; 12820 if (chromeVersion === null) { 12821 var userAgent = navigator.userAgent || ''; 12822 var result = userAgent.match(/Chrome\/(\d+)/i); 12823 chromeVersion = result ? parseInt(result[1]) : 0; 12824 } 12825 var needChromeFix = !!chromeVersion && chromeVersion <= 87; 12826 if (needChromeFix && mpegLayer === 2 && bitRate >= 224000 && channelMode === 0) { 12827 // Work around bug in Chromium by setting channelMode to dual-channel (01) instead of stereo (00) 12828 data[offset + 3] = data[offset + 3] | 0x80; 12829 } 12830 return { 12831 sampleRate: sampleRate, 12832 channelCount: channelCount, 12833 frameLength: frameLength, 12834 samplesPerFrame: samplesPerFrame 12835 }; 12836 } 12837} 12838function isHeaderPattern(data, offset) { 12839 return data[offset] === 0xff && (data[offset + 1] & 0xe0) === 0xe0 && (data[offset + 1] & 0x06) !== 0x00; 12840} 12841function isHeader(data, offset) { 12842 // Look for MPEG header | 1111 1111 | 111X XYZX | where X can be either 0 or 1 and Y or Z should be 1 12843 // Layer bits (position 14 and 15) in header should be always different from 0 (Layer I or Layer II or Layer III) 12844 // More info http://www.mp3-tech.org/programmer/frame_header.html 12845 return offset + 1 < data.length && isHeaderPattern(data, offset); 12846} 12847function canParse(data, offset) { 12848 var headerSize = 4; 12849 return isHeaderPattern(data, offset) && headerSize <= data.length - offset; 12850} 12851function probe(data, offset) { 12852 // same as isHeader but we also check that MPEG frame follows last MPEG frame 12853 // or end of data is reached 12854 if (offset + 1 < data.length && isHeaderPattern(data, offset)) { 12855 // MPEG header Length 12856 var headerLength = 4; 12857 // MPEG frame Length 12858 var header = parseHeader(data, offset); 12859 var frameLength = headerLength; 12860 if (header !== null && header !== void 0 && header.frameLength) { 12861 frameLength = header.frameLength; 12862 } 12863 var newOffset = offset + frameLength; 12864 return newOffset === data.length || isHeader(data, newOffset); 12865 } 12866 return false; 12867} 12868 12869/***/ }), 12870 12871/***/ "./src/demux/sample-aes.ts": 12872/*!*********************************!*\ 12873 !*** ./src/demux/sample-aes.ts ***! 12874 \*********************************/ 12875/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 12876 12877"use strict"; 12878__webpack_require__.r(__webpack_exports__); 12879/* harmony export */ __webpack_require__.d(__webpack_exports__, { 12880/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 12881/* harmony export */ }); 12882/* harmony import */ var _crypt_decrypter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../crypt/decrypter */ "./src/crypt/decrypter.ts"); 12883/* harmony import */ var _utils_mp4_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils/mp4-tools */ "./src/utils/mp4-tools.ts"); 12884/** 12885 * SAMPLE-AES decrypter 12886 */ 12887 12888 12889 12890var SampleAesDecrypter = /*#__PURE__*/function () { 12891 function SampleAesDecrypter(observer, config, keyData) { 12892 this.keyData = void 0; 12893 this.decrypter = void 0; 12894 this.keyData = keyData; 12895 this.decrypter = new _crypt_decrypter__WEBPACK_IMPORTED_MODULE_0__["default"](config, { 12896 removePKCS7Padding: false 12897 }); 12898 } 12899 var _proto = SampleAesDecrypter.prototype; 12900 _proto.decryptBuffer = function decryptBuffer(encryptedData) { 12901 return this.decrypter.decrypt(encryptedData, this.keyData.key.buffer, this.keyData.iv.buffer); 12902 } 12903 12904 // AAC - encrypt all full 16 bytes blocks starting from offset 16 12905 ; 12906 _proto.decryptAacSample = function decryptAacSample(samples, sampleIndex, callback) { 12907 var _this = this; 12908 var curUnit = samples[sampleIndex].unit; 12909 if (curUnit.length <= 16) { 12910 // No encrypted portion in this sample (first 16 bytes is not 12911 // encrypted, see https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/HLS_Sample_Encryption/Encryption/Encryption.html), 12912 return; 12913 } 12914 var encryptedData = curUnit.subarray(16, curUnit.length - curUnit.length % 16); 12915 var encryptedBuffer = encryptedData.buffer.slice(encryptedData.byteOffset, encryptedData.byteOffset + encryptedData.length); 12916 this.decryptBuffer(encryptedBuffer).then(function (decryptedBuffer) { 12917 var decryptedData = new Uint8Array(decryptedBuffer); 12918 curUnit.set(decryptedData, 16); 12919 if (!_this.decrypter.isSync()) { 12920 _this.decryptAacSamples(samples, sampleIndex + 1, callback); 12921 } 12922 }); 12923 }; 12924 _proto.decryptAacSamples = function decryptAacSamples(samples, sampleIndex, callback) { 12925 for (;; sampleIndex++) { 12926 if (sampleIndex >= samples.length) { 12927 callback(); 12928 return; 12929 } 12930 if (samples[sampleIndex].unit.length < 32) { 12931 continue; 12932 } 12933 this.decryptAacSample(samples, sampleIndex, callback); 12934 if (!this.decrypter.isSync()) { 12935 return; 12936 } 12937 } 12938 } 12939 12940 // AVC - encrypt one 16 bytes block out of ten, starting from offset 32 12941 ; 12942 _proto.getAvcEncryptedData = function getAvcEncryptedData(decodedData) { 12943 var encryptedDataLen = Math.floor((decodedData.length - 48) / 160) * 16 + 16; 12944 var encryptedData = new Int8Array(encryptedDataLen); 12945 var outputPos = 0; 12946 for (var inputPos = 32; inputPos < decodedData.length - 16; inputPos += 160, outputPos += 16) { 12947 encryptedData.set(decodedData.subarray(inputPos, inputPos + 16), outputPos); 12948 } 12949 return encryptedData; 12950 }; 12951 _proto.getAvcDecryptedUnit = function getAvcDecryptedUnit(decodedData, decryptedData) { 12952 var uint8DecryptedData = new Uint8Array(decryptedData); 12953 var inputPos = 0; 12954 for (var outputPos = 32; outputPos < decodedData.length - 16; outputPos += 160, inputPos += 16) { 12955 decodedData.set(uint8DecryptedData.subarray(inputPos, inputPos + 16), outputPos); 12956 } 12957 return decodedData; 12958 }; 12959 _proto.decryptAvcSample = function decryptAvcSample(samples, sampleIndex, unitIndex, callback, curUnit) { 12960 var _this2 = this; 12961 var decodedData = (0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_1__.discardEPB)(curUnit.data); 12962 var encryptedData = this.getAvcEncryptedData(decodedData); 12963 this.decryptBuffer(encryptedData.buffer).then(function (decryptedBuffer) { 12964 curUnit.data = _this2.getAvcDecryptedUnit(decodedData, decryptedBuffer); 12965 if (!_this2.decrypter.isSync()) { 12966 _this2.decryptAvcSamples(samples, sampleIndex, unitIndex + 1, callback); 12967 } 12968 }); 12969 }; 12970 _proto.decryptAvcSamples = function decryptAvcSamples(samples, sampleIndex, unitIndex, callback) { 12971 if (samples instanceof Uint8Array) { 12972 throw new Error('Cannot decrypt samples of type Uint8Array'); 12973 } 12974 for (;; sampleIndex++, unitIndex = 0) { 12975 if (sampleIndex >= samples.length) { 12976 callback(); 12977 return; 12978 } 12979 var curUnits = samples[sampleIndex].units; 12980 for (;; unitIndex++) { 12981 if (unitIndex >= curUnits.length) { 12982 break; 12983 } 12984 var curUnit = curUnits[unitIndex]; 12985 if (curUnit.data.length <= 48 || curUnit.type !== 1 && curUnit.type !== 5) { 12986 continue; 12987 } 12988 this.decryptAvcSample(samples, sampleIndex, unitIndex, callback, curUnit); 12989 if (!this.decrypter.isSync()) { 12990 return; 12991 } 12992 } 12993 } 12994 }; 12995 return SampleAesDecrypter; 12996}(); 12997/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SampleAesDecrypter); 12998 12999/***/ }), 13000 13001/***/ "./src/demux/transmuxer-interface.ts": 13002/*!*******************************************!*\ 13003 !*** ./src/demux/transmuxer-interface.ts ***! 13004 \*******************************************/ 13005/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 13006 13007"use strict"; 13008__webpack_require__.r(__webpack_exports__); 13009/* harmony export */ __webpack_require__.d(__webpack_exports__, { 13010/* harmony export */ "default": () => (/* binding */ TransmuxerInterface) 13011/* harmony export */ }); 13012/* harmony import */ var _webworkify_webpack__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./webworkify-webpack */ "./src/demux/webworkify-webpack.js"); 13013/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 13014/* harmony import */ var _demux_transmuxer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../demux/transmuxer */ "./src/demux/transmuxer.ts"); 13015/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 13016/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../errors */ "./src/errors.ts"); 13017/* harmony import */ var _utils_mediasource_helper__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../utils/mediasource-helper */ "./src/utils/mediasource-helper.ts"); 13018/* harmony import */ var eventemitter3__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! eventemitter3 */ "./node_modules/eventemitter3/index.js"); 13019/* harmony import */ var eventemitter3__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(eventemitter3__WEBPACK_IMPORTED_MODULE_6__); 13020 13021 13022 13023 13024 13025 13026 13027var MediaSource = (0,_utils_mediasource_helper__WEBPACK_IMPORTED_MODULE_5__.getMediaSource)() || { 13028 isTypeSupported: function isTypeSupported() { 13029 return false; 13030 } 13031}; 13032var TransmuxerInterface = /*#__PURE__*/function () { 13033 function TransmuxerInterface(hls, id, onTransmuxComplete, onFlush) { 13034 var _this = this; 13035 this.hls = void 0; 13036 this.id = void 0; 13037 this.observer = void 0; 13038 this.frag = null; 13039 this.part = null; 13040 this.useWorker = void 0; 13041 this.worker = void 0; 13042 this.onwmsg = void 0; 13043 this.transmuxer = null; 13044 this.onTransmuxComplete = void 0; 13045 this.onFlush = void 0; 13046 var config = hls.config; 13047 this.hls = hls; 13048 this.id = id; 13049 this.useWorker = !!config.enableWorker; 13050 this.onTransmuxComplete = onTransmuxComplete; 13051 this.onFlush = onFlush; 13052 var forwardMessage = function forwardMessage(ev, data) { 13053 data = data || {}; 13054 data.frag = _this.frag; 13055 data.id = _this.id; 13056 _this.hls.trigger(ev, data); 13057 }; 13058 13059 // forward events to main thread 13060 this.observer = new eventemitter3__WEBPACK_IMPORTED_MODULE_6__.EventEmitter(); 13061 this.observer.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.FRAG_DECRYPTED, forwardMessage); 13062 this.observer.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.ERROR, forwardMessage); 13063 var typeSupported = { 13064 mp4: MediaSource.isTypeSupported('video/mp4'), 13065 mpeg: MediaSource.isTypeSupported('audio/mpeg'), 13066 mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"') 13067 }; 13068 // navigator.vendor is not always available in Web Worker 13069 // refer to https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/navigator 13070 var vendor = navigator.vendor; 13071 if (this.useWorker && typeof Worker !== 'undefined') { 13072 _utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger.log('demuxing in webworker'); 13073 var worker; 13074 try { 13075 worker = this.worker = (0,_webworkify_webpack__WEBPACK_IMPORTED_MODULE_0__["default"])(/*require.resolve*/(/*! ../demux/transmuxer-worker.ts */ "./src/demux/transmuxer-worker.ts")); 13076 this.onwmsg = this.onWorkerMessage.bind(this); 13077 worker.addEventListener('message', this.onwmsg); 13078 worker.onerror = function (event) { 13079 _this.useWorker = false; 13080 _utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger.warn('Exception in webworker, fallback to inline'); 13081 _this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.ERROR, { 13082 type: _errors__WEBPACK_IMPORTED_MODULE_4__.ErrorTypes.OTHER_ERROR, 13083 details: _errors__WEBPACK_IMPORTED_MODULE_4__.ErrorDetails.INTERNAL_EXCEPTION, 13084 fatal: false, 13085 event: 'demuxerWorker', 13086 error: new Error(event.message + " (" + event.filename + ":" + event.lineno + ")") 13087 }); 13088 }; 13089 worker.postMessage({ 13090 cmd: 'init', 13091 typeSupported: typeSupported, 13092 vendor: vendor, 13093 id: id, 13094 config: JSON.stringify(config) 13095 }); 13096 } catch (err) { 13097 _utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger.warn('Error in worker:', err); 13098 _utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger.error('Error while initializing DemuxerWorker, fallback to inline'); 13099 if (worker) { 13100 // revoke the Object URL that was used to create transmuxer worker, so as not to leak it 13101 self.URL.revokeObjectURL(worker.objectURL); 13102 } 13103 this.transmuxer = new _demux_transmuxer__WEBPACK_IMPORTED_MODULE_2__["default"](this.observer, typeSupported, config, vendor, id); 13104 this.worker = null; 13105 } 13106 } else { 13107 this.transmuxer = new _demux_transmuxer__WEBPACK_IMPORTED_MODULE_2__["default"](this.observer, typeSupported, config, vendor, id); 13108 } 13109 } 13110 var _proto = TransmuxerInterface.prototype; 13111 _proto.destroy = function destroy() { 13112 var w = this.worker; 13113 if (w) { 13114 w.removeEventListener('message', this.onwmsg); 13115 w.terminate(); 13116 this.worker = null; 13117 this.onwmsg = undefined; 13118 } else { 13119 var transmuxer = this.transmuxer; 13120 if (transmuxer) { 13121 transmuxer.destroy(); 13122 this.transmuxer = null; 13123 } 13124 } 13125 var observer = this.observer; 13126 if (observer) { 13127 observer.removeAllListeners(); 13128 } 13129 this.frag = null; 13130 // @ts-ignore 13131 this.observer = null; 13132 // @ts-ignore 13133 this.hls = null; 13134 }; 13135 _proto.push = function push(data, initSegmentData, audioCodec, videoCodec, frag, part, duration, accurateTimeOffset, chunkMeta, defaultInitPTS) { 13136 var _frag$initSegment, 13137 _lastFrag$initSegment, 13138 _this2 = this; 13139 chunkMeta.transmuxing.start = self.performance.now(); 13140 var transmuxer = this.transmuxer, 13141 worker = this.worker; 13142 var timeOffset = part ? part.start : frag.start; 13143 // TODO: push "clear-lead" decrypt data for unencrypted fragments in streams with encrypted ones 13144 var decryptdata = frag.decryptdata; 13145 var lastFrag = this.frag; 13146 var discontinuity = !(lastFrag && frag.cc === lastFrag.cc); 13147 var trackSwitch = !(lastFrag && chunkMeta.level === lastFrag.level); 13148 var snDiff = lastFrag ? chunkMeta.sn - lastFrag.sn : -1; 13149 var partDiff = this.part ? chunkMeta.part - this.part.index : -1; 13150 var progressive = snDiff === 0 && chunkMeta.id > 1 && chunkMeta.id === (lastFrag === null || lastFrag === void 0 ? void 0 : lastFrag.stats.chunkCount); 13151 var contiguous = !trackSwitch && (snDiff === 1 || snDiff === 0 && (partDiff === 1 || progressive && partDiff <= 0)); 13152 var now = self.performance.now(); 13153 if (trackSwitch || snDiff || frag.stats.parsing.start === 0) { 13154 frag.stats.parsing.start = now; 13155 } 13156 if (part && (partDiff || !contiguous)) { 13157 part.stats.parsing.start = now; 13158 } 13159 var initSegmentChange = !(lastFrag && ((_frag$initSegment = frag.initSegment) === null || _frag$initSegment === void 0 ? void 0 : _frag$initSegment.url) === ((_lastFrag$initSegment = lastFrag.initSegment) === null || _lastFrag$initSegment === void 0 ? void 0 : _lastFrag$initSegment.url)); 13160 var state = new _demux_transmuxer__WEBPACK_IMPORTED_MODULE_2__.TransmuxState(discontinuity, contiguous, accurateTimeOffset, trackSwitch, timeOffset, initSegmentChange); 13161 if (!contiguous || discontinuity || initSegmentChange) { 13162 _utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger.log("[transmuxer-interface, " + frag.type + "]: Starting new transmux session for sn: " + chunkMeta.sn + " p: " + chunkMeta.part + " level: " + chunkMeta.level + " id: " + chunkMeta.id + "\n discontinuity: " + discontinuity + "\n trackSwitch: " + trackSwitch + "\n contiguous: " + contiguous + "\n accurateTimeOffset: " + accurateTimeOffset + "\n timeOffset: " + timeOffset + "\n initSegmentChange: " + initSegmentChange); 13163 var config = new _demux_transmuxer__WEBPACK_IMPORTED_MODULE_2__.TransmuxConfig(audioCodec, videoCodec, initSegmentData, duration, defaultInitPTS); 13164 this.configureTransmuxer(config); 13165 } 13166 this.frag = frag; 13167 this.part = part; 13168 13169 // Frags with sn of 'initSegment' are not transmuxed 13170 if (worker) { 13171 // post fragment payload as transferable objects for ArrayBuffer (no copy) 13172 worker.postMessage({ 13173 cmd: 'demux', 13174 data: data, 13175 decryptdata: decryptdata, 13176 chunkMeta: chunkMeta, 13177 state: state 13178 }, data instanceof ArrayBuffer ? [data] : []); 13179 } else if (transmuxer) { 13180 var _transmuxResult = transmuxer.push(data, decryptdata, chunkMeta, state); 13181 if ((0,_demux_transmuxer__WEBPACK_IMPORTED_MODULE_2__.isPromise)(_transmuxResult)) { 13182 transmuxer.async = true; 13183 _transmuxResult.then(function (data) { 13184 _this2.handleTransmuxComplete(data); 13185 }).catch(function (error) { 13186 _this2.transmuxerError(error, chunkMeta, 'transmuxer-interface push error'); 13187 }); 13188 } else { 13189 transmuxer.async = false; 13190 this.handleTransmuxComplete(_transmuxResult); 13191 } 13192 } 13193 }; 13194 _proto.flush = function flush(chunkMeta) { 13195 var _this3 = this; 13196 chunkMeta.transmuxing.start = self.performance.now(); 13197 var transmuxer = this.transmuxer, 13198 worker = this.worker; 13199 if (worker) { 13200 1; 13201 worker.postMessage({ 13202 cmd: 'flush', 13203 chunkMeta: chunkMeta 13204 }); 13205 } else if (transmuxer) { 13206 var _transmuxResult2 = transmuxer.flush(chunkMeta); 13207 var asyncFlush = (0,_demux_transmuxer__WEBPACK_IMPORTED_MODULE_2__.isPromise)(_transmuxResult2); 13208 if (asyncFlush || transmuxer.async) { 13209 if (!(0,_demux_transmuxer__WEBPACK_IMPORTED_MODULE_2__.isPromise)(_transmuxResult2)) { 13210 _transmuxResult2 = Promise.resolve(_transmuxResult2); 13211 } 13212 _transmuxResult2.then(function (data) { 13213 _this3.handleFlushResult(data, chunkMeta); 13214 }).catch(function (error) { 13215 _this3.transmuxerError(error, chunkMeta, 'transmuxer-interface flush error'); 13216 }); 13217 } else { 13218 this.handleFlushResult(_transmuxResult2, chunkMeta); 13219 } 13220 } 13221 }; 13222 _proto.transmuxerError = function transmuxerError(error, chunkMeta, reason) { 13223 if (!this.hls) { 13224 return; 13225 } 13226 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.ERROR, { 13227 type: _errors__WEBPACK_IMPORTED_MODULE_4__.ErrorTypes.MEDIA_ERROR, 13228 details: _errors__WEBPACK_IMPORTED_MODULE_4__.ErrorDetails.FRAG_PARSING_ERROR, 13229 chunkMeta: chunkMeta, 13230 fatal: false, 13231 error: error, 13232 err: error, 13233 reason: reason 13234 }); 13235 }; 13236 _proto.handleFlushResult = function handleFlushResult(results, chunkMeta) { 13237 var _this4 = this; 13238 results.forEach(function (result) { 13239 _this4.handleTransmuxComplete(result); 13240 }); 13241 this.onFlush(chunkMeta); 13242 }; 13243 _proto.onWorkerMessage = function onWorkerMessage(ev) { 13244 var data = ev.data; 13245 var hls = this.hls; 13246 switch (data.event) { 13247 case 'init': 13248 { 13249 // revoke the Object URL that was used to create transmuxer worker, so as not to leak it 13250 self.URL.revokeObjectURL(this.worker.objectURL); 13251 break; 13252 } 13253 case 'transmuxComplete': 13254 { 13255 this.handleTransmuxComplete(data.data); 13256 break; 13257 } 13258 case 'flush': 13259 { 13260 this.onFlush(data.data); 13261 break; 13262 } 13263 13264 // pass logs from the worker thread to the main logger 13265 case 'workerLog': 13266 if (_utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger[data.data.logType]) { 13267 _utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger[data.data.logType](data.data.message); 13268 } 13269 break; 13270 default: 13271 { 13272 data.data = data.data || {}; 13273 data.data.frag = this.frag; 13274 data.data.id = this.id; 13275 hls.trigger(data.event, data.data); 13276 break; 13277 } 13278 } 13279 }; 13280 _proto.configureTransmuxer = function configureTransmuxer(config) { 13281 var worker = this.worker, 13282 transmuxer = this.transmuxer; 13283 if (worker) { 13284 worker.postMessage({ 13285 cmd: 'configure', 13286 config: config 13287 }); 13288 } else if (transmuxer) { 13289 transmuxer.configure(config); 13290 } 13291 }; 13292 _proto.handleTransmuxComplete = function handleTransmuxComplete(result) { 13293 result.chunkMeta.transmuxing.end = self.performance.now(); 13294 this.onTransmuxComplete(result); 13295 }; 13296 return TransmuxerInterface; 13297}(); 13298 13299 13300/***/ }), 13301 13302/***/ "./src/demux/transmuxer-worker.ts": 13303/*!****************************************!*\ 13304 !*** ./src/demux/transmuxer-worker.ts ***! 13305 \****************************************/ 13306/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 13307 13308"use strict"; 13309__webpack_require__.r(__webpack_exports__); 13310/* harmony export */ __webpack_require__.d(__webpack_exports__, { 13311/* harmony export */ "default": () => (/* binding */ TransmuxerWorker) 13312/* harmony export */ }); 13313/* harmony import */ var _demux_transmuxer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../demux/transmuxer */ "./src/demux/transmuxer.ts"); 13314/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 13315/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 13316/* harmony import */ var eventemitter3__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! eventemitter3 */ "./node_modules/eventemitter3/index.js"); 13317/* harmony import */ var eventemitter3__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(eventemitter3__WEBPACK_IMPORTED_MODULE_3__); 13318/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../errors */ "./src/errors.ts"); 13319 13320 13321 13322 13323 13324function TransmuxerWorker(self) { 13325 var observer = new eventemitter3__WEBPACK_IMPORTED_MODULE_3__.EventEmitter(); 13326 var forwardMessage = function forwardMessage(ev, data) { 13327 self.postMessage({ 13328 event: ev, 13329 data: data 13330 }); 13331 }; 13332 13333 // forward events to main thread 13334 observer.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.FRAG_DECRYPTED, forwardMessage); 13335 observer.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.ERROR, forwardMessage); 13336 13337 // forward logger events to main thread 13338 var forwardWorkerLogs = function forwardWorkerLogs() { 13339 var _loop = function _loop(logFn) { 13340 var func = function func(message) { 13341 forwardMessage('workerLog', { 13342 logType: logFn, 13343 message: message 13344 }); 13345 }; 13346 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger[logFn] = func; 13347 }; 13348 for (var logFn in _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger) { 13349 _loop(logFn); 13350 } 13351 }; 13352 self.addEventListener('message', function (ev) { 13353 var data = ev.data; 13354 switch (data.cmd) { 13355 case 'init': 13356 { 13357 var config = JSON.parse(data.config); 13358 self.transmuxer = new _demux_transmuxer__WEBPACK_IMPORTED_MODULE_0__["default"](observer, data.typeSupported, config, data.vendor, data.id); 13359 (0,_utils_logger__WEBPACK_IMPORTED_MODULE_2__.enableLogs)(config.debug, data.id); 13360 forwardWorkerLogs(); 13361 forwardMessage('init', null); 13362 break; 13363 } 13364 case 'configure': 13365 { 13366 self.transmuxer.configure(data.config); 13367 break; 13368 } 13369 case 'demux': 13370 { 13371 var transmuxResult = self.transmuxer.push(data.data, data.decryptdata, data.chunkMeta, data.state); 13372 if ((0,_demux_transmuxer__WEBPACK_IMPORTED_MODULE_0__.isPromise)(transmuxResult)) { 13373 self.transmuxer.async = true; 13374 transmuxResult.then(function (data) { 13375 emitTransmuxComplete(self, data); 13376 }).catch(function (error) { 13377 forwardMessage(_events__WEBPACK_IMPORTED_MODULE_1__.Events.ERROR, { 13378 type: _errors__WEBPACK_IMPORTED_MODULE_4__.ErrorTypes.MEDIA_ERROR, 13379 details: _errors__WEBPACK_IMPORTED_MODULE_4__.ErrorDetails.FRAG_PARSING_ERROR, 13380 chunkMeta: data.chunkMeta, 13381 fatal: false, 13382 error: error, 13383 err: error, 13384 reason: "transmuxer-worker push error" 13385 }); 13386 }); 13387 } else { 13388 self.transmuxer.async = false; 13389 emitTransmuxComplete(self, transmuxResult); 13390 } 13391 break; 13392 } 13393 case 'flush': 13394 { 13395 var id = data.chunkMeta; 13396 var _transmuxResult = self.transmuxer.flush(id); 13397 var asyncFlush = (0,_demux_transmuxer__WEBPACK_IMPORTED_MODULE_0__.isPromise)(_transmuxResult); 13398 if (asyncFlush || self.transmuxer.async) { 13399 if (!(0,_demux_transmuxer__WEBPACK_IMPORTED_MODULE_0__.isPromise)(_transmuxResult)) { 13400 _transmuxResult = Promise.resolve(_transmuxResult); 13401 } 13402 _transmuxResult.then(function (results) { 13403 handleFlushResult(self, results, id); 13404 }).catch(function (error) { 13405 forwardMessage(_events__WEBPACK_IMPORTED_MODULE_1__.Events.ERROR, { 13406 type: _errors__WEBPACK_IMPORTED_MODULE_4__.ErrorTypes.MEDIA_ERROR, 13407 details: _errors__WEBPACK_IMPORTED_MODULE_4__.ErrorDetails.FRAG_PARSING_ERROR, 13408 chunkMeta: data.chunkMeta, 13409 fatal: false, 13410 error: error, 13411 err: error, 13412 reason: "transmuxer-worker flush error" 13413 }); 13414 }); 13415 } else { 13416 handleFlushResult(self, _transmuxResult, id); 13417 } 13418 break; 13419 } 13420 default: 13421 break; 13422 } 13423 }); 13424} 13425function emitTransmuxComplete(self, transmuxResult) { 13426 if (isEmptyResult(transmuxResult.remuxResult)) { 13427 return false; 13428 } 13429 var transferable = []; 13430 var _transmuxResult$remux = transmuxResult.remuxResult, 13431 audio = _transmuxResult$remux.audio, 13432 video = _transmuxResult$remux.video; 13433 if (audio) { 13434 addToTransferable(transferable, audio); 13435 } 13436 if (video) { 13437 addToTransferable(transferable, video); 13438 } 13439 self.postMessage({ 13440 event: 'transmuxComplete', 13441 data: transmuxResult 13442 }, transferable); 13443 return true; 13444} 13445 13446// Converts data to a transferable object https://developers.google.com/web/updates/2011/12/Transferable-Objects-Lightning-Fast) 13447// in order to minimize message passing overhead 13448function addToTransferable(transferable, track) { 13449 if (track.data1) { 13450 transferable.push(track.data1.buffer); 13451 } 13452 if (track.data2) { 13453 transferable.push(track.data2.buffer); 13454 } 13455} 13456function handleFlushResult(self, results, chunkMeta) { 13457 var parsed = results.reduce(function (parsed, result) { 13458 return emitTransmuxComplete(self, result) || parsed; 13459 }, false); 13460 if (!parsed) { 13461 // Emit at least one "transmuxComplete" message even if media is not found to update stream-controller state to PARSING 13462 self.postMessage({ 13463 event: 'transmuxComplete', 13464 data: results[0] 13465 }); 13466 } 13467 self.postMessage({ 13468 event: 'flush', 13469 data: chunkMeta 13470 }); 13471} 13472function isEmptyResult(remuxResult) { 13473 return !remuxResult.audio && !remuxResult.video && !remuxResult.text && !remuxResult.id3 && !remuxResult.initSegment; 13474} 13475 13476/***/ }), 13477 13478/***/ "./src/demux/transmuxer.ts": 13479/*!*********************************!*\ 13480 !*** ./src/demux/transmuxer.ts ***! 13481 \*********************************/ 13482/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 13483 13484"use strict"; 13485__webpack_require__.r(__webpack_exports__); 13486/* harmony export */ __webpack_require__.d(__webpack_exports__, { 13487/* harmony export */ "TransmuxConfig": () => (/* binding */ TransmuxConfig), 13488/* harmony export */ "TransmuxState": () => (/* binding */ TransmuxState), 13489/* harmony export */ "default": () => (/* binding */ Transmuxer), 13490/* harmony export */ "isPromise": () => (/* binding */ isPromise) 13491/* harmony export */ }); 13492/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 13493/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../errors */ "./src/errors.ts"); 13494/* harmony import */ var _crypt_decrypter__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../crypt/decrypter */ "./src/crypt/decrypter.ts"); 13495/* harmony import */ var _demux_aacdemuxer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../demux/aacdemuxer */ "./src/demux/aacdemuxer.ts"); 13496/* harmony import */ var _demux_mp4demuxer__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../demux/mp4demuxer */ "./src/demux/mp4demuxer.ts"); 13497/* harmony import */ var _demux_tsdemuxer__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../demux/tsdemuxer */ "./src/demux/tsdemuxer.ts"); 13498/* harmony import */ var _demux_mp3demuxer__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../demux/mp3demuxer */ "./src/demux/mp3demuxer.ts"); 13499/* harmony import */ var _remux_mp4_remuxer__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../remux/mp4-remuxer */ "./src/remux/mp4-remuxer.ts"); 13500/* harmony import */ var _remux_passthrough_remuxer__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../remux/passthrough-remuxer */ "./src/remux/passthrough-remuxer.ts"); 13501/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 13502 13503 13504 13505 13506 13507 13508 13509 13510 13511 13512var now; 13513// performance.now() not available on WebWorker, at least on Safari Desktop 13514try { 13515 now = self.performance.now.bind(self.performance); 13516} catch (err) { 13517 _utils_logger__WEBPACK_IMPORTED_MODULE_9__.logger.debug('Unable to use Performance API on this environment'); 13518 now = self.Date.now; 13519} 13520var muxConfig = [{ 13521 demux: _demux_mp4demuxer__WEBPACK_IMPORTED_MODULE_4__["default"], 13522 remux: _remux_passthrough_remuxer__WEBPACK_IMPORTED_MODULE_8__["default"] 13523}, { 13524 demux: _demux_tsdemuxer__WEBPACK_IMPORTED_MODULE_5__["default"], 13525 remux: _remux_mp4_remuxer__WEBPACK_IMPORTED_MODULE_7__["default"] 13526}, { 13527 demux: _demux_aacdemuxer__WEBPACK_IMPORTED_MODULE_3__["default"], 13528 remux: _remux_mp4_remuxer__WEBPACK_IMPORTED_MODULE_7__["default"] 13529}, { 13530 demux: _demux_mp3demuxer__WEBPACK_IMPORTED_MODULE_6__["default"], 13531 remux: _remux_mp4_remuxer__WEBPACK_IMPORTED_MODULE_7__["default"] 13532}]; 13533var Transmuxer = /*#__PURE__*/function () { 13534 function Transmuxer(observer, typeSupported, config, vendor, id) { 13535 this.async = false; 13536 this.observer = void 0; 13537 this.typeSupported = void 0; 13538 this.config = void 0; 13539 this.vendor = void 0; 13540 this.id = void 0; 13541 this.demuxer = void 0; 13542 this.remuxer = void 0; 13543 this.decrypter = void 0; 13544 this.probe = void 0; 13545 this.decryptionPromise = null; 13546 this.transmuxConfig = void 0; 13547 this.currentTransmuxState = void 0; 13548 this.observer = observer; 13549 this.typeSupported = typeSupported; 13550 this.config = config; 13551 this.vendor = vendor; 13552 this.id = id; 13553 } 13554 var _proto = Transmuxer.prototype; 13555 _proto.configure = function configure(transmuxConfig) { 13556 this.transmuxConfig = transmuxConfig; 13557 if (this.decrypter) { 13558 this.decrypter.reset(); 13559 } 13560 }; 13561 _proto.push = function push(data, decryptdata, chunkMeta, state) { 13562 var _this = this; 13563 var stats = chunkMeta.transmuxing; 13564 stats.executeStart = now(); 13565 var uintData = new Uint8Array(data); 13566 var currentTransmuxState = this.currentTransmuxState, 13567 transmuxConfig = this.transmuxConfig; 13568 if (state) { 13569 this.currentTransmuxState = state; 13570 } 13571 var _ref = state || currentTransmuxState, 13572 contiguous = _ref.contiguous, 13573 discontinuity = _ref.discontinuity, 13574 trackSwitch = _ref.trackSwitch, 13575 accurateTimeOffset = _ref.accurateTimeOffset, 13576 timeOffset = _ref.timeOffset, 13577 initSegmentChange = _ref.initSegmentChange; 13578 var audioCodec = transmuxConfig.audioCodec, 13579 videoCodec = transmuxConfig.videoCodec, 13580 defaultInitPts = transmuxConfig.defaultInitPts, 13581 duration = transmuxConfig.duration, 13582 initSegmentData = transmuxConfig.initSegmentData; 13583 var keyData = getEncryptionType(uintData, decryptdata); 13584 if (keyData && keyData.method === 'AES-128') { 13585 var decrypter = this.getDecrypter(); 13586 // Software decryption is synchronous; webCrypto is not 13587 if (decrypter.isSync()) { 13588 // Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached 13589 // data is handled in the flush() call 13590 var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer); 13591 if (!decryptedData) { 13592 stats.executeEnd = now(); 13593 return emptyResult(chunkMeta); 13594 } 13595 uintData = new Uint8Array(decryptedData); 13596 } else { 13597 this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer).then(function (decryptedData) { 13598 // Calling push here is important; if flush() is called while this is still resolving, this ensures that 13599 // the decrypted data has been transmuxed 13600 var result = _this.push(decryptedData, null, chunkMeta); 13601 _this.decryptionPromise = null; 13602 return result; 13603 }); 13604 return this.decryptionPromise; 13605 } 13606 } 13607 var resetMuxers = this.needsProbing(discontinuity, trackSwitch); 13608 if (resetMuxers) { 13609 this.configureTransmuxer(uintData); 13610 } 13611 if (discontinuity || trackSwitch || initSegmentChange || resetMuxers) { 13612 this.resetInitSegment(initSegmentData, audioCodec, videoCodec, duration, decryptdata); 13613 } 13614 if (discontinuity || initSegmentChange || resetMuxers) { 13615 this.resetInitialTimestamp(defaultInitPts); 13616 } 13617 if (!contiguous) { 13618 this.resetContiguity(); 13619 } 13620 var result = this.transmux(uintData, keyData, timeOffset, accurateTimeOffset, chunkMeta); 13621 var currentState = this.currentTransmuxState; 13622 currentState.contiguous = true; 13623 currentState.discontinuity = false; 13624 currentState.trackSwitch = false; 13625 stats.executeEnd = now(); 13626 return result; 13627 } 13628 13629 // Due to data caching, flush calls can produce more than one TransmuxerResult (hence the Array type) 13630 ; 13631 _proto.flush = function flush(chunkMeta) { 13632 var _this2 = this; 13633 var stats = chunkMeta.transmuxing; 13634 stats.executeStart = now(); 13635 var decrypter = this.decrypter, 13636 currentTransmuxState = this.currentTransmuxState, 13637 decryptionPromise = this.decryptionPromise; 13638 if (decryptionPromise) { 13639 // Upon resolution, the decryption promise calls push() and returns its TransmuxerResult up the stack. Therefore 13640 // only flushing is required for async decryption 13641 return decryptionPromise.then(function () { 13642 return _this2.flush(chunkMeta); 13643 }); 13644 } 13645 var transmuxResults = []; 13646 var timeOffset = currentTransmuxState.timeOffset; 13647 if (decrypter) { 13648 // The decrypter may have data cached, which needs to be demuxed. In this case we'll have two TransmuxResults 13649 // This happens in the case that we receive only 1 push call for a segment (either for non-progressive downloads, 13650 // or for progressive downloads with small segments) 13651 var decryptedData = decrypter.flush(); 13652 if (decryptedData) { 13653 // Push always returns a TransmuxerResult if decryptdata is null 13654 transmuxResults.push(this.push(decryptedData, null, chunkMeta)); 13655 } 13656 } 13657 var demuxer = this.demuxer, 13658 remuxer = this.remuxer; 13659 if (!demuxer || !remuxer) { 13660 // If probing failed, then Hls.js has been given content its not able to handle 13661 this.observer.emit(_events__WEBPACK_IMPORTED_MODULE_0__.Events.ERROR, _events__WEBPACK_IMPORTED_MODULE_0__.Events.ERROR, { 13662 type: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorTypes.MEDIA_ERROR, 13663 details: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorDetails.FRAG_PARSING_ERROR, 13664 fatal: true, 13665 reason: 'no demux matching with content found' 13666 }); 13667 stats.executeEnd = now(); 13668 return [emptyResult(chunkMeta)]; 13669 } 13670 var demuxResultOrPromise = demuxer.flush(timeOffset); 13671 if (isPromise(demuxResultOrPromise)) { 13672 // Decrypt final SAMPLE-AES samples 13673 return demuxResultOrPromise.then(function (demuxResult) { 13674 _this2.flushRemux(transmuxResults, demuxResult, chunkMeta); 13675 return transmuxResults; 13676 }); 13677 } 13678 this.flushRemux(transmuxResults, demuxResultOrPromise, chunkMeta); 13679 return transmuxResults; 13680 }; 13681 _proto.flushRemux = function flushRemux(transmuxResults, demuxResult, chunkMeta) { 13682 var audioTrack = demuxResult.audioTrack, 13683 videoTrack = demuxResult.videoTrack, 13684 id3Track = demuxResult.id3Track, 13685 textTrack = demuxResult.textTrack; 13686 var _this$currentTransmux = this.currentTransmuxState, 13687 accurateTimeOffset = _this$currentTransmux.accurateTimeOffset, 13688 timeOffset = _this$currentTransmux.timeOffset; 13689 _utils_logger__WEBPACK_IMPORTED_MODULE_9__.logger.log("[transmuxer.ts]: Flushed fragment " + chunkMeta.sn + (chunkMeta.part > -1 ? ' p: ' + chunkMeta.part : '') + " of level " + chunkMeta.level); 13690 var remuxResult = this.remuxer.remux(audioTrack, videoTrack, id3Track, textTrack, timeOffset, accurateTimeOffset, true, this.id); 13691 transmuxResults.push({ 13692 remuxResult: remuxResult, 13693 chunkMeta: chunkMeta 13694 }); 13695 chunkMeta.transmuxing.executeEnd = now(); 13696 }; 13697 _proto.resetInitialTimestamp = function resetInitialTimestamp(defaultInitPts) { 13698 var demuxer = this.demuxer, 13699 remuxer = this.remuxer; 13700 if (!demuxer || !remuxer) { 13701 return; 13702 } 13703 demuxer.resetTimeStamp(defaultInitPts); 13704 remuxer.resetTimeStamp(defaultInitPts); 13705 }; 13706 _proto.resetContiguity = function resetContiguity() { 13707 var demuxer = this.demuxer, 13708 remuxer = this.remuxer; 13709 if (!demuxer || !remuxer) { 13710 return; 13711 } 13712 demuxer.resetContiguity(); 13713 remuxer.resetNextTimestamp(); 13714 }; 13715 _proto.resetInitSegment = function resetInitSegment(initSegmentData, audioCodec, videoCodec, trackDuration, decryptdata) { 13716 var demuxer = this.demuxer, 13717 remuxer = this.remuxer; 13718 if (!demuxer || !remuxer) { 13719 return; 13720 } 13721 demuxer.resetInitSegment(initSegmentData, audioCodec, videoCodec, trackDuration); 13722 remuxer.resetInitSegment(initSegmentData, audioCodec, videoCodec, decryptdata); 13723 }; 13724 _proto.destroy = function destroy() { 13725 if (this.demuxer) { 13726 this.demuxer.destroy(); 13727 this.demuxer = undefined; 13728 } 13729 if (this.remuxer) { 13730 this.remuxer.destroy(); 13731 this.remuxer = undefined; 13732 } 13733 }; 13734 _proto.transmux = function transmux(data, keyData, timeOffset, accurateTimeOffset, chunkMeta) { 13735 var result; 13736 if (keyData && keyData.method === 'SAMPLE-AES') { 13737 result = this.transmuxSampleAes(data, keyData, timeOffset, accurateTimeOffset, chunkMeta); 13738 } else { 13739 result = this.transmuxUnencrypted(data, timeOffset, accurateTimeOffset, chunkMeta); 13740 } 13741 return result; 13742 }; 13743 _proto.transmuxUnencrypted = function transmuxUnencrypted(data, timeOffset, accurateTimeOffset, chunkMeta) { 13744 var _demux = this.demuxer.demux(data, timeOffset, false, !this.config.progressive), 13745 audioTrack = _demux.audioTrack, 13746 videoTrack = _demux.videoTrack, 13747 id3Track = _demux.id3Track, 13748 textTrack = _demux.textTrack; 13749 var remuxResult = this.remuxer.remux(audioTrack, videoTrack, id3Track, textTrack, timeOffset, accurateTimeOffset, false, this.id); 13750 return { 13751 remuxResult: remuxResult, 13752 chunkMeta: chunkMeta 13753 }; 13754 }; 13755 _proto.transmuxSampleAes = function transmuxSampleAes(data, decryptData, timeOffset, accurateTimeOffset, chunkMeta) { 13756 var _this3 = this; 13757 return this.demuxer.demuxSampleAes(data, decryptData, timeOffset).then(function (demuxResult) { 13758 var remuxResult = _this3.remuxer.remux(demuxResult.audioTrack, demuxResult.videoTrack, demuxResult.id3Track, demuxResult.textTrack, timeOffset, accurateTimeOffset, false, _this3.id); 13759 return { 13760 remuxResult: remuxResult, 13761 chunkMeta: chunkMeta 13762 }; 13763 }); 13764 }; 13765 _proto.configureTransmuxer = function configureTransmuxer(data) { 13766 var config = this.config, 13767 observer = this.observer, 13768 typeSupported = this.typeSupported, 13769 vendor = this.vendor; 13770 // probe for content type 13771 var mux; 13772 for (var i = 0, len = muxConfig.length; i < len; i++) { 13773 if (muxConfig[i].demux.probe(data)) { 13774 mux = muxConfig[i]; 13775 break; 13776 } 13777 } 13778 if (!mux) { 13779 // If probing previous configs fail, use mp4 passthrough 13780 _utils_logger__WEBPACK_IMPORTED_MODULE_9__.logger.warn('Failed to find demuxer by probing frag, treating as mp4 passthrough'); 13781 mux = { 13782 demux: _demux_mp4demuxer__WEBPACK_IMPORTED_MODULE_4__["default"], 13783 remux: _remux_passthrough_remuxer__WEBPACK_IMPORTED_MODULE_8__["default"] 13784 }; 13785 } 13786 // so let's check that current remuxer and demuxer are still valid 13787 var demuxer = this.demuxer; 13788 var remuxer = this.remuxer; 13789 var Remuxer = mux.remux; 13790 var Demuxer = mux.demux; 13791 if (!remuxer || !(remuxer instanceof Remuxer)) { 13792 this.remuxer = new Remuxer(observer, config, typeSupported, vendor); 13793 } 13794 if (!demuxer || !(demuxer instanceof Demuxer)) { 13795 this.demuxer = new Demuxer(observer, config, typeSupported); 13796 this.probe = Demuxer.probe; 13797 } 13798 }; 13799 _proto.needsProbing = function needsProbing(discontinuity, trackSwitch) { 13800 // in case of continuity change, or track switch 13801 // we might switch from content type (AAC container to TS container, or TS to fmp4 for example) 13802 return !this.demuxer || !this.remuxer || discontinuity || trackSwitch; 13803 }; 13804 _proto.getDecrypter = function getDecrypter() { 13805 var decrypter = this.decrypter; 13806 if (!decrypter) { 13807 decrypter = this.decrypter = new _crypt_decrypter__WEBPACK_IMPORTED_MODULE_2__["default"](this.config); 13808 } 13809 return decrypter; 13810 }; 13811 return Transmuxer; 13812}(); 13813 13814function getEncryptionType(data, decryptData) { 13815 var encryptionType = null; 13816 if (data.byteLength > 0 && decryptData != null && decryptData.key != null && decryptData.iv !== null && decryptData.method != null) { 13817 encryptionType = decryptData; 13818 } 13819 return encryptionType; 13820} 13821var emptyResult = function emptyResult(chunkMeta) { 13822 return { 13823 remuxResult: {}, 13824 chunkMeta: chunkMeta 13825 }; 13826}; 13827function isPromise(p) { 13828 return 'then' in p && p.then instanceof Function; 13829} 13830var TransmuxConfig = function TransmuxConfig(audioCodec, videoCodec, initSegmentData, duration, defaultInitPts) { 13831 this.audioCodec = void 0; 13832 this.videoCodec = void 0; 13833 this.initSegmentData = void 0; 13834 this.duration = void 0; 13835 this.defaultInitPts = void 0; 13836 this.audioCodec = audioCodec; 13837 this.videoCodec = videoCodec; 13838 this.initSegmentData = initSegmentData; 13839 this.duration = duration; 13840 this.defaultInitPts = defaultInitPts; 13841}; 13842var TransmuxState = function TransmuxState(discontinuity, contiguous, accurateTimeOffset, trackSwitch, timeOffset, initSegmentChange) { 13843 this.discontinuity = void 0; 13844 this.contiguous = void 0; 13845 this.accurateTimeOffset = void 0; 13846 this.trackSwitch = void 0; 13847 this.timeOffset = void 0; 13848 this.initSegmentChange = void 0; 13849 this.discontinuity = discontinuity; 13850 this.contiguous = contiguous; 13851 this.accurateTimeOffset = accurateTimeOffset; 13852 this.trackSwitch = trackSwitch; 13853 this.timeOffset = timeOffset; 13854 this.initSegmentChange = initSegmentChange; 13855}; 13856 13857/***/ }), 13858 13859/***/ "./src/demux/tsdemuxer.ts": 13860/*!********************************!*\ 13861 !*** ./src/demux/tsdemuxer.ts ***! 13862 \********************************/ 13863/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 13864 13865"use strict"; 13866__webpack_require__.r(__webpack_exports__); 13867/* harmony export */ __webpack_require__.d(__webpack_exports__, { 13868/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 13869/* harmony export */ }); 13870/* harmony import */ var _adts__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./adts */ "./src/demux/adts.ts"); 13871/* harmony import */ var _mpegaudio__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./mpegaudio */ "./src/demux/mpegaudio.ts"); 13872/* harmony import */ var _exp_golomb__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./exp-golomb */ "./src/demux/exp-golomb.ts"); 13873/* harmony import */ var _sample_aes__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./sample-aes */ "./src/demux/sample-aes.ts"); 13874/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 13875/* harmony import */ var _utils_mp4_tools__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../utils/mp4-tools */ "./src/utils/mp4-tools.ts"); 13876/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 13877/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../errors */ "./src/errors.ts"); 13878/* harmony import */ var _types_demuxer__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../types/demuxer */ "./src/types/demuxer.ts"); 13879function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } 13880/** 13881 * highly optimized TS demuxer: 13882 * parse PAT, PMT 13883 * extract PES packet from audio and video PIDs 13884 * extract AVC/H264 NAL units and AAC/ADTS samples from PES packet 13885 * trigger the remuxer upon parsing completion 13886 * it also tries to workaround as best as it can audio codec switch (HE-AAC to AAC and vice versa), without having to restart the MediaSource. 13887 * it also controls the remuxing process : 13888 * upon discontinuity or level switch detection, it will also notifies the remuxer so that it can reset its state. 13889 */ 13890 13891 13892 13893 13894 13895 13896 13897 13898 13899 13900var PACKET_LENGTH = 188; 13901var TSDemuxer = /*#__PURE__*/function () { 13902 function TSDemuxer(observer, config, typeSupported) { 13903 this.observer = void 0; 13904 this.config = void 0; 13905 this.typeSupported = void 0; 13906 this.sampleAes = null; 13907 this.pmtParsed = false; 13908 this.audioCodec = void 0; 13909 this.videoCodec = void 0; 13910 this._duration = 0; 13911 this._pmtId = -1; 13912 this._avcTrack = void 0; 13913 this._audioTrack = void 0; 13914 this._id3Track = void 0; 13915 this._txtTrack = void 0; 13916 this.aacOverFlow = null; 13917 this.avcSample = null; 13918 this.remainderData = null; 13919 this.observer = observer; 13920 this.config = config; 13921 this.typeSupported = typeSupported; 13922 } 13923 TSDemuxer.probe = function probe(data) { 13924 var syncOffset = TSDemuxer.syncOffset(data); 13925 if (syncOffset > 0) { 13926 _utils_logger__WEBPACK_IMPORTED_MODULE_6__.logger.warn("MPEG2-TS detected but first sync word found @ offset " + syncOffset); 13927 } 13928 return syncOffset !== -1; 13929 }; 13930 TSDemuxer.syncOffset = function syncOffset(data) { 13931 var
13931scanwindow = Math.min(PACKET_LENGTH * 5, data.length - PACKET_LENGTH * 2) + 1; 13932 var i = 0; 13933 while (i < scanwindow) { 13934 // a TS init segment should contain at least 2 TS packets: PAT and PMT, each starting with 0x47 13935 if (data[i] === 0x47 && data[i + PACKET_LENGTH] === 0x47) { 13936 return i; 13937 } 13938 i++; 13939 } 13940 return -1; 13941 } 13942 13943 /** 13944 * Creates a track model internal to demuxer used to drive remuxing input 13945 * 13946 * @param type 'audio' | 'video' | 'id3' | 'text' 13947 * @param duration 13948 * @return TSDemuxer's internal track model 13949 */; 13950 TSDemuxer.createTrack = function createTrack(type, duration) { 13951 return { 13952 container: type === 'video' || type === 'audio' ? 'video/mp2t' : undefined, 13953 type: type, 13954 id: _utils_mp4_tools__WEBPACK_IMPORTED_MODULE_5__.RemuxerTrackIdConfig[type], 13955 pid: -1, 13956 inputTimeScale: 90000, 13957 sequenceNumber: 0, 13958 samples: [], 13959 dropped: 0, 13960 duration: type === 'audio' ? duration : undefined 13961 }; 13962 } 13963 13964 /** 13965 * Initializes a new init segment on the demuxer/remuxer interface. Needed for discontinuities/track-switches (or at stream start) 13966 * Resets all internal track instances of the demuxer. 13967 */; 13968 var _proto = TSDemuxer.prototype; 13969 _proto.resetInitSegment = function resetInitSegment(initSegment, audioCodec, videoCodec, trackDuration) { 13970 this.pmtParsed = false;
vendor: 5,329 bytes, lines 13971-14133
13971 this._pmtId = -1; 13972 this._avcTrack = TSDemuxer.createTrack('video'); 13973 this._audioTrack = TSDemuxer.createTrack('audio', trackDuration); 13974 this._id3Track = TSDemuxer.createTrack('id3'); 13975 this._txtTrack = TSDemuxer.createTrack('text'); 13976 this._audioTrack.segmentCodec = 'aac'; 13977 13978 // flush any partial content 13979 this.aacOverFlow = null; 13980 this.avcSample = null; 13981 this.remainderData = null; 13982 this.audioCodec = audioCodec; 13983 this.videoCodec = videoCodec; 13984 this._duration = trackDuration; 13985 }; 13986 _proto.resetTimeStamp = function resetTimeStamp() {}; 13987 _proto.resetContiguity = function resetContiguity() { 13988 var _audioTrack = this._audioTrack, 13989 _avcTrack = this._avcTrack, 13990 _id3Track = this._id3Track; 13991 if (_audioTrack) { 13992 _audioTrack.pesData = null; 13993 } 13994 if (_avcTrack) { 13995 _avcTrack.pesData = null; 13996 } 13997 if (_id3Track) { 13998 _id3Track.pesData = null; 13999 } 14000 this.aacOverFlow = null; 14001 this.avcSample = null; 14002 this.remainderData = null; 14003 }; 14004 _proto.demux = function demux(data, timeOffset, isSampleAes, flush) { 14005 if (isSampleAes === void 0) { 14006 isSampleAes = false; 14007 } 14008 if (flush === void 0) { 14009 flush = false; 14010 } 14011 if (!isSampleAes) { 14012 this.sampleAes = null; 14013 } 14014 var pes; 14015 var videoTrack = this._avcTrack; 14016 var audioTrack = this._audioTrack; 14017 var id3Track = this._id3Track; 14018 var textTrack = this._txtTrack; 14019 var avcId = videoTrack.pid; 14020 var avcData = videoTrack.pesData; 14021 var audioId = audioTrack.pid; 14022 var id3Id = id3Track.pid; 14023 var audioData = audioTrack.pesData; 14024 var id3Data = id3Track.pesData; 14025 var unknownPID = null; 14026 var pmtParsed = this.pmtParsed; 14027 var pmtId = this._pmtId; 14028 var len = data.length; 14029 if (this.remainderData) { 14030 data = (0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_5__.appendUint8Array)(this.remainderData, data); 14031 len = data.length; 14032 this.remainderData = null; 14033 } 14034 if (len < PACKET_LENGTH && !flush) { 14035 this.remainderData = data; 14036 return { 14037 audioTrack: audioTrack, 14038 videoTrack: videoTrack, 14039 id3Track: id3Track, 14040 textTrack: textTrack 14041 }; 14042 } 14043 var syncOffset = Math.max(0, TSDemuxer.syncOffset(data)); 14044 len -= (len - syncOffset) % PACKET_LENGTH; 14045 if (len < data.byteLength && !flush) { 14046 this.remainderData = new Uint8Array(data.buffer, len, data.buffer.byteLength - len); 14047 } 14048 14049 // loop through TS packets 14050 var tsPacketErrors = 0; 14051 for (var start = syncOffset; start < len; start += PACKET_LENGTH) { 14052 if (data[start] === 0x47) { 14053 var stt = !!(data[start + 1] & 0x40); 14054 // pid is a 13-bit field starting at the last bit of TS[1] 14055 var pid = ((data[start + 1] & 0x1f) << 8) + data[start + 2]; 14056 var atf = (data[start + 3] & 0x30) >> 4; 14057 14058 // if an adaption field is present, its length is specified by the fifth byte of the TS packet header. 14059 var offset = void 0; 14060 if (atf > 1) { 14061 offset = start + 5 + data[start + 4]; 14062 // continue if there is only adaptation field 14063 if (offset === start + PACKET_LENGTH) { 14064 continue; 14065 } 14066 } else { 14067 offset = start + 4; 14068 } 14069 switch (pid) { 14070 case avcId: 14071 if (stt) { 14072 if (avcData && (pes = parsePES(avcData))) { 14073 this.parseAVCPES(videoTrack, textTrack, pes, false); 14074 } 14075 avcData = { 14076 data: [], 14077 size: 0 14078 }; 14079 } 14080 if (avcData) { 14081 avcData.data.push(data.subarray(offset, start + PACKET_LENGTH)); 14082 avcData.size += start + PACKET_LENGTH - offset; 14083 } 14084 break; 14085 case audioId: 14086 if (stt) { 14087 if (audioData && (pes = parsePES(audioData))) { 14088 switch (audioTrack.segmentCodec) { 14089 case 'aac': 14090 this.parseAACPES(audioTrack, pes); 14091 break; 14092 case 'mp3': 14093 this.parseMPEGPES(audioTrack, pes); 14094 break; 14095 } 14096 } 14097 audioData = { 14098 data: [], 14099 size: 0 14100 }; 14101 } 14102 if (audioData) { 14103 audioData.data.push(data.subarray(offset, start + PACKET_LENGTH)); 14104 audioData.size += start + PACKET_LENGTH - offset; 14105 } 14106 break; 14107 case id3Id: 14108 if (stt) { 14109 if (id3Data && (pes = parsePES(id3Data))) { 14110 this.parseID3PES(id3Track, pes); 14111 } 14112 id3Data = { 14113 data: [], 14114 size: 0 14115 }; 14116 } 14117 if (id3Data) { 14118 id3Data.data.push(data.subarray(offset, start + PACKET_LENGTH)); 14119 id3Data.size += start + PACKET_LENGTH - offset; 14120 } 14121 break; 14122 case 0: 14123 if (stt) { 14124 offset += data[offset] + 1; 14125 } 14126 pmtId = this._pmtId = parsePAT(data, offset); 14127 break; 14128 case pmtId: 14129 { 14130 if (stt) { 14131 offset += data[offset] + 1; 14132 } 14133 var parsedPIDs = parsePMT(data, offset, this.typeSupp
14133orted, isSampleAes); 14134 14135 // only update track id if track PID found while parsing PMT 14136 // this is to avoid resetting the PID to -1 in case 14137 // track PID transiently disappears from the stream 14138 // this could happen in case of transient missing audio samples for example 14139 // NOTE this is only the PID of the track as found in TS, 14140 // but we are not using this for MP4 track IDs. 14141 avcId = parsedPIDs.avc; 14142 if (avcId > 0) { 14143 videoTrack.pid = avcId; 14144 } 14145 audioId = parsedPIDs.audio; 14146 if (audioId > 0) { 14147 audioTrack.pid = audioId; 14148 audioTrack.segmentCodec = parsedPIDs.segmentCodec; 14149 } 14150 id3Id = parsedPIDs.id3; 14151 if (id3Id > 0) { 14152 id3Track.pid = id3Id; 14153 } 14154 if (unknownPID !== null && !pmtParsed) { 14155 _utils_logger__WEBPACK_IMPORTED_MODULE_6__.logger.log("unknown PID '" + unknownPID + "' in TS found"); 14156 unknownPID = null; 14157 // we set it to -188, the += 188 in the for loop will reset start to 0 14158 start = syncOffset - 188; 14159 } 14160 pmtParsed = this.pmtParsed = true; 14161 break; 14162 } 14163 case 17
vendor: 18,610 bytes, lines 14163-14685
14163: 14164 case 0x1fff: 14165 break; 14166 default: 14167 unknownPID = pid; 14168 break; 14169 } 14170 } else { 14171 tsPacketErrors++; 14172 } 14173 } 14174 if (tsPacketErrors > 0) { 14175 this.observer.emit(_events__WEBPACK_IMPORTED_MODULE_4__.Events.ERROR, _events__WEBPACK_IMPORTED_MODULE_4__.Events.ERROR, { 14176 type: _errors__WEBPACK_IMPORTED_MODULE_7__.ErrorTypes.MEDIA_ERROR, 14177 details: _errors__WEBPACK_IMPORTED_MODULE_7__.ErrorDetails.FRAG_PARSING_ERROR, 14178 fatal: false, 14179 reason: "Found " + tsPacketErrors + " TS packet/s that do not start with 0x47" 14180 }); 14181 } 14182 videoTrack.pesData = avcData; 14183 audioTrack.pesData = audioData; 14184 id3Track.pesData = id3Data; 14185 var demuxResult = { 14186 audioTrack: audioTrack, 14187 videoTrack: videoTrack, 14188 id3Track: id3Track, 14189 textTrack: textTrack 14190 }; 14191 if (flush) { 14192 this.extractRemainingSamples(demuxResult); 14193 } 14194 return demuxResult; 14195 }; 14196 _proto.flush = function flush() { 14197 var remainderData = this.remainderData; 14198 this.remainderData = null; 14199 var result; 14200 if (remainderData) { 14201 result = this.demux(remainderData, -1, false, true); 14202 } else { 14203 result = { 14204 videoTrack: this._avcTrack, 14205 audioTrack: this._audioTrack, 14206 id3Track: this._id3Track, 14207 textTrack: this._txtTrack 14208 }; 14209 } 14210 this.extractRemainingSamples(result); 14211 if (this.sampleAes) { 14212 return this.decrypt(result, this.sampleAes); 14213 } 14214 return result; 14215 }; 14216 _proto.extractRemainingSamples = function extractRemainingSamples(demuxResult) { 14217 var audioTrack = demuxResult.audioTrack, 14218 videoTrack = demuxResult.videoTrack, 14219 id3Track = demuxResult.id3Track, 14220 textTrack = demuxResult.textTrack; 14221 var avcData = videoTrack.pesData; 14222 var audioData = audioTrack.pesData; 14223 var id3Data = id3Track.pesData; 14224 // try to parse last PES packets 14225 var pes; 14226 if (avcData && (pes = parsePES(avcData))) { 14227 this.parseAVCPES(videoTrack, textTrack, pes, true); 14228 videoTrack.pesData = null; 14229 } else { 14230 // either avcData null or PES truncated, keep it for next frag parsing 14231 videoTrack.pesData = avcData; 14232 } 14233 if (audioData && (pes = parsePES(audioData))) { 14234 switch (audioTrack.segmentCodec) { 14235 case 'aac': 14236 this.parseAACPES(audioTrack, pes); 14237 break; 14238 case 'mp3': 14239 this.parseMPEGPES(audioTrack, pes); 14240 break; 14241 } 14242 audioTrack.pesData = null; 14243 } else { 14244 if (audioData !== null && audioData !== void 0 && audioData.size) { 14245 _utils_logger__WEBPACK_IMPORTED_MODULE_6__.logger.log('last AAC PES packet truncated,might overlap between fragments'); 14246 } 14247 14248 // either audioData null or PES truncated, keep it for next frag parsing 14249 audioTrack.pesData = audioData; 14250 } 14251 if (id3Data && (pes = parsePES(id3Data))) { 14252 this.parseID3PES(id3Track, pes); 14253 id3Track.pesData = null; 14254 } else { 14255 // either id3Data null or PES truncated, keep it for next frag parsing 14256 id3Track.pesData = id3Data; 14257 } 14258 }; 14259 _proto.demuxSampleAes = function demuxSampleAes(data, keyData, timeOffset) { 14260 var demuxResult = this.demux(data, timeOffset, true, !this.config.progressive); 14261 var sampleAes = this.sampleAes = new _sample_aes__WEBPACK_IMPORTED_MODULE_3__["default"](this.observer, this.config, keyData); 14262 return this.decrypt(demuxResult, sampleAes); 14263 }; 14264 _proto.decrypt = function decrypt(demuxResult, sampleAes) { 14265 return new Promise(function (resolve) { 14266 var audioTrack = demuxResult.audioTrack, 14267 videoTrack = demuxResult.videoTrack; 14268 if (audioTrack.samples && audioTrack.segmentCodec === 'aac') { 14269 sampleAes.decryptAacSamples(audioTrack.samples, 0, function () { 14270 if (videoTrack.samples) { 14271 sampleAes.decryptAvcSamples(videoTrack.samples, 0, 0, function () { 14272 resolve(demuxResult); 14273 }); 14274 } else { 14275 resolve(demuxResult); 14276 } 14277 }); 14278 } else if (videoTrack.samples) { 14279 sampleAes.decryptAvcSamples(videoTrack.samples, 0, 0, function () { 14280 resolve(demuxResult); 14281 }); 14282 } 14283 }); 14284 }; 14285 _proto.destroy = function destroy() { 14286 this._duration = 0; 14287 }; 14288 _proto.parseAVCPES = function parseAVCPES(track, textTrack, pes, last) { 14289 var _this = this; 14290 var units = this.parseAVCNALu(track, pes.data); 14291 var debug = false; 14292 var avcSample = this.avcSample; 14293 var push; 14294 var spsfound = false; 14295 // free pes.data to save up some memory 14296 pes.data = null; 14297 14298 // if new NAL units found and last sample still there, let's push ... 14299 // this helps parsing streams with missing AUD (only do this if AUD never found) 14300 if (avcSample && units.length && !track.audFound) { 14301 pushAccessUnit(avcSample, track); 14302 avcSample = this.avcSample = createAVCSample(false, pes.pts, pes.dts, ''); 14303 } 14304 units.forEach(function (unit) { 14305 switch (unit.type) { 14306 // NDR 14307 case 1: 14308 { 14309 push = true; 14310 if (!avcSample) { 14311 avcSample = _this.avcSample = createAVCSample(true, pes.pts, pes.dts, ''); 14312 } 14313 if (debug) { 14314 avcSample.debug += 'NDR '; 14315 } 14316 avcSample.frame = true; 14317 var data = unit.data; 14318 // only check slice type to detect KF in case SPS found in same packet (any keyframe is preceded by SPS ...) 14319 if (spsfound && data.length > 4) { 14320 // retrieve slice type by parsing beginning of NAL unit (follow H264 spec, slice_header definition) to detect keyframe embedded in NDR 14321 var sliceType = new _exp_golomb__WEBPACK_IMPORTED_MODULE_2__["default"](data).readSliceType(); 14322 // 2 : I slice, 4 : SI slice, 7 : I slice, 9: SI slice 14323 // SI slice : A slice that is coded using intra prediction only and using quantisation of the prediction samples. 14324 // An SI slice can be coded such that its decoded samples can be constructed identically to an SP slice. 14325 // I slice: A slice that is not an SI slice that is decoded using intra prediction only. 14326 // if (sliceType === 2 || sliceType === 7) { 14327 if (sliceType === 2 || sliceType === 4 || sliceType === 7 || sliceType === 9) { 14328 avcSample.key = true; 14329 } 14330 } 14331 break; 14332 // IDR 14333 } 14334 14335 case 5: 14336 push = true; 14337 // handle PES not starting with AUD 14338 if (!avcSample) { 14339 avcSample = _this.avcSample = createAVCSample(true, pes.pts, pes.dts, ''); 14340 } 14341 if (debug) { 14342 avcSample.debug += 'IDR '; 14343 } 14344 avcSample.key = true; 14345 avcSample.frame = true; 14346 break; 14347 // SEI 14348 case 6: 14349 { 14350 push = true; 14351 if (debug && avcSample) { 14352 avcSample.debug += 'SEI '; 14353 } 14354 (0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_5__.parseSEIMessageFromNALu)(unit.data, 1, pes.pts, textTrack.samples); 14355 break; 14356 // SPS 14357 } 14358 14359 case 7: 14360 push = true; 14361 spsfound = true; 14362 if (debug && avcSample) { 14363 avcSample.debug += 'SPS '; 14364 } 14365 if (!track.sps) { 14366 var expGolombDecoder = new _exp_golomb__WEBPACK_IMPORTED_MODULE_2__["default"](unit.data); 14367 var config = expGolombDecoder.readSPS(); 14368 track.width = config.width; 14369 track.height = config.height; 14370 track.pixelRatio = config.pixelRatio; 14371 // TODO: `track.sps` is defined as a `number[]`, but we're setting it to a `Uint8Array[]`. 14372 track.sps = [unit.data]; 14373 track.duration = _this._duration; 14374 var codecarray = unit.data.subarray(1, 4); 14375 var codecstring = 'avc1.'; 14376 for (var i = 0; i < 3; i++) { 14377 var h = codecarray[i].toString(16); 14378 if (h.length < 2) { 14379 h = '0' + h; 14380 } 14381 codecstring += h; 14382 } 14383 track.codec = codecstring; 14384 } 14385 break; 14386 // PPS 14387 case 8: 14388 push = true; 14389 if (debug && avcSample) { 14390 avcSample.debug += 'PPS '; 14391 } 14392 if (!track.pps) { 14393 // TODO: `track.pss` is defined as a `number[]`, but we're setting it to a `Uint8Array[]`. 14394 track.pps = [unit.data]; 14395 } 14396 break; 14397 // AUD 14398 case 9: 14399 push = false; 14400 track.audFound = true; 14401 if (avcSample) { 14402 pushAccessUnit(avcSample, track); 14403 } 14404 avcSample = _this.avcSample = createAVCSample(false, pes.pts, pes.dts, debug ? 'AUD ' : ''); 14405 break; 14406 // Filler Data 14407 case 12: 14408 push = true; 14409 break; 14410 default: 14411 push = false; 14412 if (avcSample) { 14413 avcSample.debug += 'unknown NAL ' + unit.type + ' '; 14414 } 14415 break; 14416 } 14417 if (avcSample && push) { 14418 var _units = avcSample.units; 14419 _units.push(unit); 14420 } 14421 }); 14422 // if last PES packet, push samples 14423 if (last && avcSample) { 14424 pushAccessUnit(avcSample, track); 14425 this.avcSample = null; 14426 } 14427 }; 14428 _proto.getLastNalUnit = function getLastNalUnit(samples) { 14429 var _avcSample; 14430 var avcSample = this.avcSample; 14431 var lastUnit; 14432 // try to fallback to previous sample if current one is empty 14433 if (!avcSample || avcSample.units.length === 0) { 14434 avcSample = samples[samples.length - 1]; 14435 } 14436 if ((_avcSample = avcSample) !== null && _avcSample !== void 0 && _avcSample.units) { 14437 var units = avcSample.units; 14438 lastUnit = units[units.length - 1]; 14439 } 14440 return lastUnit; 14441 }; 14442 _proto.parseAVCNALu = function parseAVCNALu(track, array) { 14443 var len = array.byteLength; 14444 var state = track.naluState || 0; 14445 var lastState = state; 14446 var units = []; 14447 var i = 0; 14448 var value; 14449 var overflow; 14450 var unitType; 14451 var lastUnitStart = -1; 14452 var lastUnitType = 0; 14453 // logger.log('PES:' + Hex.hexDump(array)); 14454 14455 if (state === -1) { 14456 // special use case where we found 3 or 4-byte start codes exactly at the end of previous PES packet 14457 lastUnitStart = 0; 14458 // NALu type is value read from offset 0 14459 lastUnitType = array[0] & 0x1f; 14460 state = 0; 14461 i = 1; 14462 } 14463 while (i < len) { 14464 value = array[i++]; 14465 // optimization. state 0 and 1 are the predominant case. let's handle them outside of the switch/case 14466 if (!state) { 14467 state = value ? 0 : 1; 14468 continue; 14469 } 14470 if (state === 1) { 14471 state = value ? 0 : 2; 14472 continue; 14473 } 14474 // here we have state either equal to 2 or 3 14475 if (!value) { 14476 state = 3; 14477 } else if (value === 1) { 14478 if (lastUnitStart >= 0) { 14479 var unit = { 14480 data: array.subarray(lastUnitStart, i - state - 1), 14481 type: lastUnitType 14482 }; 14483 // logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength); 14484 units.push(unit); 14485 } else { 14486 // lastUnitStart is undefined => this is the first start code found in this PES packet 14487 // first check if start code delimiter is overlapping between 2 PES packets, 14488 // ie it started in last packet (lastState not zero) 14489 // and ended at the beginning of this PES packet (i <= 4 - lastState) 14490 var lastUnit = this.getLastNalUnit(track.samples); 14491 if (lastUnit) { 14492 if (lastState && i <= 4 - lastState) { 14493 // start delimiter overlapping between PES packets 14494 // strip start delimiter bytes from the end of last NAL unit 14495 // check if lastUnit had a state different from zero 14496 if (lastUnit.state) { 14497 // strip last bytes 14498 lastUnit.data = lastUnit.data.subarray(0, lastUnit.data.byteLength - lastState); 14499 } 14500 } 14501 // If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit. 14502 overflow = i - state - 1; 14503 if (overflow > 0) { 14504 // logger.log('first NALU found with overflow:' + overflow); 14505 var tmp = new Uint8Array(lastUnit.data.byteLength + overflow); 14506 tmp.set(lastUnit.data, 0); 14507 tmp.set(array.subarray(0, overflow), lastUnit.data.byteLength); 14508 lastUnit.data = tmp; 14509 lastUnit.state = 0; 14510 } 14511 } 14512 } 14513 // check if we can read unit type 14514 if (i < len) { 14515 unitType = array[i] & 0x1f; 14516 // logger.log('find NALU @ offset:' + i + ',type:' + unitType); 14517 lastUnitStart = i; 14518 lastUnitType = unitType; 14519 state = 0; 14520 } else { 14521 // not enough byte to read unit type. let's read it on next PES parsing 14522 state = -1; 14523 } 14524 } else { 14525 state = 0; 14526 } 14527 } 14528 if (lastUnitStart >= 0 && state >= 0) { 14529 var _unit = { 14530 data: array.subarray(lastUnitStart, len), 14531 type: lastUnitType, 14532 state: state 14533 }; 14534 units.push(_unit); 14535 // logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state); 14536 } 14537 // no NALu found 14538 if (units.length === 0) { 14539 // append pes.data to previous NAL unit 14540 var _lastUnit = this.getLastNalUnit(track.samples); 14541 if (_lastUnit) { 14542 var _tmp = new Uint8Array(_lastUnit.data.byteLength + array.byteLength); 14543 _tmp.set(_lastUnit.data, 0); 14544 _tmp.set(array, _lastUnit.data.byteLength); 14545 _lastUnit.data = _tmp; 14546 } 14547 } 14548 track.naluState = state; 14549 return units; 14550 }; 14551 _proto.parseAACPES = function parseAACPES(track, pes) { 14552 var startOffset = 0; 14553 var aacOverFlow = this.aacOverFlow; 14554 var data = pes.data; 14555 if (aacOverFlow) { 14556 this.aacOverFlow = null; 14557 var frameMissingBytes = aacOverFlow.missing; 14558 var sampleLength = aacOverFlow.sample.unit.byteLength; 14559 // logger.log(`AAC: append overflowing ${sampleLength} bytes to beginning of new PES`); 14560 if (frameMissingBytes === -1) { 14561 var tmp = new Uint8Array(sampleLength + data.byteLength); 14562 tmp.set(aacOverFlow.sample.unit, 0); 14563 tmp.set(data, sampleLength); 14564 data = tmp; 14565 } else { 14566 var frameOverflowBytes = sampleLength - frameMissingBytes; 14567 aacOverFlow.sample.unit.set(data.subarray(0, frameMissingBytes), frameOverflowBytes); 14568 track.samples.push(aacOverFlow.sample); 14569 startOffset = aacOverFlow.missing; 14570 } 14571 } 14572 // look for ADTS header (0xFFFx) 14573 var offset; 14574 var len; 14575 for (offset = startOffset, len = data.length; offset < len - 1; offset++) { 14576 if (_adts__WEBPACK_IMPORTED_MODULE_0__.isHeader(data, offset)) { 14577 break; 14578 } 14579 } 14580 // if ADTS header does not start straight from the beginning of the PES payload, raise an error 14581 if (offset !== startOffset) { 14582 var reason; 14583 var fatal; 14584 if (offset < len - 1) { 14585 reason = "AAC PES did not start with ADTS header,offset:" + offset; 14586 fatal = false; 14587 } else { 14588 reason = 'no ADTS header found in AAC PES'; 14589 fatal = true; 14590 } 14591 _utils_logger__WEBPACK_IMPORTED_MODULE_6__.logger.warn("parsing error:" + reason); 14592 this.observer.emit(_events__WEBPACK_IMPORTED_MODULE_4__.Events.ERROR, _events__WEBPACK_IMPORTED_MODULE_4__.Events.ERROR, { 14593 type: _errors__WEBPACK_IMPORTED_MODULE_7__.ErrorTypes.MEDIA_ERROR, 14594 details: _errors__WEBPACK_IMPORTED_MODULE_7__.ErrorDetails.FRAG_PARSING_ERROR, 14595 fatal: fatal, 14596 reason: reason 14597 }); 14598 if (fatal) { 14599 return; 14600 } 14601 } 14602 _adts__WEBPACK_IMPORTED_MODULE_0__.initTrackConfig(track, this.observer, data, offset, this.audioCodec); 14603 var pts; 14604 if (pes.pts !== undefined) { 14605 pts = pes.pts; 14606 } else if (aacOverFlow) { 14607 // if last AAC frame is overflowing, we should ensure timestamps are contiguous: 14608 // first sample PTS should be equal to last sample PTS + frameDuration 14609 var frameDuration = _adts__WEBPACK_IMPORTED_MODULE_0__.getFrameDuration(track.samplerate); 14610 pts = aacOverFlow.sample.pts + frameDuration; 14611 } else { 14612 _utils_logger__WEBPACK_IMPORTED_MODULE_6__.logger.warn('[tsdemuxer]: AAC PES unknown PTS'); 14613 return; 14614 } 14615 14616 // scan for aac samples 14617 var frameIndex = 0; 14618 var frame; 14619 while (offset < len) { 14620 frame = _adts__WEBPACK_IMPORTED_MODULE_0__.appendFrame(track, data, offset, pts, frameIndex); 14621 offset += frame.length; 14622 if (!frame.missing) { 14623 frameIndex++; 14624 for (; offset < len - 1; offset++) { 14625 if (_adts__WEBPACK_IMPORTED_MODULE_0__.isHeader(data, offset)) { 14626 break; 14627 } 14628 } 14629 } else { 14630 this.aacOverFlow = frame; 14631 break; 14632 } 14633 } 14634 }; 14635 _proto.parseMPEGPES = function parseMPEGPES(track, pes) { 14636 var data = pes.data; 14637 var length = data.length; 14638 var frameIndex = 0; 14639 var offset = 0; 14640 var pts = pes.pts; 14641 if (pts === undefined) { 14642 _utils_logger__WEBPACK_IMPORTED_MODULE_6__.logger.warn('[tsdemuxer]: MPEG PES unknown PTS'); 14643 return; 14644 } 14645 while (offset < length) { 14646 if (_mpegaudio__WEBPACK_IMPORTED_MODULE_1__.isHeader(data, offset)) { 14647 var frame = _mpegaudio__WEBPACK_IMPORTED_MODULE_1__.appendFrame(track, data, offset, pts, frameIndex); 14648 if (frame) { 14649 offset += frame.length; 14650 frameIndex++; 14651 } else { 14652 // logger.log('Unable to parse Mpeg audio frame'); 14653 break; 14654 } 14655 } else { 14656 // nothing found, keep looking 14657 offset++; 14658 } 14659 } 14660 }; 14661 _proto.parseID3PES = function parseID3PES(id3Track, pes) { 14662 if (pes.pts === undefined) { 14663 _utils_logger__WEBPACK_IMPORTED_MODULE_6__.logger.warn('[tsdemuxer]: ID3 PES unknown PTS'); 14664 return; 14665 } 14666 var id3Sample = _extends({}, pes, { 14667 type: this._avcTrack ? _types_demuxer__WEBPACK_IMPORTED_MODULE_8__.MetadataSchema.emsg : _types_demuxer__WEBPACK_IMPORTED_MODULE_8__.MetadataSchema.audioId3, 14668 duration: Number.POSITIVE_INFINITY 14669 }); 14670 id3Track.samples.push(id3Sample); 14671 }; 14672 return TSDemuxer; 14673}(); 14674function createAVCSample(key, pts, dts, debug) { 14675 return { 14676 key: key, 14677 frame: false, 14678 pts: pts, 14679 dts: dts, 14680 units: [], 14681 debug: debug, 14682 length: 0 14683 }; 14684} 14685function parseP
14685AT(data, offset) { 14686 // skip the PSI header and parse the first PMT entry 14687 return (data[offset + 10] & 0x1f) << 8 | data[offset + 11]; 14688 // logger.log('PMT PID:' + this._pmtId); 14689} 14690 14691function parsePMT(data, offset, typeSupported, isSampleAes) { 14692 var result = { 14693 audio: -1, 14694 avc: -1, 14695 id3: -1, 14696 segmentCodec: 'aac' 14697 }; 14698 var sectionLength = (data[offset + 1] & 0x0f) << 8 | data[offset + 2]; 14699 var tableEnd = offset + 3 + sectionLength - 4; 14700 // to determine where the table is, we have to figure out how 14701 // long the program info descriptors are 14702 var programInfoLength = (data[offset + 10] & 0x0f) << 8 | data[offset + 11]; 14703 // advance the offset to the first entry in the mapping table 14704 offset += 12 + programInfoLength; 14705 while (offset < tableEnd) { 14706 var pid = (data[offset + 1] & 0x1f) << 8 | data[offset + 2]
vendor: 51,946 bytes, lines 14706-16121
14706; 14707 switch (data[offset]) { 14708 case 0xcf: 14709 // SAMPLE-AES AAC 14710 if (!isSampleAes) { 14711 _utils_logger__WEBPACK_IMPORTED_MODULE_6__.logger.log('ADTS AAC with AES-128-CBC frame encryption found in unencrypted stream'); 14712 break; 14713 } 14714 /* falls through */ 14715 case 0x0f: 14716 // ISO/IEC 13818-7 ADTS AAC (MPEG-2 lower bit-rate audio) 14717 // logger.log('AAC PID:' + pid); 14718 if (result.audio === -1) { 14719 result.audio = pid; 14720 } 14721 break; 14722 14723 // Packetized metadata (ID3) 14724 case 0x15: 14725 // logger.log('ID3 PID:' + pid); 14726 if (result.id3 === -1) { 14727 result.id3 = pid; 14728 } 14729 break; 14730 case 0xdb: 14731 // SAMPLE-AES AVC 14732 if (!isSampleAes) { 14733 _utils_logger__WEBPACK_IMPORTED_MODULE_6__.logger.log('H.264 with AES-128-CBC slice encryption found in unencrypted stream'); 14734 break; 14735 } 14736 /* falls through */ 14737 case 0x1b: 14738 // ITU-T Rec. H.264 and ISO/IEC 14496-10 (lower bit-rate video) 14739 // logger.log('AVC PID:' + pid); 14740 if (result.avc === -1) { 14741 result.avc = pid; 14742 } 14743 break; 14744 14745 // ISO/IEC 11172-3 (MPEG-1 audio) 14746 // or ISO/IEC 13818-3 (MPEG-2 halved sample rate audio) 14747 case 0x03: 14748 case 0x04: 14749 // logger.log('MPEG PID:' + pid); 14750 if (typeSupported.mpeg !== true && typeSupported.mp3 !== true) { 14751 _utils_logger__WEBPACK_IMPORTED_MODULE_6__.logger.log('MPEG audio found, not supported in this browser'); 14752 } else if (result.audio === -1) { 14753 result.audio = pid; 14754 result.segmentCodec = 'mp3'; 14755 } 14756 break; 14757 case 0x24: 14758 _utils_logger__WEBPACK_IMPORTED_MODULE_6__.logger.warn('Unsupported HEVC stream type found'); 14759 break; 14760 default: 14761 // logger.log('unknown stream type:' + data[offset]); 14762 break; 14763 } 14764 // move to the next table entry 14765 // skip past the elementary stream descriptors, if present 14766 offset += ((data[offset + 3] & 0x0f) << 8 | data[offset + 4]) + 5; 14767 } 14768 return result; 14769} 14770function parsePES(stream) { 14771 var i = 0; 14772 var frag; 14773 var pesLen; 14774 var pesHdrLen; 14775 var pesPts; 14776 var pesDts; 14777 var data = stream.data; 14778 // safety check 14779 if (!stream || stream.size === 0) { 14780 return null; 14781 } 14782 14783 // we might need up to 19 bytes to read PES header 14784 // if first chunk of data is less than 19 bytes, let's merge it with following ones until we get 19 bytes 14785 // usually only one merge is needed (and this is rare ...) 14786 while (data[0].length < 19 && data.length > 1) { 14787 var newData = new Uint8Array(data[0].length + data[1].length); 14788 newData.set(data[0]); 14789 newData.set(data[1], data[0].length); 14790 data[0] = newData; 14791 data.splice(1, 1); 14792 } 14793 // retrieve PTS/DTS from first fragment 14794 frag = data[0]; 14795 var pesPrefix = (frag[0] << 16) + (frag[1] << 8) + frag[2]; 14796 if (pesPrefix === 1) { 14797 pesLen = (frag[4] << 8) + frag[5]; 14798 // if PES parsed length is not zero and greater than total received length, stop parsing. PES might be truncated 14799 // minus 6 : PES header size 14800 if (pesLen && pesLen > stream.size - 6) { 14801 return null; 14802 } 14803 var pesFlags = frag[7]; 14804 if (pesFlags & 0xc0) { 14805 /* PES header described here : http://dvd.sourceforge.net/dvdinfo/pes-hdr.html 14806 as PTS / DTS is 33 bit we cannot use bitwise operator in JS, 14807 as Bitwise operators treat their operands as a sequence of 32 bits */ 14808 pesPts = (frag[9] & 0x0e) * 536870912 + 14809 // 1 << 29 14810 (frag[10] & 0xff) * 4194304 + 14811 // 1 << 22 14812 (frag[11] & 0xfe) * 16384 + 14813 // 1 << 14 14814 (frag[12] & 0xff) * 128 + 14815 // 1 << 7 14816 (frag[13] & 0xfe) / 2; 14817 if (pesFlags & 0x40) { 14818 pesDts = (frag[14] & 0x0e) * 536870912 + 14819 // 1 << 29 14820 (frag[15] & 0xff) * 4194304 + 14821 // 1 << 22 14822 (frag[16] & 0xfe) * 16384 + 14823 // 1 << 14 14824 (frag[17] & 0xff) * 128 + 14825 // 1 << 7 14826 (frag[18] & 0xfe) / 2; 14827 if (pesPts - pesDts > 60 * 90000) { 14828 _utils_logger__WEBPACK_IMPORTED_MODULE_6__.logger.warn(Math.round((pesPts - pesDts) / 90000) + "s delta between PTS and DTS, align them"); 14829 pesPts = pesDts; 14830 } 14831 } else { 14832 pesDts = pesPts; 14833 } 14834 } 14835 pesHdrLen = frag[8]; 14836 // 9 bytes : 6 bytes for PES header + 3 bytes for PES extension 14837 var payloadStartOffset = pesHdrLen + 9; 14838 if (stream.size <= payloadStartOffset) { 14839 return null; 14840 } 14841 stream.size -= payloadStartOffset; 14842 // reassemble PES packet 14843 var pesData = new Uint8Array(stream.size); 14844 for (var j = 0, dataLen = data.length; j < dataLen; j++) { 14845 frag = data[j]; 14846 var len = frag.byteLength; 14847 if (payloadStartOffset) { 14848 if (payloadStartOffset > len) { 14849 // trim full frag if PES header bigger than frag 14850 payloadStartOffset -= len; 14851 continue; 14852 } else { 14853 // trim partial frag if PES header smaller than frag 14854 frag = frag.subarray(payloadStartOffset); 14855 len -= payloadStartOffset; 14856 payloadStartOffset = 0; 14857 } 14858 } 14859 pesData.set(frag, i); 14860 i += len; 14861 } 14862 if (pesLen) { 14863 // payload size : remove PES header + PES extension 14864 pesLen -= pesHdrLen + 3; 14865 } 14866 return { 14867 data: pesData, 14868 pts: pesPts, 14869 dts: pesDts, 14870 len: pesLen 14871 }; 14872 } 14873 return null; 14874} 14875function pushAccessUnit(avcSample, avcTrack) { 14876 if (avcSample.units.length && avcSample.frame) { 14877 // if sample does not have PTS/DTS, patch with last sample PTS/DTS 14878 if (avcSample.pts === undefined) { 14879 var samples = avcTrack.samples; 14880 var nbSamples = samples.length; 14881 if (nbSamples) { 14882 var lastSample = samples[nbSamples - 1]; 14883 avcSample.pts = lastSample.pts; 14884 avcSample.dts = lastSample.dts; 14885 } else { 14886 // dropping samples, no timestamp found 14887 avcTrack.dropped++; 14888 return; 14889 } 14890 } 14891 avcTrack.samples.push(avcSample); 14892 } 14893 if (avcSample.debug.length) { 14894 _utils_logger__WEBPACK_IMPORTED_MODULE_6__.logger.log(avcSample.pts + '/' + avcSample.dts + ':' + avcSample.debug); 14895 } 14896} 14897/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TSDemuxer); 14898 14899/***/ }), 14900 14901/***/ "./src/demux/webworkify-webpack.js": 14902/*!*****************************************!*\ 14903 !*** ./src/demux/webworkify-webpack.js ***! 14904 \*****************************************/ 14905/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 14906 14907"use strict"; 14908__webpack_require__.r(__webpack_exports__); 14909/* harmony export */ __webpack_require__.d(__webpack_exports__, { 14910/* harmony export */ "default": () => (/* export default binding */ __WEBPACK_DEFAULT_EXPORT__) 14911/* harmony export */ }); 14912/* 14913 * Fork of webworkify-webpack with support for Webpack 5 14914 * https://github.com/wupeng-engineer/webworkify-webpack/blob/db0de7/index.js 14915*/ 14916 14917var webpackBootstrapFunc = function webpackBootstrapFunc() { 14918 // webpackBootstrap 14919 /******/ 14920 var __webpack_modules__ = ENTRY_MODULE; 14921 /************************************************************************/ 14922 /******/ // The module cache 14923 /******/ 14924 var __webpack_module_cache__ = {}; 14925 /******/ 14926 /******/ // The require function 14927 /******/ 14928 var __nested_webpack_require_497__ = function __webpack_require__(moduleId) { 14929 /******/ // Check if module is in cache 14930 /******/var cachedModule = __webpack_module_cache__[moduleId]; 14931 /******/ 14932 if (cachedModule !== undefined) { 14933 /******/return cachedModule.exports; 14934 /******/ 14935 } 14936 /******/ // Create a new module (and put it into the cache) 14937 /******/ 14938 var module = __webpack_module_cache__[moduleId] = { 14939 /******/ // no module.id needed 14940 /******/ // no module.loaded needed 14941 /******/exports: {} 14942 /******/ 14943 }; 14944 /******/ 14945 /******/ // Execute the module function 14946 /******/ 14947 __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__); 14948 /******/ 14949 /******/ // Return the exports of the module 14950 /******/ 14951 return module.exports; 14952 /******/ 14953 }; 14954 /******/ 14955 /******/ // expose the modules object (__webpack_modules__) 14956 /******/ 14957 __nested_webpack_require_497__.m = __webpack_modules__; 14958 /******/ 14959 /************************************************************************/ 14960 /******/ /* webpack/runtime/compat get default export */ 14961 /******/ 14962 (function () { 14963 /******/ // getDefaultExport function for compatibility with non-harmony modules 14964 /******/__nested_webpack_require_497__.n = function (module) { 14965 /******/var getter = module && module.__esModule ? /******/function () { 14966 return module['default']; 14967 } : /******/function () { 14968 return module; 14969 }; 14970 /******/ 14971 __nested_webpack_require_497__.d(getter, { 14972 a: getter 14973 }); 14974 /******/ 14975 return getter; 14976 /******/ 14977 }; 14978 /******/ 14979 })(); 14980 /******/ 14981 /******/ /* webpack/runtime/define property getters */ 14982 /******/ 14983 (function () { 14984 /******/ // define getter functions for harmony exports 14985 /******/__nested_webpack_require_497__.d = function (exports, definition) { 14986 /******/for (var key in definition) { 14987 /******/if (__nested_webpack_require_497__.o(definition, key) && !__nested_webpack_require_497__.o(exports, key)) { 14988 /******/Object.defineProperty(exports, key, { 14989 enumerable: true, 14990 get: definition[key] 14991 }); 14992 /******/ 14993 } 14994 /******/ 14995 } 14996 /******/ 14997 }; 14998 /******/ 14999 })(); 15000 /******/ 15001 /******/ /* webpack/runtime/hasOwnProperty shorthand */ 15002 /******/ 15003 (function () { 15004 /******/__nested_webpack_require_497__.o = function (obj, prop) { 15005 return Object.prototype.hasOwnProperty.call(obj, prop); 15006 }; 15007 /******/ 15008 })(); 15009 /******/ 15010 /******/ /* webpack/runtime/make namespace object */ 15011 /******/ 15012 (function () { 15013 /******/ // define __esModule on exports 15014 /******/__nested_webpack_require_497__.r = function (exports) { 15015 /******/if (typeof Symbol !== 'undefined' && Symbol.toStringTag) { 15016 /******/Object.defineProperty(exports, Symbol.toStringTag, { 15017 value: 'Module' 15018 }); 15019 /******/ 15020 } 15021 /******/ 15022 Object.defineProperty(exports, '__esModule', { 15023 value: true 15024 }); 15025 /******/ 15026 }; 15027 /******/ 15028 })(); 15029 /******/ 15030 /************************************************************************/ 15031 /******/ 15032 /******/ // module factories are used so entry inlining is disabled 15033 /******/ // startup 15034 /******/ // Load entry module and return exports 15035 /******/ 15036 var result = __nested_webpack_require_497__(ENTRY_MODULE); 15037 /******/ 15038 return result.default || result; 15039}; 15040var webpackBootstrapFuncArr = webpackBootstrapFunc.toString().split('ENTRY_MODULE'); 15041var moduleNameReqExp = '[\\.|\\-|\\+|\\w|\/|@]+'; 15042var dependencyRegExp = '\\(\\s*(\/\\*.*?\\*\/)?\\s*.*?(' + moduleNameReqExp + ').*?\\)'; 15043function quoteRegExp(str) { 15044 return (str + '').replace(/[.?*+^$[\]\\(){}|-]/g, '\\$&'); 15045} 15046function isNumeric(n) { 15047 return !isNaN(1 * n); 15048} 15049function getModuleDependencies(sources, module, queueName) { 15050 var retval = {}; 15051 retval[queueName] = []; 15052 var fnString = module.toString().replace(/^"[^"]+"/, 'function'); 15053 ; 15054 var wrapperSignature = fnString.match(/^function\s?\w*\(\w+,\s*\w+,\s*(\w+)\)/) || fnString.match(/^\(\w+,\s*\w+,\s*(\w+)\)\s?\=\s?\>/); 15055 if (!wrapperSignature) return retval; 15056 var webpackRequireName = wrapperSignature[1]; 15057 var re = new RegExp('(\\\\n|\\W)' + quoteRegExp(webpackRequireName) + dependencyRegExp, 'g'); 15058 var match; 15059 while (match = re.exec(fnString)) { 15060 if (match[3] === 'dll-reference') continue; 15061 retval[queueName].push(match[3]); 15062 } 15063 re = new RegExp('\\(' + quoteRegExp(webpackRequireName) + '\\("(dll-reference\\s(' + moduleNameReqExp + '))"\\)\\)' + dependencyRegExp, 'g'); 15064 while (match = re.exec(fnString)) { 15065 if (!sources[match[2]]) { 15066 retval[queueName].push(match[1]); 15067 sources[match[2]] = __webpack_require__(match[1]).m; 15068 } 15069 retval[match[2]] = retval[match[2]] || []; 15070 retval[match[2]].push(match[4]); 15071 } 15072 var keys = Object.keys(retval); 15073 for (var i = 0; i < keys.length; i++) { 15074 for (var j = 0; j < retval[keys[i]].length; j++) { 15075 if (isNumeric(retval[keys[i]][j])) { 15076 retval[keys[i]][j] = 1 * retval[keys[i]][j]; 15077 } 15078 } 15079 } 15080 return retval; 15081} 15082function hasValuesInQueues(queues) { 15083 var keys = Object.keys(queues); 15084 return keys.reduce(function (hasValues, key) { 15085 return hasValues || queues[key].length > 0; 15086 }, false); 15087} 15088function getRequiredModules(sources, moduleId) { 15089 var modulesQueue = { 15090 main: [moduleId] 15091 }; 15092 var requiredModules = { 15093 main: [] 15094 }; 15095 var seenModules = { 15096 main: {} 15097 }; 15098 while (hasValuesInQueues(modulesQueue)) { 15099 var queues = Object.keys(modulesQueue); 15100 for (var i = 0; i < queues.length; i++) { 15101 var queueName = queues[i]; 15102 var queue = modulesQueue[queueName]; 15103 var moduleToCheck = queue.pop(); 15104 seenModules[queueName] = seenModules[queueName] || {}; 15105 if (seenModules[queueName][moduleToCheck] || !sources[queueName][moduleToCheck]) continue; 15106 seenModules[queueName][moduleToCheck] = true; 15107 requiredModules[queueName] = requiredModules[queueName] || []; 15108 requiredModules[queueName].push(moduleToCheck); 15109 var newModules = getModuleDependencies(sources, sources[queueName][moduleToCheck], queueName); 15110 var newModulesKeys = Object.keys(newModules); 15111 for (var j = 0; j < newModulesKeys.length; j++) { 15112 modulesQueue[newModulesKeys[j]] = modulesQueue[newModulesKeys[j]] || []; 15113 modulesQueue[newModulesKeys[j]] = modulesQueue[newModulesKeys[j]].concat(newModules[newModulesKeys[j]]); 15114 } 15115 } 15116 } 15117 return requiredModules; 15118} 15119function getWebpackString(requiredModules, sources, entryModule, key) { 15120 var moduleString = requiredModules[key].map(function (id) { 15121 return "\"" + id + "\": " + sources[key][id].toString().replace(/^"[^"]+"/, 'function'); 15122 }).join(","); 15123 return webpackBootstrapFuncArr[0] + "{" + moduleString + "}" + webpackBootstrapFuncArr[1] + "\"" + entryModule + "\"" + webpackBootstrapFuncArr[2]; 15124} 15125/* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__(moduleId, options) { 15126 options = options || {}; 15127 var sources = { 15128 main: __webpack_require__.m 15129 }; 15130 var requiredModules = options.all ? { 15131 main: Object.keys(sources.main) 15132 } : getRequiredModules(sources, moduleId); 15133 var src = ''; 15134 Object.keys(requiredModules).filter(function (m) { 15135 return m !== 'main'; 15136 }).forEach(function (module) { 15137 var entryModule = 0; 15138 while (requiredModules[module][entryModule]) { 15139 entryModule++; 15140 } 15141 requiredModules[module].push(entryModule); 15142 sources[module][entryModule] = '(function(module, exports, __webpack_require__) { module.exports = __webpack_require__; })'; 15143 src = src + ("var " + module + " = (" + getWebpackString(requiredModules, sources, entryModule, modules) + ")();\n"); 15144 }); 15145 src = src + ("new ((" + getWebpackString(requiredModules, sources, moduleId, 'main') + ")())(self);"); 15146 var blob = new window.Blob([src], { 15147 type: 'text/javascript' 15148 }); 15149 var URL = window.URL || window.webkitURL || window.mozURL || window.msURL; 15150 var workerUrl = URL.createObjectURL(blob); 15151 var worker = new window.Worker(workerUrl); 15152 worker.objectURL = workerUrl; 15153 return worker; 15154} 15155 15156/***/ }), 15157 15158/***/ "./src/errors.ts": 15159/*!***********************!*\ 15160 !*** ./src/errors.ts ***! 15161 \***********************/ 15162/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 15163 15164"use strict"; 15165__webpack_require__.r(__webpack_exports__); 15166/* harmony export */ __webpack_require__.d(__webpack_exports__, { 15167/* harmony export */ "ErrorDetails": () => (/* binding */ ErrorDetails), 15168/* harmony export */ "ErrorTypes": () => (/* binding */ ErrorTypes) 15169/* harmony export */ }); 15170var ErrorTypes; 15171 15172/** 15173 * @enum {ErrorDetails} 15174 * @typedef {string} ErrorDetail 15175 */ 15176(function (ErrorTypes) { 15177 ErrorTypes["NETWORK_ERROR"] = "networkError"; 15178 ErrorTypes["MEDIA_ERROR"] = "mediaError"; 15179 ErrorTypes["KEY_SYSTEM_ERROR"] = "keySystemError"; 15180 ErrorTypes["MUX_ERROR"] = "muxError"; 15181 ErrorTypes["OTHER_ERROR"] = "otherError"; 15182})(ErrorTypes || (ErrorTypes = {})); 15183var ErrorDetails; 15184(function (ErrorDetails) { 15185 ErrorDetails["KEY_SYSTEM_NO_KEYS"] = "keySystemNoKeys"; 15186 ErrorDetails["KEY_SYSTEM_NO_ACCESS"] = "keySystemNoAccess"; 15187 ErrorDetails["KEY_SYSTEM_NO_SESSION"] = "keySystemNoSession"; 15188 ErrorDetails["KEY_SYSTEM_NO_CONFIGURED_LICENSE"] = "keySystemNoConfiguredLicense"; 15189 ErrorDetails["KEY_SYSTEM_LICENSE_REQUEST_FAILED"] = "keySystemLicenseRequestFailed"; 15190 ErrorDetails["KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED"] = "keySystemServerCertificateRequestFailed"; 15191 ErrorDetails["KEY_SYSTEM_SERVER_CERTIFICATE_UPDATE_FAILED"] = "keySystemServerCertificateUpdateFailed"; 15192 ErrorDetails["KEY_SYSTEM_SESSION_UPDATE_FAILED"] = "keySystemSessionUpdateFailed"; 15193 ErrorDetails["KEY_SYSTEM_STATUS_OUTPUT_RESTRICTED"] = "keySystemStatusOutputRestricted"; 15194 ErrorDetails["KEY_SYSTEM_STATUS_INTERNAL_ERROR"] = "keySystemStatusInternalError"; 15195 ErrorDetails["MANIFEST_LOAD_ERROR"] = "manifestLoadError"; 15196 ErrorDetails["MANIFEST_LOAD_TIMEOUT"] = "manifestLoadTimeOut"; 15197 ErrorDetails["MANIFEST_PARSING_ERROR"] = "manifestParsingError"; 15198 ErrorDetails["MANIFEST_INCOMPATIBLE_CODECS_ERROR"] = "manifestIncompatibleCodecsError"; 15199 ErrorDetails["LEVEL_EMPTY_ERROR"] = "levelEmptyError"; 15200 ErrorDetails["LEVEL_LOAD_ERROR"] = "levelLoadError"; 15201 ErrorDetails["LEVEL_LOAD_TIMEOUT"] = "levelLoadTimeOut"; 15202 ErrorDetails["LEVEL_SWITCH_ERROR"] = "levelSwitchError"; 15203 ErrorDetails["AUDIO_TRACK_LOAD_ERROR"] = "audioTrackLoadError"; 15204 ErrorDetails["AUDIO_TRACK_LOAD_TIMEOUT"] = "audioTrackLoadTimeOut"; 15205 ErrorDetails["SUBTITLE_LOAD_ERROR"] = "subtitleTrackLoadError"; 15206 ErrorDetails["SUBTITLE_TRACK_LOAD_TIMEOUT"] = "subtitleTrackLoadTimeOut"; 15207 ErrorDetails["FRAG_LOAD_ERROR"] = "fragLoadError"; 15208 ErrorDetails["FRAG_LOAD_TIMEOUT"] = "fragLoadTimeOut"; 15209 ErrorDetails["FRAG_DECRYPT_ERROR"] = "fragDecryptError"; 15210 ErrorDetails["FRAG_PARSING_ERROR"] = "fragParsingError"; 15211 ErrorDetails["REMUX_ALLOC_ERROR"] = "remuxAllocError"; 15212 ErrorDetails["KEY_LOAD_ERROR"] = "keyLoadError"; 15213 ErrorDetails["KEY_LOAD_TIMEOUT"] = "keyLoadTimeOut"; 15214 ErrorDetails["BUFFER_ADD_CODEC_ERROR"] = "bufferAddCodecError"; 15215 ErrorDetails["BUFFER_INCOMPATIBLE_CODECS_ERROR"] = "bufferIncompatibleCodecsError"; 15216 ErrorDetails["BUFFER_APPEND_ERROR"] = "bufferAppendError"; 15217 ErrorDetails["BUFFER_APPENDING_ERROR"] = "bufferAppendingError"; 15218 ErrorDetails["BUFFER_STALLED_ERROR"] = "bufferStalledError"; 15219 ErrorDetails["BUFFER_FULL_ERROR"] = "bufferFullError"; 15220 ErrorDetails["BUFFER_SEEK_OVER_HOLE"] = "bufferSeekOverHole"; 15221 ErrorDetails["BUFFER_NUDGE_ON_STALL"] = "bufferNudgeOnStall"; 15222 ErrorDetails["INTERNAL_EXCEPTION"] = "internalException"; 15223 ErrorDetails["INTERNAL_ABORTED"] = "aborted"; 15224 ErrorDetails["UNKNOWN"] = "unknown"; 15225})(ErrorDetails || (ErrorDetails = {})); 15226 15227/***/ }), 15228 15229/***/ "./src/events.ts": 15230/*!***********************!*\ 15231 !*** ./src/events.ts ***! 15232 \***********************/ 15233/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 15234 15235"use strict"; 15236__webpack_require__.r(__webpack_exports__); 15237/* harmony export */ __webpack_require__.d(__webpack_exports__, { 15238/* harmony export */ "Events": () => (/* binding */ Events) 15239/* harmony export */ }); 15240/** 15241 * @readonly 15242 * @enum {string} 15243 */ 15244var Events; 15245(function (Events) { 15246 Events["MEDIA_ATTACHING"] = "hlsMediaAttaching"; 15247 Events["MEDIA_ATTACHED"] = "hlsMediaAttached"; 15248 Events["MEDIA_DETACHING"] = "hlsMediaDetaching"; 15249 Events["MEDIA_DETACHED"] = "hlsMediaDetached"; 15250 Events["BUFFER_RESET"] = "hlsBufferReset"; 15251 Events["BUFFER_CODECS"] = "hlsBufferCodecs"; 15252 Events["BUFFER_CREATED"] = "hlsBufferCreated"; 15253 Events["BUFFER_APPENDING"] = "hlsBufferAppending"; 15254 Events["BUFFER_APPENDED"] = "hlsBufferAppended"; 15255 Events["BUFFER_EOS"] = "hlsBufferEos"; 15256 Events["BUFFER_FLUSHING"] = "hlsBufferFlushing"; 15257 Events["BUFFER_FLUSHED"] = "hlsBufferFlushed"; 15258 Events["MANIFEST_LOADING"] = "hlsManifestLoading"; 15259 Events["MANIFEST_LOADED"] = "hlsManifestLoaded"; 15260 Events["MANIFEST_PARSED"] = "hlsManifestParsed"; 15261 Events["LEVEL_SWITCHING"] = "hlsLevelSwitching"; 15262 Events["LEVEL_SWITCHED"] = "hlsLevelSwitched"; 15263 Events["LEVEL_LOADING"] = "hlsLevelLoading"; 15264 Events["LEVEL_LOADED"] = "hlsLevelLoaded"; 15265 Events["LEVEL_UPDATED"] = "hlsLevelUpdated"; 15266 Events["LEVEL_PTS_UPDATED"] = "hlsLevelPtsUpdated"; 15267 Events["LEVELS_UPDATED"] = "hlsLevelsUpdated"; 15268 Events["AUDIO_TRACKS_UPDATED"] = "hlsAudioTracksUpdated"; 15269 Events["AUDIO_TRACK_SWITCHING"] = "hlsAudioTrackSwitching"; 15270 Events["AUDIO_TRACK_SWITCHED"] = "hlsAudioTrackSwitched"; 15271 Events["AUDIO_TRACK_LOADING"] = "hlsAudioTrackLoading"; 15272 Events["AUDIO_TRACK_LOADED"] = "hlsAudioTrackLoaded"; 15273 Events["SUBTITLE_TRACKS_UPDATED"] = "hlsSubtitleTracksUpdated"; 15274 Events["SUBTITLE_TRACKS_CLEARED"] = "hlsSubtitleTracksCleared"; 15275 Events["SUBTITLE_TRACK_SWITCH"] = "hlsSubtitleTrackSwitch"; 15276 Events["SUBTITLE_TRACK_LOADING"] = "hlsSubtitleTrackLoading"; 15277 Events["SUBTITLE_TRACK_LOADED"] = "hlsSubtitleTrackLoaded"; 15278 Events["SUBTITLE_FRAG_PROCESSED"] = "hlsSubtitleFragProcessed"; 15279 Events["CUES_PARSED"] = "hlsCuesParsed"; 15280 Events["NON_NATIVE_TEXT_TRACKS_FOUND"] = "hlsNonNativeTextTracksFound"; 15281 Events["INIT_PTS_FOUND"] = "hlsInitPtsFound"; 15282 Events["FRAG_LOADING"] = "hlsFragLoading"; 15283 Events["FRAG_LOAD_EMERGENCY_ABORTED"] = "hlsFragLoadEmergencyAborted"; 15284 Events["FRAG_LOADED"] = "hlsFragLoaded"; 15285 Events["FRAG_DECRYPTED"] = "hlsFragDecrypted"; 15286 Events["FRAG_PARSING_INIT_SEGMENT"] = "hlsFragParsingInitSegment"; 15287 Events["FRAG_PARSING_USERDATA"] = "hlsFragParsingUserdata"; 15288 Events["FRAG_PARSING_METADATA"] = "hlsFragParsingMetadata"; 15289 Events["FRAG_PARSED"] = "hlsFragParsed"; 15290 Events["FRAG_BUFFERED"] = "hlsFragBuffered"; 15291 Events["FRAG_CHANGED"] = "hlsFragChanged"; 15292 Events["FPS_DROP"] = "hlsFpsDrop"; 15293 Events["FPS_DROP_LEVEL_CAPPING"] = "hlsFpsDropLevelCapping"; 15294 Events["ERROR"] = "hlsError"; 15295 Events["DESTROYING"] = "hlsDestroying"; 15296 Events["KEY_LOADING"] = "hlsKeyLoading"; 15297 Events["KEY_LOADED"] = "hlsKeyLoaded"; 15298 Events["LIVE_BACK_BUFFER_REACHED"] = "hlsLiveBackBufferReached"; 15299 Events["BACK_BUFFER_REACHED"] = "hlsBackBufferReached"; 15300})(Events || (Events = {})); 15301 15302/***/ }), 15303 15304/***/ "./src/hls.ts": 15305/*!********************!*\ 15306 !*** ./src/hls.ts ***! 15307 \********************/ 15308/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 15309 15310"use strict"; 15311__webpack_require__.r(__webpack_exports__); 15312/* harmony export */ __webpack_require__.d(__webpack_exports__, { 15313/* harmony export */ "default": () => (/* binding */ Hls) 15314/* harmony export */ }); 15315/* harmony import */ var url_toolkit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! url-toolkit */ "./node_modules/url-toolkit/src/url-toolkit.js"); 15316/* harmony import */ var url_toolkit__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(url_toolkit__WEBPACK_IMPORTED_MODULE_0__); 15317/* harmony import */ var _loader_playlist_loader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./loader/playlist-loader */ "./src/loader/playlist-loader.ts"); 15318/* harmony import */ var _controller_id3_track_controller__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./controller/id3-track-controller */ "./src/controller/id3-track-controller.ts"); 15319/* harmony import */ var _controller_latency_controller__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./controller/latency-controller */ "./src/controller/latency-controller.ts"); 15320/* harmony import */ var _controller_level_controller__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./controller/level-controller */ "./src/controller/level-controller.ts"); 15321/* harmony import */ var _controller_fragment_tracker__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./controller/fragment-tracker */ "./src/controller/fragment-tracker.ts"); 15322/* harmony import */ var _loader_key_loader__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./loader/key-loader */ "./src/loader/key-loader.ts"); 15323/* harmony import */ var _controller_stream_controller__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./controller/stream-controller */ "./src/controller/stream-controller.ts"); 15324/* harmony import */ var _is_supported__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./is-supported */ "./src/is-supported.ts"); 15325/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./utils/logger */ "./src/utils/logger.ts"); 15326/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./config */ "./src/config.ts"); 15327/* harmony import */ var eventemitter3__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! eventemitter3 */ "./node_modules/eventemitter3/index.js"); 15328/* harmony import */ var eventemitter3__WEBPACK_IMPORTED_MODULE_11___default = /*#__PURE__*/__webpack_require__.n(eventemitter3__WEBPACK_IMPORTED_MODULE_11__); 15329/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./events */ "./src/events.ts"); 15330/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./errors */ "./src/errors.ts"); 15331/* harmony import */ var _types_level__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./types/level */ "./src/types/level.ts"); 15332function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } 15333function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } 15334function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } 15335function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } 15336 15337 15338 15339 15340 15341 15342 15343 15344 15345 15346 15347 15348 15349 15350 15351/** 15352 * @module Hls 15353 * @class 15354 * @constructor 15355 */ 15356var Hls = /*#__PURE__*/function () { 15357 Hls.isSupported = function isSupported() { 15358 return (0,_is_supported__WEBPACK_IMPORTED_MODULE_8__.isSupported)(); 15359 }; 15360 /** 15361 * Creates an instance of an HLS client that can attach to exactly one `HTMLMediaElement`. 15362 * 15363 * @constructs Hls 15364 * @param {HlsConfig} config 15365 */ 15366 function Hls(userConfig) { 15367 if (userConfig === void 0) { 15368 userConfig = {}; 15369 } 15370 this.config = void 0; 15371 this.userConfig = void 0; 15372 this.coreComponents = void 0; 15373 this.networkControllers = void 0; 15374 this._emitter = new eventemitter3__WEBPACK_IMPORTED_MODULE_11__.EventEmitter(); 15375 this._autoLevelCapping = void 0; 15376 this._maxHdcpLevel = null; 15377 this.abrController = void 0; 15378 this.bufferController = void 0; 15379 this.capLevelController = void 0; 15380 this.latencyController = void 0; 15381 this.levelController = void 0; 15382 this.streamController = void 0; 15383 this.audioTrackController = void 0; 15384 this.subtitleTrackController = void 0; 15385 this.emeController = void 0; 15386 this.cmcdController = void 0; 15387 this._media = null; 15388 this.url = null; 15389 var config = this.config = (0,_config__WEBPACK_IMPORTED_MODULE_10__.mergeConfig)(Hls.DefaultConfig, userConfig); 15390 this.userConfig = userConfig; 15391 (0,_utils_logger__WEBPACK_IMPORTED_MODULE_9__.enableLogs)(config.debug, 'Hls instance'); 15392 this._autoLevelCapping = -1; 15393 if (config.progressive) { 15394 (0,_config__WEBPACK_IMPORTED_MODULE_10__.enableStreamingMode)(config); 15395 } 15396 15397 // core controllers and network loaders 15398 var ConfigAbrController = config.abrController, 15399 ConfigBufferController = config.bufferController, 15400 ConfigCapLevelController = config.capLevelController, 15401 ConfigFpsController = config.fpsController; 15402 var abrController = this.abrController = new ConfigAbrController(this); 15403 var bufferController = this.bufferController = new ConfigBufferController(this); 15404 var capLevelController = this.capLevelController = new ConfigCapLevelController(this); 15405 var fpsController = new ConfigFpsController(this); 15406 var playListLoader = new _loader_playlist_loader__WEBPACK_IMPORTED_MODULE_1__["default"](this); 15407 var id3TrackController = new _controller_id3_track_controller__WEBPACK_IMPORTED_MODULE_2__["default"](this); 15408 15409 // network controllers 15410 var levelController = this.levelController = new _controller_level_controller__WEBPACK_IMPORTED_MODULE_4__["default"](this); 15411 // FragmentTracker must be defined before StreamController because the order of event handling is important 15412 var fragmentTracker = new _controller_fragment_tracker__WEBPACK_IMPORTED_MODULE_5__.FragmentTracker(this); 15413 var keyLoader = new _loader_key_loader__WEBPACK_IMPORTED_MODULE_6__["default"](this.config); 15414 var streamController = this.streamController = new _controller_stream_controller__WEBPACK_IMPORTED_MODULE_7__["default"](this, fragmentTracker, keyLoader); 15415 15416 // Cap level controller uses streamController to flush the buffer 15417 capLevelController.setStreamController(streamController); 15418 // fpsController uses streamController to switch when frames are being dropped 15419 fpsController.setStreamController(streamController); 15420 var networkControllers = [playListLoader, levelController, streamController]; 15421 this.networkControllers = networkControllers; 15422 var coreComponents = [abrController, bufferController, capLevelController, fpsController, id3TrackController, fragmentTracker]; 15423 this.audioTrackController = this.createController(config.audioTrackController, networkControllers); 15424 var AudioStreamControllerClass = config.audioStreamController; 15425 if (AudioStreamControllerClass) { 15426 networkControllers.push(new AudioStreamControllerClass(this, fragmentTracker, keyLoader)); 15427 } 15428 // subtitleTrackController must be defined before subtitleStreamController because the order of event handling is important 15429 this.subtitleTrackController = this.createController(config.subtitleTrackController, networkControllers); 15430 var SubtitleStreamControllerClass = config.subtitleStreamController; 15431 if (SubtitleStreamControllerClass) { 15432 networkControllers.push(new SubtitleStreamControllerClass(this, fragmentTracker, keyLoader)); 15433 } 15434 this.createController(config.timelineController, coreComponents); 15435 keyLoader.emeController = this.emeController = this.createController(config.emeController, coreComponents); 15436 this.cmcdController = this.createController(config.cmcdController, coreComponents); 15437 this.latencyController = this.createController(_controller_latency_controller__WEBPACK_IMPORTED_MODULE_3__["default"], coreComponents); 15438 this.coreComponents = coreComponents; 15439 } 15440 var _proto = Hls.prototype; 15441 _proto.createController = function createController(ControllerClass, components) { 15442 if (ControllerClass) { 15443 var controllerInstance = new ControllerClass(this); 15444 if (components) { 15445 components.push(controllerInstance); 15446 } 15447 return controllerInstance; 15448 } 15449 return null; 15450 } 15451 15452 // Delegate the EventEmitter through the public API of Hls.js 15453 ; 15454 _proto.on = function on(event, listener, context) { 15455 if (context === void 0) { 15456 context = this; 15457 } 15458 this._emitter.on(event, listener, context); 15459 }; 15460 _proto.once = function once(event, listener, context) { 15461 if (context === void 0) { 15462 context = this; 15463 } 15464 this._emitter.once(event, listener, context); 15465 }; 15466 _proto.removeAllListeners = function removeAllListeners(event) { 15467 this._emitter.removeAllListeners(event); 15468 }; 15469 _proto.off = function off(event, listener, context, once) { 15470 if (context === void 0) { 15471 context = this; 15472 } 15473 this._emitter.off(event, listener, context, once); 15474 }; 15475 _proto.listeners = function listeners(event) { 15476 return this._emitter.listeners(event); 15477 }; 15478 _proto.emit = function emit(event, name, eventObject) { 15479 return this._emitter.emit(event, name, eventObject); 15480 }; 15481 _proto.trigger = function trigger(event, eventObject) { 15482 if (this.config.debug) { 15483 return this.emit(event, event, eventObject); 15484 } else { 15485 try { 15486 return this.emit(event, event, eventObject); 15487 } catch (e) { 15488 _utils_logger__WEBPACK_IMPORTED_MODULE_9__.logger.error('An internal error happened while handling event ' + event + '. Error message: "' + e.message + '". Here is a stacktrace:', e); 15489 this.trigger(_events__WEBPACK_IMPORTED_MODULE_12__.Events.ERROR, { 15490 type: _errors__WEBPACK_IMPORTED_MODULE_13__.ErrorTypes.OTHER_ERROR, 15491 details: _errors__WEBPACK_IMPORTED_MODULE_13__.ErrorDetails.INTERNAL_EXCEPTION, 15492 fatal: false, 15493 event: event, 15494 error: e 15495 }); 15496 } 15497 } 15498 return false; 15499 }; 15500 _proto.listenerCount = function listenerCount(event) { 15501 return this._emitter.listenerCount(event); 15502 } 15503 15504 /** 15505 * Dispose of the instance 15506 */; 15507 _proto.destroy = function destroy() { 15508 _utils_logger__WEBPACK_IMPORTED_MODULE_9__.logger.log('destroy'); 15509 this.trigger(_events__WEBPACK_IMPORTED_MODULE_12__.Events.DESTROYING, undefined); 15510 this.detachMedia(); 15511 this.removeAllListeners(); 15512 this._autoLevelCapping = -1; 15513 this.url = null; 15514 this.networkControllers.forEach(function (component) { 15515 return component.destroy(); 15516 }); 15517 this.networkControllers.length = 0; 15518 this.coreComponents.forEach(function (component) { 15519 return component.destroy(); 15520 }); 15521 this.coreComponents.length = 0; 15522 } 15523 15524 /** 15525 * Attaches Hls.js to a media element 15526 * @param {HTMLMediaElement} media 15527 */; 15528 _proto.attachMedia = function attachMedia(media) { 15529 _utils_logger__WEBPACK_IMPORTED_MODULE_9__.logger.log('attachMedia'); 15530 this._media = media; 15531 this.trigger(_events__WEBPACK_IMPORTED_MODULE_12__.Events.MEDIA_ATTACHING, { 15532 media: media 15533 }); 15534 } 15535 15536 /** 15537 * Detach Hls.js from the media 15538 */; 15539 _proto.detachMedia = function detachMedia() { 15540 _utils_logger__WEBPACK_IMPORTED_MODULE_9__.logger.log('detachMedia'); 15541 this.trigger(_events__WEBPACK_IMPORTED_MODULE_12__.Events.MEDIA_DETACHING, undefined); 15542 this._media = null; 15543 } 15544 15545 /** 15546 * Set the source URL. Can be relative or absolute. 15547 * @param {string} url 15548 */; 15549 _proto.loadSource = function loadSource(url) { 15550 this.stopLoad(); 15551 var media = this.media; 15552 var loadedSource = this.url; 15553 var loadingSource = this.url = url_toolkit__WEBPACK_IMPORTED_MODULE_0__.buildAbsoluteURL(self.location.href, url, { 15554 alwaysNormalize: true 15555 }); 15556 _utils_logger__WEBPACK_IMPORTED_MODULE_9__.logger.log("loadSource:" + loadingSource); 15557 if (media && loadedSource && loadedSource !== loadingSource && this.bufferController.hasSourceTypes()) { 15558 this.detachMedia(); 15559 this.attachMedia(media); 15560 } 15561 // when attaching to a source URL, trigger a playlist load 15562 this.trigger(_events__WEBPACK_IMPORTED_MODULE_12__.Events.MANIFEST_LOADING, { 15563 url: url 15564 }); 15565 } 15566 15567 /** 15568 * Start loading data from the stream source. 15569 * Depending on default config, client starts loading automatically when a source is set. 15570 * 15571 * @param {number} startPosition Set the start position to stream from 15572 * @default -1 None (from earliest point) 15573 */; 15574 _proto.startLoad = function startLoad(startPosition) { 15575 if (startPosition === void 0) { 15576 startPosition = -1; 15577 } 15578 _utils_logger__WEBPACK_IMPORTED_MODULE_9__.logger.log("startLoad(" + startPosition + ")"); 15579 this.networkControllers.forEach(function (controller) { 15580 controller.startLoad(startPosition); 15581 }); 15582 } 15583 15584 /** 15585 * Stop loading of any stream data. 15586 */; 15587 _proto.stopLoad = function stopLoad() { 15588 _utils_logger__WEBPACK_IMPORTED_MODULE_9__.logger.log('stopLoad'); 15589 this.networkControllers.forEach(function (controller) { 15590 controller.stopLoad(); 15591 }); 15592 } 15593 15594 /** 15595 * Swap through possible audio codecs in the stream (for example to switch from stereo to 5.1) 15596 */; 15597 _proto.swapAudioCodec = function swapAudioCodec() { 15598 _utils_logger__WEBPACK_IMPORTED_MODULE_9__.logger.log('swapAudioCodec'); 15599 this.streamController.swapAudioCodec(); 15600 } 15601 15602 /** 15603 * When the media-element fails, this allows to detach and then re-attach it 15604 * as one call (convenience method). 15605 * 15606 * Automatic recovery of media-errors by this process is configurable. 15607 */; 15608 _proto.recoverMediaError = function recoverMediaError() { 15609 _utils_logger__WEBPACK_IMPORTED_MODULE_9__.logger.log('recoverMediaError'); 15610 var media = this._media; 15611 this.detachMedia(); 15612 if (media) { 15613 this.attachMedia(media); 15614 } 15615 }; 15616 _proto.removeLevel = function removeLevel(levelIndex, urlId) { 15617 if (urlId === void 0) { 15618 urlId = 0; 15619 } 15620 this.levelController.removeLevel(levelIndex, urlId); 15621 } 15622 15623 /** 15624 * @type {Level[]} 15625 */; 15626 _createClass(Hls, [{ 15627 key: "levels", 15628 get: function get() { 15629 var levels = this.levelController.levels; 15630 return levels ? levels : []; 15631 } 15632 15633 /** 15634 * Index of quality level currently played 15635 * @type {number} 15636 */ 15637 }, { 15638 key: "currentLevel", 15639 get: function get() { 15640 return this.streamController.currentLevel; 15641 } 15642 15643 /** 15644 * Set quality level index immediately . 15645 * This will flush the current buffer to replace the quality asap. 15646 * That means playback will interrupt at least shortly to re-buffer and re-sync eventually. 15647 * @type {number} -1 for automatic level selection 15648 */, 15649 set: function set(newLevel) { 15650 _utils_logger__WEBPACK_IMPORTED_MODULE_9__.logger.log("set currentLevel:" + newLevel); 15651 this.loadLevel = newLevel; 15652 this.abrController.clearTimer(); 15653 this.streamController.immediateLevelSwitch(); 15654 } 15655 15656 /** 15657 * Index of next quality level loaded as scheduled by stream controller. 15658 * @type {number} 15659 */ 15660 }, { 15661 key: "nextLevel", 15662 get: function get() { 15663 return this.streamController.nextLevel; 15664 } 15665 15666 /** 15667 * Set quality level index for next loaded data. 15668 * This will switch the video quality asap, without interrupting playback. 15669 * May abort current loading of data, and flush parts of buffer (outside currently played fragment region). 15670 * @type {number} -1 for automatic level selection 15671 */, 15672 set: function set(newLevel) { 15673 _utils_logger__WEBPACK_IMPORTED_MODULE_9__.logger.log("set nextLevel:" + newLevel); 15674 this.levelController.manualLevel = newLevel; 15675 this.streamController.nextLevelSwitch(); 15676 } 15677 15678 /** 15679 * Return the quality level of the currently or last (of none is loaded currently) segment 15680 * @type {number} 15681 */ 15682 }, { 15683 key: "loadLevel", 15684 get: function get() { 15685 return this.levelController.level; 15686 } 15687 15688 /** 15689 * Set quality level index for next loaded data in a conservative way. 15690 * This will switch the quality without flushing, but interrupt current loading. 15691 * Thus the moment when the quality switch will appear in effect will only be after the already existing buffer. 15692 * @type {number} newLevel -1 for automatic level selection 15693 */, 15694 set: function set(newLevel) { 15695 _utils_logger__WEBPACK_IMPORTED_MODULE_9__.logger.log("set loadLevel:" + newLevel); 15696 this.levelController.manualLevel = newLevel; 15697 } 15698 15699 /** 15700 * get next quality level loaded 15701 * @type {number} 15702 */ 15703 }, { 15704 key: "nextLoadLevel", 15705 get: function get() { 15706 return this.levelController.nextLoadLevel; 15707 } 15708 15709 /** 15710 * Set quality level of next loaded segment in a fully "non-destructive" way. 15711 * Same as `loadLevel` but will wait for next switch (until current loading is done). 15712 * @type {number} level 15713 */, 15714 set: function set(level) { 15715 this.levelController.nextLoadLevel = level; 15716 } 15717 15718 /** 15719 * Return "first level": like a default level, if not set, 15720 * falls back to index of first level referenced in manifest 15721 * @type {number} 15722 */ 15723 }, { 15724 key: "firstLevel", 15725 get: function get() { 15726 return Math.max(this.levelController.firstLevel, this.minAutoLevel); 15727 } 15728 15729 /** 15730 * Sets "first-level", see getter. 15731 * @type {number} 15732 */, 15733 set: function set(newLevel) { 15734 _utils_logger__WEBPACK_IMPORTED_MODULE_9__.logger.log("set firstLevel:" + newLevel); 15735 this.levelController.firstLevel = newLevel; 15736 } 15737 15738 /** 15739 * Return start level (level of first fragment that will be played back) 15740 * if not overrided by user, first level appearing in manifest will be used as start level 15741 * if -1 : automatic start level selection, playback will start from level matching download bandwidth 15742 * (determined from download of first segment) 15743 * @type {number} 15744 */ 15745 }, { 15746 key: "startLevel", 15747 get: function get() { 15748 return this.levelController.startLevel; 15749 } 15750 15751 /** 15752 * set start level (level of first fragment that will be played back) 15753 * if not overrided by user, first level appearing in manifest will be used as start level 15754 * if -1 : automatic start level selection, playback will start from level matching download bandwidth 15755 * (determined from download of first segment) 15756 * @type {number} newLevel 15757 */, 15758 set: function set(newLevel) { 15759 _utils_logger__WEBPACK_IMPORTED_MODULE_9__.logger.log("set startLevel:" + newLevel); 15760 // if not in automatic start level detection, ensure startLevel is greater than minAutoLevel 15761 if (newLevel !== -1) { 15762 newLevel = Math.max(newLevel, this.minAutoLevel); 15763 } 15764 this.levelController.startLevel = newLevel; 15765 } 15766 15767 /** 15768 * Get the current setting for capLevelToPlayerSize 15769 * 15770 * @type {boolean} 15771 */ 15772 }, { 15773 key: "capLevelToPlayerSize", 15774 get: function get() { 15775 return this.config.capLevelToPlayerSize; 15776 } 15777 15778 /** 15779 * set dynamically set capLevelToPlayerSize against (`CapLevelController`) 15780 * 15781 * @type {boolean} 15782 */, 15783 set: function set(shouldStartCapping) { 15784 var newCapLevelToPlayerSize = !!shouldStartCapping; 15785 if (newCapLevelToPlayerSize !== this.config.capLevelToPlayerSize) { 15786 if (newCapLevelToPlayerSize) { 15787 this.capLevelController.startCapping(); // If capping occurs, nextLevelSwitch will happen based on size. 15788 } else { 15789 this.capLevelController.stopCapping(); 15790 this.autoLevelCapping = -1; 15791 this.streamController.nextLevelSwitch(); // Now we're uncapped, get the next level asap. 15792 } 15793 15794 this.config.capLevelToPlayerSize = newCapLevelToPlayerSize; 15795 } 15796 } 15797 15798 /** 15799 * Capping/max level value that should be used by automatic level selection algorithm (`ABRController`) 15800 * @type {number} 15801 */ 15802 }, { 15803 key: "autoLevelCapping", 15804 get: function get() { 15805 return this._autoLevelCapping; 15806 } 15807 15808 /** 15809 * get bandwidth estimate 15810 * @type {number} 15811 */, 15812 set: 15813 /** 15814 * Capping/max level value that should be used by automatic level selection algorithm (`ABRController`) 15815 * @type {number} 15816 */ 15817 function set(newLevel) { 15818 if (this._autoLevelCapping !== newLevel) { 15819 _utils_logger__WEBPACK_IMPORTED_MODULE_9__.logger.log("set autoLevelCapping:" + newLevel); 15820 this._autoLevelCapping = newLevel; 15821 } 15822 } 15823 }, { 15824 key: "bandwidthEstimate", 15825 get: function get() { 15826 var bwEstimator = this.abrController.bwEstimator; 15827 if (!bwEstimator) { 15828 return NaN; 15829 } 15830 return bwEstimator.getEstimate(); 15831 } 15832 }, { 15833 key: "maxHdcpLevel", 15834 get: function get() { 15835 return this._maxHdcpLevel; 15836 }, 15837 set: function set(value) { 15838 if (_types_level__WEBPACK_IMPORTED_MODULE_14__.HdcpLevels.indexOf(value) > -1) { 15839 this._maxHdcpLevel = value; 15840 } 15841 } 15842 15843 /** 15844 * True when automatic level selection enabled 15845 * @type {boolean} 15846 */ 15847 }, { 15848 key: "autoLevelEnabled", 15849 get: function get() { 15850 return this.levelController.manualLevel === -1; 15851 } 15852 15853 /** 15854 * Level set manually (if any) 15855 * @type {number} 15856 */ 15857 }, { 15858 key: "manualLevel", 15859 get: function get() { 15860 return this.levelController.manualLevel; 15861 } 15862 15863 /** 15864 * min level selectable in auto mode according to config.minAutoBitrate 15865 * @type {number} 15866 */ 15867 }, { 15868 key: "minAutoLevel", 15869 get: function get() { 15870 var levels = this.levels, 15871 minAutoBitrate = this.config.minAutoBitrate; 15872 if (!levels) return 0; 15873 var len = levels.length; 15874 for (var i = 0; i < len; i++) { 15875 if (levels[i].maxBitrate >= minAutoBitrate) { 15876 return i; 15877 } 15878 } 15879 return 0; 15880 } 15881 15882 /** 15883 * max level selectable in auto mode according to autoLevelCapping 15884 * @type {number} 15885 */ 15886 }, { 15887 key: "maxAutoLevel", 15888 get: function get() { 15889 var levels = this.levels, 15890 autoLevelCapping = this.autoLevelCapping, 15891 maxHdcpLevel = this.maxHdcpLevel; 15892 var maxAutoLevel; 15893 if (autoLevelCapping === -1 && levels && levels.length) { 15894 maxAutoLevel = levels.length - 1; 15895 } else { 15896 maxAutoLevel = autoLevelCapping; 15897 } 15898 if (maxHdcpLevel) { 15899 for (var i = maxAutoLevel; i--;) { 15900 var hdcpLevel = levels[i].attrs['HDCP-LEVEL']; 15901 if (hdcpLevel && hdcpLevel <= maxHdcpLevel) { 15902 return i; 15903 } 15904 } 15905 } 15906 return maxAutoLevel; 15907 } 15908 15909 /** 15910 * next automatically selected quality level 15911 * @type {number} 15912 */ 15913 }, { 15914 key: "nextAutoLevel", 15915 get: function get() { 15916 // ensure next auto level is between min and max auto level 15917 return Math.min(Math.max(this.abrController.nextAutoLevel, this.minAutoLevel), this.maxAutoLevel); 15918 } 15919 15920 /** 15921 * this setter is used to force next auto level. 15922 * this is useful to force a switch down in auto mode: 15923 * in case of load error on level N, hls.js can set nextAutoLevel to N-1 for example) 15924 * forced value is valid for one fragment. upon successful frag loading at forced level, 15925 * this value will be resetted to -1 by ABR controller. 15926 * @type {number} 15927 */, 15928 set: function set(nextLevel) { 15929 this.abrController.nextAutoLevel = Math.max(this.minAutoLevel, nextLevel); 15930 } 15931 15932 /** 15933 * get the datetime value relative to media.currentTime for the active level Program Date Time if present 15934 * @type {Date} 15935 */ 15936 }, { 15937 key: "playingDate", 15938 get: function get() { 15939 return this.streamController.currentProgramDateTime; 15940 } 15941 }, { 15942 key: "mainForwardBufferInfo", 15943 get: function get() { 15944 return this.streamController.getMainFwdBufferInfo(); 15945 } 15946 15947 /** 15948 * @type {AudioTrack[]} 15949 */ 15950 }, { 15951 key: "audioTracks", 15952 get: function get() { 15953 var audioTrackController = this.audioTrackController; 15954 return audioTrackController ? audioTrackController.audioTracks : []; 15955 } 15956 15957 /** 15958 * index of the selected audio track (index in audio track lists) 15959 * @type {number} 15960 */ 15961 }, { 15962 key: "audioTrack", 15963 get: function get() { 15964 var audioTrackController = this.audioTrackController; 15965 return audioTrackController ? audioTrackController.audioTrack : -1; 15966 } 15967 15968 /** 15969 * selects an audio track, based on its index in audio track lists 15970 * @type {number} 15971 */, 15972 set: function set(audioTrackId) { 15973 var audioTrackController = this.audioTrackController; 15974 if (audioTrackController) { 15975 audioTrackController.audioTrack = audioTrackId; 15976 } 15977 } 15978 15979 /** 15980 * get alternate subtitle tracks list from playlist 15981 * @type {MediaPlaylist[]} 15982 */ 15983 }, { 15984 key: "subtitleTracks", 15985 get: function get() { 15986 var subtitleTrackController = this.subtitleTrackController; 15987 return subtitleTrackController ? subtitleTrackController.subtitleTracks : []; 15988 } 15989 15990 /** 15991 * index of the selected subtitle track (index in subtitle track lists) 15992 * @type {number} 15993 */ 15994 }, { 15995 key: "subtitleTrack", 15996 get: function get() { 15997 var subtitleTrackController = this.subtitleTrackController; 15998 return subtitleTrackController ? subtitleTrackController.subtitleTrack : -1; 15999 }, 16000 set: 16001 /** 16002 * select an subtitle track, based on its index in subtitle track lists 16003 * @type {number} 16004 */ 16005 function set(subtitleTrackId) { 16006 var subtitleTrackController = this.subtitleTrackController; 16007 if (subtitleTrackController) { 16008 subtitleTrackController.subtitleTrack = subtitleTrackId; 16009 } 16010 } 16011 16012 /** 16013 * @type {boolean} 16014 */ 16015 }, { 16016 key: "media", 16017 get: function get() { 16018 return this._media; 16019 } 16020 }, { 16021 key: "subtitleDisplay", 16022 get: function get() { 16023 var subtitleTrackController = this.subtitleTrackController; 16024 return subtitleTrackController ? subtitleTrackController.subtitleDisplay : false; 16025 } 16026 16027 /** 16028 * Enable/disable subtitle display rendering 16029 * @type {boolean} 16030 */, 16031 set: function set(value) { 16032 var subtitleTrackController = this.subtitleTrackController; 16033 if (subtitleTrackController) { 16034 subtitleTrackController.subtitleDisplay = value; 16035 } 16036 } 16037 16038 /** 16039 * get mode for Low-Latency HLS loading 16040 * @type {boolean} 16041 */ 16042 }, { 16043 key: "lowLatencyMode", 16044 get: function get() { 16045 return this.config.lowLatencyMode; 16046 } 16047 16048 /** 16049 * Enable/disable Low-Latency HLS part playlist and segment loading, and start live streams at playlist PART-HOLD-BACK rather than HOLD-BACK. 16050 * @type {boolean} 16051 */, 16052 set: function set(mode) { 16053 this.config.lowLatencyMode = mode; 16054 } 16055 16056 /** 16057 * position (in seconds) of live sync point (ie edge of live position minus safety delay defined by ```hls.config.liveSyncDuration```) 16058 * @type {number} 16059 */ 16060 }, { 16061 key: "liveSyncPosition", 16062 get: function get() { 16063 return this.latencyController.liveSyncPosition; 16064 } 16065 16066 /** 16067 * estimated position (in seconds) of live edge (ie edge of live playlist plus time sync playlist advanced) 16068 * returns 0 before first playlist is loaded 16069 * @type {number} 16070 */ 16071 }, { 16072 key: "latency", 16073 get: function get() { 16074 return this.latencyController.latency; 16075 } 16076 16077 /** 16078 * maximum distance from the edge before the player seeks forward to ```hls.liveSyncPosition``` 16079 * configured using ```liveMaxLatencyDurationCount``` (multiple of target duration) or ```liveMaxLatencyDuration``` 16080 * returns 0 before first playlist is loaded 16081 * @type {number} 16082 */ 16083 }, { 16084 key: "maxLatency", 16085 get: function get() { 16086 return this.latencyController.maxLatency; 16087 } 16088 16089 /** 16090 * target distance from the edge as calculated by the latency controller 16091 * @type {number} 16092 */ 16093 }, { 16094 key: "targetLatency", 16095 get: function get() { 16096 return this.latencyController.targetLatency; 16097 } 16098 16099 /** 16100 * the rate at which the edge of the current live playlist is advancing or 1 if there is none 16101 * @type {number} 16102 */ 16103 }, { 16104 key: "drift", 16105 get: function get() { 16106 return this.latencyController.drift; 16107 } 16108 16109 /** 16110 * set to true when startLoad is called before MANIFEST_PARSED event 16111 * @type {boolean} 16112 */ 16113 }, { 16114 key: "forceStartLoad", 16115 get: function get() { 16116 return this.streamController.forceStartLoad; 16117 } 16118 }], [{ 16119 key: "version", 16120 get: function get() { 16121 return "1.3.
161212
vendor: 70,259 bytes, lines 16121-17791
16121"; 16122 } 16123 }, { 16124 key: "Events", 16125 get: function get() { 16126 return _events__WEBPACK_IMPORTED_MODULE_12__.Events; 16127 } 16128 }, { 16129 key: "ErrorTypes", 16130 get: function get() { 16131 return _errors__WEBPACK_IMPORTED_MODULE_13__.ErrorTypes; 16132 } 16133 }, { 16134 key: "ErrorDetails", 16135 get: function get() { 16136 return _errors__WEBPACK_IMPORTED_MODULE_13__.ErrorDetails; 16137 } 16138 }, { 16139 key: "DefaultConfig", 16140 get: function get() { 16141 if (!Hls.defaultConfig) { 16142 return _config__WEBPACK_IMPORTED_MODULE_10__.hlsDefaultConfig; 16143 } 16144 return Hls.defaultConfig; 16145 } 16146 16147 /** 16148 * @type {HlsConfig} 16149 */, 16150 set: function set(defaultConfig) { 16151 Hls.defaultConfig = defaultConfig; 16152 } 16153 }]); 16154 return Hls; 16155}(); 16156Hls.defaultConfig = void 0; 16157 16158 16159/***/ }), 16160 16161/***/ "./src/is-supported.ts": 16162/*!*****************************!*\ 16163 !*** ./src/is-supported.ts ***! 16164 \*****************************/ 16165/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 16166 16167"use strict"; 16168__webpack_require__.r(__webpack_exports__); 16169/* harmony export */ __webpack_require__.d(__webpack_exports__, { 16170/* harmony export */ "changeTypeSupported": () => (/* binding */ changeTypeSupported), 16171/* harmony export */ "isSupported": () => (/* binding */ isSupported) 16172/* harmony export */ }); 16173/* harmony import */ var _utils_mediasource_helper__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils/mediasource-helper */ "./src/utils/mediasource-helper.ts"); 16174 16175function getSourceBuffer() { 16176 return self.SourceBuffer || self.WebKitSourceBuffer; 16177} 16178function isSupported() { 16179 var mediaSource = (0,_utils_mediasource_helper__WEBPACK_IMPORTED_MODULE_0__.getMediaSource)(); 16180 if (!mediaSource) { 16181 return false; 16182 } 16183 var sourceBuffer = getSourceBuffer(); 16184 var isTypeSupported = mediaSource && typeof mediaSource.isTypeSupported === 'function' && mediaSource.isTypeSupported('video/mp4; codecs="avc1.42E01E,mp4a.40.2"'); 16185 16186 // if SourceBuffer is exposed ensure its API is valid 16187 // safari and old version of Chrome doe not expose SourceBuffer globally so checking SourceBuffer.prototype is impossible 16188 var sourceBufferValidAPI = !sourceBuffer || sourceBuffer.prototype && typeof sourceBuffer.prototype.appendBuffer === 'function' && typeof sourceBuffer.prototype.remove === 'function'; 16189 return !!isTypeSupported && !!sourceBufferValidAPI; 16190} 16191function changeTypeSupported() { 16192 var _sourceBuffer$prototy; 16193 var sourceBuffer = getSourceBuffer(); 16194 return typeof (sourceBuffer === null || sourceBuffer === void 0 ? void 0 : (_sourceBuffer$prototy = sourceBuffer.prototype) === null || _sourceBuffer$prototy === void 0 ? void 0 : _sourceBuffer$prototy.changeType) === 'function'; 16195} 16196 16197/***/ }), 16198 16199/***/ "./src/loader/date-range.ts": 16200/*!**********************************!*\ 16201 !*** ./src/loader/date-range.ts ***! 16202 \**********************************/ 16203/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 16204 16205"use strict"; 16206__webpack_require__.r(__webpack_exports__); 16207/* harmony export */ __webpack_require__.d(__webpack_exports__, { 16208/* harmony export */ "DateRange": () => (/* binding */ DateRange), 16209/* harmony export */ "DateRangeAttribute": () => (/* binding */ DateRangeAttribute) 16210/* harmony export */ }); 16211/* harmony import */ var _home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.ts"); 16212/* harmony import */ var _utils_attr_list__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils/attr-list */ "./src/utils/attr-list.ts"); 16213/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 16214 16215 16216 16217function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } 16218function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } 16219function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } 16220function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } 16221function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } 16222 16223 16224var DateRangeAttribute; 16225(function (DateRangeAttribute) { 16226 DateRangeAttribute["ID"] = "ID"; 16227 DateRangeAttribute["CLASS"] = "CLASS"; 16228 DateRangeAttribute["START_DATE"] = "START-DATE"; 16229 DateRangeAttribute["DURATION"] = "DURATION"; 16230 DateRangeAttribute["END_DATE"] = "END-DATE"; 16231 DateRangeAttribute["END_ON_NEXT"] = "END-ON-NEXT"; 16232 DateRangeAttribute["PLANNED_DURATION"] = "PLANNED-DURATION"; 16233 DateRangeAttribute["SCTE35_OUT"] = "SCTE35-OUT"; 16234 DateRangeAttribute["SCTE35_IN"] = "SCTE35-IN"; 16235})(DateRangeAttribute || (DateRangeAttribute = {})); 16236var DateRange = /*#__PURE__*/function () { 16237 function DateRange(dateRangeAttr, dateRangeWithSameId) { 16238 this.attr = void 0; 16239 this._startDate = void 0; 16240 this._endDate = void 0; 16241 this._badValueForSameId = void 0; 16242 if (dateRangeWithSameId) { 16243 var previousAttr = dateRangeWithSameId.attr; 16244 for (var key in previousAttr) { 16245 if (Object.prototype.hasOwnProperty.call(dateRangeAttr, key) && dateRangeAttr[key] !== previousAttr[key]) { 16246 _utils_logger__WEBPACK_IMPORTED_MODULE_2__.logger.warn("DATERANGE tag attribute: \"" + key + "\" does not match for tags with ID: \"" + dateRangeAttr.ID + "\""); 16247 this._badValueForSameId = key; 16248 break; 16249 } 16250 } 16251 // Merge DateRange tags with the same ID 16252 dateRangeAttr = _extends(new _utils_attr_list__WEBPACK_IMPORTED_MODULE_1__.AttrList({}), previousAttr, dateRangeAttr); 16253 } 16254 this.attr = dateRangeAttr; 16255 this._startDate = new Date(dateRangeAttr[DateRangeAttribute.START_DATE]); 16256 if (DateRangeAttribute.END_DATE in this.attr) { 16257 var endDate = new Date(this.attr[DateRangeAttribute.END_DATE]); 16258 if ((0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(endDate.getTime())) { 16259 this._endDate = endDate; 16260 } 16261 } 16262 } 16263 _createClass(DateRange, [{ 16264 key: "id", 16265 get: function get() { 16266 return this.attr.ID; 16267 } 16268 }, { 16269 key: "class", 16270 get: function get() { 16271 return this.attr.CLASS; 16272 } 16273 }, { 16274 key: "startDate", 16275 get: function get() { 16276 return this._startDate; 16277 } 16278 }, { 16279 key: "endDate", 16280 get: function get() { 16281 if (this._endDate) { 16282 return this._endDate; 16283 } 16284 var duration = this.duration; 16285 if (duration !== null) { 16286 return new Date(this._startDate.getTime() + duration * 1000); 16287 } 16288 return null; 16289 } 16290 }, { 16291 key: "duration", 16292 get: function get() { 16293 if (DateRangeAttribute.DURATION in this.attr) { 16294 var duration = this.attr.decimalFloatingPoint(DateRangeAttribute.DURATION); 16295 if ((0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(duration)) { 16296 return duration; 16297 } 16298 } else if (this._endDate) { 16299 return (this._endDate.getTime() - this._startDate.getTime()) / 1000; 16300 } 16301 return null; 16302 } 16303 }, { 16304 key: "plannedDuration", 16305 get: function get() { 16306 if (DateRangeAttribute.PLANNED_DURATION in this.attr) { 16307 return this.attr.decimalFloatingPoint(DateRangeAttribute.PLANNED_DURATION); 16308 } 16309 return null; 16310 } 16311 }, { 16312 key: "endOnNext", 16313 get: function get() { 16314 return this.attr.bool(DateRangeAttribute.END_ON_NEXT); 16315 } 16316 }, { 16317 key: "isValid", 16318 get: function get() { 16319 return !!this.id && !this._badValueForSameId && (0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(this.startDate.getTime()) && (this.duration === null || this.duration >= 0) && (!this.endOnNext || !!this.class); 16320 } 16321 }]); 16322 return DateRange; 16323}(); 16324 16325/***/ }), 16326 16327/***/ "./src/loader/fragment-loader.ts": 16328/*!***************************************!*\ 16329 !*** ./src/loader/fragment-loader.ts ***! 16330 \***************************************/ 16331/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 16332 16333"use strict"; 16334__webpack_require__.r(__webpack_exports__); 16335/* harmony export */ __webpack_require__.d(__webpack_exports__, { 16336/* harmony export */ "LoadError": () => (/* binding */ LoadError), 16337/* harmony export */ "default": () => (/* binding */ FragmentLoader) 16338/* harmony export */ }); 16339/* harmony import */ var _home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.ts"); 16340/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../errors */ "./src/errors.ts"); 16341 16342 16343function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); } 16344function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); } 16345function _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct.bind(); } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); } 16346function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } 16347function _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; } 16348function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } 16349function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } 16350 16351var MIN_CHUNK_SIZE = Math.pow(2, 17); // 128kb 16352var FragmentLoader = /*#__PURE__*/function () { 16353 function FragmentLoader(config) { 16354 this.config = void 0; 16355 this.loader = null; 16356 this.partLoadTimeout = -1; 16357 this.config = config; 16358 } 16359 var _proto = FragmentLoader.prototype; 16360 _proto.destroy = function destroy() { 16361 if (this.loader) { 16362 this.loader.destroy(); 16363 this.loader = null; 16364 } 16365 }; 16366 _proto.abort = function abort() { 16367 if (this.loader) { 16368 // Abort the loader for current fragment. Only one may load at any given time 16369 this.loader.abort(); 16370 } 16371 }; 16372 _proto.load = function load(frag, _onProgress) { 16373 var _this = this; 16374 var url = frag.url; 16375 if (!url) { 16376 return Promise.reject(new LoadError({ 16377 type: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorTypes.NETWORK_ERROR, 16378 details: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorDetails.FRAG_LOAD_ERROR, 16379 fatal: false, 16380 frag: frag, 16381 networkDetails: null 16382 }, "Fragment does not have a " + (url ? 'part list' : 'url'))); 16383 } 16384 this.abort(); 16385 var config = this.config; 16386 var FragmentILoader = config.fLoader; 16387 var DefaultILoader = config.loader; 16388 return new Promise(function (resolve, reject) { 16389 if (_this.loader) { 16390 _this.loader.destroy(); 16391 } 16392 var loader = _this.loader = frag.loader = FragmentILoader ? new FragmentILoader(config) : new DefaultILoader(config); 16393 var loaderContext = createLoaderContext(frag); 16394 var loaderConfig = { 16395 timeout: config.fragLoadingTimeOut, 16396 maxRetry: 0, 16397 retryDelay: 0, 16398 maxRetryDelay: config.fragLoadingMaxRetryTimeout, 16399 highWaterMark: frag.sn === 'initSegment' ? Infinity : MIN_CHUNK_SIZE 16400 }; 16401 // Assign frag stats to the loader's stats reference 16402 frag.stats = loader.stats; 16403 loader.load(loaderContext, loaderConfig, { 16404 onSuccess: function onSuccess(response, stats, context, networkDetails) { 16405 _this.resetLoader(frag, loader); 16406 var payload = response.data; 16407 if (context.resetIV && frag.decryptdata) { 16408 frag.decryptdata.iv = new Uint8Array(payload.slice(0, 16)); 16409 payload = payload.slice(16); 16410 } 16411 resolve({ 16412 frag: frag, 16413 part: null, 16414 payload: payload, 16415 networkDetails: networkDetails 16416 }); 16417 }, 16418 onError: function onError(response, context, networkDetails) { 16419 _this.resetLoader(frag, loader); 16420 reject(new LoadError({ 16421 type: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorTypes.NETWORK_ERROR, 16422 details: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorDetails.FRAG_LOAD_ERROR, 16423 fatal: false, 16424 frag: frag, 16425 response: response, 16426 networkDetails: networkDetails 16427 })); 16428 }, 16429 onAbort: function onAbort(stats, context, networkDetails) { 16430 _this.resetLoader(frag, loader); 16431 reject(new LoadError({ 16432 type: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorTypes.NETWORK_ERROR, 16433 details: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorDetails.INTERNAL_ABORTED, 16434 fatal: false, 16435 frag: frag, 16436 networkDetails: networkDetails 16437 })); 16438 }, 16439 onTimeout: function onTimeout(response, context, networkDetails) { 16440 _this.resetLoader(frag, loader); 16441 reject(new LoadError({ 16442 type: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorTypes.NETWORK_ERROR, 16443 details: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorDetails.FRAG_LOAD_TIMEOUT, 16444 fatal: false, 16445 frag: frag, 16446 networkDetails: networkDetails 16447 })); 16448 }, 16449 onProgress: function onProgress(stats, context, data, networkDetails) { 16450 if (_onProgress) { 16451 _onProgress({ 16452 frag: frag, 16453 part: null, 16454 payload: data, 16455 networkDetails: networkDetails 16456 }); 16457 } 16458 } 16459 }); 16460 }); 16461 }; 16462 _proto.loadPart = function loadPart(frag, part, onProgress) { 16463 var _this2 = this; 16464 this.abort(); 16465 var config = this.config; 16466 var FragmentILoader = config.fLoader; 16467 var DefaultILoader = config.loader; 16468 return new Promise(function (resolve, reject) { 16469 if (_this2.loader) { 16470 _this2.loader.destroy(); 16471 } 16472 var loader = _this2.loader = frag.loader = FragmentILoader ? new FragmentILoader(config) : new DefaultILoader(config); 16473 var loaderContext = createLoaderContext(frag, part); 16474 var loaderConfig = { 16475 timeout: config.fragLoadingTimeOut, 16476 maxRetry: 0, 16477 retryDelay: 0, 16478 maxRetryDelay: config.fragLoadingMaxRetryTimeout, 16479 highWaterMark: MIN_CHUNK_SIZE 16480 }; 16481 // Assign part stats to the loader's stats reference 16482 part.stats = loader.stats; 16483 loader.load(loaderContext, loaderConfig, { 16484 onSuccess: function onSuccess(response, stats, context, networkDetails) { 16485 _this2.resetLoader(frag, loader); 16486 _this2.updateStatsFromPart(frag, part); 16487 var partLoadedData = { 16488 frag: frag, 16489 part: part, 16490 payload: response.data, 16491 networkDetails: networkDetails 16492 }; 16493 onProgress(partLoadedData); 16494 resolve(partLoadedData); 16495 }, 16496 onError: function onError(response, context, networkDetails) { 16497 _this2.resetLoader(frag, loader); 16498 reject(new LoadError({ 16499 type: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorTypes.NETWORK_ERROR, 16500 details: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorDetails.FRAG_LOAD_ERROR, 16501 fatal: false, 16502 frag: frag, 16503 part: part, 16504 response: response, 16505 networkDetails: networkDetails 16506 })); 16507 }, 16508 onAbort: function onAbort(stats, context, networkDetails) { 16509 frag.stats.aborted = part.stats.aborted; 16510 _this2.resetLoader(frag, loader); 16511 reject(new LoadError({ 16512 type: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorTypes.NETWORK_ERROR, 16513 details: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorDetails.INTERNAL_ABORTED, 16514 fatal: false, 16515 frag: frag, 16516 part: part, 16517 networkDetails: networkDetails 16518 })); 16519 }, 16520 onTimeout: function onTimeout(response, context, networkDetails) { 16521 _this2.resetLoader(frag, loader); 16522 reject(new LoadError({ 16523 type: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorTypes.NETWORK_ERROR, 16524 details: _errors__WEBPACK_IMPORTED_MODULE_1__.ErrorDetails.FRAG_LOAD_TIMEOUT, 16525 fatal: false, 16526 frag: frag, 16527 part: part, 16528 networkDetails: networkDetails 16529 })); 16530 } 16531 }); 16532 }); 16533 }; 16534 _proto.updateStatsFromPart = function updateStatsFromPart(frag, part) { 16535 var fragStats = frag.stats; 16536 var partStats = part.stats; 16537 var partTotal = partStats.total; 16538 fragStats.loaded += partStats.loaded; 16539 if (partTotal) { 16540 var estTotalParts = Math.round(frag.duration / part.duration); 16541 var estLoadedParts = Math.min(Math.round(fragStats.loaded / partTotal), estTotalParts); 16542 var estRemainingParts = estTotalParts - estLoadedParts; 16543 var estRemainingBytes = estRemainingParts * Math.round(fragStats.loaded / estLoadedParts); 16544 fragStats.total = fragStats.loaded + estRemainingBytes; 16545 } else { 16546 fragStats.total = Math.max(fragStats.loaded, fragStats.total); 16547 } 16548 var fragLoading = fragStats.loading; 16549 var partLoading = partStats.loading; 16550 if (fragLoading.start) { 16551 // add to fragment loader latency 16552 fragLoading.first += partLoading.first - partLoading.start; 16553 } else { 16554 fragLoading.start = partLoading.start; 16555 fragLoading.first = partLoading.first; 16556 } 16557 fragLoading.end = partLoading.end; 16558 }; 16559 _proto.resetLoader = function resetLoader(frag, loader) { 16560 frag.loader = null; 16561 if (this.loader === loader) { 16562 self.clearTimeout(this.partLoadTimeout); 16563 this.loader = null; 16564 } 16565 loader.destroy(); 16566 }; 16567 return FragmentLoader; 16568}(); 16569 16570function createLoaderContext(frag, part) { 16571 if (part === void 0) { 16572 part = null; 16573 } 16574 var segment = part || frag; 16575 var loaderContext = { 16576 frag: frag, 16577 part: part, 16578 responseType: 'arraybuffer', 16579 url: segment.url, 16580 headers: {}, 16581 rangeStart: 0, 16582 rangeEnd: 0 16583 }; 16584 var start = segment.byteRangeStartOffset; 16585 var end = segment.byteRangeEndOffset; 16586 if ((0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(start) && (0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(end)) { 16587 var _frag$decryptdata; 16588 var byteRangeStart = start; 16589 var byteRangeEnd = end; 16590 if (frag.sn === 'initSegment' && ((_frag$decryptdata = frag.decryptdata) === null || _frag$decryptdata === void 0 ? void 0 : _frag$decryptdata.method) === 'AES-128') { 16591 // MAP segment encrypted with method 'AES-128', when served with HTTP Range, 16592 // has the unencrypted size specified in the range. 16593 // Ref: https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-6.3.6 16594 var fragmentLen = end - start; 16595 if (fragmentLen % 16) { 16596 byteRangeEnd = end + (16 - fragmentLen % 16); 16597 } 16598 if (start !== 0) { 16599 loaderContext.resetIV = true; 16600 byteRangeStart = start - 16; 16601 } 16602 } 16603 loaderContext.rangeStart = byteRangeStart; 16604 loaderContext.rangeEnd = byteRangeEnd; 16605 } 16606 return loaderContext; 16607} 16608var LoadError = /*#__PURE__*/function (_Error) { 16609 _inheritsLoose(LoadError, _Error); 16610 function LoadError(data) { 16611 var _this3; 16612 for (var _len = arguments.length, params = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 16613 params[_key - 1] = arguments[_key]; 16614 } 16615 _this3 = _Error.call.apply(_Error, [this].concat(params)) || this; 16616 _this3.data = void 0; 16617 _this3.data = data; 16618 return _this3; 16619 } 16620 return LoadError; 16621}( /*#__PURE__*/_wrapNativeSuper(Error)); 16622 16623/***/ }), 16624 16625/***/ "./src/loader/fragment.ts": 16626/*!********************************!*\ 16627 !*** ./src/loader/fragment.ts ***! 16628 \********************************/ 16629/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 16630 16631"use strict"; 16632__webpack_require__.r(__webpack_exports__); 16633/* harmony export */ __webpack_require__.d(__webpack_exports__, { 16634/* harmony export */ "BaseSegment": () => (/* binding */ BaseSegment), 16635/* harmony export */ "ElementaryStreamTypes": () => (/* binding */ ElementaryStreamTypes), 16636/* harmony export */ "Fragment": () => (/* binding */ Fragment), 16637/* harmony export */ "Part": () => (/* binding */ Part) 16638/* harmony export */ }); 16639/* harmony import */ var _home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.ts"); 16640/* harmony import */ var url_toolkit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! url-toolkit */ "./node_modules/url-toolkit/src/url-toolkit.js"); 16641/* harmony import */ var url_toolkit__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(url_toolkit__WEBPACK_IMPORTED_MODULE_1__); 16642/* harmony import */ var _load_stats__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./load-stats */ "./src/loader/load-stats.ts"); 16643 16644 16645function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); } 16646function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } 16647function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } 16648function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } 16649function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } 16650function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } 16651 16652 16653var ElementaryStreamTypes; 16654(function (ElementaryStreamTypes) { 16655 ElementaryStreamTypes["AUDIO"] = "audio"; 16656 ElementaryStreamTypes["VIDEO"] = "video"; 16657 ElementaryStreamTypes["AUDIOVIDEO"] = "audiovideo"; 16658})(ElementaryStreamTypes || (ElementaryStreamTypes = {})); 16659var BaseSegment = /*#__PURE__*/function () { 16660 // baseurl is the URL to the playlist 16661 16662 // relurl is the portion of the URL that comes from inside the playlist. 16663 16664 // Holds the types of data this fragment supports 16665 16666 function BaseSegment(baseurl) { 16667 var _this$elementaryStrea; 16668 this._byteRange = null; 16669 this._url = null; 16670 this.baseurl = void 0; 16671 this.relurl = void 0; 16672 this.elementaryStreams = (_this$elementaryStrea = {}, _this$elementaryStrea[ElementaryStreamTypes.AUDIO] = null, _this$elementaryStrea[ElementaryStreamTypes.VIDEO] = null, _this$elementaryStrea[ElementaryStreamTypes.AUDIOVIDEO] = null, _this$elementaryStrea); 16673 this.baseurl = baseurl; 16674 } 16675 16676 // setByteRange converts a EXT-X-BYTERANGE attribute into a two element array 16677 var _proto = BaseSegment.prototype; 16678 _proto.setByteRange = function setByteRange(value, previous) { 16679 var params = value.split('@', 2); 16680 var byteRange = []; 16681 if (params.length === 1) { 16682 byteRange[0] = previous ? previous.byteRangeEndOffset : 0; 16683 } else { 16684 byteRange[0] = parseInt(params[1]); 16685 } 16686 byteRange[1] = parseInt(params[0]) + byteRange[0]; 16687 this._byteRange = byteRange; 16688 }; 16689 _createClass(BaseSegment, [{ 16690 key: "byteRange", 16691 get: function get() { 16692 if (!this._byteRange) { 16693 return []; 16694 } 16695 return this._byteRange; 16696 } 16697 }, { 16698 key: "byteRangeStartOffset", 16699 get: function get() { 16700 return this.byteRange[0]; 16701 } 16702 }, { 16703 key: "byteRangeEndOffset", 16704 get: function get() { 16705 return this.byteRange[1]; 16706 } 16707 }, { 16708 key: "url", 16709 get: function get() { 16710 if (!this._url && this.baseurl && this.relurl) { 16711 this._url = (0,url_toolkit__WEBPACK_IMPORTED_MODULE_1__.buildAbsoluteURL)(this.baseurl, this.relurl, { 16712 alwaysNormalize: true 16713 }); 16714 } 16715 return this._url || ''; 16716 }, 16717 set: function set(value) { 16718 this._url = value; 16719 } 16720 }]); 16721 return BaseSegment; 16722}(); 16723var Fragment = /*#__PURE__*/function (_BaseSegment) { 16724 _inheritsLoose(Fragment, _BaseSegment); 16725 // EXTINF has to be present for a m3u8 to be considered valid 16726 16727 // sn notates the sequence number for a segment, and if set to a string can be 'initSegment' 16728 16729 // levelkeys are the EXT-X-KEY tags that apply to this segment for decryption 16730 // core difference from the private field _decryptdata is the lack of the initialized IV 16731 // _decryptdata will set the IV for this segment based on the segment number in the fragment 16732 16733 // A string representing the fragment type 16734 16735 // A reference to the loader. Set while the fragment is loading, and removed afterwards. Used to abort fragment loading 16736 16737 // A reference to the key loader. Set while the key is loading, and removed afterwards. Used to abort key loading 16738 16739 // The level/track index to which the fragment belongs 16740 16741 // The continuity counter of the fragment 16742 16743 // The starting Presentation Time Stamp (PTS) of the fragment. Set after transmux complete. 16744 16745 // The ending Presentation Time Stamp (PTS) of the fragment. Set after transmux complete. 16746 16747 // The latest Presentation Time Stamp (PTS) appended to the buffer. 16748 16749 // The starting Decode Time Stamp (DTS) of the fragment. Set after transmux complete. 16750 16751 // The ending Decode Time Stamp (DTS) of the fragment. Set after transmux complete. 16752 16753 // The start time of the fragment, as listed in the manifest. Updated after transmux complete. 16754 16755 // Set by `updateFragPTSDTS` in level-helper 16756 16757 // The maximum starting Presentation Time Stamp (audio/video PTS) of the fragment. Set after transmux complete. 16758 16759 // The minimum ending Presentation Time Stamp (audio/video PTS) of the fragment. Set after transmux complete. 16760 16761 // Load/parse timing information 16762 16763 // A flag indicating whether the segment was downloaded in order to test bitrate, and was not buffered 16764 16765 // #EXTINF segment title 16766 16767 // The Media Initialization Section for this segment 16768 16769 // Fragment is the last fragment in the media playlist 16770 16771 function Fragment(type, baseurl) { 16772 var _this; 16773 _this = _BaseSegment.call(this, baseurl) || this; 16774 _this._decryptdata = null; 16775 _this.rawProgramDateTime = null; 16776 _this.programDateTime = null; 16777 _this.tagList = []; 16778 _this.duration = 0; 16779 _this.sn = 0; 16780 _this.levelkeys = void 0; 16781 _this.type = void 0; 16782 _this.loader = null; 16783 _this.keyLoader = null; 16784 _this.level = -1; 16785 _this.cc = 0; 16786 _this.startPTS = void 0; 16787 _this.endPTS = void 0; 16788 _this.appendedPTS = void 0; 16789 _this.startDTS = void 0; 16790 _this.endDTS = void 0; 16791 _this.start = 0; 16792 _this.deltaPTS = void 0; 16793 _this.maxStartPTS = void 0; 16794 _this.minEndPTS = void 0; 16795 _this.stats = new _load_stats__WEBPACK_IMPORTED_MODULE_2__.LoadStats(); 16796 _this.urlId = 0; 16797 _this.data = void 0; 16798 _this.bitrateTest = false; 16799 _this.title = null; 16800 _this.initSegment = null; 16801 _this.endList = void 0; 16802 _this.type = type; 16803 return _this; 16804 } 16805 var _proto2 = Fragment.prototype; 16806 _proto2.setKeyFormat = function setKeyFormat(keyFormat) { 16807 if (this.levelkeys) { 16808 var _key = this.levelkeys[keyFormat]; 16809 if (_key && !this._decryptdata) { 16810 this._decryptdata = _key.getDecryptData(this.sn); 16811 } 16812 } 16813 }; 16814 _proto2.abortRequests = function abortRequests() { 16815 var _this$loader, _this$keyLoader; 16816 (_this$loader = this.loader) === null || _this$loader === void 0 ? void 0 : _this$loader.abort(); 16817 (_this$keyLoader = this.keyLoader) === null || _this$keyLoader === void 0 ? void 0 : _this$keyLoader.abort(); 16818 }; 16819 _proto2.setElementaryStreamInfo = function setElementaryStreamInfo(type, startPTS, endPTS, startDTS, endDTS, partial) { 16820 if (partial === void 0) { 16821 partial = false; 16822 } 16823 var elementaryStreams = this.elementaryStreams; 16824 var info = elementaryStreams[type]; 16825 if (!info) { 16826 elementaryStreams[type] = { 16827 startPTS: startPTS, 16828 endPTS: endPTS, 16829 startDTS: startDTS, 16830 endDTS: endDTS, 16831 partial: partial 16832 }; 16833 return; 16834 } 16835 info.startPTS = Math.min(info.startPTS, startPTS); 16836 info.endPTS = Math.max(info.endPTS, endPTS); 16837 info.startDTS = Math.min(info.startDTS, startDTS); 16838 info.endDTS = Math.max(info.endDTS, endDTS); 16839 }; 16840 _proto2.clearElementaryStreamInfo = function clearElementaryStreamInfo() { 16841 var elementaryStreams = this.elementaryStreams; 16842 elementaryStreams[ElementaryStreamTypes.AUDIO] = null; 16843 elementaryStreams[ElementaryStreamTypes.VIDEO] = null; 16844 elementaryStreams[ElementaryStreamTypes.AUDIOVIDEO] = null; 16845 }; 16846 _createClass(Fragment, [{ 16847 key: "decryptdata", 16848 get: function get() { 16849 var levelkeys = this.levelkeys; 16850 if (!levelkeys && !this._decryptdata) { 16851 return null; 16852 } 16853 if (!this._decryptdata && this.levelkeys && !this.levelkeys.NONE) { 16854 var _key2 = this.levelkeys.identity; 16855 if (_key2) { 16856 this._decryptdata = _key2.getDecryptData(this.sn); 16857 } else { 16858 var keyFormats = Object.keys(this.levelkeys); 16859 if (keyFormats.length === 1) { 16860 return this._decryptdata = this.levelkeys[keyFormats[0]].getDecryptData(this.sn); 16861 } else { 16862 // Multiple keys. key-loader to call Fragment.setKeyFormat based on selected key-system. 16863 } 16864 } 16865 } 16866 return this._decryptdata; 16867 } 16868 }, { 16869 key: "end", 16870 get: function get() { 16871 return this.start + this.duration; 16872 } 16873 }, { 16874 key: "endProgramDateTime", 16875 get: function get() { 16876 if (this.programDateTime === null) { 16877 return null; 16878 } 16879 if (!(0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(this.programDateTime)) { 16880 return null; 16881 } 16882 var duration = !(0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(this.duration) ? 0 : this.duration; 16883 return this.programDateTime + duration * 1000; 16884 } 16885 }, { 16886 key: "encrypted", 16887 get: function get() { 16888 var _this$_decryptdata; 16889 // At the m3u8-parser level we need to add support for manifest signalled keyformats 16890 // when we want the fragment to start reporting that it is encrypted. 16891 // Currently, keyFormat will only be set for identity keys 16892 if ((_this$_decryptdata = this._decryptdata) !== null && _this$_decryptdata !== void 0 && _this$_decryptdata.encrypted) { 16893 return true; 16894 } else if (this.levelkeys) { 16895 var keyFormats = Object.keys(this.levelkeys); 16896 var len = keyFormats.length; 16897 if (len > 1 || len === 1 && this.levelkeys[keyFormats[0]].encrypted) { 16898 return true; 16899 } 16900 } 16901 return false; 16902 } 16903 }]); 16904 return Fragment; 16905}(BaseSegment); 16906var Part = /*#__PURE__*/function (_BaseSegment2) { 16907 _inheritsLoose(Part, _BaseSegment2); 16908 function Part(partAttrs, frag, baseurl, index, previous) { 16909 var _this2; 16910 _this2 = _BaseSegment2.call(this, baseurl) || this; 16911 _this2.fragOffset = 0; 16912 _this2.duration = 0; 16913 _this2.gap = false; 16914 _this2.independent = false; 16915 _this2.relurl = void 0; 16916 _this2.fragment = void 0; 16917 _this2.index = void 0; 16918 _this2.stats = new _load_stats__WEBPACK_IMPORTED_MODULE_2__.LoadStats(); 16919 _this2.duration = partAttrs.decimalFloatingPoint('DURATION'); 16920 _this2.gap = partAttrs.bool('GAP'); 16921 _this2.independent = partAttrs.bool('INDEPENDENT'); 16922 _this2.relurl = partAttrs.enumeratedString('URI'); 16923 _this2.fragment = frag; 16924 _this2.index = index; 16925 var byteRange = partAttrs.enumeratedString('BYTERANGE'); 16926 if (byteRange) { 16927 _this2.setByteRange(byteRange, previous); 16928 } 16929 if (previous) { 16930 _this2.fragOffset = previous.fragOffset + previous.duration; 16931 } 16932 return _this2; 16933 } 16934 _createClass(Part, [{ 16935 key: "start", 16936 get: function get() { 16937 return this.fragment.start + this.fragOffset; 16938 } 16939 }, { 16940 key: "end", 16941 get: function get() { 16942 return this.start + this.duration; 16943 } 16944 }, { 16945 key: "loaded", 16946 get: function get() { 16947 var elementaryStreams = this.elementaryStreams; 16948 return !!(elementaryStreams.audio || elementaryStreams.video || elementaryStreams.audiovideo); 16949 } 16950 }]); 16951 return Part; 16952}(BaseSegment); 16953 16954/***/ }), 16955 16956/***/ "./src/loader/key-loader.ts": 16957/*!**********************************!*\ 16958 !*** ./src/loader/key-loader.ts ***! 16959 \**********************************/ 16960/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 16961 16962"use strict"; 16963__webpack_require__.r(__webpack_exports__); 16964/* harmony export */ __webpack_require__.d(__webpack_exports__, { 16965/* harmony export */ "default": () => (/* binding */ KeyLoader) 16966/* harmony export */ }); 16967/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../errors */ "./src/errors.ts"); 16968/* harmony import */ var _fragment_loader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./fragment-loader */ "./src/loader/fragment-loader.ts"); 16969 16970 16971var KeyLoader = /*#__PURE__*/function () { 16972 function KeyLoader(config) { 16973 this.config = void 0; 16974 this.keyUriToKeyInfo = {}; 16975 this.emeController = null; 16976 this.config = config; 16977 } 16978 var _proto = KeyLoader.prototype; 16979 _proto.abort = function abort() { 16980 for (var uri in this.keyUriToKeyInfo) { 16981 var loader = this.keyUriToKeyInfo[uri].loader; 16982 if (loader) { 16983 loader.abort(); 16984 } 16985 } 16986 }; 16987 _proto.detach = function detach() { 16988 for (var uri in this.keyUriToKeyInfo) { 16989 var keyInfo = this.keyUriToKeyInfo[uri]; 16990 // Remove cached EME keys on detach 16991 if (keyInfo.mediaKeySessionContext || keyInfo.decryptdata.isCommonEncryption) { 16992 delete this.keyUriToKeyInfo[uri]; 16993 } 16994 } 16995 }; 16996 _proto.destroy = function destroy() { 16997 this.detach(); 16998 for (var uri in this.keyUriToKeyInfo) { 16999 var loader = this.keyUriToKeyInfo[uri].loader; 17000 if (loader) { 17001 loader.destroy(); 17002 } 17003 } 17004 this.keyUriToKeyInfo = {}; 17005 }; 17006 _proto.createKeyLoadError = function createKeyLoadError(frag, details, networkDetails, message) { 17007 if (details === void 0) { 17008 details = _errors__WEBPACK_IMPORTED_MODULE_0__.ErrorDetails.KEY_LOAD_ERROR; 17009 } 17010 return new _fragment_loader__WEBPACK_IMPORTED_MODULE_1__.LoadError({ 17011 type: _errors__WEBPACK_IMPORTED_MODULE_0__.ErrorTypes.NETWORK_ERROR, 17012 details: details, 17013 fatal: false, 17014 frag: frag, 17015 networkDetails: networkDetails 17016 }); 17017 }; 17018 _proto.loadClear = function loadClear(loadingFrag, encryptedFragments) { 17019 var _this = this; 17020 if (this.emeController && this.config.emeEnabled) { 17021 // access key-system with nearest key on start (loaidng frag is unencrypted) 17022 var sn = loadingFrag.sn, 17023 cc = loadingFrag.cc; 17024 var _loop = function _loop(i) { 17025 var frag = encryptedFragments[i]; 17026 if (cc <= frag.cc && (sn === 'initSegment' || sn < frag.sn)) { 17027 _this.emeController.selectKeySystemFormat(frag).then(function (keySystemFormat) { 17028 frag.setKeyFormat(keySystemFormat); 17029 }); 17030 return "break"; 17031 } 17032 }; 17033 for (var i = 0; i < encryptedFragments.length; i++) { 17034 var _ret = _loop(i); 17035 if (_ret === "break") break; 17036 } 17037 } 17038 }; 17039 _proto.load = function load(frag) { 17040 var _this2 = this; 17041 if (!frag.decryptdata && frag.encrypted && this.emeController) { 17042 // Multiple keys, but none selected, resolve in eme-controller 17043 return this.emeController.selectKeySystemFormat(frag).then(function (keySystemFormat) { 17044 return _this2.loadInternal(frag, keySystemFormat); 17045 }); 17046 } 17047 return this.loadInternal(frag); 17048 }; 17049 _proto.loadInternal = function loadInternal(frag, keySystemFormat) { 17050 var _keyInfo, _keyInfo2; 17051 if (keySystemFormat) { 17052 frag.setKeyFormat(keySystemFormat); 17053 } 17054 var decryptdata = frag.decryptdata; 17055 if (!decryptdata) { 17056 var errorMessage = keySystemFormat ? "Expected frag.decryptdata to be defined after setting format " + keySystemFormat : 'Missing decryption data on fragment in onKeyLoading'; 17057 return Promise.reject(this.createKeyLoadError(frag, _errors__WEBPACK_IMPORTED_MODULE_0__.ErrorDetails.KEY_LOAD_ERROR, null, errorMessage)); 17058 } 17059 var uri = decryptdata.uri; 17060 if (!uri) { 17061 return Promise.reject(this.createKeyLoadError(frag, _errors__WEBPACK_IMPORTED_MODULE_0__.ErrorDetails.KEY_LOAD_ERROR, null, "Invalid key URI: \"" + uri + "\"")); 17062 } 17063 var keyInfo = this.keyUriToKeyInfo[uri]; 17064 if ((_keyInfo = keyInfo) !== null && _keyInfo !== void 0 && _keyInfo.decryptdata.key) { 17065 decryptdata.key = keyInfo.decryptdata.key; 17066 return Promise.resolve({ 17067 frag: frag, 17068 keyInfo: keyInfo 17069 }); 17070 } 17071 // Return key load promise as long as it does not have a mediakey session with an unusable key status 17072 if ((_keyInfo2 = keyInfo) !== null && _keyInfo2 !== void 0 && _keyInfo2.keyLoadPromise) { 17073 var _keyInfo$mediaKeySess; 17074 switch ((_keyInfo$mediaKeySess = keyInfo.mediaKeySessionContext) === null || _keyInfo$mediaKeySess === void 0 ? void 0 : _keyInfo$mediaKeySess.keyStatus) { 17075 case undefined: 17076 case 'status-pending': 17077 case 'usable': 17078 case 'usable-in-future': 17079 return keyInfo.keyLoadPromise; 17080 } 17081 // If we have a key session and status and it is not pending or usable, continue 17082 // This will go back to the eme-controller for expired keys to get a new keyLoadPromise 17083 } 17084 17085 // Load the key or return the loading promise 17086 keyInfo = this.keyUriToKeyInfo[uri] = { 17087 decryptdata: decryptdata, 17088 keyLoadPromise: null, 17089 loader: null, 17090 mediaKeySessionContext: null 17091 }; 17092 switch (decryptdata.method) { 17093 case 'ISO-23001-7': 17094 case 'SAMPLE-AES': 17095 case 'SAMPLE-AES-CENC': 17096 case 'SAMPLE-AES-CTR': 17097 if (decryptdata.keyFormat === 'identity') { 17098 // loadKeyHTTP handles http(s) and data URLs 17099 return this.loadKeyHTTP(keyInfo, frag); 17100 } 17101 return this.loadKeyEME(keyInfo, frag); 17102 case 'AES-128': 17103 return this.loadKeyHTTP(keyInfo, frag); 17104 default: 17105 return Promise.reject(this.createKeyLoadError(frag, _errors__WEBPACK_IMPORTED_MODULE_0__.ErrorDetails.KEY_LOAD_ERROR, null, "Key supplied with unsupported METHOD: \"" + decryptdata.method + "\"")); 17106 } 17107 }; 17108 _proto.loadKeyEME = function loadKeyEME(keyInfo, frag) { 17109 var keyLoadedData = { 17110 frag: frag, 17111 keyInfo: keyInfo 17112 }; 17113 if (this.emeController && this.config.emeEnabled) { 17114 var keySessionContextPromise = this.emeController.loadKey(keyLoadedData); 17115 if (keySessionContextPromise) { 17116 return (keyInfo.keyLoadPromise = keySessionContextPromise.then(function (keySessionContext) { 17117 keyInfo.mediaKeySessionContext = keySessionContext; 17118 return keyLoadedData; 17119 })).catch(function (error) { 17120 // Remove promise for license renewal or retry 17121 keyInfo.keyLoadPromise = null; 17122 throw error; 17123 }); 17124 } 17125 } 17126 return Promise.resolve(keyLoadedData); 17127 }; 17128 _proto.loadKeyHTTP = function loadKeyHTTP(keyInfo, frag) { 17129 var _this3 = this; 17130 var config = this.config; 17131 var Loader = config.loader; 17132 var keyLoader = new Loader(config); 17133 frag.keyLoader = keyInfo.loader = keyLoader; 17134 return keyInfo.keyLoadPromise = new Promise(function (resolve, reject) { 17135 var loaderContext = { 17136 keyInfo: keyInfo, 17137 frag: frag, 17138 responseType: 'arraybuffer', 17139 url: keyInfo.decryptdata.uri 17140 }; 17141 17142 // maxRetry is 0 so that instead of retrying the same key on the same variant multiple times, 17143 // key-loader will trigger an error and rely on stream-controller to handle retry logic. 17144 // this will also align retry logic with fragment-loader 17145 var loaderConfig = { 17146 timeout: config.fragLoadingTimeOut, 17147 maxRetry: 0, 17148 retryDelay: config.fragLoadingRetryDelay, 17149 maxRetryDelay: config.fragLoadingMaxRetryTimeout, 17150 highWaterMark: 0 17151 }; 17152 var loaderCallbacks = { 17153 onSuccess: function onSuccess(response, stats, context, networkDetails) { 17154 var frag = context.frag, 17155 keyInfo = context.keyInfo, 17156 uri = context.url; 17157 if (!frag.decryptdata || keyInfo !== _this3.keyUriToKeyInfo[uri]) { 17158 return reject(_this3.createKeyLoadError(frag, _errors__WEBPACK_IMPORTED_MODULE_0__.ErrorDetails.KEY_LOAD_ERROR, networkDetails, 'after key load, decryptdata unset or changed')); 17159 } 17160 keyInfo.decryptdata.key = frag.decryptdata.key = new Uint8Array(response.data); 17161 17162 // detach fragment key loader on load success 17163 frag.keyLoader = null; 17164 keyInfo.loader = null; 17165 resolve({ 17166 frag: frag, 17167 keyInfo: keyInfo 17168 }); 17169 }, 17170 onError: function onError(error, context, networkDetails) { 17171 _this3.resetLoader(context); 17172 reject(_this3.createKeyLoadError(frag, _errors__WEBPACK_IMPORTED_MODULE_0__.ErrorDetails.KEY_LOAD_ERROR, networkDetails)); 17173 }, 17174 onTimeout: function onTimeout(stats, context, networkDetails) { 17175 _this3.resetLoader(context); 17176 reject(_this3.createKeyLoadError(frag, _errors__WEBPACK_IMPORTED_MODULE_0__.ErrorDetails.KEY_LOAD_TIMEOUT, networkDetails)); 17177 }, 17178 onAbort: function onAbort(stats, context, networkDetails) { 17179 _this3.resetLoader(context); 17180 reject(_this3.createKeyLoadError(frag, _errors__WEBPACK_IMPORTED_MODULE_0__.ErrorDetails.INTERNAL_ABORTED, networkDetails)); 17181 } 17182 }; 17183 keyLoader.load(loaderContext, loaderConfig, loaderCallbacks); 17184 }); 17185 }; 17186 _proto.resetLoader = function resetLoader(context) { 17187 var frag = context.frag, 17188 keyInfo = context.keyInfo, 17189 uri = context.url; 17190 var loader = keyInfo.loader; 17191 if (frag.keyLoader === loader) { 17192 frag.keyLoader = null; 17193 keyInfo.loader = null; 17194 } 17195 delete this.keyUriToKeyInfo[uri]; 17196 if (loader) { 17197 loader.destroy(); 17198 } 17199 }; 17200 return KeyLoader; 17201}(); 17202 17203 17204/***/ }), 17205 17206/***/ "./src/loader/level-details.ts": 17207/*!*************************************!*\ 17208 !*** ./src/loader/level-details.ts ***! 17209 \*************************************/ 17210/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 17211 17212"use strict"; 17213__webpack_require__.r(__webpack_exports__); 17214/* harmony export */ __webpack_require__.d(__webpack_exports__, { 17215/* harmony export */ "LevelDetails": () => (/* binding */ LevelDetails) 17216/* harmony export */ }); 17217/* harmony import */ var _home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.ts"); 17218 17219function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } 17220function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } 17221function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } 17222function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } 17223var DEFAULT_TARGET_DURATION = 10; 17224var LevelDetails = /*#__PURE__*/function () { 17225 // Manifest reload synchronization 17226 17227 function LevelDetails(baseUrl) { 17228 this.PTSKnown = false; 17229 this.alignedSliding = false; 17230 this.averagetargetduration = void 0; 17231 this.endCC = 0; 17232 this.endSN = 0; 17233 this.fragments = void 0; 17234 this.fragmentHint = void 0; 17235 this.partList = null; 17236 this.dateRanges = void 0; 17237 this.live = true; 17238 this.ageHeader = 0; 17239 this.advancedDateTime = void 0; 17240 this.updated = true; 17241 this.advanced = true; 17242 this.availabilityDelay = void 0; 17243 this.misses = 0; 17244 this.startCC = 0; 17245 this.startSN = 0; 17246 this.startTimeOffset = null; 17247 this.targetduration = 0; 17248 this.totalduration = 0; 17249 this.type = null; 17250 this.url = void 0; 17251 this.m3u8 = ''; 17252 this.version = null; 17253 this.canBlockReload = false; 17254 this.canSkipUntil = 0; 17255 this.canSkipDateRanges = false; 17256 this.skippedSegments = 0; 17257 this.recentlyRemovedDateranges = void 0; 17258 this.partHoldBack = 0; 17259 this.holdBack = 0; 17260 this.partTarget = 0; 17261 this.preloadHint = void 0; 17262 this.renditionReports = void 0; 17263 this.tuneInGoal = 0; 17264 this.deltaUpdateFailed = void 0; 17265 this.driftStartTime = 0; 17266 this.driftEndTime = 0; 17267 this.driftStart = 0; 17268 this.driftEnd = 0; 17269 this.encryptedFragments = void 0; 17270 this.fragments = []; 17271 this.encryptedFragments = []; 17272 this.dateRanges = {}; 17273 this.url = baseUrl; 17274 } 17275 var _proto = LevelDetails.prototype; 17276 _proto.reloaded = function reloaded(previous) { 17277 if (!previous) { 17278 this.advanced = true; 17279 this.updated = true; 17280 return; 17281 } 17282 var partSnDiff = this.lastPartSn - previous.lastPartSn; 17283 var partIndexDiff = this.lastPartIndex - previous.lastPartIndex; 17284 this.updated = this.endSN !== previous.endSN || !!partIndexDiff || !!partSnDiff; 17285 this.advanced = this.endSN > previous.endSN || partSnDiff > 0 || partSnDiff === 0 && partIndexDiff > 0; 17286 if (this.updated || this.advanced) { 17287 this.misses = Math.floor(previous.misses * 0.6); 17288 } else { 17289 this.misses = previous.misses + 1; 17290 } 17291 this.availabilityDelay = previous.availabilityDelay; 17292 }; 17293 _createClass(LevelDetails, [{ 17294 key: "hasProgramDateTime", 17295 get: function get() { 17296 if (this.fragments.length) { 17297 return (0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(this.fragments[this.fragments.length - 1].programDateTime); 17298 } 17299 return false; 17300 } 17301 }, { 17302 key: "levelTargetDuration", 17303 get: function get() { 17304 return this.averagetargetduration || this.targetduration || DEFAULT_TARGET_DURATION; 17305 } 17306 }, { 17307 key: "drift", 17308 get: function get() { 17309 var runTime = this.driftEndTime - this.driftStartTime; 17310 if (runTime > 0) { 17311 var runDuration = this.driftEnd - this.driftStart; 17312 return runDuration * 1000 / runTime; 17313 } 17314 return 1; 17315 } 17316 }, { 17317 key: "edge", 17318 get: function get() { 17319 return this.partEnd || this.fragmentEnd; 17320 } 17321 }, { 17322 key: "partEnd", 17323 get: function get() { 17324 var _this$partList; 17325 if ((_this$partList = this.partList) !== null && _this$partList !== void 0 && _this$partList.length) { 17326 return this.partList[this.partList.length - 1].end; 17327 } 17328 return this.fragmentEnd; 17329 } 17330 }, { 17331 key: "fragmentEnd", 17332 get: function get() { 17333 var _this$fragments; 17334 if ((_this$fragments = this.fragments) !== null && _this$fragments !== void 0 && _this$fragments.length) { 17335 return this.fragments[this.fragments.length - 1].end; 17336 } 17337 return 0; 17338 } 17339 }, { 17340 key: "age", 17341 get: function get() { 17342 if (this.advancedDateTime) { 17343 return Math.max(Date.now() - this.advancedDateTime, 0) / 1000; 17344 } 17345 return 0; 17346 } 17347 }, { 17348 key: "lastPartIndex", 17349 get: function get() { 17350 var _this$partList2; 17351 if ((_this$partList2 = this.partList) !== null && _this$partList2 !== void 0 && _this$partList2.length) { 17352 return this.partList[this.partList.length - 1].index; 17353 } 17354 return -1; 17355 } 17356 }, { 17357 key: "lastPartSn", 17358 get: function get() { 17359 var _this$partList3; 17360 if ((_this$partList3 = this.partList) !== null && _this$partList3 !== void 0 && _this$partList3.length) { 17361 return this.partList[this.partList.length - 1].fragment.sn; 17362 } 17363 return this.endSN; 17364 } 17365 }]); 17366 return LevelDetails; 17367}(); 17368 17369/***/ }), 17370 17371/***/ "./src/loader/level-key.ts": 17372/*!*********************************!*\ 17373 !*** ./src/loader/level-key.ts ***! 17374 \*********************************/ 17375/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 17376 17377"use strict"; 17378__webpack_require__.r(__webpack_exports__); 17379/* harmony export */ __webpack_require__.d(__webpack_exports__, { 17380/* harmony export */ "LevelKey": () => (/* binding */ LevelKey) 17381/* harmony export */ }); 17382/* harmony import */ var _utils_keysystem_util__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils/keysystem-util */ "./src/utils/keysystem-util.ts"); 17383/* harmony import */ var _utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils/mediakeys-helper */ "./src/utils/mediakeys-helper.ts"); 17384/* harmony import */ var _utils_mp4_tools__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils/mp4-tools */ "./src/utils/mp4-tools.ts"); 17385/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 17386/* harmony import */ var _utils_numeric_encoding_utils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../utils/numeric-encoding-utils */ "./src/utils/numeric-encoding-utils.ts"); 17387 17388 17389 17390 17391 17392var keyUriToKeyIdMap = {}; 17393var LevelKey = /*#__PURE__*/function () { 17394 LevelKey.clearKeyUriToKeyIdMap = function clearKeyUriToKeyIdMap() { 17395 keyUriToKeyIdMap = {}; 17396 }; 17397 function LevelKey(method, uri, format, formatversions, iv) { 17398 if (formatversions === void 0) { 17399 formatversions = [1]; 17400 } 17401 if (iv === void 0) { 17402 iv = null; 17403 } 17404 this.uri = void 0; 17405 this.method = void 0; 17406 this.keyFormat = void 0; 17407 this.keyFormatVersions = void 0; 17408 this.encrypted = void 0; 17409 this.isCommonEncryption = void 0; 17410 this.iv = null; 17411 this.key = null; 17412 this.keyId = null; 17413 this.pssh = null; 17414 this.method = method; 17415 this.uri = uri; 17416 this.keyFormat = format; 17417 this.keyFormatVersions = formatversions; 17418 this.iv = iv; 17419 this.encrypted = method ? method !== 'NONE' : false; 17420 this.isCommonEncryption = this.encrypted && method !== 'AES-128'; 17421 } 17422 var _proto = LevelKey.prototype; 17423 _proto.isSupported = function isSupported() { 17424 // If it's Segment encryption or No encryption, just select that key system 17425 if (this.method) { 17426 if (this.method === 'AES-128' || this.method === 'NONE') { 17427 return true; 17428 } 17429 switch (this.keyFormat) { 17430 case 'identity': 17431 // Maintain support for clear SAMPLE-AES with MPEG-3 TS 17432 return this.method === 'SAMPLE-AES'; 17433 case _utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_1__.KeySystemFormats.FAIRPLAY: 17434 case _utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_1__.KeySystemFormats.WIDEVINE: 17435 case _utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_1__.KeySystemFormats.PLAYREADY: 17436 case _utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_1__.KeySystemFormats.CLEARKEY: 17437 return ['ISO-23001-7', 'SAMPLE-AES', 'SAMPLE-AES-CENC', 'SAMPLE-AES-CTR'].indexOf(this.method) !== -1; 17438 } 17439 } 17440 return false; 17441 }; 17442 _proto.getDecryptData = function getDecryptData(sn) { 17443 if (!this.encrypted || !this.uri) { 17444 return null; 17445 } 17446 if (this.method === 'AES-128' && this.uri && !this.iv) { 17447 if (typeof sn !== 'number') { 17448 // We are fetching decryption data for a initialization segment 17449 // If the segment was encrypted with AES-128 17450 // It must have an IV defined. We cannot substitute the Segment Number in. 17451 if (this.method === 'AES-128' && !this.iv) { 17452 _utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger.warn("missing IV for initialization segment with method=\"" + this.method + "\" - compliance issue"); 17453 } 17454 // Explicitly set sn to resulting value from implicit conversions 'initSegment' values for IV generation. 17455 sn = 0; 17456 } 17457 var iv = createInitializationVector(sn); 17458 var decryptdata = new LevelKey(this.method, this.uri, 'identity', this.keyFormatVersions, iv); 17459 return decryptdata; 17460 } 17461 17462 // Initialize keyId if possible 17463 var keyBytes = (0,_utils_keysystem_util__WEBPACK_IMPORTED_MODULE_0__.convertDataUriToArrayBytes)(this.uri); 17464 if (keyBytes) { 17465 switch (this.keyFormat) { 17466 case _utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_1__.KeySystemFormats.WIDEVINE: 17467 this.pssh = keyBytes; 17468 // In case of widevine keyID is embedded in PSSH box. Read Key ID. 17469 if (keyBytes.length >= 22) { 17470 this.keyId = keyBytes.subarray(keyBytes.length - 22, keyBytes.length - 6); 17471 } 17472 break; 17473 case _utils_mediakeys_helper__WEBPACK_IMPORTED_MODULE_1__.KeySystemFormats.PLAYREADY: 17474 { 17475 var PlayReadyKeySystemUUID = new Uint8Array([0x9a, 0x04, 0xf0, 0x79, 0x98, 0x40, 0x42, 0x86, 0xab, 0x92, 0xe6, 0x5b, 0xe0, 0x88, 0x5f, 0x95]); 17476 this.pssh = (0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_2__.mp4pssh)(PlayReadyKeySystemUUID, null, keyBytes); 17477 var keyBytesUtf16 = new Uint16Array(keyBytes.buffer, keyBytes.byteOffset, keyBytes.byteLength / 2); 17478 var keyByteStr = String.fromCharCode.apply(null, Array.from(keyBytesUtf16)); 17479 17480 // Parse Playready WRMHeader XML 17481 var xmlKeyBytes = keyByteStr.substring(keyByteStr.indexOf('<'), keyByteStr.length); 17482 var parser = new DOMParser(); 17483 var xmlDoc = parser.parseFromString(xmlKeyBytes, 'text/xml'); 17484 var keyData = xmlDoc.getElementsByTagName('KID')[0]; 17485 if (keyData) { 17486 var keyId = keyData.childNodes[0] ? keyData.childNodes[0].nodeValue : keyData.getAttribute('VALUE'); 17487 if (keyId) { 17488 var keyIdArray = (0,_utils_numeric_encoding_utils__WEBPACK_IMPORTED_MODULE_4__.base64Decode)(keyId).subarray(0, 16); 17489 // KID value in PRO is a base64-encoded little endian GUID interpretation of UUID 17490 // KID value in ‘tenc’ is a big endian UUID GUID interpretation of UUID 17491 (0,_utils_keysystem_util__WEBPACK_IMPORTED_MODULE_0__.changeEndianness)(keyIdArray); 17492 this.keyId = keyIdArray; 17493 } 17494 } 17495 break; 17496 } 17497 default: 17498 { 17499 var keydata = keyBytes.subarray(0, 16); 17500 if (keydata.length !== 16) { 17501 var padded = new Uint8Array(16); 17502 padded.set(keydata, 16 - keydata.length); 17503 keydata = padded; 17504 } 17505 this.keyId = keydata; 17506 break; 17507 } 17508 } 17509 } 17510 17511 // Default behavior: assign a new keyId for each uri 17512 if (!this.keyId || this.keyId.byteLength !== 16) { 17513 var _keyId = keyUriToKeyIdMap[this.uri]; 17514 if (!_keyId) { 17515 var val = Object.keys(keyUriToKeyIdMap).length % Number.MAX_SAFE_INTEGER; 17516 _keyId = new Uint8Array(16); 17517 var dv = new DataView(_keyId.buffer, 12, 4); // Just set the last 4 bytes 17518 dv.setUint32(0, val); 17519 keyUriToKeyIdMap[this.uri] = _keyId; 17520 } 17521 this.keyId = _keyId; 17522 } 17523 return this; 17524 }; 17525 return LevelKey; 17526}(); 17527function createInitializationVector(segmentNumber) { 17528 var uint8View = new Uint8Array(16); 17529 for (var i = 12; i < 16; i++) { 17530 uint8View[i] = segmentNumber >> 8 * (15 - i) & 0xff; 17531 } 17532 return uint8View; 17533} 17534 17535/***/ }), 17536 17537/***/ "./src/loader/load-stats.ts": 17538/*!**********************************!*\ 17539 !*** ./src/loader/load-stats.ts ***! 17540 \**********************************/ 17541/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 17542 17543"use strict"; 17544__webpack_require__.r(__webpack_exports__); 17545/* harmony export */ __webpack_require__.d(__webpack_exports__, { 17546/* harmony export */ "LoadStats": () => (/* binding */ LoadStats) 17547/* harmony export */ }); 17548var LoadStats = function LoadStats() { 17549 this.aborted = false; 17550 this.loaded = 0; 17551 this.retry = 0; 17552 this.total = 0; 17553 this.chunkCount = 0; 17554 this.bwEstimate = 0; 17555 this.loading = { 17556 start: 0, 17557 first: 0, 17558 end: 0 17559 }; 17560 this.parsing = { 17561 start: 0, 17562 end: 0 17563 }; 17564 this.buffering = { 17565 start: 0, 17566 first: 0, 17567 end: 0 17568 }; 17569}; 17570 17571/***/ }), 17572 17573/***/ "./src/loader/m3u8-parser.ts": 17574/*!***********************************!*\ 17575 !*** ./src/loader/m3u8-parser.ts ***! 17576 \***********************************/ 17577/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 17578 17579"use strict"; 17580__webpack_require__.r(__webpack_exports__); 17581/* harmony export */ __webpack_require__.d(__webpack_exports__, { 17582/* harmony export */ "default": () => (/* binding */ M3U8Parser) 17583/* harmony export */ }); 17584/* harmony import */ var _home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.ts"); 17585/* harmony import */ var url_toolkit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! url-toolkit */ "./node_modules/url-toolkit/src/url-toolkit.js"); 17586/* harmony import */ var url_toolkit__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(url_toolkit__WEBPACK_IMPORTED_MODULE_1__); 17587/* harmony import */ var _date_range__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./date-range */ "./src/loader/date-range.ts"); 17588/* harmony import */ var _fragment__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./fragment */ "./src/loader/fragment.ts"); 17589/* harmony import */ var _level_details__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./level-details */ "./src/loader/level-details.ts"); 17590/* harmony import */ var _level_key__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./level-key */ "./src/loader/level-key.ts"); 17591/* harmony import */ var _utils_attr_list__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../utils/attr-list */ "./src/utils/attr-list.ts"); 17592/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 17593/* harmony import */ var _utils_codecs__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../utils/codecs */ "./src/utils/codecs.ts"); 17594 17595 17596 17597 17598function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } 17599 17600 17601 17602 17603 17604 17605 17606 17607// https://regex101.com is your friend 17608var MASTER_PLAYLIST_REGEX = /#EXT-X-STREAM-INF:([^\r\n]*)(?:[\r\n](?:#[^\r\n]*)?)*([^\r\n]+)|#EXT-X-SESSION-DATA:([^\r\n]*)[\r\n]+|#EXT-X-SESSION-KEY:([^\n\r]*)[\r\n]+/g; 17609var MASTER_PLAYLIST_MEDIA_REGEX = /#EXT-X-MEDIA:(.*)/g; 17610var LEVEL_PLAYLIST_REGEX_FAST = new RegExp([/#EXTINF:\s*(\d*(?:\.\d+)?)(?:,(.*)\s+)?/.source, 17611// duration (#EXTINF:<duration>,<title>), group 1 => duration, group 2 => title 17612/(?!#) *(\S[\S ]*)/.source, 17613// segment URI, group 3 => the URI (note newline is not eaten) 17614/#EXT-X-BYTERANGE:*(.+)/.source, 17615// next segment's byterange, group 4 => range spec (x@y) 17616/#EXT-X-PROGRAM-DATE-TIME:(.+)/.source, 17617// next segment's program date/time group 5 => the datetime spec 17618/#.*/.source // All other non-segment oriented tags will match with all groups empty 17619].join('|'), 'g'); 17620var LEVEL_PLAYLIST_REGEX_SLOW = new RegExp([/#(EXTM3U)/.source, /#EXT-X-(DATERANGE|KEY|MAP|PART|PART-INF|PLAYLIST-TYPE|PRELOAD-HINT|RENDITION-REPORT|SERVER-CONTROL|SKIP|START):(.+)/.source, /#EXT-X-(BITRATE|DISCONTINUITY-SEQUENCE|MEDIA-SEQUENCE|TARGETDURATION|VERSION): *(\d+)/.source, /#EXT-X-(DISCONTINUITY|ENDLIST|GAP)/.source, /(#)([^:]*):(.*)/.source, /(#)(.*)(?:.*)\r?\n?/.source].join('|')); 17621var M3U8Parser = /*#__PURE__*/function () { 17622 function M3U8Parser() {} 17623 M3U8Parser.findGroup = function findGroup(groups, mediaGroupId) { 17624 for (var i = 0; i < groups.length; i++) { 17625 var group = groups[i]; 17626 if (group.id === mediaGroupId) { 17627 return group; 17628 } 17629 } 17630 }; 17631 M3U8Parser.convertAVC1ToAVCOTI = function convertAVC1ToAVCOTI(codec) { 17632 // Convert avc1 codec string from RFC-4281 to RFC-6381 for MediaSource.isTypeSupported 17633 var avcdata = codec.split('.'); 17634 if (avcdata.length > 2) { 17635 var result = avcdata.shift() + '.'; 17636 result += parseInt(avcdata.shift()).toString(16); 17637 result += ('000' + parseInt(avcdata.shift()).toString(16)).slice(-4); 17638 return result; 17639 } 17640 return codec; 17641 }; 17642 M3U8Parser.resolve = function resolve(url, baseUrl) { 17643 return (0,url_toolkit__WEBPACK_IMPORTED_MODULE_1__.buildAbsoluteURL)(baseUrl, url, { 17644 alwaysNormalize: true 17645 }); 17646 }; 17647 M3U8Parser.parseMasterPlaylist = function parseMasterPlaylist(string, baseurl) { 17648 var levels = []; 17649 var levelsWithKnownCodecs = []; 17650 var sessionData = {}; 17651 var sessionKeys = []; 17652 var hasSessionData = false; 17653 MASTER_PLAYLIST_REGEX.lastIndex = 0; 17654 var result; 17655 while ((result = MASTER_PLAYLIST_REGEX.exec(string)) != null) { 17656 if (result[1]) { 17657 var _level$unknownCodecs; 17658 // '#EXT-X-STREAM-INF' is found, parse level tag in group 1 17659 var attrs = new _utils_attr_list__WEBPACK_IMPORTED_MODULE_6__.AttrList(result[1]); 17660 var level = { 17661 attrs: attrs, 17662 bitrate: attrs.decimalInteger('AVERAGE-BANDWIDTH') || attrs.decimalInteger('BANDWIDTH'), 17663 name: attrs.NAME, 17664 url: M3U8Parser.resolve(result[2], baseurl) 17665 }; 17666 var resolution = attrs.decimalResolution('RESOLUTION'); 17667 if (resolution) { 17668 level.width = resolution.width; 17669 level.height = resolution.height; 17670 } 17671 setCodecs((attrs.CODECS || '').split(/[ ,]+/).filter(function (c) { 17672 return c; 17673 }), level); 17674 if (level.videoCodec && level.videoCodec.indexOf('avc1') !== -1) { 17675 level.videoCodec = M3U8Parser.convertAVC1ToAVCOTI(level.videoCodec); 17676 } 17677 if (!((_level$unknownCodecs = level.unknownCodecs) !== null && _level$unknownCodecs !== void 0 && _level$unknownCodecs.length)) { 17678 levelsWithKnownCodecs.push(level); 17679 } 17680 levels.push(level); 17681 } else if (result[3]) { 17682 // '#EXT-X-SESSION-DATA' is found, parse session data in group 3 17683 var sessionAttrs = new _utils_attr_list__WEBPACK_IMPORTED_MODULE_6__.AttrList(result[3]); 17684 if (sessionAttrs['DATA-ID']) { 17685 hasSessionData = true; 17686 sessionData[sessionAttrs['DATA-ID']] = sessionAttrs; 17687 } 17688 } else if (result[4]) { 17689 // '#EXT-X-SESSION-KEY' is found 17690 var keyTag = result[4]; 17691 var sessionKey = parseKey(keyTag, baseurl); 17692 if (sessionKey.encrypted && sessionKey.isSupported()) { 17693 sessionKeys.push(sessionKey); 17694 } else { 17695 _utils_logger__WEBPACK_IMPORTED_MODULE_7__.logger.warn("[Keys] Ignoring invalid EXT-X-SESSION-KEY tag: \"" + keyTag + "\""); 17696 } 17697 } 17698 } 17699 // Filter out levels with unknown codecs if it does not remove all levels 17700 var stripUnknownCodecLevels = levelsWithKnownCodecs.length > 0 && levelsWithKnownCodecs.length < levels.length; 17701 return { 17702 levels: stripUnknownCodecLevels ? levelsWithKnownCodecs : levels, 17703 sessionData: hasSessionData ? sessionData : null, 17704 sessionKeys: sessionKeys.length ? sessionKeys : null 17705 }; 17706 }; 17707 M3U8Parser.parseMasterPlaylistMedia = function parseMasterPlaylistMedia(string, baseurl, type, groups) { 17708 if (groups === void 0) { 17709 groups = []; 17710 } 17711 var result; 17712 var medias = []; 17713 var id = 0; 17714 MASTER_PLAYLIST_MEDIA_REGEX.lastIndex = 0; 17715 while ((result = MASTER_PLAYLIST_MEDIA_REGEX.exec(string)) !== null) { 17716 var attrs = new _utils_attr_list__WEBPACK_IMPORTED_MODULE_6__.AttrList(result[1]); 17717 if (attrs.TYPE === type) { 17718 var media = { 17719 attrs: attrs, 17720 bitrate: 0, 17721 id: id++, 17722 groupId: attrs['GROUP-ID'], 17723 instreamId: attrs['INSTREAM-ID'], 17724 name: attrs.NAME || attrs.LANGUAGE || '', 17725 type: type, 17726 default: attrs.bool('DEFAULT'), 17727 autoselect: attrs.bool('AUTOSELECT'), 17728 forced: attrs.bool('FORCED'), 17729 lang: attrs.LANGUAGE, 17730 url: attrs.URI ? M3U8Parser.resolve(attrs.URI, baseurl) : '' 17731 }; 17732 if (groups.length) { 17733 // If there are audio or text groups signalled in the manifest, let's look for a matching codec string for this track 17734 // If we don't find the track signalled, lets use the first audio groups codec we have 17735 // Acting as a best guess 17736 var groupCodec = M3U8Parser.findGroup(groups, media.groupId) || groups[0]; 17737 assignCodec(media, groupCodec, 'audioCodec'); 17738 assignCodec(media, groupCodec, 'textCodec'); 17739 } 17740 medias.push(media); 17741 } 17742 } 17743 return medias; 17744 }; 17745 M3U8Parser.parseLevelPlaylist = function parseLevelPlaylist(string, baseurl, id, type, levelUrlId) { 17746 var level = new _level_details__WEBPACK_IMPORTED_MODULE_4__.LevelDetails(baseurl); 17747 var fragments = level.fragments; 17748 // The most recent init segment seen (applies to all subsequent segments) 17749 var currentInitSegment = null; 17750 var currentSN = 0; 17751 var currentPart = 0; 17752 var totalduration = 0; 17753 var discontinuityCounter = 0; 17754 var prevFrag = null; 17755 var frag = new _fragment__WEBPACK_IMPORTED_MODULE_3__.Fragment(type, baseurl); 17756 var result; 17757 var i; 17758 var levelkeys; 17759 var firstPdtIndex = -1; 17760 var createNextFrag = false; 17761 LEVEL_PLAYLIST_REGEX_FAST.lastIndex = 0; 17762 level.m3u8 = string; 17763 while ((result = LEVEL_PLAYLIST_REGEX_FAST.exec(string)) !== null) { 17764 if (createNextFrag) { 17765 createNextFrag = false; 17766 frag = new _fragment__WEBPACK_IMPORTED_MODULE_3__.Fragment(type, baseurl); 17767 // setup the next fragment for part loading 17768 frag.start = totalduration; 17769 frag.sn = currentSN; 17770 frag.cc = discontinuityCounter; 17771 frag.level = id; 17772 if (currentInitSegment) { 17773 frag.initSegment = currentInitSegment; 17774 frag.rawProgramDateTime = currentInitSegment.rawProgramDateTime; 17775 currentInitSegment.rawProgramDateTime = null; 17776 } 17777 } 17778 var duration = result[1]; 17779 if (duration) { 17780 // INF 17781 frag.duration = parseFloat(duration); 17782 // avoid sliced strings https://github.com/video-dev/hls.js/issues/939 17783 var title = (' ' + result[2]).slice(1); 17784 frag.title = title || null; 17785 frag.tagList.push(title ? ['INF', duration, title] : ['INF', duration]); 17786 } else if (result[3]) { 17787 // url 17788 if ((0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(frag.duration)) { 17789 frag.start = totalduration; 17790 if (levelkeys) { 17791
vendor: 14,754 bytes, lines 17791-18141
17791frag.levelkeys = levelkeys; 17792 var encryptedFragments = level.encryptedFragments; 17793 if (frag.levelkeys && Object.keys(frag.levelkeys).some(function (format) { 17794 return frag.levelkeys[format].isCommonEncryption; 17795 }) && (!encryptedFragments.length || encryptedFragments[encryptedFragments.length - 1].levelkeys !== levelkeys)) { 17796 encryptedFragments.push(frag); 17797 } 17798 } 17799 frag.sn = currentSN; 17800 frag.level = id; 17801 frag.cc = discontinuityCounter; 17802 frag.urlId = levelUrlId; 17803 fragments.push(frag); 17804 // avoid sliced strings https://github.com/video-dev/hls.js/issues/939 17805 frag.relurl = (' ' + result[3]).slice(1); 17806 assignProgramDateTime(frag, prevFrag); 17807 prevFrag = frag; 17808 totalduration += frag.duration; 17809 currentSN++; 17810 currentPart = 0; 17811 createNextFrag = true; 17812 } 17813 } else if (result[4]) { 17814 // X-BYTERANGE 17815 var data = (' ' + result[4]).slice(1); 17816 if (prevFrag) { 17817 frag.setByteRange(data, prevFrag); 17818 } else { 17819 frag.setByteRange(data); 17820 } 17821 } else if (result[5]) { 17822 // PROGRAM-DATE-TIME 17823 // avoid sliced strings https://github.com/video-dev/hls.js/issues/939 17824 frag.rawProgramDateTime = (' ' + result[5]).slice(1); 17825 frag.tagList.push(['PROGRAM-DATE-TIME', frag.rawProgramDateTime]); 17826 if (firstPdtIndex === -1) { 17827 firstPdtIndex = fragments.length; 17828 } 17829 } else { 17830 result = result[0].match(LEVEL_PLAYLIST_REGEX_SLOW); 17831 if (!result) { 17832 _utils_logger__WEBPACK_IMPORTED_MODULE_7__.logger.warn('No matches on slow regex match for level playlist!'); 17833 continue; 17834 } 17835 for (i = 1; i < result.length; i++) { 17836 if (typeof result[i] !== 'undefined') { 17837 break; 17838 } 17839 } 17840 17841 // avoid sliced strings https://github.com/video-dev/hls.js/issues/939 17842 var tag = (' ' + result[i]).slice(1); 17843 var value1 = (' ' + result[i + 1]).slice(1); 17844 var value2 = result[i + 2] ? (' ' + result[i + 2]).slice(1) : ''; 17845 switch (tag) { 17846 case 'PLAYLIST-TYPE': 17847 level.type = value1.toUpperCase(); 17848 break; 17849 case 'MEDIA-SEQUENCE': 17850 currentSN = level.startSN = parseInt(value1); 17851 break; 17852 case 'SKIP': 17853 { 17854 var skipAttrs = new _utils_attr_list__WEBPACK_IMPORTED_MODULE_6__.AttrList(value1); 17855 var skippedSegments = skipAttrs.decimalInteger('SKIPPED-SEGMENTS'); 17856 if ((0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(skippedSegments)) { 17857 level.skippedSegments = skippedSegments; 17858 // This will result in fragments[] containing undefined values, which we will fill in with `mergeDetails` 17859 for (var _i = skippedSegments; _i--;) { 17860 fragments.unshift(null); 17861 } 17862 currentSN += skippedSegments; 17863 } 17864 var recentlyRemovedDateranges = skipAttrs.enumeratedString('RECENTLY-REMOVED-DATERANGES'); 17865 if (recentlyRemovedDateranges) { 17866 level.recentlyRemovedDateranges = recentlyRemovedDateranges.split('\t'); 17867 } 17868 break; 17869 } 17870 case 'TARGETDURATION': 17871 level.targetduration = parseFloat(value1); 17872 break; 17873 case 'VERSION': 17874 level.version = parseInt(value1); 17875 break; 17876 case 'EXTM3U': 17877 break; 17878 case 'ENDLIST': 17879 level.live = false; 17880 break; 17881 case '#': 17882 if (value1 || value2) { 17883 frag.tagList.push(value2 ? [value1, value2] : [value1]); 17884 } 17885 break; 17886 case 'DISCONTINUITY': 17887 discontinuityCounter++; 17888 frag.tagList.push(['DIS']); 17889 break; 17890 case 'GAP': 17891 frag.tagList.push([tag]); 17892 break; 17893 case 'BITRATE': 17894 frag.tagList.push([tag, value1]); 17895 break; 17896 case 'DATERANGE': 17897 { 17898 var dateRangeAttr = new _utils_attr_list__WEBPACK_IMPORTED_MODULE_6__.AttrList(value1); 17899 var dateRange = new _date_range__WEBPACK_IMPORTED_MODULE_2__.DateRange(dateRangeAttr, level.dateRanges[dateRangeAttr.ID]); 17900 if (dateRange.isValid || level.skippedSegments) { 17901 level.dateRanges[dateRange.id] = dateRange; 17902 } else { 17903 _utils_logger__WEBPACK_IMPORTED_MODULE_7__.logger.warn("Ignoring invalid DATERANGE tag: \"" + value1 + "\""); 17904 } 17905 // Add to fragment tag list for backwards compatibility (< v1.2.0) 17906 frag.tagList.push(['EXT-X-DATERANGE', value1]); 17907 break; 17908 } 17909 case 'DISCONTINUITY-SEQUENCE': 17910 discontinuityCounter = parseInt(value1); 17911 break; 17912 case 'KEY': 17913 { 17914 var levelKey = parseKey(value1, baseurl); 17915 if (levelKey.isSupported()) { 17916 if (levelKey.method === 'NONE') { 17917 levelkeys = undefined; 17918 break; 17919 } 17920 if (!levelkeys) { 17921 levelkeys = {}; 17922 } 17923 if (levelkeys[levelKey.keyFormat]) { 17924 levelkeys = _extends({}, levelkeys); 17925 } 17926 levelkeys[levelKey.keyFormat] = levelKey; 17927 } else { 17928 _utils_logger__WEBPACK_IMPORTED_MODULE_7__.logger.warn("[Keys] Ignoring invalid EXT-X-KEY tag: \"" + value1 + "\""); 17929 } 17930 break; 17931 } 17932 case 'START': 17933 { 17934 var startAttrs = new _utils_attr_list__WEBPACK_IMPORTED_MODULE_6__.AttrList(value1); 17935 var startTimeOffset = startAttrs.decimalFloatingPoint('TIME-OFFSET'); 17936 // TIME-OFFSET can be 0 17937 if ((0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(startTimeOffset)) { 17938 level.startTimeOffset = startTimeOffset; 17939 } 17940 break; 17941 } 17942 case 'MAP': 17943 { 17944 var mapAttrs = new _utils_attr_list__WEBPACK_IMPORTED_MODULE_6__.AttrList(value1); 17945 if (frag.duration) { 17946 // Initial segment tag is after segment duration tag. 17947 // #EXTINF: 6.0 17948 // #EXT-X-MAP:URI="init.mp4 17949 var init = new _fragment__WEBPACK_IMPORTED_MODULE_3__.Fragment(type, baseurl); 17950 setInitSegment(init, mapAttrs, id, levelkeys); 17951 currentInitSegment = init; 17952 frag.initSegment = currentInitSegment; 17953 if (currentInitSegment.rawProgramDateTime && !frag.rawProgramDateTime) { 17954 frag.rawProgramDateTime = currentInitSegment.rawProgramDateTime; 17955 } 17956 } else { 17957 // Initial segment tag is before segment duration tag 17958 setInitSegment(frag, mapAttrs, id, levelkeys); 17959 currentInitSegment = frag; 17960 createNextFrag = true; 17961 } 17962 break; 17963 } 17964 case 'SERVER-CONTROL': 17965 { 17966 var serverControlAttrs = new _utils_attr_list__WEBPACK_IMPORTED_MODULE_6__.AttrList(value1); 17967 level.canBlockReload = serverControlAttrs.bool('CAN-BLOCK-RELOAD'); 17968 level.canSkipUntil = serverControlAttrs.optionalFloat('CAN-SKIP-UNTIL', 0); 17969 level.canSkipDateRanges = level.canSkipUntil > 0 && serverControlAttrs.bool('CAN-SKIP-DATERANGES'); 17970 level.partHoldBack = serverControlAttrs.optionalFloat('PART-HOLD-BACK', 0); 17971 level.holdBack = serverControlAttrs.optionalFloat('HOLD-BACK', 0); 17972 break; 17973 } 17974 case 'PART-INF': 17975 { 17976 var partInfAttrs = new _utils_attr_list__WEBPACK_IMPORTED_MODULE_6__.AttrList(value1); 17977 level.partTarget = partInfAttrs.decimalFloatingPoint('PART-TARGET'); 17978 break; 17979 } 17980 case 'PART': 17981 { 17982 var partList = level.partList; 17983 if (!partList) { 17984 partList = level.partList = []; 17985 } 17986 var previousFragmentPart = currentPart > 0 ? partList[partList.length - 1] : undefined; 17987 var index = currentPart++; 17988 var part = new _fragment__WEBPACK_IMPORTED_MODULE_3__.Part(new _utils_attr_list__WEBPACK_IMPORTED_MODULE_6__.AttrList(value1), frag, baseurl, index, previousFragmentPart); 17989 partList.push(part); 17990 frag.duration += part.duration; 17991 break; 17992 } 17993 case 'PRELOAD-HINT': 17994 { 17995 var preloadHintAttrs = new _utils_attr_list__WEBPACK_IMPORTED_MODULE_6__.AttrList(value1); 17996 level.preloadHint = preloadHintAttrs; 17997 break; 17998 } 17999 case 'RENDITION-REPORT': 18000 { 18001 var renditionReportAttrs = new _utils_attr_list__WEBPACK_IMPORTED_MODULE_6__.AttrList(value1); 18002 level.renditionReports = level.renditionReports || []; 18003 level.renditionReports.push(renditionReportAttrs); 18004 break; 18005 } 18006 default: 18007 _utils_logger__WEBPACK_IMPORTED_MODULE_7__.logger.warn("line parsed but not handled: " + result); 18008 break; 18009 } 18010 } 18011 } 18012 if (prevFrag && !prevFrag.relurl) { 18013 fragments.pop(); 18014 totalduration -= prevFrag.duration; 18015 if (level.partList) { 18016 level.fragmentHint = prevFrag; 18017 } 18018 } else if (level.partList) { 18019 assignProgramDateTime(frag, prevFrag); 18020 frag.cc = discontinuityCounter; 18021 level.fragmentHint = frag; 18022 } 18023 var fragmentLength = fragments.length; 18024 var firstFragment = fragments[0]; 18025 var lastFragment = fragments[fragmentLength - 1]; 18026 totalduration += level.skippedSegments * level.targetduration; 18027 if (totalduration > 0 && fragmentLength && lastFragment) { 18028 level.averagetargetduration = totalduration / fragmentLength; 18029 var lastSn = lastFragment.sn; 18030 level.endSN = lastSn !== 'initSegment' ? lastSn : 0; 18031 if (!level.live) { 18032 lastFragment.endList = true; 18033 } 18034 if (firstFragment) { 18035 level.startCC = firstFragment.cc; 18036 } 18037 } else { 18038 level.endSN = 0; 18039 level.startCC = 0; 18040 } 18041 if (level.fragmentHint) { 18042 totalduration += level.fragmentHint.duration; 18043 } 18044 level.totalduration = totalduration; 18045 level.endCC = discontinuityCounter; 18046 18047 /** 18048 * Backfill any missing PDT values 18049 * "If the first EXT-X-PROGRAM-DATE-TIME tag in a Playlist appears after 18050 * one or more Media Segment URIs, the client SHOULD extrapolate 18051 * backward from that tag (using EXTINF durations and/or media 18052 * timestamps) to associate dates with those segments." 18053 * We have already extrapolated forward, but all fragments up to the first instance of PDT do not have their PDTs 18054 * computed. 18055 */ 18056 if (firstPdtIndex > 0) { 18057 backfillProgramDateTimes(fragments, firstPdtIndex); 18058 } 18059 return level; 18060 }; 18061 return M3U8Parser; 18062}(); 18063 18064function parseKey(keyTag, baseurl) { 18065 var _keyAttrs$enumeratedS, _keyAttrs$enumeratedS2; 18066 // https://tools.ietf.org/html/rfc8216#section-4.3.2.4 18067 var keyAttrs = new _utils_attr_list__WEBPACK_IMPORTED_MODULE_6__.AttrList(keyTag); 18068 var decryptmethod = (_keyAttrs$enumeratedS = keyAttrs.enumeratedString('METHOD')) != null ? _keyAttrs$enumeratedS : ''; 18069 var decrypturi = keyAttrs.URI; 18070 var decryptiv = keyAttrs.hexadecimalInteger('IV'); 18071 var decryptkeyformatversions = keyAttrs.enumeratedString('KEYFORMATVERSIONS'); 18072 // From RFC: This attribute is OPTIONAL; its absence indicates an implicit value of "identity". 18073 var decryptkeyformat = (_keyAttrs$enumeratedS2 = keyAttrs.enumeratedString('KEYFORMAT')) != null ? _keyAttrs$enumeratedS2 : 'identity'; 18074 if (decrypturi && keyAttrs.IV && !decryptiv) { 18075 _utils_logger__WEBPACK_IMPORTED_MODULE_7__.logger.error("Invalid IV: " + keyAttrs.IV); 18076 } 18077 // If decrypturi is a URI with a scheme, then baseurl will be ignored 18078 // No uri is allowed when METHOD is NONE 18079 var resolvedUri = decrypturi ? M3U8Parser.resolve(decrypturi, baseurl) : ''; 18080 var keyFormatVersions = (decryptkeyformatversions ? decryptkeyformatversions : '1').split('/').map(Number).filter(Number.isFinite); 18081 return new _level_key__WEBPACK_IMPORTED_MODULE_5__.LevelKey(decryptmethod, resolvedUri, decryptkeyformat, keyFormatVersions, decryptiv); 18082} 18083function setCodecs(codecs, level) { 18084 ['video', 'audio', 'text'].forEach(function (type) { 18085 var filtered = codecs.filter(function (codec) { 18086 return (0,_utils_codecs__WEBPACK_IMPORTED_MODULE_8__.isCodecType)(codec, type); 18087 }); 18088 if (filtered.length) { 18089 var preferred = filtered.filter(function (codec) { 18090 return codec.lastIndexOf('avc1', 0) === 0 || codec.lastIndexOf('mp4a', 0) === 0; 18091 }); 18092 level[type + "Codec"] = preferred.length > 0 ? preferred[0] : filtered[0]; 18093 18094 // remove from list 18095 codecs = codecs.filter(function (codec) { 18096 return filtered.indexOf(codec) === -1; 18097 }); 18098 } 18099 }); 18100 level.unknownCodecs = codecs; 18101} 18102function assignCodec(media, groupItem, codecProperty) { 18103 var codecValue = groupItem[codecProperty]; 18104 if (codecValue) { 18105 media[codecProperty] = codecValue; 18106 } 18107} 18108function backfillProgramDateTimes(fragments, firstPdtIndex) { 18109 var fragPrev = fragments[firstPdtIndex]; 18110 for (var i = firstPdtIndex; i--;) { 18111 var frag = fragments[i]; 18112 // Exit on delta-playlist skipped segments 18113 if (!frag) { 18114 return; 18115 } 18116 frag.programDateTime = fragPrev.programDateTime - frag.duration * 1000; 18117 fragPrev = frag; 18118 } 18119} 18120function assignProgramDateTime(frag, prevFrag) { 18121 if (frag.rawProgramDateTime) { 18122 frag.programDateTime = Date.parse(frag.rawProgramDateTime); 18123 } else if (prevFrag !== null && prevFrag !== void 0 && prevFrag.programDateTime) { 18124 frag.programDateTime = prevFrag.endProgramDateTime; 18125 } 18126 if (!(0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(frag.programDateTime)) { 18127 frag.programDateTime = null; 18128 frag.rawProgramDateTime = null; 18129 } 18130} 18131function setInitSegment(frag, mapAttrs, id, levelkeys) { 18132 frag.relurl = mapAttrs.URI; 18133 if (mapAttrs.BYTERANGE) { 18134 frag.setByteRange(mapAttrs.BYTERANGE); 18135 } 18136 frag.level = id; 18137 frag.sn = 'initSegment'; 18138 if (levelkeys) { 18139 frag.levelkeys = levelkeys; 18140 } 18141 frag.initSegment = null;
vendor: 99,435 bytes, lines 18141-20584
18141 18142} 18143 18144/***/ }), 18145 18146/***/ "./src/loader/playlist-loader.ts": 18147/*!***************************************!*\ 18148 !*** ./src/loader/playlist-loader.ts ***! 18149 \***************************************/ 18150/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 18151 18152"use strict"; 18153__webpack_require__.r(__webpack_exports__); 18154/* harmony export */ __webpack_require__.d(__webpack_exports__, { 18155/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 18156/* harmony export */ }); 18157/* harmony import */ var _home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.ts"); 18158/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 18159/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../errors */ "./src/errors.ts"); 18160/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 18161/* harmony import */ var _m3u8_parser__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./m3u8-parser */ "./src/loader/m3u8-parser.ts"); 18162/* harmony import */ var _types_loader__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../types/loader */ "./src/types/loader.ts"); 18163/* harmony import */ var _utils_attr_list__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../utils/attr-list */ "./src/utils/attr-list.ts"); 18164 18165 18166/** 18167 * PlaylistLoader - delegate for media manifest/playlist loading tasks. Takes care of parsing media to internal data-models. 18168 * 18169 * Once loaded, dispatches events with parsed data-models of manifest/levels/audio/subtitle tracks. 18170 * 18171 * Uses loader(s) set in config to do actual internal loading of resource tasks. 18172 * 18173 * @module 18174 * 18175 */ 18176 18177 18178 18179 18180 18181 18182 18183function mapContextToLevelType(context) { 18184 var type = context.type; 18185 switch (type) { 18186 case _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistContextType.AUDIO_TRACK: 18187 return _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistLevelType.AUDIO; 18188 case _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistContextType.SUBTITLE_TRACK: 18189 return _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistLevelType.SUBTITLE; 18190 default: 18191 return _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistLevelType.MAIN; 18192 } 18193} 18194function getResponseUrl(response, context) { 18195 var url = response.url; 18196 // responseURL not supported on some browsers (it is used to detect URL redirection) 18197 // data-uri mode also not supported (but no need to detect redirection) 18198 if (url === undefined || url.indexOf('data:') === 0) { 18199 // fallback to initial URL 18200 url = context.url; 18201 } 18202 return url; 18203} 18204var PlaylistLoader = /*#__PURE__*/function () { 18205 function PlaylistLoader(hls) { 18206 this.hls = void 0; 18207 this.loaders = Object.create(null); 18208 this.hls = hls; 18209 this.registerListeners(); 18210 } 18211 var _proto = PlaylistLoader.prototype; 18212 _proto.startLoad = function startLoad(startPosition) {}; 18213 _proto.stopLoad = function stopLoad() { 18214 this.destroyInternalLoaders(); 18215 }; 18216 _proto.registerListeners = function registerListeners() { 18217 var hls = this.hls; 18218 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MANIFEST_LOADING, this.onManifestLoading, this); 18219 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.LEVEL_LOADING, this.onLevelLoading, this); 18220 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.AUDIO_TRACK_LOADING, this.onAudioTrackLoading, this); 18221 hls.on(_events__WEBPACK_IMPORTED_MODULE_1__.Events.SUBTITLE_TRACK_LOADING, this.onSubtitleTrackLoading, this); 18222 }; 18223 _proto.unregisterListeners = function unregisterListeners() { 18224 var hls = this.hls; 18225 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MANIFEST_LOADING, this.onManifestLoading, this); 18226 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.LEVEL_LOADING, this.onLevelLoading, this); 18227 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.AUDIO_TRACK_LOADING, this.onAudioTrackLoading, this); 18228 hls.off(_events__WEBPACK_IMPORTED_MODULE_1__.Events.SUBTITLE_TRACK_LOADING, this.onSubtitleTrackLoading, this); 18229 } 18230 18231 /** 18232 * Returns defaults or configured loader-type overloads (pLoader and loader config params) 18233 */; 18234 _proto.createInternalLoader = function createInternalLoader(context) { 18235 var config = this.hls.config; 18236 var PLoader = config.pLoader; 18237 var Loader = config.loader; 18238 var InternalLoader = PLoader || Loader; 18239 var loader = new InternalLoader(config); 18240 context.loader = loader; 18241 this.loaders[context.type] = loader; 18242 return loader; 18243 }; 18244 _proto.getInternalLoader = function getInternalLoader(context) { 18245 return this.loaders[context.type]; 18246 }; 18247 _proto.resetInternalLoader = function resetInternalLoader(contextType) { 18248 if (this.loaders[contextType]) { 18249 delete this.loaders[contextType]; 18250 } 18251 } 18252 18253 /** 18254 * Call `destroy` on all internal loader instances mapped (one per context type) 18255 */; 18256 _proto.destroyInternalLoaders = function destroyInternalLoaders() { 18257 for (var contextType in this.loaders) { 18258 var loader = this.loaders[contextType]; 18259 if (loader) { 18260 loader.destroy(); 18261 } 18262 this.resetInternalLoader(contextType); 18263 } 18264 }; 18265 _proto.destroy = function destroy() { 18266 this.unregisterListeners(); 18267 this.destroyInternalLoaders(); 18268 }; 18269 _proto.onManifestLoading = function onManifestLoading(event, data) { 18270 var url = data.url; 18271 this.load({ 18272 id: null, 18273 groupId: null, 18274 level: 0, 18275 responseType: 'text', 18276 type: _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistContextType.MANIFEST, 18277 url: url, 18278 deliveryDirectives: null 18279 }); 18280 }; 18281 _proto.onLevelLoading = function onLevelLoading(event, data) { 18282 var id = data.id, 18283 level = data.level, 18284 url = data.url, 18285 deliveryDirectives = data.deliveryDirectives; 18286 this.load({ 18287 id: id, 18288 groupId: null, 18289 level: level, 18290 responseType: 'text', 18291 type: _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistContextType.LEVEL, 18292 url: url, 18293 deliveryDirectives: deliveryDirectives 18294 }); 18295 }; 18296 _proto.onAudioTrackLoading = function onAudioTrackLoading(event, data) { 18297 var id = data.id, 18298 groupId = data.groupId, 18299 url = data.url, 18300 deliveryDirectives = data.deliveryDirectives; 18301 this.load({ 18302 id: id, 18303 groupId: groupId, 18304 level: null, 18305 responseType: 'text', 18306 type: _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistContextType.AUDIO_TRACK, 18307 url: url, 18308 deliveryDirectives: deliveryDirectives 18309 }); 18310 }; 18311 _proto.onSubtitleTrackLoading = function onSubtitleTrackLoading(event, data) { 18312 var id = data.id, 18313 groupId = data.groupId, 18314 url = data.url, 18315 deliveryDirectives = data.deliveryDirectives; 18316 this.load({ 18317 id: id, 18318 groupId: groupId, 18319 level: null, 18320 responseType: 'text', 18321 type: _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistContextType.SUBTITLE_TRACK, 18322 url: url, 18323 deliveryDirectives: deliveryDirectives 18324 }); 18325 }; 18326 _proto.load = function load(context) { 18327 var _context$deliveryDire; 18328 var config = this.hls.config; 18329 18330 // logger.debug(`[playlist-loader]: Loading playlist of type ${context.type}, level: ${context.level}, id: ${context.id}`); 18331 18332 // Check if a loader for this context already exists 18333 var loader = this.getInternalLoader(context); 18334 if (loader) { 18335 var loaderContext = loader.context; 18336 if (loaderContext && loaderContext.url === context.url) { 18337 // same URL can't overlap 18338 _utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger.trace('[playlist-loader]: playlist request ongoing'); 18339 return; 18340 } 18341 _utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger.log("[playlist-loader]: aborting previous loader for type: " + context.type); 18342 loader.abort(); 18343 } 18344 var maxRetry; 18345 var timeout; 18346 var retryDelay; 18347 var maxRetryDelay; 18348 18349 // apply different configs for retries depending on 18350 // context (manifest, level, audio/subs playlist) 18351 switch (context.type) { 18352 case _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistContextType.MANIFEST: 18353 maxRetry = config.manifestLoadingMaxRetry; 18354 timeout = config.manifestLoadingTimeOut; 18355 retryDelay = config.manifestLoadingRetryDelay; 18356 maxRetryDelay = config.manifestLoadingMaxRetryTimeout; 18357 break; 18358 case _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistContextType.LEVEL: 18359 case _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistContextType.AUDIO_TRACK: 18360 case _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistContextType.SUBTITLE_TRACK: 18361 // Manage retries in Level/Track Controller 18362 maxRetry = 0; 18363 timeout = config.levelLoadingTimeOut; 18364 break; 18365 default: 18366 maxRetry = config.levelLoadingMaxRetry; 18367 timeout = config.levelLoadingTimeOut; 18368 retryDelay = config.levelLoadingRetryDelay; 18369 maxRetryDelay = config.levelLoadingMaxRetryTimeout; 18370 break; 18371 } 18372 loader = this.createInternalLoader(context); 18373 18374 // Override level/track timeout for LL-HLS requests 18375 // (the default of 10000ms is counter productive to blocking playlist reload requests) 18376 if ((_context$deliveryDire = context.deliveryDirectives) !== null && _context$deliveryDire !== void 0 && _context$deliveryDire.part) { 18377 var levelDetails; 18378 if (context.type === _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistContextType.LEVEL && context.level !== null) { 18379 levelDetails = this.hls.levels[context.level].details; 18380 } else if (context.type === _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistContextType.AUDIO_TRACK && context.id !== null) { 18381 levelDetails = this.hls.audioTracks[context.id].details; 18382 } else if (context.type === _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistContextType.SUBTITLE_TRACK && context.id !== null) { 18383 levelDetails = this.hls.subtitleTracks[context.id].details; 18384 } 18385 if (levelDetails) { 18386 var partTarget = levelDetails.partTarget; 18387 var targetDuration = levelDetails.targetduration; 18388 if (partTarget && targetDuration) { 18389 timeout = Math.min(Math.max(partTarget * 3, targetDuration * 0.8) * 1000, timeout); 18390 } 18391 } 18392 } 18393 var loaderConfig = { 18394 timeout: timeout, 18395 maxRetry: maxRetry, 18396 retryDelay: retryDelay, 18397 maxRetryDelay: maxRetryDelay, 18398 highWaterMark: 0 18399 }; 18400 var loaderCallbacks = { 18401 onSuccess: this.loadsuccess.bind(this), 18402 onError: this.loaderror.bind(this), 18403 onTimeout: this.loadtimeout.bind(this) 18404 }; 18405 18406 // logger.debug(`[playlist-loader]: Calling internal loader delegate for URL: ${context.url}`); 18407 18408 loader.load(context, loaderConfig, loaderCallbacks); 18409 }; 18410 _proto.loadsuccess = function loadsuccess(response, stats, context, networkDetails) { 18411 if (networkDetails === void 0) { 18412 networkDetails = null; 18413 } 18414 this.resetInternalLoader(context.type); 18415 var string = response.data; 18416 18417 // Validate if it is an M3U8 at all 18418 if (string.indexOf('#EXTM3U') !== 0) { 18419 this.handleManifestParsingError(response, context, 'no EXTM3U delimiter', networkDetails); 18420 return; 18421 } 18422 stats.parsing.start = performance.now(); 18423 // Check if chunk-list or master. handle empty chunk list case (first EXTINF not signaled, but TARGETDURATION present) 18424 if (string.indexOf('#EXTINF:') > 0 || string.indexOf('#EXT-X-TARGETDURATION:') > 0) { 18425 this.handleTrackOrLevelPlaylist(response, stats, context, networkDetails); 18426 } else { 18427 this.handleMasterPlaylist(response, stats, context, networkDetails); 18428 } 18429 }; 18430 _proto.loaderror = function loaderror(response, context, networkDetails) { 18431 if (networkDetails === void 0) { 18432 networkDetails = null; 18433 } 18434 this.handleNetworkError(context, networkDetails, false, response); 18435 }; 18436 _proto.loadtimeout = function loadtimeout(stats, context, networkDetails) { 18437 if (networkDetails === void 0) { 18438 networkDetails = null; 18439 } 18440 this.handleNetworkError(context, networkDetails, true); 18441 }; 18442 _proto.handleMasterPlaylist = function handleMasterPlaylist(response, stats, context, networkDetails) { 18443 var hls = this.hls; 18444 var string = response.data; 18445 var url = getResponseUrl(response, context); 18446 var _M3U8Parser$parseMast = _m3u8_parser__WEBPACK_IMPORTED_MODULE_4__["default"].parseMasterPlaylist(string, url), 18447 levels = _M3U8Parser$parseMast.levels, 18448 sessionData = _M3U8Parser$parseMast.sessionData, 18449 sessionKeys = _M3U8Parser$parseMast.sessionKeys; 18450 if (!levels.length) { 18451 this.handleManifestParsingError(response, context, 'no level found in manifest', networkDetails); 18452 return; 18453 } 18454 18455 // multi level playlist, parse level info 18456 var audioGroups = levels.map(function (level) { 18457 return { 18458 id: level.attrs.AUDIO, 18459 audioCodec: level.audioCodec 18460 }; 18461 }); 18462 var subtitleGroups = levels.map(function (level) { 18463 return { 18464 id: level.attrs.SUBTITLES, 18465 textCodec: level.textCodec 18466 }; 18467 }); 18468 var audioTracks = _m3u8_parser__WEBPACK_IMPORTED_MODULE_4__["default"].parseMasterPlaylistMedia(string, url, 'AUDIO', audioGroups); 18469 var subtitles = _m3u8_parser__WEBPACK_IMPORTED_MODULE_4__["default"].parseMasterPlaylistMedia(string, url, 'SUBTITLES', subtitleGroups); 18470 var captions = _m3u8_parser__WEBPACK_IMPORTED_MODULE_4__["default"].parseMasterPlaylistMedia(string, url, 'CLOSED-CAPTIONS'); 18471 if (audioTracks.length) { 18472 // check if we have found an audio track embedded in main playlist (audio track without URI attribute) 18473 var embeddedAudioFound = audioTracks.some(function (audioTrack) { 18474 return !audioTrack.url; 18475 }); 18476 18477 // if no embedded audio track defined, but audio codec signaled in quality level, 18478 // we need to signal this main audio track this could happen with playlists with 18479 // alt audio rendition in which quality levels (main) 18480 // contains both audio+video. but with mixed audio track not signaled 18481 if (!embeddedAudioFound && levels[0].audioCodec && !levels[0].attrs.AUDIO) { 18482 _utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger.log('[playlist-loader]: audio codec signaled in quality level, but no embedded audio track signaled, create one'); 18483 audioTracks.unshift({ 18484 type: 'main', 18485 name: 'main', 18486 default: false, 18487 autoselect: false, 18488 forced: false, 18489 id: -1, 18490 attrs: new _utils_attr_list__WEBPACK_IMPORTED_MODULE_6__.AttrList({}), 18491 bitrate: 0, 18492 url: '' 18493 }); 18494 } 18495 } 18496 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MANIFEST_LOADED, { 18497 levels: levels, 18498 audioTracks: audioTracks, 18499 subtitles: subtitles, 18500 captions: captions, 18501 url: url, 18502 stats: stats, 18503 networkDetails: networkDetails, 18504 sessionData: sessionData, 18505 sessionKeys: sessionKeys 18506 }); 18507 }; 18508 _proto.handleTrackOrLevelPlaylist = function handleTrackOrLevelPlaylist(response, stats, context, networkDetails) { 18509 var hls = this.hls; 18510 var id = context.id, 18511 level = context.level, 18512 type = context.type; 18513 var url = getResponseUrl(response, context); 18514 var levelUrlId = (0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(id) ? id : 0; 18515 var levelId = (0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(level) ? level : levelUrlId; 18516 var levelType = mapContextToLevelType(context); 18517 var levelDetails = _m3u8_parser__WEBPACK_IMPORTED_MODULE_4__["default"].parseLevelPlaylist(response.data, url, levelId, levelType, levelUrlId); 18518 if (!levelDetails.fragments.length) { 18519 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.ERROR, { 18520 type: _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorTypes.NETWORK_ERROR, 18521 details: _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorDetails.LEVEL_EMPTY_ERROR, 18522 fatal: false, 18523 url: url, 18524 reason: 'no fragments found in level', 18525 level: typeof context.level === 'number' ? context.level : undefined 18526 }); 18527 return; 18528 } 18529 18530 // We have done our first request (Manifest-type) and receive 18531 // not a master playlist but a chunk-list (track/level) 18532 // We fire the manifest-loaded event anyway with the parsed level-details 18533 // by creating a single-level structure for it. 18534 if (type === _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistContextType.MANIFEST) { 18535 var singleLevel = { 18536 attrs: new _utils_attr_list__WEBPACK_IMPORTED_MODULE_6__.AttrList({}), 18537 bitrate: 0, 18538 details: levelDetails, 18539 name: '', 18540 url: url 18541 }; 18542 hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.MANIFEST_LOADED, { 18543 levels: [singleLevel], 18544 audioTracks: [], 18545 url: url, 18546 stats: stats, 18547 networkDetails: networkDetails, 18548 sessionData: null, 18549 sessionKeys: null 18550 }); 18551 } 18552 18553 // save parsing time 18554 stats.parsing.end = performance.now(); 18555 18556 // extend the context with the new levelDetails property 18557 context.levelDetails = levelDetails; 18558 this.handlePlaylistLoaded(response, stats, context, networkDetails); 18559 }; 18560 _proto.handleManifestParsingError = function handleManifestParsingError(response, context, reason, networkDetails) { 18561 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.ERROR, { 18562 type: _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorTypes.NETWORK_ERROR, 18563 details: _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorDetails.MANIFEST_PARSING_ERROR, 18564 fatal: context.type === _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistContextType.MANIFEST, 18565 url: response.url, 18566 reason: reason, 18567 response: response, 18568 context: context, 18569 networkDetails: networkDetails 18570 }); 18571 }; 18572 _proto.handleNetworkError = function handleNetworkError(context, networkDetails, timeout, response) { 18573 if (timeout === void 0) { 18574 timeout = false; 18575 } 18576 _utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger.warn("[playlist-loader]: A network " + (timeout ? 'timeout' : 'error') + " occurred while loading " + context.type + " level: " + context.level + " id: " + context.id + " group-id: \"" + context.groupId + "\""); 18577 var details = _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorDetails.UNKNOWN; 18578 var fatal = false; 18579 var loader = this.getInternalLoader(context); 18580 switch (context.type) { 18581 case _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistContextType.MANIFEST: 18582 details = timeout ? _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorDetails.MANIFEST_LOAD_TIMEOUT : _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorDetails.MANIFEST_LOAD_ERROR; 18583 fatal = true; 18584 break; 18585 case _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistContextType.LEVEL: 18586 details = timeout ? _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorDetails.LEVEL_LOAD_TIMEOUT : _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorDetails.LEVEL_LOAD_ERROR; 18587 fatal = false; 18588 break; 18589 case _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistContextType.AUDIO_TRACK: 18590 details = timeout ? _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorDetails.AUDIO_TRACK_LOAD_TIMEOUT : _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorDetails.AUDIO_TRACK_LOAD_ERROR; 18591 fatal = false; 18592 break; 18593 case _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistContextType.SUBTITLE_TRACK: 18594 details = timeout ? _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorDetails.SUBTITLE_TRACK_LOAD_TIMEOUT : _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorDetails.SUBTITLE_LOAD_ERROR; 18595 fatal = false; 18596 break; 18597 } 18598 if (loader) { 18599 this.resetInternalLoader(context.type); 18600 } 18601 var errorData = { 18602 type: _errors__WEBPACK_IMPORTED_MODULE_2__.ErrorTypes.NETWORK_ERROR, 18603 details: details, 18604 fatal: fatal, 18605 url: context.url, 18606 loader: loader, 18607 context: context, 18608 networkDetails: networkDetails 18609 }; 18610 if (response) { 18611 errorData.response = response; 18612 } 18613 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.ERROR, errorData); 18614 }; 18615 _proto.handlePlaylistLoaded = function handlePlaylistLoaded(response, stats, context, networkDetails) { 18616 var type = context.type, 18617 level = context.level, 18618 id = context.id, 18619 groupId = context.groupId, 18620 loader = context.loader, 18621 levelDetails = context.levelDetails, 18622 deliveryDirectives = context.deliveryDirectives; 18623 if (!(levelDetails !== null && levelDetails !== void 0 && levelDetails.targetduration)) { 18624 this.handleManifestParsingError(response, context, 'invalid target duration', networkDetails); 18625 return; 18626 } 18627 if (!loader) { 18628 return; 18629 } 18630 if (levelDetails.live) { 18631 if (loader.getCacheAge) { 18632 levelDetails.ageHeader = loader.getCacheAge() || 0; 18633 } 18634 if (!loader.getCacheAge || isNaN(levelDetails.ageHeader)) { 18635 levelDetails.ageHeader = 0; 18636 } 18637 } 18638 switch (type) { 18639 case _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistContextType.MANIFEST: 18640 case _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistContextType.LEVEL: 18641 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.LEVEL_LOADED, { 18642 details: levelDetails, 18643 level: level || 0, 18644 id: id || 0, 18645 stats: stats, 18646 networkDetails: networkDetails, 18647 deliveryDirectives: deliveryDirectives 18648 }); 18649 break; 18650 case _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistContextType.AUDIO_TRACK: 18651 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.AUDIO_TRACK_LOADED, { 18652 details: levelDetails, 18653 id: id || 0, 18654 groupId: groupId || '', 18655 stats: stats, 18656 networkDetails: networkDetails, 18657 deliveryDirectives: deliveryDirectives 18658 }); 18659 break; 18660 case _types_loader__WEBPACK_IMPORTED_MODULE_5__.PlaylistContextType.SUBTITLE_TRACK: 18661 this.hls.trigger(_events__WEBPACK_IMPORTED_MODULE_1__.Events.SUBTITLE_TRACK_LOADED, { 18662 details: levelDetails, 18663 id: id || 0, 18664 groupId: groupId || '', 18665 stats: stats, 18666 networkDetails: networkDetails, 18667 deliveryDirectives: deliveryDirectives 18668 }); 18669 break; 18670 } 18671 }; 18672 return PlaylistLoader; 18673}(); 18674/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PlaylistLoader); 18675 18676/***/ }), 18677 18678/***/ "./src/polyfills/number.ts": 18679/*!*********************************!*\ 18680 !*** ./src/polyfills/number.ts ***! 18681 \*********************************/ 18682/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 18683 18684"use strict"; 18685__webpack_require__.r(__webpack_exports__); 18686/* harmony export */ __webpack_require__.d(__webpack_exports__, { 18687/* harmony export */ "MAX_SAFE_INTEGER": () => (/* binding */ MAX_SAFE_INTEGER), 18688/* harmony export */ "isFiniteNumber": () => (/* binding */ isFiniteNumber) 18689/* harmony export */ }); 18690var isFiniteNumber = Number.isFinite || function (value) { 18691 return typeof value === 'number' && isFinite(value); 18692}; 18693var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991; 18694 18695/***/ }), 18696 18697/***/ "./src/remux/aac-helper.ts": 18698/*!*********************************!*\ 18699 !*** ./src/remux/aac-helper.ts ***! 18700 \*********************************/ 18701/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 18702 18703"use strict"; 18704__webpack_require__.r(__webpack_exports__); 18705/* harmony export */ __webpack_require__.d(__webpack_exports__, { 18706/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 18707/* harmony export */ }); 18708/** 18709 * AAC helper 18710 */ 18711var AAC = /*#__PURE__*/function () { 18712 function AAC() {} 18713 AAC.getSilentFrame = function getSilentFrame(codec, channelCount) { 18714 switch (codec) { 18715 case 'mp4a.40.2': 18716 if (channelCount === 1) { 18717 return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x23, 0x80]); 18718 } else if (channelCount === 2) { 18719 return new Uint8Array([0x21, 0x00, 0x49, 0x90, 0x02, 0x19, 0x00, 0x23, 0x80]); 18720 } else if (channelCount === 3) { 18721 return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x8e]); 18722 } else if (channelCount === 4) { 18723 return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x80, 0x2c, 0x80, 0x08, 0x02, 0x38]); 18724 } else if (channelCount === 5) { 18725 return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x82, 0x30, 0x04, 0x99, 0x00, 0x21, 0x90, 0x02, 0x38]); 18726 } else if (channelCount === 6) { 18727 return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x82, 0x30, 0x04, 0x99, 0x00, 0x21, 0x90, 0x02, 0x00, 0xb2, 0x00, 0x20, 0x08, 0xe0]); 18728 } 18729 break; 18730 // handle HE-AAC below (mp4a.40.5 / mp4a.40.29) 18731 default: 18732 if (channelCount === 1) { 18733 // ffmpeg -y -f lavfi -i "aevalsrc=0:d=0.05" -c:a libfdk_aac -profile:a aac_he -b:a 4k output.aac && hexdump -v -e '16/1 "0x%x," "\n"' -v output.aac 18734 return new Uint8Array([0x1, 0x40, 0x22, 0x80, 0xa3, 0x4e, 0xe6, 0x80, 0xba, 0x8, 0x0, 0x0, 0x0, 0x1c, 0x6, 0xf1, 0xc1, 0xa, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5e]); 18735 } else if (channelCount === 2) { 18736 // ffmpeg -y -f lavfi -i "aevalsrc=0|0:d=0.05" -c:a libfdk_aac -profile:a aac_he_v2 -b:a 4k output.aac && hexdump -v -e '16/1 "0x%x," "\n"' -v output.aac 18737 return new Uint8Array([0x1, 0x40, 0x22, 0x80, 0xa3, 0x5e, 0xe6, 0x80, 0xba, 0x8, 0x0, 0x0, 0x0, 0x0, 0x95, 0x0, 0x6, 0xf1, 0xa1, 0xa, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5e]); 18738 } else if (channelCount === 3) { 18739 // ffmpeg -y -f lavfi -i "aevalsrc=0|0|0:d=0.05" -c:a libfdk_aac -profile:a aac_he_v2 -b:a 4k output.aac && hexdump -v -e '16/1 "0x%x," "\n"' -v output.aac 18740 return new Uint8Array([0x1, 0x40, 0x22, 0x80, 0xa3, 0x5e, 0xe6, 0x80, 0xba, 0x8, 0x0, 0x0, 0x0, 0x0, 0x95, 0x0, 0x6, 0xf1, 0xa1, 0xa, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5e]); 18741 } 18742 break; 18743 } 18744 return undefined; 18745 }; 18746 return AAC; 18747}(); 18748/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AAC); 18749 18750/***/ }), 18751 18752/***/ "./src/remux/mp4-generator.ts": 18753/*!************************************!*\ 18754 !*** ./src/remux/mp4-generator.ts ***! 18755 \************************************/ 18756/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 18757 18758"use strict"; 18759__webpack_require__.r(__webpack_exports__); 18760/* harmony export */ __webpack_require__.d(__webpack_exports__, { 18761/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 18762/* harmony export */ }); 18763/** 18764 * Generate MP4 Box 18765 */ 18766 18767var UINT32_MAX = Math.pow(2, 32) - 1; 18768var MP4 = /*#__PURE__*/function () { 18769 function MP4() {} 18770 MP4.init = function init() { 18771 MP4.types = { 18772 avc1: [], 18773 // codingname 18774 avcC: [], 18775 btrt: [], 18776 dinf: [], 18777 dref: [], 18778 esds: [], 18779 ftyp: [], 18780 hdlr: [], 18781 mdat: [], 18782 mdhd: [], 18783 mdia: [], 18784 mfhd: [], 18785 minf: [], 18786 moof: [], 18787 moov: [], 18788 mp4a: [], 18789 '.mp3': [], 18790 mvex: [], 18791 mvhd: [], 18792 pasp: [], 18793 sdtp: [], 18794 stbl: [], 18795 stco: [], 18796 stsc: [], 18797 stsd: [], 18798 stsz: [], 18799 stts: [], 18800 tfdt: [], 18801 tfhd: [], 18802 traf: [], 18803 trak: [], 18804 trun: [], 18805 trex: [], 18806 tkhd: [], 18807 vmhd: [], 18808 smhd: [] 18809 }; 18810 var i; 18811 for (i in MP4.types) { 18812 if (MP4.types.hasOwnProperty(i)) { 18813 MP4.types[i] = [i.charCodeAt(0), i.charCodeAt(1), i.charCodeAt(2), i.charCodeAt(3)]; 18814 } 18815 } 18816 var videoHdlr = new Uint8Array([0x00, 18817 // version 0 18818 0x00, 0x00, 0x00, 18819 // flags 18820 0x00, 0x00, 0x00, 0x00, 18821 // pre_defined 18822 0x76, 0x69, 0x64, 0x65, 18823 // handler_type: 'vide' 18824 0x00, 0x00, 0x00, 0x00, 18825 // reserved 18826 0x00, 0x00, 0x00, 0x00, 18827 // reserved 18828 0x00, 0x00, 0x00, 0x00, 18829 // reserved 18830 0x56, 0x69, 0x64, 0x65, 0x6f, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x00 // name: 'VideoHandler' 18831 ]); 18832 18833 var audioHdlr = new Uint8Array([0x00, 18834 // version 0 18835 0x00, 0x00, 0x00, 18836 // flags 18837 0x00, 0x00, 0x00, 0x00, 18838 // pre_defined 18839 0x73, 0x6f, 0x75, 0x6e, 18840 // handler_type: 'soun' 18841 0x00, 0x00, 0x00, 0x00, 18842 // reserved 18843 0x00, 0x00, 0x00, 0x00, 18844 // reserved 18845 0x00, 0x00, 0x00, 0x00, 18846 // reserved 18847 0x53, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x00 // name: 'SoundHandler' 18848 ]); 18849 18850 MP4.HDLR_TYPES = { 18851 video: videoHdlr, 18852 audio: audioHdlr 18853 }; 18854 var dref = new Uint8Array([0x00, 18855 // version 0 18856 0x00, 0x00, 0x00, 18857 // flags 18858 0x00, 0x00, 0x00, 0x01, 18859 // entry_count 18860 0x00, 0x00, 0x00, 0x0c, 18861 // entry_size 18862 0x75, 0x72, 0x6c, 0x20, 18863 // 'url' type 18864 0x00, 18865 // version 0 18866 0x00, 0x00, 0x01 // entry_flags 18867 ]); 18868 18869 var stco = new Uint8Array([0x00, 18870 // version 18871 0x00, 0x00, 0x00, 18872 // flags 18873 0x00, 0x00, 0x00, 0x00 // entry_count 18874 ]); 18875 18876 MP4.STTS = MP4.STSC = MP4.STCO = stco; 18877 MP4.STSZ = new Uint8Array([0x00, 18878 // version 18879 0x00, 0x00, 0x00, 18880 // flags 18881 0x00, 0x00, 0x00, 0x00, 18882 // sample_size 18883 0x00, 0x00, 0x00, 0x00 // sample_count 18884 ]); 18885 18886 MP4.VMHD = new Uint8Array([0x00, 18887 // version 18888 0x00, 0x00, 0x01, 18889 // flags 18890 0x00, 0x00, 18891 // graphicsmode 18892 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // opcolor 18893 ]); 18894 18895 MP4.SMHD = new Uint8Array([0x00, 18896 // version 18897 0x00, 0x00, 0x00, 18898 // flags 18899 0x00, 0x00, 18900 // balance 18901 0x00, 0x00 // reserved 18902 ]); 18903 18904 MP4.STSD = new Uint8Array([0x00, 18905 // version 0 18906 0x00, 0x00, 0x00, 18907 // flags 18908 0x00, 0x00, 0x00, 0x01]); // entry_count 18909 18910 var majorBrand = new Uint8Array([105, 115, 111, 109]); // isom 18911 var avc1Brand = new Uint8Array([97, 118, 99, 49]); // avc1 18912 var minorVersion = new Uint8Array([0, 0, 0, 1]); 18913 MP4.FTYP = MP4.box(MP4.types.ftyp, majorBrand, minorVersion, majorBrand, avc1Brand); 18914 MP4.DINF = MP4.box(MP4.types.dinf, MP4.box(MP4.types.dref, dref)); 18915 }; 18916 MP4.box = function box(type) { 18917 var size = 8; 18918 for (var _len = arguments.length, payload = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 18919 payload[_key - 1] = arguments[_key]; 18920 } 18921 var i = payload.length; 18922 var len = i; 18923 // calculate the total size we need to allocate 18924 while (i--) { 18925 size += payload[i].byteLength; 18926 } 18927 var result = new Uint8Array(size); 18928 result[0] = size >> 24 & 0xff; 18929 result[1] = size >> 16 & 0xff; 18930 result[2] = size >> 8 & 0xff; 18931 result[3] = size & 0xff; 18932 result.set(type, 4); 18933 // copy the payload into the result 18934 for (i = 0, size = 8; i < len; i++) { 18935 // copy payload[i] array @ offset size 18936 result.set(payload[i], size); 18937 size += payload[i].byteLength; 18938 } 18939 return result; 18940 }; 18941 MP4.hdlr = function hdlr(type) { 18942 return MP4.box(MP4.types.hdlr, MP4.HDLR_TYPES[type]); 18943 }; 18944 MP4.mdat = function mdat(data) { 18945 return MP4.box(MP4.types.mdat, data); 18946 }; 18947 MP4.mdhd = function mdhd(timescale, duration) { 18948 duration *= timescale; 18949 var upperWordDuration = Math.floor(duration / (UINT32_MAX + 1)); 18950 var lowerWordDuration = Math.floor(duration % (UINT32_MAX + 1)); 18951 return MP4.box(MP4.types.mdhd, new Uint8Array([0x01, 18952 // version 1 18953 0x00, 0x00, 0x00, 18954 // flags 18955 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 18956 // creation_time 18957 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 18958 // modification_time 18959 timescale >> 24 & 0xff, timescale >> 16 & 0xff, timescale >> 8 & 0xff, timescale & 0xff, 18960 // timescale 18961 upperWordDuration >> 24, upperWordDuration >> 16 & 0xff, upperWordDuration >> 8 & 0xff, upperWordDuration & 0xff, lowerWordDuration >> 24, lowerWordDuration >> 16 & 0xff, lowerWordDuration >> 8 & 0xff, lowerWordDuration & 0xff, 0x55, 0xc4, 18962 // 'und' language (undetermined) 18963 0x00, 0x00])); 18964 }; 18965 MP4.mdia = function mdia(track) { 18966 return MP4.box(MP4.types.mdia, MP4.mdhd(track.timescale, track.duration), MP4.hdlr(track.type), MP4.minf(track)); 18967 }; 18968 MP4.mfhd = function mfhd(sequenceNumber) { 18969 return MP4.box(MP4.types.mfhd, new Uint8Array([0x00, 0x00, 0x00, 0x00, 18970 // flags 18971 sequenceNumber >> 24, sequenceNumber >> 16 & 0xff, sequenceNumber >> 8 & 0xff, sequenceNumber & 0xff // sequence_number 18972 ])); 18973 }; 18974 MP4.minf = function minf(track) { 18975 if (track.type === 'audio') { 18976 return MP4.box(MP4.types.minf, MP4.box(MP4.types.smhd, MP4.SMHD), MP4.DINF, MP4.stbl(track)); 18977 } else { 18978 return MP4.box(MP4.types.minf, MP4.box(MP4.types.vmhd, MP4.VMHD), MP4.DINF, MP4.stbl(track)); 18979 } 18980 }; 18981 MP4.moof = function moof(sn, baseMediaDecodeTime, track) { 18982 return MP4.box(MP4.types.moof, MP4.mfhd(sn), MP4.traf(track, baseMediaDecodeTime)); 18983 } 18984 18985 /** 18986 * @param tracks... (optional) {array} the tracks associated with this movie 18987 */; 18988 MP4.moov = function moov(tracks) { 18989 var i = tracks.length; 18990 var boxes = []; 18991 while (i--) { 18992 boxes[i] = MP4.trak(tracks[i]); 18993 } 18994 return MP4.box.apply(null, [MP4.types.moov, MP4.mvhd(tracks[0].timescale, tracks[0].duration)].concat(boxes).concat(MP4.mvex(tracks))); 18995 }; 18996 MP4.mvex = function mvex(tracks) { 18997 var i = tracks.length; 18998 var boxes = []; 18999 while (i--) { 19000 boxes[i] = MP4.trex(tracks[i]); 19001 } 19002 return MP4.box.apply(null, [MP4.types.mvex].concat(boxes)); 19003 }; 19004 MP4.mvhd = function mvhd(timescale, duration) { 19005 duration *= timescale; 19006 var upperWordDuration = Math.floor(duration / (UINT32_MAX + 1)); 19007 var lowerWordDuration = Math.floor(duration % (UINT32_MAX + 1)); 19008 var bytes = new Uint8Array([0x01, 19009 // version 1 19010 0x00, 0x00, 0x00, 19011 // flags 19012 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 19013 // creation_time 19014 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 19015 // modification_time 19016 timescale >> 24 & 0xff, timescale >> 16 & 0xff, timescale >> 8 & 0xff, timescale & 0xff, 19017 // timescale 19018 upperWordDuration >> 24, upperWordDuration >> 16 & 0xff, upperWordDuration >> 8 & 0xff, upperWordDuration & 0xff, lowerWordDuration >> 24, lowerWordDuration >> 16 & 0xff, lowerWordDuration >> 8 & 0xff, lowerWordDuration & 0xff, 0x00, 0x01, 0x00, 0x00, 19019 // 1.0 rate 19020 0x01, 0x00, 19021 // 1.0 volume 19022 0x00, 0x00, 19023 // reserved 19024 0x00, 0x00, 0x00, 0x00, 19025 // reserved 19026 0x00, 0x00, 0x00, 0x00, 19027 // reserved 19028 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 19029 // transformation: unity matrix 19030 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 19031 // pre_defined 19032 0xff, 0xff, 0xff, 0xff // next_track_ID 19033 ]); 19034 19035 return MP4.box(MP4.types.mvhd, bytes); 19036 }; 19037 MP4.sdtp = function sdtp(track) { 19038 var samples = track.samples || []; 19039 var bytes = new Uint8Array(4 + samples.length); 19040 var i; 19041 var flags; 19042 // leave the full box header (4 bytes) all zero 19043 // write the sample table 19044 for (i = 0; i < samples.length; i++) { 19045 flags = samples[i].flags; 19046 bytes[i + 4] = flags.dependsOn << 4 | flags.isDependedOn << 2 | flags.hasRedundancy; 19047 } 19048 return MP4.box(MP4.types.sdtp, bytes); 19049 }; 19050 MP4.stbl = function stbl(track) { 19051 return MP4.box(MP4.types.stbl, MP4.stsd(track), MP4.box(MP4.types.stts, MP4.STTS), MP4.box(MP4.types.stsc, MP4.STSC), MP4.box(MP4.types.stsz, MP4.STSZ), MP4.box(MP4.types.stco, MP4.STCO)); 19052 }; 19053 MP4.avc1 = function avc1(track) { 19054 var sps = []; 19055 var pps = []; 19056 var i; 19057 var data; 19058 var len; 19059 // assemble the SPSs 19060 19061 for (i = 0; i < track.sps.length; i++) { 19062 data = track.sps[i]; 19063 len = data.byteLength; 19064 sps.push(len >>> 8 & 0xff); 19065 sps.push(len & 0xff); 19066 19067 // SPS 19068 sps = sps.concat(Array.prototype.slice.call(data)); 19069 } 19070 19071 // assemble the PPSs 19072 for (i = 0; i < track.pps.length; i++) { 19073 data = track.pps[i]; 19074 len = data.byteLength; 19075 pps.push(len >>> 8 & 0xff); 19076 pps.push(len & 0xff); 19077 pps = pps.concat(Array.prototype.slice.call(data)); 19078 } 19079 var avcc = MP4.box(MP4.types.avcC, new Uint8Array([0x01, 19080 // version 19081 sps[3], 19082 // profile 19083 sps[4], 19084 // profile compat 19085 sps[5], 19086 // level 19087 0xfc | 3, 19088 // lengthSizeMinusOne, hard-coded to 4 bytes 19089 0xe0 | track.sps.length // 3bit reserved (111) + numOfSequenceParameterSets 19090 ].concat(sps).concat([track.pps.length // numOfPictureParameterSets 19091 ]).concat(pps))); // "PPS" 19092 var width = track.width; 19093 var height = track.height; 19094 var hSpacing = track.pixelRatio[0]; 19095 var vSpacing = track.pixelRatio[1]; 19096 return MP4.box(MP4.types.avc1, new Uint8Array([0x00, 0x00, 0x00, 19097 // reserved 19098 0x00, 0x00, 0x00, 19099 // reserved 19100 0x00, 0x01, 19101 // data_reference_index 19102 0x00, 0x00, 19103 // pre_defined 19104 0x00, 0x00, 19105 // reserved 19106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 19107 // pre_defined 19108 width >> 8 & 0xff, width & 0xff, 19109 // width 19110 height >> 8 & 0xff, height & 0xff, 19111 // height 19112 0x00, 0x48, 0x00, 0x00, 19113 // horizresolution 19114 0x00, 0x48, 0x00, 0x00, 19115 // vertresolution 19116 0x00, 0x00, 0x00, 0x00, 19117 // reserved 19118 0x00, 0x01, 19119 // frame_count 19120 0x12, 0x64, 0x61, 0x69, 0x6c, 19121 // dailymotion/hls.js 19122 0x79, 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x68, 0x6c, 0x73, 0x2e, 0x6a, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 19123 // compressorname 19124 0x00, 0x18, 19125 // depth = 24 19126 0x11, 0x11]), 19127 // pre_defined = -1 19128 avcc, MP4.box(MP4.types.btrt, new Uint8Array([0x00, 0x1c, 0x9c, 0x80, 19129 // bufferSizeDB 19130 0x00, 0x2d, 0xc6, 0xc0, 19131 // maxBitrate 19132 0x00, 0x2d, 0xc6, 0xc0])), 19133 // avgBitrate 19134 MP4.box(MP4.types.pasp, new Uint8Array([hSpacing >> 24, 19135 // hSpacing 19136 hSpacing >> 16 & 0xff, hSpacing >> 8 & 0xff, hSpacing & 0xff, vSpacing >> 24, 19137 // vSpacing 19138 vSpacing >> 16 & 0xff, vSpacing >> 8 & 0xff, vSpacing & 0xff]))); 19139 }; 19140 MP4.esds = function esds(track) { 19141 var configlen = track.config.length; 19142 return new Uint8Array([0x00, 19143 // version 0 19144 0x00, 0x00, 0x00, 19145 // flags 19146 19147 0x03, 19148 // descriptor_type 19149 0x17 + configlen, 19150 // length 19151 0x00, 0x01, 19152 // es_id 19153 0x00, 19154 // stream_priority 19155 19156 0x04, 19157 // descriptor_type 19158 0x0f + configlen, 19159 // length 19160 0x40, 19161 // codec : mpeg4_audio 19162 0x15, 19163 // stream_type 19164 0x00, 0x00, 0x00, 19165 // buffer_size 19166 0x00, 0x00, 0x00, 0x00, 19167 // maxBitrate 19168 0x00, 0x00, 0x00, 0x00, 19169 // avgBitrate 19170 19171 0x05 // descriptor_type 19172 ].concat([configlen]).concat(track.config).concat([0x06, 0x01, 0x02])); // GASpecificConfig)); // length + audio config descriptor 19173 }; 19174 MP4.mp4a = function mp4a(track) { 19175 var samplerate = track.samplerate; 19176 return MP4.box(MP4.types.mp4a, new Uint8Array([0x00, 0x00, 0x00, 19177 // reserved 19178 0x00, 0x00, 0x00, 19179 // reserved 19180 0x00, 0x01, 19181 // data_reference_index 19182 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 19183 // reserved 19184 0x00, track.channelCount, 19185 // channelcount 19186 0x00, 0x10, 19187 // sampleSize:16bits 19188 0x00, 0x00, 0x00, 0x00, 19189 // reserved2 19190 samplerate >> 8 & 0xff, samplerate & 0xff, 19191 // 19192 0x00, 0x00]), MP4.box(MP4.types.esds, MP4.esds(track))); 19193 }; 19194 MP4.mp3 = function mp3(track) { 19195 var samplerate = track.samplerate; 19196 return MP4.box(MP4.types['.mp3'], new Uint8Array([0x00, 0x00, 0x00, 19197 // reserved 19198 0x00, 0x00, 0x00, 19199 // reserved 19200 0x00, 0x01, 19201 // data_reference_index 19202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 19203 // reserved 19204 0x00, track.channelCount, 19205 // channelcount 19206 0x00, 0x10, 19207 // sampleSize:16bits 19208 0x00, 0x00, 0x00, 0x00, 19209 // reserved2 19210 samplerate >> 8 & 0xff, samplerate & 0xff, 19211 // 19212 0x00, 0x00])); 19213 }; 19214 MP4.stsd = function stsd(track) { 19215 if (track.type === 'audio') { 19216 if (track.segmentCodec === 'mp3' && track.codec === 'mp3') { 19217 return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp3(track)); 19218 } 19219 return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp4a(track)); 19220 } else { 19221 return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track)); 19222 } 19223 }; 19224 MP4.tkhd = function tkhd(track) { 19225 var id = track.id; 19226 var duration = track.duration * track.timescale; 19227 var width = track.width; 19228 var height = track.height; 19229 var upperWordDuration = Math.floor(duration / (UINT32_MAX + 1)); 19230 var lowerWordDuration = Math.floor(duration % (UINT32_MAX + 1)); 19231 return MP4.box(MP4.types.tkhd, new Uint8Array([0x01, 19232 // version 1 19233 0x00, 0x00, 0x07, 19234 // flags 19235 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 19236 // creation_time 19237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 19238 // modification_time 19239 id >> 24 & 0xff, id >> 16 & 0xff, id >> 8 & 0xff, id & 0xff, 19240 // track_ID 19241 0x00, 0x00, 0x00, 0x00, 19242 // reserved 19243 upperWordDuration >> 24, upperWordDuration >> 16 & 0xff, upperWordDuration >> 8 & 0xff, upperWordDuration & 0xff, lowerWordDuration >> 24, lowerWordDuration >> 16 & 0xff, lowerWordDuration >> 8 & 0xff, lowerWordDuration & 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 19244 // reserved 19245 0x00, 0x00, 19246 // layer 19247 0x00, 0x00, 19248 // alternate_group 19249 0x00, 0x00, 19250 // non-audio track volume 19251 0x00, 0x00, 19252 // reserved 19253 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 19254 // transformation: unity matrix 19255 width >> 8 & 0xff, width & 0xff, 0x00, 0x00, 19256 // width 19257 height >> 8 & 0xff, height & 0xff, 0x00, 0x00 // height 19258 ])); 19259 }; 19260 MP4.traf = function traf(track, baseMediaDecodeTime) { 19261 var sampleDependencyTable = MP4.sdtp(track); 19262 var id = track.id; 19263 var upperWordBaseMediaDecodeTime = Math.floor(baseMediaDecodeTime / (UINT32_MAX + 1)); 19264 var lowerWordBaseMediaDecodeTime = Math.floor(baseMediaDecodeTime % (UINT32_MAX + 1)); 19265 return MP4.box(MP4.types.traf, MP4.box(MP4.types.tfhd, new Uint8Array([0x00, 19266 // version 0 19267 0x00, 0x00, 0x00, 19268 // flags 19269 id >> 24, id >> 16 & 0xff, id >> 8 & 0xff, id & 0xff // track_ID 19270 ])), MP4.box(MP4.types.tfdt, new Uint8Array([0x01, 19271 // version 1 19272 0x00, 0x00, 0x00, 19273 // flags 19274 upperWordBaseMediaDecodeTime >> 24, upperWordBaseMediaDecodeTime >> 16 & 0xff, upperWordBaseMediaDecodeTime >> 8 & 0xff, upperWordBaseMediaDecodeTime & 0xff, lowerWordBaseMediaDecodeTime >> 24, lowerWordBaseMediaDecodeTime >> 16 & 0xff, lowerWordBaseMediaDecodeTime >> 8 & 0xff, lowerWordBaseMediaDecodeTime & 0xff])), MP4.trun(track, sampleDependencyTable.length + 16 + 19275 // tfhd 19276 20 + 19277 // tfdt 19278 8 + 19279 // traf header 19280 16 + 19281 // mfhd 19282 8 + 19283 // moof header 19284 8), 19285 // mdat header 19286 sampleDependencyTable); 19287 } 19288 19289 /** 19290 * Generate a track box. 19291 * @param track {object} a track definition 19292 * @return {Uint8Array} the track box 19293 */; 19294 MP4.trak = function trak(track) { 19295 track.duration = track.duration || 0xffffffff; 19296 return MP4.box(MP4.types.trak, MP4.tkhd(track), MP4.mdia(track)); 19297 }; 19298 MP4.trex = function trex(track) { 19299 var id = track.id; 19300 return MP4.box(MP4.types.trex, new Uint8Array([0x00, 19301 // version 0 19302 0x00, 0x00, 0x00, 19303 // flags 19304 id >> 24, id >> 16 & 0xff, id >> 8 & 0xff, id & 0xff, 19305 // track_ID 19306 0x00, 0x00, 0x00, 0x01, 19307 // default_sample_description_index 19308 0x00, 0x00, 0x00, 0x00, 19309 // default_sample_duration 19310 0x00, 0x00, 0x00, 0x00, 19311 // default_sample_size 19312 0x00, 0x01, 0x00, 0x01 // default_sample_flags 19313 ])); 19314 }; 19315 MP4.trun = function trun(track, offset) { 19316 var samples = track.samples || []; 19317 var len = samples.length; 19318 var arraylen = 12 + 16 * len; 19319 var array = new Uint8Array(arraylen); 19320 var i; 19321 var sample; 19322 var duration; 19323 var size; 19324 var flags; 19325 var cts; 19326 offset += 8 + arraylen; 19327 array.set([track.type === 'video' ? 0x01 : 0x00, 19328 // version 1 for video with signed-int sample_composition_time_offset 19329 0x00, 0x0f, 0x01, 19330 // flags 19331 len >>> 24 & 0xff, len >>> 16 & 0xff, len >>> 8 & 0xff, len & 0xff, 19332 // sample_count 19333 offset >>> 24 & 0xff, offset >>> 16 & 0xff, offset >>> 8 & 0xff, offset & 0xff // data_offset 19334 ], 0); 19335 for (i = 0; i < len; i++) { 19336 sample = samples[i]; 19337 duration = sample.duration; 19338 size = sample.size; 19339 flags = sample.flags; 19340 cts = sample.cts; 19341 array.set([duration >>> 24 & 0xff, duration >>> 16 & 0xff, duration >>> 8 & 0xff, duration & 0xff, 19342 // sample_duration 19343 size >>> 24 & 0xff, size >>> 16 & 0xff, size >>> 8 & 0xff, size & 0xff, 19344 // sample_size 19345 flags.isLeading << 2 | flags.dependsOn, flags.isDependedOn << 6 | flags.hasRedundancy << 4 | flags.paddingValue << 1 | flags.isNonSync, flags.degradPrio & 0xf0 << 8, flags.degradPrio & 0x0f, 19346 // sample_flags 19347 cts >>> 24 & 0xff, cts >>> 16 & 0xff, cts >>> 8 & 0xff, cts & 0xff // sample_composition_time_offset 19348 ], 12 + 16 * i); 19349 } 19350 return MP4.box(MP4.types.trun, array); 19351 }; 19352 MP4.initSegment = function initSegment(tracks) { 19353 if (!MP4.types) { 19354 MP4.init(); 19355 } 19356 var movie = MP4.moov(tracks); 19357 var result = new Uint8Array(MP4.FTYP.byteLength + movie.byteLength); 19358 result.set(MP4.FTYP); 19359 result.set(movie, MP4.FTYP.byteLength); 19360 return result; 19361 }; 19362 return MP4; 19363}(); 19364MP4.types = void 0; 19365MP4.HDLR_TYPES = void 0; 19366MP4.STTS = void 0; 19367MP4.STSC = void 0; 19368MP4.STCO = void 0; 19369MP4.STSZ = void 0; 19370MP4.VMHD = void 0; 19371MP4.SMHD = void 0; 19372MP4.STSD = void 0; 19373MP4.FTYP = void 0; 19374MP4.DINF = void 0; 19375/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (MP4); 19376 19377/***/ }), 19378 19379/***/ "./src/remux/mp4-remuxer.ts": 19380/*!**********************************!*\ 19381 !*** ./src/remux/mp4-remuxer.ts ***! 19382 \**********************************/ 19383/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 19384 19385"use strict"; 19386__webpack_require__.r(__webpack_exports__); 19387/* harmony export */ __webpack_require__.d(__webpack_exports__, { 19388/* harmony export */ "default": () => (/* binding */ MP4Remuxer), 19389/* harmony export */ "flushTextTrackMetadataCueSamples": () => (/* binding */ flushTextTrackMetadataCueSamples), 19390/* harmony export */ "flushTextTrackUserdataCueSamples": () => (/* binding */ flushTextTrackUserdataCueSamples), 19391/* harmony export */ "normalizePts": () => (/* binding */ normalizePts) 19392/* harmony export */ }); 19393/* harmony import */ var _home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.ts"); 19394/* harmony import */ var _aac_helper__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./aac-helper */ "./src/remux/aac-helper.ts"); 19395/* harmony import */ var _mp4_generator__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./mp4-generator */ "./src/remux/mp4-generator.ts"); 19396/* harmony import */ var _events__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../events */ "./src/events.ts"); 19397/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../errors */ "./src/errors.ts"); 19398/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 19399/* harmony import */ var _types_loader__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../types/loader */ "./src/types/loader.ts"); 19400/* harmony import */ var _utils_timescale_conversion__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../utils/timescale-conversion */ "./src/utils/timescale-conversion.ts"); 19401 19402function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } 19403 19404 19405 19406 19407 19408 19409 19410var MAX_SILENT_FRAME_DURATION = 10 * 1000; // 10 seconds 19411var AAC_SAMPLES_PER_FRAME = 1024; 19412var MPEG_AUDIO_SAMPLE_PER_FRAME = 1152; 19413var chromeVersion = null; 19414var safariWebkitVersion = null; 19415var MP4Remuxer = /*#__PURE__*/function () { 19416 function MP4Remuxer(observer, config, typeSupported, vendor) { 19417 if (vendor === void 0) { 19418 vendor = ''; 19419 } 19420 this.observer = void 0; 19421 this.config = void 0; 19422 this.typeSupported = void 0; 19423 this.ISGenerated = false; 19424 this._initPTS = void 0; 19425 this._initDTS = void 0; 19426 this.nextAvcDts = null; 19427 this.nextAudioPts = null; 19428 this.videoSampleDuration = null; 19429 this.isAudioContiguous = false; 19430 this.isVideoContiguous = false; 19431 this.observer = observer; 19432 this.config = config; 19433 this.typeSupported = typeSupported; 19434 this.ISGenerated = false; 19435 if (chromeVersion === null) { 19436 var userAgent = navigator.userAgent || ''; 19437 var result = userAgent.match(/Chrome\/(\d+)/i); 19438 chromeVersion = result ? parseInt(result[1]) : 0; 19439 } 19440 if (safariWebkitVersion === null) { 19441 var _result = navigator.userAgent.match(/Safari\/(\d+)/i); 19442 safariWebkitVersion = _result ? parseInt(_result[1]) : 0; 19443 } 19444 } 19445 var _proto = MP4Remuxer.prototype; 19446 _proto.destroy = function destroy() {}; 19447 _proto.resetTimeStamp = function resetTimeStamp(defaultTimeStamp) { 19448 _utils_logger__WEBPACK_IMPORTED_MODULE_5__.logger.log('[mp4-remuxer]: initPTS & initDTS reset'); 19449 this._initPTS = this._initDTS = defaultTimeStamp; 19450 }; 19451 _proto.resetNextTimestamp = function resetNextTimestamp() { 19452 _utils_logger__WEBPACK_IMPORTED_MODULE_5__.logger.log('[mp4-remuxer]: reset next timestamp'); 19453 this.isVideoContiguous = false; 19454 this.isAudioContiguous = false; 19455 }; 19456 _proto.resetInitSegment = function resetInitSegment() { 19457 _utils_logger__WEBPACK_IMPORTED_MODULE_5__.logger.log('[mp4-remuxer]: ISGenerated flag reset'); 19458 this.ISGenerated = false; 19459 }; 19460 _proto.getVideoStartPts = function getVideoStartPts(videoSamples) { 19461 var rolloverDetected = false; 19462 var startPTS = videoSamples.reduce(function (minPTS, sample) { 19463 var delta = sample.pts - minPTS; 19464 if (delta < -4294967296) { 19465 // 2^32, see PTSNormalize for reasoning, but we're hitting a rollover here, and we don't want that to impact the timeOffset calculation 19466 rolloverDetected = true; 19467 return normalizePts(minPTS, sample.pts); 19468 } else if (delta > 0) { 19469 return minPTS; 19470 } else { 19471 return sample.pts; 19472 } 19473 }, videoSamples[0].pts); 19474 if (rolloverDetected) { 19475 _utils_logger__WEBPACK_IMPORTED_MODULE_5__.logger.debug('PTS rollover detected'); 19476 } 19477 return startPTS; 19478 }; 19479 _proto.remux = function remux(audioTrack, videoTrack, id3Track, textTrack, timeOffset, accurateTimeOffset, flush, playlistType) { 19480 var video; 19481 var audio; 19482 var initSegment; 19483 var text; 19484 var id3; 19485 var independent; 19486 var audioTimeOffset = timeOffset; 19487 var videoTimeOffset = timeOffset; 19488 19489 // If we're remuxing audio and video progressively, wait until we've received enough samples for each track before proceeding. 19490 // This is done to synchronize the audio and video streams. We know if the current segment will have samples if the "pid" 19491 // parameter is greater than -1. The pid is set when the PMT is parsed, which contains the tracks list. 19492 // However, if the initSegment has already been generated, or we've reached the end of a segment (flush), 19493 // then we can remux one track without waiting for the other. 19494 var hasAudio = audioTrack.pid > -1; 19495 var hasVideo = videoTrack.pid > -1; 19496 var length = videoTrack.samples.length; 19497 var enoughAudioSamples = audioTrack.samples.length > 0; 19498 var enoughVideoSamples = flush && length > 0 || length > 1; 19499 var canRemuxAvc = (!hasAudio || enoughAudioSamples) && (!hasVideo || enoughVideoSamples) || this.ISGenerated || flush; 19500 if (canRemuxAvc) { 19501 if (!this.ISGenerated) { 19502 initSegment = this.generateIS(audioTrack, videoTrack, timeOffset); 19503 } 19504 var isVideoContiguous = this.isVideoContiguous; 19505 var firstKeyFrameIndex = -1; 19506 var firstKeyFramePTS; 19507 if (enoughVideoSamples) { 19508 firstKeyFrameIndex = findKeyframeIndex(videoTrack.samples); 19509 if (!isVideoContiguous && this.config.forceKeyFrameOnDiscontinuity) { 19510 independent = true; 19511 if (firstKeyFrameIndex > 0) { 19512 _utils_logger__WEBPACK_IMPORTED_MODULE_5__.logger.warn("[mp4-remuxer]: Dropped " + firstKeyFrameIndex + " out of " + length + " video samples due to a missing keyframe"); 19513 var startPTS = this.getVideoStartPts(videoTrack.samples); 19514 videoTrack.samples = videoTrack.samples.slice(firstKeyFrameIndex); 19515 videoTrack.dropped += firstKeyFrameIndex; 19516 videoTimeOffset += (videoTrack.samples[0].pts - startPTS) / videoTrack.inputTimeScale; 19517 firstKeyFramePTS = videoTimeOffset; 19518 } else if (firstKeyFrameIndex === -1) { 19519 _utils_logger__WEBPACK_IMPORTED_MODULE_5__.logger.warn("[mp4-remuxer]: No keyframe found out of " + length + " video samples"); 19520 independent = false; 19521 } 19522 } 19523 } 19524 if (this.ISGenerated) { 19525 if (enoughAudioSamples && enoughVideoSamples) { 19526 // timeOffset is expected to be the offset of the first timestamp of this fragment (first DTS) 19527 // if first audio DTS is not aligned with first video DTS then we need to take that into account 19528 // when providing timeOffset to remuxAudio / remuxVideo. if we don't do that, there might be a permanent / small 19529 // drift between audio and video streams 19530 var _startPTS = this.getVideoStartPts(videoTrack.samples); 19531 var tsDelta = normalizePts(audioTrack.samples[0].pts, _startPTS) - _startPTS; 19532 var audiovideoTimestampDelta = tsDelta / videoTrack.inputTimeScale; 19533 audioTimeOffset += Math.max(0, audiovideoTimestampDelta); 19534 videoTimeOffset += Math.max(0, -audiovideoTimestampDelta); 19535 } 19536 19537 // Purposefully remuxing audio before video, so that remuxVideo can use nextAudioPts, which is calculated in remuxAudio. 19538 if (enoughAudioSamples) { 19539 // if initSegment was generated without audio samples, regenerate it again 19540 if (!audioTrack.samplerate) { 19541 _utils_logger__WEBPACK_IMPORTED_MODULE_5__.logger.warn('[mp4-remuxer]: regenerate InitSegment as audio detected'); 19542 initSegment = this.generateIS(audioTrack, videoTrack, timeOffset); 19543 } 19544 audio = this.remuxAudio(audioTrack, audioTimeOffset, this.isAudioContiguous, accurateTimeOffset, hasVideo || enoughVideoSamples || playlistType === _types_loader__WEBPACK_IMPORTED_MODULE_6__.PlaylistLevelType.AUDIO ? videoTimeOffset : undefined); 19545 if (enoughVideoSamples) { 19546 var audioTrackLength = audio ? audio.endPTS - audio.startPTS : 0; 19547 // if initSegment was generated without video samples, regenerate it again 19548 if (!videoTrack.inputTimeScale) { 19549 _utils_logger__WEBPACK_IMPORTED_MODULE_5__.logger.warn('[mp4-remuxer]: regenerate InitSegment as video detected'); 19550 initSegment = this.generateIS(audioTrack, videoTrack, timeOffset); 19551 } 19552 video = this.remuxVideo(videoTrack, videoTimeOffset, isVideoContiguous, audioTrackLength); 19553 } 19554 } else if (enoughVideoSamples) { 19555 video = this.remuxVideo(videoTrack, videoTimeOffset, isVideoContiguous, 0); 19556 } 19557 if (video) { 19558 video.firstKeyFrame = firstKeyFrameIndex; 19559 video.independent = firstKeyFrameIndex !== -1; 19560 video.firstKeyFramePTS = firstKeyFramePTS; 19561 } 19562 } 19563 } 19564 19565 // Allow ID3 and text to remux, even if more audio/video samples are required 19566 if (this.ISGenerated) { 19567 if (id3Track.samples.length) { 19568 id3 = flushTextTrackMetadataCueSamples(id3Track, timeOffset, this._initPTS, this._initDTS); 19569 } 19570 if (textTrack.samples.length) { 19571 text = flushTextTrackUserdataCueSamples(textTrack, timeOffset, this._initPTS); 19572 } 19573 } 19574 return { 19575 audio: audio, 19576 video: video, 19577 initSegment: initSegment, 19578 independent: independent, 19579 text: text, 19580 id3: id3 19581 }; 19582 }; 19583 _proto.generateIS = function generateIS(audioTrack, videoTrack, timeOffset) { 19584 var audioSamples = audioTrack.samples; 19585 var videoSamples = videoTrack.samples; 19586 var typeSupported = this.typeSupported; 19587 var tracks = {}; 19588 var computePTSDTS = !(0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(this._initPTS); 19589 var container = 'audio/mp4'; 19590 var initPTS; 19591 var initDTS; 19592 var timescale; 19593 if (computePTSDTS) { 19594 initPTS = initDTS = Infinity; 19595 } 19596 if (audioTrack.config && audioSamples.length) { 19597 // let's use audio sampling rate as MP4 time scale. 19598 // rationale is that there is a integer nb of audio frames per audio sample (1024 for AAC) 19599 // using audio sampling rate here helps having an integer MP4 frame duration 19600 // this avoids potential rounding issue and AV sync issue 19601 audioTrack.timescale = audioTrack.samplerate; 19602 switch (audioTrack.segmentCodec) { 19603 case 'mp3': 19604 if (typeSupported.mpeg) { 19605 // Chrome and Safari 19606 container = 'audio/mpeg'; 19607 audioTrack.codec = ''; 19608 } else if (typeSupported.mp3) { 19609 // Firefox 19610 audioTrack.codec = 'mp3'; 19611 } 19612 break; 19613 } 19614 tracks.audio = { 19615 id: 'audio', 19616 container: container, 19617 codec: audioTrack.codec, 19618 initSegment: audioTrack.segmentCodec === 'mp3' && typeSupported.mpeg ? new Uint8Array(0) : _mp4_generator__WEBPACK_IMPORTED_MODULE_2__["default"].initSegment([audioTrack]), 19619 metadata: { 19620 channelCount: audioTrack.channelCount 19621 } 19622 }; 19623 if (computePTSDTS) { 19624 timescale = audioTrack.inputTimeScale; 19625 // remember first PTS of this demuxing context. for audio, PTS = DTS 19626 initPTS = initDTS = audioSamples[0].pts - Math.round(timescale * timeOffset); 19627 } 19628 } 19629 if (videoTrack.sps && videoTrack.pps && videoSamples.length) { 19630 // let's use input time scale as MP4 video timescale 19631 // we use input time scale straight away to avoid rounding issues on frame duration / cts computation 19632 videoTrack.timescale = videoTrack.inputTimeScale; 19633 tracks.video = { 19634 id: 'main', 19635 container: 'video/mp4', 19636 codec: videoTrack.codec, 19637 initSegment: _mp4_generator__WEBPACK_IMPORTED_MODULE_2__["default"].initSegment([videoTrack]), 19638 metadata: { 19639 width: videoTrack.width, 19640 height: videoTrack.height 19641 } 19642 }; 19643 if (computePTSDTS) { 19644 timescale = videoTrack.inputTimeScale; 19645 var startPTS = this.getVideoStartPts(videoSamples); 19646 var startOffset = Math.round(timescale * timeOffset); 19647 initDTS = Math.min(initDTS, normalizePts(videoSamples[0].dts, startPTS) - startOffset); 19648 initPTS = Math.min(initPTS, startPTS - startOffset); 19649 } 19650 } 19651 if (Object.keys(tracks).length) { 19652 this.ISGenerated = true; 19653 if (computePTSDTS) { 19654 this._initPTS = initPTS; 19655 this._initDTS = initDTS; 19656 } 19657 return { 19658 tracks: tracks, 19659 initPTS: initPTS, 19660 timescale: timescale 19661 }; 19662 } 19663 }; 19664 _proto.remuxVideo = function remuxVideo(track, timeOffset, contiguous, audioTrackLength) { 19665 var timeScale = track.inputTimeScale; 19666 var inputSamples = track.samples; 19667 var outputSamples = []; 19668 var nbSamples = inputSamples.length; 19669 var initPTS = this._initPTS; 19670 var nextAvcDts = this.nextAvcDts; 19671 var offset = 8; 19672 var mp4SampleDuration = this.videoSampleDuration; 19673 var firstDTS; 19674 var lastDTS; 19675 var minPTS = Number.POSITIVE_INFINITY; 19676 var maxPTS = Number.NEGATIVE_INFINITY; 19677 var sortSamples = false; 19678 19679 // if parsed fragment is contiguous with last one, let's use last DTS value as reference 19680 if (!contiguous || nextAvcDts === null) { 19681 var pts = timeOffset * timeScale; 19682 var cts = inputSamples[0].pts - normalizePts(inputSamples[0].dts, inputSamples[0].pts); 19683 // if not contiguous, let's use target timeOffset 19684 nextAvcDts = pts - cts; 19685 } 19686 19687 // PTS is coded on 33bits, and can loop from -2^32 to 2^32 19688 // PTSNormalize will make PTS/DTS value monotonic, we use last known DTS value as reference value 19689 for (var i = 0; i < nbSamples; i++) { 19690 var sample = inputSamples[i]; 19691 sample.pts = normalizePts(sample.pts - initPTS, nextAvcDts); 19692 sample.dts = normalizePts(sample.dts - initPTS, nextAvcDts); 19693 if (sample.dts < inputSamples[i > 0 ? i - 1 : i].dts) { 19694 sortSamples = true; 19695 } 19696 } 19697 19698 // sort video samples by DTS then PTS then demux id order 19699 if (sortSamples) { 19700 inputSamples.sort(function (a, b) { 19701 var deltadts = a.dts - b.dts; 19702 var deltapts = a.pts - b.pts; 19703 return deltadts || deltapts; 19704 }); 19705 } 19706 19707 // Get first/last DTS 19708 firstDTS = inputSamples[0].dts; 19709 lastDTS = inputSamples[inputSamples.length - 1].dts; 19710 19711 // Sample duration (as expected by trun MP4 boxes), should be the delta between sample DTS 19712 // set this constant duration as being the avg delta between consecutive DTS. 19713 var inputDuration = lastDTS - firstDTS; 19714 var averageSampleDuration = inputDuration ? Math.round(inputDuration / (nbSamples - 1)) : mp4SampleDuration || track.inputTimeScale / 30; 19715 19716 // if fragment are contiguous, detect hole/overlapping between fragments 19717 if (contiguous) { 19718 // check timestamp continuity across consecutive fragments (this is to remove inter-fragment gap/hole) 19719 var delta = firstDTS - nextAvcDts; 19720 var foundHole = delta > averageSampleDuration; 19721 var foundOverlap = delta < -1; 19722 if (foundHole || foundOverlap) { 19723 if (foundHole) { 19724 _utils_logger__WEBPACK_IMPORTED_MODULE_5__.logger.warn("AVC: " + (0,_utils_timescale_conversion__WEBPACK_IMPORTED_MODULE_7__.toMsFromMpegTsClock)(delta, true) + " ms (" + delta + "dts) hole between fragments detected, filling it"); 19725 } else { 19726 _utils_logger__WEBPACK_IMPORTED_MODULE_5__.logger.warn("AVC: " + (0,_utils_timescale_conversion__WEBPACK_IMPORTED_MODULE_7__.toMsFromMpegTsClock)(-delta, true) + " ms (" + delta + "dts) overlapping between fragments detected"); 19727 } 19728 if (!foundOverlap || nextAvcDts > inputSamples[0].pts) { 19729 firstDTS = nextAvcDts; 19730 var firstPTS = inputSamples[0].pts - delta; 19731 inputSamples[0].dts = firstDTS; 19732 inputSamples[0].pts = firstPTS; 19733 _utils_logger__WEBPACK_IMPORTED_MODULE_5__.logger.log("Video: First PTS/DTS adjusted: " + (0,_utils_timescale_conversion__WEBPACK_IMPORTED_MODULE_7__.toMsFromMpegTsClock)(firstPTS, true) + "/" + (0,_utils_timescale_conversion__WEBPACK_IMPORTED_MODULE_7__.toMsFromMpegTsClock)(firstDTS, true) + ", delta: " + (0,_utils_timescale_conversion__WEBPACK_IMPORTED_MODULE_7__.toMsFromMpegTsClock)(delta, true) + " ms"); 19734 } 19735 } 19736 } 19737 firstDTS = Math.max(0, firstDTS); 19738 var nbNalu = 0; 19739 var naluLen = 0; 19740 for (var _i = 0; _i < nbSamples; _i++) { 19741 // compute total/avc sample length and nb of NAL units 19742 var _sample = inputSamples[_i]; 19743 var units = _sample.units; 19744 var nbUnits = units.length; 19745 var sampleLen = 0; 19746 for (var j = 0; j < nbUnits; j++) { 19747 sampleLen += units[j].data.length; 19748 } 19749 naluLen += sampleLen; 19750 nbNalu += nbUnits; 19751 _sample.length = sampleLen; 19752 19753 // ensure sample monotonic DTS 19754 _sample.dts = Math.max(_sample.dts, firstDTS); 19755 minPTS = Math.min(_sample.pts, minPTS); 19756 maxPTS = Math.max(_sample.pts, maxPTS); 19757 } 19758 lastDTS = inputSamples[nbSamples - 1].dts; 19759 19760 /* concatenate the video data and construct the mdat in place 19761 (need 8 more bytes to fill length and mpdat type) */ 19762 var mdatSize = naluLen + 4 * nbNalu + 8; 19763 var mdat; 19764 try { 19765 mdat = new Uint8Array(mdatSize); 19766 } catch (err) { 19767 this.observer.emit(_events__WEBPACK_IMPORTED_MODULE_3__.Events.ERROR, _events__WEBPACK_IMPORTED_MODULE_3__.Events.ERROR, { 19768 type: _errors__WEBPACK_IMPORTED_MODULE_4__.ErrorTypes.MUX_ERROR, 19769 details: _errors__WEBPACK_IMPORTED_MODULE_4__.ErrorDetails.REMUX_ALLOC_ERROR, 19770 fatal: false, 19771 bytes: mdatSize, 19772 reason: "fail allocating video mdat " + mdatSize 19773 }); 19774 return; 19775 } 19776 var view = new DataView(mdat.buffer); 19777 view.setUint32(0, mdatSize); 19778 mdat.set(_mp4_generator__WEBPACK_IMPORTED_MODULE_2__["default"].types.mdat, 4); 19779 var stretchedLastFrame = false; 19780 var minDtsDelta = Number.POSITIVE_INFINITY; 19781 var minPtsDelta = Number.POSITIVE_INFINITY; 19782 var maxDtsDelta = Number.NEGATIVE_INFINITY; 19783 var maxPtsDelta = Number.NEGATIVE_INFINITY; 19784 for (var _i2 = 0; _i2 < nbSamples; _i2++) { 19785 var avcSample = inputSamples[_i2]; 19786 var avcSampleUnits = avcSample.units; 19787 var mp4SampleLength = 0; 19788 // convert NALU bitstream to MP4 format (prepend NALU with size field) 19789 for (var _j = 0, _nbUnits = avcSampleUnits.length; _j < _nbUnits; _j++) { 19790 var unit = avcSampleUnits[_j]; 19791 var unitData = unit.data; 19792 var unitDataLen = unit.data.byteLength; 19793 view.setUint32(offset, unitDataLen); 19794 offset += 4; 19795 mdat.set(unitData, offset); 19796 offset += unitDataLen; 19797 mp4SampleLength += 4 + unitDataLen; 19798 } 19799 19800 // expected sample duration is the Decoding Timestamp diff of consecutive samples 19801 var ptsDelta = void 0; 19802 if (_i2 < nbSamples - 1) { 19803 mp4SampleDuration = inputSamples[_i2 + 1].dts - avcSample.dts; 19804 ptsDelta = inputSamples[_i2 + 1].pts - avcSample.pts; 19805 } else { 19806 var config = this.config; 19807 var lastFrameDuration = _i2 > 0 ? avcSample.dts - inputSamples[_i2 - 1].dts : averageSampleDuration; 19808 ptsDelta = _i2 > 0 ? avcSample.pts - inputSamples[_i2 - 1].pts : averageSampleDuration; 19809 if (config.stretchShortVideoTrack && this.nextAudioPts !== null) { 19810 // In some cases, a segment's audio track duration may exceed the video track duration. 19811 // Since we've already remuxed audio, and we know how long the audio track is, we look to 19812 // see if the delta to the next segment is longer than maxBufferHole. 19813 // If so, playback would potentially get stuck, so we artificially inflate 19814 // the duration of the last frame to minimize any potential gap between segments. 19815 var gapTolerance = Math.floor(config.maxBufferHole * timeScale); 19816 var deltaToFrameEnd = (audioTrackLength ? minPTS + audioTrackLength * timeScale : this.nextAudioPts) - avcSample.pts; 19817 if (deltaToFrameEnd > gapTolerance) { 19818 // We subtract lastFrameDuration from deltaToFrameEnd to try to prevent any video 19819 // frame overlap. maxBufferHole should be >> lastFrameDuration anyway. 19820 mp4SampleDuration = deltaToFrameEnd - lastFrameDuration; 19821 if (mp4SampleDuration < 0) { 19822 mp4SampleDuration = lastFrameDuration; 19823 } else { 19824 stretchedLastFrame = true; 19825 } 19826 _utils_logger__WEBPACK_IMPORTED_MODULE_5__.logger.log("[mp4-remuxer]: It is approximately " + deltaToFrameEnd / 90 + " ms to the next segment; using duration " + mp4SampleDuration / 90 + " ms for the last video frame."); 19827 } else { 19828 mp4SampleDuration = lastFrameDuration; 19829 } 19830 } else { 19831 mp4SampleDuration = lastFrameDuration; 19832 } 19833 } 19834 var compositionTimeOffset = Math.round(avcSample.pts - avcSample.dts); 19835 minDtsDelta = Math.min(minDtsDelta, mp4SampleDuration); 19836 maxDtsDelta = Math.max(maxDtsDelta, mp4SampleDuration); 19837 minPtsDelta = Math.min(minPtsDelta, ptsDelta); 19838 maxPtsDelta = Math.max(maxPtsDelta, ptsDelta); 19839 outputSamples.push(new Mp4Sample(avcSample.key, mp4SampleDuration, mp4SampleLength, compositionTimeOffset)); 19840 } 19841 if (outputSamples.length) { 19842 if (chromeVersion) { 19843 if (chromeVersion < 70) { 19844 // Chrome workaround, mark first sample as being a Random Access Point (keyframe) to avoid sourcebuffer append issue 19845 // https://code.google.com/p/chromium/issues/detail?id=229412 19846 var flags = outputSamples[0].flags; 19847 flags.dependsOn = 2; 19848 flags.isNonSync = 0; 19849 } 19850 } else if (safariWebkitVersion) { 19851 // Fix for "CNN special report, with CC" in test-streams (Safari browser only) 19852 // Ignore DTS when frame durations are irregular. Safari MSE does not handle this leading to gaps. 19853 if (maxPtsDelta - minPtsDelta < maxDtsDelta - minDtsDelta && averageSampleDuration / maxDtsDelta < 0.025 && outputSamples[0].cts === 0) { 19854 _utils_logger__WEBPACK_IMPORTED_MODULE_5__.logger.warn('Found irregular gaps in sample duration. Using PTS instead of DTS to determine MP4 sample duration.'); 19855 var dts = firstDTS; 19856 for (var _i3 = 0, len = outputSamples.length; _i3 < len; _i3++) { 19857 var nextDts = dts + outputSamples[_i3].duration; 19858 var _pts = dts + outputSamples[_i3].cts; 19859 if (_i3 < len - 1) { 19860 var nextPts = nextDts + outputSamples[_i3 + 1].cts; 19861 outputSamples[_i3].duration = nextPts - _pts; 19862 } else { 19863 outputSamples[_i3].duration = _i3 ? outputSamples[_i3 - 1].duration : averageSampleDuration; 19864 } 19865 outputSamples[_i3].cts = 0; 19866 dts = nextDts; 19867 } 19868 } 19869 } 19870 } 19871 console.assert(mp4SampleDuration !== null, 'mp4SampleDuration must be computed'); 19872 // next AVC sample DTS should be equal to last sample DTS + last sample duration (in PES timescale) 19873 mp4SampleDuration = stretchedLastFrame || !mp4SampleDuration ? averageSampleDuration : mp4SampleDuration; 19874 this.nextAvcDts = nextAvcDts = lastDTS + mp4SampleDuration; 19875 this.videoSampleDuration = mp4SampleDuration; 19876 this.isVideoContiguous = true; 19877 var moof = _mp4_generator__WEBPACK_IMPORTED_MODULE_2__["default"].moof(track.sequenceNumber++, firstDTS, _extends({}, track, { 19878 samples: outputSamples 19879 })); 19880 var type = 'video'; 19881 var data = { 19882 data1: moof, 19883 data2: mdat, 19884 startPTS: minPTS / timeScale, 19885 endPTS: (maxPTS + mp4SampleDuration) / timeScale, 19886 startDTS: firstDTS / timeScale, 19887 endDTS: nextAvcDts / timeScale, 19888 type: type, 19889 hasAudio: false, 19890 hasVideo: true, 19891 nb: outputSamples.length, 19892 dropped: track.dropped 19893 }; 19894 track.samples = []; 19895 track.dropped = 0; 19896 console.assert(mdat.length, 'MDAT length must not be zero'); 19897 return data; 19898 }; 19899 _proto.remuxAudio = function remuxAudio(track, timeOffset, contiguous, accurateTimeOffset, videoTimeOffset) { 19900 var inputTimeScale = track.inputTimeScale; 19901 var mp4timeScale = track.samplerate ? track.samplerate : inputTimeScale; 19902 var scaleFactor = inputTimeScale / mp4timeScale; 19903 var mp4SampleDuration = track.segmentCodec === 'aac' ? AAC_SAMPLES_PER_FRAME : MPEG_AUDIO_SAMPLE_PER_FRAME; 19904 var inputSampleDuration = mp4SampleDuration * scaleFactor; 19905 var initPTS = this._initPTS; 19906 var rawMPEG = track.segmentCodec === 'mp3' && this.typeSupported.mpeg; 19907 var outputSamples = []; 19908 var alignedWithVideo = videoTimeOffset !== undefined; 19909 var inputSamples = track.samples; 19910 var offset = rawMPEG ? 0 : 8; 19911 var nextAudioPts = this.nextAudioPts || -1; 19912 19913 // window.audioSamples ? window.audioSamples.push(inputSamples.map(s => s.pts)) : (window.audioSamples = [inputSamples.map(s => s.pts)]); 19914 19915 // for audio samples, also consider consecutive fragments as being contiguous (even if a level switch occurs), 19916 // for sake of clarity: 19917 // consecutive fragments are frags with 19918 // - less than 100ms gaps between new time offset (if accurate) and next expected PTS OR 19919 // - less than 20 audio frames distance 19920 // contiguous fragments are consecutive fragments from same quality level (same level, new SN = old SN + 1) 19921 // this helps ensuring audio continuity 19922 // and this also avoids audio glitches/cut when switching quality, or reporting wrong duration on first audio frame 19923 var timeOffsetMpegTS = timeOffset * inputTimeScale; 19924 this.isAudioContiguous = contiguous = contiguous || inputSamples.length && nextAudioPts > 0 && (accurateTimeOffset && Math.abs(timeOffsetMpegTS - nextAudioPts) < 9000 || Math.abs(normalizePts(inputSamples[0].pts - initPTS, timeOffsetMpegTS) - nextAudioPts) < 20 * inputSampleDuration); 19925 19926 // compute normalized PTS 19927 inputSamples.forEach(function (sample) { 19928 sample.pts = normalizePts(sample.pts - initPTS, timeOffsetMpegTS); 19929 }); 19930 if (!contiguous || nextAudioPts < 0) { 19931 // filter out sample with negative PTS that are not playable anyway 19932 // if we don't remove these negative samples, they will shift all audio samples forward. 19933 // leading to audio overlap between current / next fragment 19934 inputSamples = inputSamples.filter(function (sample) { 19935 return sample.pts >= 0; 19936 }); 19937 19938 // in case all samples have negative PTS, and have been filtered out, return now 19939 if (!inputSamples.length) { 19940 return; 19941 } 19942 if (videoTimeOffset === 0) { 19943 // Set the start to 0 to match video so that start gaps larger than inputSampleDuration are filled with silence 19944 nextAudioPts = 0; 19945 } else if (accurateTimeOffset && !alignedWithVideo) { 19946 // When not seeking, not live, and LevelDetails.PTSKnown, use fragment start as predicted next audio PTS 19947 nextAudioPts = Math.max(0, timeOffsetMpegTS); 19948 } else { 19949 // if frags are not contiguous and if we cant trust time offset, let's use first sample PTS as next audio PTS 19950 nextAudioPts = inputSamples[0].pts; 19951 } 19952 } 19953 19954 // If the audio track is missing samples, the frames seem to get "left-shifted" within the 19955 // resulting mp4 segment, causing sync issues and leaving gaps at the end of the audio segment. 19956 // In an effort to prevent this from happening, we inject frames here where there are gaps. 19957 // When possible, we inject a silent frame; when that's not possible, we duplicate the last 19958 // frame. 19959 19960 if (track.segmentCodec === 'aac') { 19961 var maxAudioFramesDrift = this.config.maxAudioFramesDrift; 19962 for (var i = 0, nextPts = nextAudioPts; i < inputSamples.length; i++) { 19963 // First, let's see how far off this frame is from where we expect it to be 19964 var sample = inputSamples[i]; 19965 var pts = sample.pts; 19966 var delta = pts - nextPts; 19967 var duration = Math.abs(1000 * delta / inputTimeScale); 19968 19969 // When remuxing with video, if we're overlapping by more than a duration, drop this sample to stay in sync 19970 if (delta <= -maxAudioFramesDrift * inputSampleDuration && alignedWithVideo) { 19971 if (i === 0) { 19972 _utils_logger__WEBPACK_IMPORTED_MODULE_5__.logger.warn("Audio frame @ " + (pts / inputTimeScale).toFixed(3) + "s overlaps nextAudioPts by " + Math.round(1000 * delta / inputTimeScale) + " ms."); 19973 this.nextAudioPts = nextAudioPts = nextPts = pts; 19974 } 19975 } // eslint-disable-line brace-style 19976 19977 // Insert missing frames if: 19978 // 1: We're more than maxAudioFramesDrift frame away 19979 // 2: Not more than MAX_SILENT_FRAME_DURATION away 19980 // 3: currentTime (aka nextPtsNorm) is not 0 19981 // 4: remuxing with video (videoTimeOffset !== undefined) 19982 else if (delta >= maxAudioFramesDrift * inputSampleDuration && duration < MAX_SILENT_FRAME_DURATION && alignedWithVideo) { 19983 var missing = Math.round(delta / inputSampleDuration); 19984 // Adjust nextPts so that silent samples are aligned with media pts. This will prevent media samples from 19985 // later being shifted if nextPts is based on timeOffset and delta is not a multiple of inputSampleDuration. 19986 nextPts = pts - missing * inputSampleDuration; 19987 if (nextPts < 0) { 19988 missing--; 19989 nextPts += inputSampleDuration; 19990 } 19991 if (i === 0) { 19992 this.nextAudioPts = nextAudioPts = nextPts; 19993 } 19994 _utils_logger__WEBPACK_IMPORTED_MODULE_5__.logger.warn("[mp4-remuxer]: Injecting " + missing + " audio frame @ " + (nextPts / inputTimeScale).toFixed(3) + "s due to " + Math.round(1000 * delta / inputTimeScale) + " ms gap."); 19995 for (var j = 0; j < missing; j++) { 19996 var newStamp = Math.max(nextPts, 0); 19997 var fillFrame = _aac_helper__WEBPACK_IMPORTED_MODULE_1__["default"].getSilentFrame(track.manifestCodec || track.codec, track.channelCount); 19998 if (!fillFrame) { 19999 _utils_logger__WEBPACK_IMPORTED_MODULE_5__.logger.log('[mp4-remuxer]: Unable to get silent frame for given audio codec; duplicating last frame instead.'); 20000 fillFrame = sample.unit.subarray(); 20001 } 20002 inputSamples.splice(i, 0, { 20003 unit: fillFrame, 20004 pts: newStamp 20005 }); 20006 nextPts += inputSampleDuration; 20007 i++; 20008 } 20009 } 20010 sample.pts = nextPts; 20011 nextPts += inputSampleDuration; 20012 } 20013 } 20014 var firstPTS = null; 20015 var lastPTS = null; 20016 var mdat; 20017 var mdatSize = 0; 20018 var sampleLength = inputSamples.length; 20019 while (sampleLength--) { 20020 mdatSize += inputSamples[sampleLength].unit.byteLength; 20021 } 20022 for (var _j2 = 0, _nbSamples = inputSamples.length; _j2 < _nbSamples; _j2++) { 20023 var audioSample = inputSamples[_j2]; 20024 var unit = audioSample.unit; 20025 var _pts2 = audioSample.pts; 20026 if (lastPTS !== null) { 20027 // If we have more than one sample, set the duration of the sample to the "real" duration; the PTS diff with 20028 // the previous sample 20029 var prevSample = outputSamples[_j2 - 1]; 20030 prevSample.duration = Math.round((_pts2 - lastPTS) / scaleFactor); 20031 } else { 20032 if (contiguous && track.segmentCodec === 'aac') { 20033 // set PTS/DTS to expected PTS/DTS 20034 _pts2 = nextAudioPts; 20035 } 20036 // remember first PTS of our audioSamples 20037 firstPTS = _pts2; 20038 if (mdatSize > 0) { 20039 /* concatenate the audio data and construct the mdat in place 20040 (need 8 more bytes to fill length and mdat type) */ 20041 mdatSize += offset; 20042 try { 20043 mdat = new Uint8Array(mdatSize); 20044 } catch (err) { 20045 this.observer.emit(_events__WEBPACK_IMPORTED_MODULE_3__.Events.ERROR, _events__WEBPACK_IMPORTED_MODULE_3__.Events.ERROR, { 20046 type: _errors__WEBPACK_IMPORTED_MODULE_4__.ErrorTypes.MUX_ERROR, 20047 details: _errors__WEBPACK_IMPORTED_MODULE_4__.ErrorDetails.REMUX_ALLOC_ERROR, 20048 fatal: false, 20049 bytes: mdatSize, 20050 reason: "fail allocating audio mdat " + mdatSize 20051 }); 20052 return; 20053 } 20054 if (!rawMPEG) { 20055 var view = new DataView(mdat.buffer); 20056 view.setUint32(0, mdatSize); 20057 mdat.set(_mp4_generator__WEBPACK_IMPORTED_MODULE_2__["default"].types.mdat, 4); 20058 } 20059 } else { 20060 // no audio samples 20061 return; 20062 } 20063 } 20064 mdat.set(unit, offset); 20065 var unitLen = unit.byteLength; 20066 offset += unitLen; 20067 // Default the sample's duration to the computed mp4SampleDuration, which will either be 1024 for AAC or 1152 for MPEG 20068 // In the case that we have 1 sample, this will be the duration. If we have more than one sample, the duration 20069 // becomes the PTS diff with the previous sample 20070 outputSamples.push(new Mp4Sample(true, mp4SampleDuration, unitLen, 0)); 20071 lastPTS = _pts2; 20072 } 20073 20074 // We could end up with no audio samples if all input samples were overlapping with the previously remuxed ones 20075 var nbSamples = outputSamples.length; 20076 if (!nbSamples) { 20077 return; 20078 } 20079 20080 // The next audio sample PTS should be equal to last sample PTS + duration 20081 var lastSample = outputSamples[outputSamples.length - 1]; 20082 this.nextAudioPts = nextAudioPts = lastPTS + scaleFactor * lastSample.duration; 20083 20084 // Set the track samples from inputSamples to outputSamples before remuxing 20085 var moof = rawMPEG ? new Uint8Array(0) : _mp4_generator__WEBPACK_IMPORTED_MODULE_2__["default"].moof(track.sequenceNumber++, firstPTS / scaleFactor, _extends({}, track, { 20086 samples: outputSamples 20087 })); 20088 20089 // Clear the track samples. This also clears the samples array in the demuxer, since the reference is shared 20090 track.samples = []; 20091 var start = firstPTS / inputTimeScale; 20092 var end = nextAudioPts / inputTimeScale; 20093 var type = 'audio'; 20094 var audioData = { 20095 data1: moof, 20096 data2: mdat, 20097 startPTS: start, 20098 endPTS: end, 20099 startDTS: start, 20100 endDTS: end, 20101 type: type, 20102 hasAudio: true, 20103 hasVideo: false, 20104 nb: nbSamples 20105 }; 20106 this.isAudioContiguous = true; 20107 console.assert(mdat.length, 'MDAT length must not be zero'); 20108 return audioData; 20109 }; 20110 _proto.remuxEmptyAudio = function remuxEmptyAudio(track, timeOffset, contiguous, videoData) { 20111 var inputTimeScale = track.inputTimeScale; 20112 var mp4timeScale = track.samplerate ? track.samplerate : inputTimeScale; 20113 var scaleFactor = inputTimeScale / mp4timeScale; 20114 var nextAudioPts = this.nextAudioPts; 20115 // sync with video's timestamp 20116 var startDTS = (nextAudioPts !== null ? nextAudioPts : videoData.startDTS * inputTimeScale) + this._initDTS; 20117 var endDTS = videoData.endDTS * inputTimeScale + this._initDTS; 20118 // one sample's duration value 20119 var frameDuration = scaleFactor * AAC_SAMPLES_PER_FRAME; 20120 // samples count of this segment's duration 20121 var nbSamples = Math.ceil((endDTS - startDTS) / frameDuration); 20122 // silent frame 20123 var silentFrame = _aac_helper__WEBPACK_IMPORTED_MODULE_1__["default"].getSilentFrame(track.manifestCodec || track.codec, track.channelCount); 20124 _utils_logger__WEBPACK_IMPORTED_MODULE_5__.logger.warn('[mp4-remuxer]: remux empty Audio'); 20125 // Can't remux if we can't generate a silent frame... 20126 if (!silentFrame) { 20127 _utils_logger__WEBPACK_IMPORTED_MODULE_5__.logger.trace('[mp4-remuxer]: Unable to remuxEmptyAudio since we were unable to get a silent frame for given audio codec'); 20128 return; 20129 } 20130 var samples = []; 20131 for (var i = 0; i < nbSamples; i++) { 20132 var stamp = startDTS + i * frameDuration; 20133 samples.push({ 20134 unit: silentFrame, 20135 pts: stamp, 20136 dts: stamp 20137 }); 20138 } 20139 track.samples = samples; 20140 return this.remuxAudio(track, timeOffset, contiguous, false); 20141 }; 20142 return MP4Remuxer; 20143}(); 20144 20145function normalizePts(value, reference) { 20146 var offset; 20147 if (reference === null) { 20148 return value; 20149 } 20150 if (reference < value) { 20151 // - 2^33 20152 offset = -8589934592; 20153 } else { 20154 // + 2^33 20155 offset = 8589934592; 20156 } 20157 /* PTS is 33bit (from 0 to 2^33 -1) 20158 if diff between value and reference is bigger than half of the amplitude (2^32) then it means that 20159 PTS looping occured. fill the gap */ 20160 while (Math.abs(value - reference) > 4294967296) { 20161 value += offset; 20162 } 20163 return value; 20164} 20165function findKeyframeIndex(samples) { 20166 for (var i = 0; i < samples.length; i++) { 20167 if (samples[i].key) { 20168 return i; 20169 } 20170 } 20171 return -1; 20172} 20173function flushTextTrackMetadataCueSamples(track, timeOffset, initPTS, initDTS) { 20174 var length = track.samples.length; 20175 if (!length) { 20176 return; 20177 } 20178 var inputTimeScale = track.inputTimeScale; 20179 for (var index = 0; index < length; index++) { 20180 var sample = track.samples[index]; 20181 // setting id3 pts, dts to relative time 20182 // using this._initPTS and this._initDTS to calculate relative time 20183 sample.pts = normalizePts(sample.pts - initPTS, timeOffset * inputTimeScale) / inputTimeScale; 20184 sample.dts = normalizePts(sample.dts - initDTS, timeOffset * inputTimeScale) / inputTimeScale; 20185 } 20186 var samples = track.samples; 20187 track.samples = []; 20188 return { 20189 samples: samples 20190 }; 20191} 20192function flushTextTrackUserdataCueSamples(track, timeOffset, initPTS) { 20193 var length = track.samples.length; 20194 if (!length) { 20195 return; 20196 } 20197 var inputTimeScale = track.inputTimeScale; 20198 for (var index = 0; index < length; index++) { 20199 var sample = track.samples[index]; 20200 // setting text pts, dts to relative time 20201 // using this._initPTS and this._initDTS to calculate relative time 20202 sample.pts = normalizePts(sample.pts - initPTS, timeOffset * inputTimeScale) / inputTimeScale; 20203 } 20204 track.samples.sort(function (a, b) { 20205 return a.pts - b.pts; 20206 }); 20207 var samples = track.samples; 20208 track.samples = []; 20209 return { 20210 samples: samples 20211 }; 20212} 20213var Mp4Sample = function Mp4Sample(isKeyframe, duration, size, cts) { 20214 this.size = void 0; 20215 this.duration = void 0; 20216 this.cts = void 0; 20217 this.flags = void 0; 20218 this.duration = duration; 20219 this.size = size; 20220 this.cts = cts; 20221 this.flags = new Mp4SampleFlags(isKeyframe); 20222}; 20223var Mp4SampleFlags = function Mp4SampleFlags(isKeyframe) { 20224 this.isLeading = 0; 20225 this.isDependedOn = 0; 20226 this.hasRedundancy = 0; 20227 this.degradPrio = 0; 20228 this.dependsOn = 1; 20229 this.isNonSync = 1; 20230 this.dependsOn = isKeyframe ? 2 : 1; 20231 this.isNonSync = isKeyframe ? 0 : 1; 20232}; 20233 20234/***/ }), 20235 20236/***/ "./src/remux/passthrough-remuxer.ts": 20237/*!******************************************!*\ 20238 !*** ./src/remux/passthrough-remuxer.ts ***! 20239 \******************************************/ 20240/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 20241 20242"use strict"; 20243__webpack_require__.r(__webpack_exports__); 20244/* harmony export */ __webpack_require__.d(__webpack_exports__, { 20245/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 20246/* harmony export */ }); 20247/* harmony import */ var _home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.ts"); 20248/* harmony import */ var _mp4_remuxer__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./mp4-remuxer */ "./src/remux/mp4-remuxer.ts"); 20249/* harmony import */ var _utils_mp4_tools__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils/mp4-tools */ "./src/utils/mp4-tools.ts"); 20250/* harmony import */ var _loader_fragment__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../loader/fragment */ "./src/loader/fragment.ts"); 20251/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 20252 20253 20254 20255 20256 20257 20258 20259var PassThroughRemuxer = /*#__PURE__*/function () { 20260 function PassThroughRemuxer() { 20261 this.emitInitSegment = false; 20262 this.audioCodec = void 0; 20263 this.videoCodec = void 0; 20264 this.initData = void 0; 20265 this.initPTS = void 0; 20266 this.initTracks = void 0; 20267 this.lastEndTime = null; 20268 } 20269 var _proto = PassThroughRemuxer.prototype; 20270 _proto.destroy = function destroy() {}; 20271 _proto.resetTimeStamp = function resetTimeStamp(defaultInitPTS) { 20272 this.initPTS = defaultInitPTS; 20273 this.lastEndTime = null; 20274 }; 20275 _proto.resetNextTimestamp = function resetNextTimestamp() { 20276 this.lastEndTime = null; 20277 }; 20278 _proto.resetInitSegment = function resetInitSegment(initSegment, audioCodec, videoCodec, decryptdata) { 20279 this.audioCodec = audioCodec; 20280 this.videoCodec = videoCodec; 20281 this.generateInitSegment((0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_2__.patchEncyptionData)(initSegment, decryptdata)); 20282 this.emitInitSegment = true; 20283 }; 20284 _proto.generateInitSegment = function generateInitSegment(initSegment) { 20285 var audioCodec = this.audioCodec, 20286 videoCodec = this.videoCodec; 20287 if (!initSegment || !initSegment.byteLength) { 20288 this.initTracks = undefined; 20289 this.initData = undefined; 20290 return; 20291 } 20292 var initData = this.initData = (0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_2__.parseInitSegment)(initSegment); 20293 20294 // Get codec from initSegment or fallback to default 20295 if (!audioCodec) { 20296 audioCodec = getParsedTrackCodec(initData.audio, _loader_fragment__WEBPACK_IMPORTED_MODULE_3__.ElementaryStreamTypes.AUDIO); 20297 } 20298 if (!videoCodec) { 20299 videoCodec = getParsedTrackCodec(initData.video, _loader_fragment__WEBPACK_IMPORTED_MODULE_3__.ElementaryStreamTypes.VIDEO); 20300 } 20301 var tracks = {}; 20302 if (initData.audio && initData.video) { 20303 tracks.audiovideo = { 20304 container: 'video/mp4', 20305 codec: audioCodec + ',' + videoCodec, 20306 initSegment: initSegment, 20307 id: 'main' 20308 }; 20309 } else if (initData.audio) { 20310 tracks.audio = { 20311 container: 'audio/mp4', 20312 codec: audioCodec, 20313 initSegment: initSegment, 20314 id: 'audio' 20315 }; 20316 } else if (initData.video) { 20317 tracks.video = { 20318 container: 'video/mp4', 20319 codec: videoCodec, 20320 initSegment: initSegment, 20321 id: 'main' 20322 }; 20323 } else { 20324 _utils_logger__WEBPACK_IMPORTED_MODULE_4__.logger.warn('[passthrough-remuxer.ts]: initSegment does not contain moov or trak boxes.'); 20325 } 20326 this.initTracks = tracks; 20327 }; 20328 _proto.remux = function remux(audioTrack, videoTrack, id3Track, textTrack, timeOffset) { 20329 var _this$initPTS; 20330 var initPTS = this.initPTS, 20331 lastEndTime = this.lastEndTime; 20332 var result = { 20333 audio: undefined, 20334 video: undefined, 20335 text: textTrack, 20336 id3: id3Track, 20337 initSegment: undefined 20338 }; 20339 20340 // If we haven't yet set a lastEndDTS, or it was reset, set it to the provided timeOffset. We want to use the 20341 // lastEndDTS over timeOffset whenever possible; during progressive playback, the media source will not update 20342 // the media duration (which is what timeOffset is provided as) before we need to process the next chunk. 20343 if (!(0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(lastEndTime)) { 20344 lastEndTime = this.lastEndTime = timeOffset || 0; 20345 } 20346 20347 // The binary segment data is added to the videoTrack in the mp4demuxer. We don't check to see if the data is only 20348 // audio or video (or both); adding it to video was an arbitrary choice. 20349 var data = videoTrack.samples; 20350 if (!data || !data.length) { 20351 return result; 20352 } 20353 var initSegment = { 20354 initPTS: undefined, 20355 timescale: 1 20356 }; 20357 var initData = this.initData; 20358 if (!initData || !initData.length) { 20359 this.generateInitSegment(data); 20360 initData = this.initData; 20361 } 20362 if (!initData || !initData.length) { 20363 // We can't remux if the initSegment could not be generated 20364 _utils_logger__WEBPACK_IMPORTED_MODULE_4__.logger.warn('[passthrough-remuxer.ts]: Failed to generate initSegment.'); 20365 return result; 20366 } 20367 if (this.emitInitSegment) { 20368 initSegment.tracks = this.initTracks; 20369 this.emitInitSegment = false; 20370 } 20371 var startDTS = (0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_2__.getStartDTS)(initData, data); 20372 if (!(0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(initPTS)) { 20373 this.initPTS = initSegment.initPTS = initPTS = startDTS - timeOffset; 20374 } 20375 var duration = (0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_2__.getDuration)(data, initData); 20376 var startTime = audioTrack ? startDTS - initPTS : lastEndTime; 20377 var endTime = startTime + duration; 20378 (0,_utils_mp4_tools__WEBPACK_IMPORTED_MODULE_2__.offsetStartDTS)(initData, data, initPTS); 20379 if (duration > 0) { 20380 this.lastEndTime = endTime; 20381 } else { 20382 _utils_logger__WEBPACK_IMPORTED_MODULE_4__.logger.warn('Duration parsed from mp4 should be greater than zero'); 20383 this.resetNextTimestamp(); 20384 } 20385 var hasAudio = !!initData.audio; 20386 var hasVideo = !!initData.video; 20387 var type = ''; 20388 if (hasAudio) { 20389 type += 'audio'; 20390 } 20391 if (hasVideo) { 20392 type += 'video'; 20393 } 20394 var track = { 20395 data1: data, 20396 startPTS: startTime, 20397 startDTS: startTime, 20398 endPTS: endTime, 20399 endDTS: endTime, 20400 type: type, 20401 hasAudio: hasAudio, 20402 hasVideo: hasVideo, 20403 nb: 1, 20404 dropped: 0 20405 }; 20406 result.audio = track.type === 'audio' ? track : undefined; 20407 result.video = track.type !== 'audio' ? track : undefined; 20408 result.initSegment = initSegment; 20409 var initPtsNum = (_this$initPTS = this.initPTS) != null ? _this$initPTS : 0; 20410 result.id3 = (0,_mp4_remuxer__WEBPACK_IMPORTED_MODULE_1__.flushTextTrackMetadataCueSamples)(id3Track, timeOffset, initPtsNum, initPtsNum); 20411 if (textTrack.samples.length) { 20412 result.text = (0,_mp4_remuxer__WEBPACK_IMPORTED_MODULE_1__.flushTextTrackUserdataCueSamples)(textTrack, timeOffset, initPtsNum); 20413 } 20414 return result; 20415 }; 20416 return PassThroughRemuxer; 20417}(); 20418function getParsedTrackCodec(track, type) { 20419 var parsedCodec = track === null || track === void 0 ? void 0 : track.codec; 20420 if (parsedCodec && parsedCodec.length > 4) { 20421 return parsedCodec; 20422 } 20423 // Since mp4-tools cannot parse full codec string (see 'TODO: Parse codec details'... in mp4-tools) 20424 // Provide defaults based on codec type 20425 // This allows for some playback of some fmp4 playlists without CODECS defined in manifest 20426 if (parsedCodec === 'hvc1' || parsedCodec === 'hev1') { 20427 return 'hvc1.1.c.L120.90'; 20428 } 20429 if (parsedCodec === 'av01') { 20430 return 'av01.0.04M.08'; 20431 } 20432 if (parsedCodec === 'avc1' || type === _loader_fragment__WEBPACK_IMPORTED_MODULE_3__.ElementaryStreamTypes.VIDEO) { 20433 return 'avc1.42e01e'; 20434 } 20435 return 'mp4a.40.5'; 20436} 20437/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PassThroughRemuxer); 20438 20439/***/ }), 20440 20441/***/ "./src/task-loop.ts": 20442/*!**************************!*\ 20443 !*** ./src/task-loop.ts ***! 20444 \**************************/ 20445/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 20446 20447"use strict"; 20448__webpack_require__.r(__webpack_exports__); 20449/* harmony export */ __webpack_require__.d(__webpack_exports__, { 20450/* harmony export */ "default": () => (/* binding */ TaskLoop) 20451/* harmony export */ }); 20452/** 20453 * Sub-class specialization of EventHandler base class. 20454 * 20455 * TaskLoop allows to schedule a task function being called (optionnaly repeatedly) on the main loop, 20456 * scheduled asynchroneously, avoiding recursive calls in the same tick. 20457 * 20458 * The task itself is implemented in `doTick`. It can be requested and called for single execution 20459 * using the `tick` method. 20460 * 20461 * It will be assured that the task execution method (`tick`) only gets called once per main loop "tick", 20462 * no matter how often it gets requested for execution. Execution in further ticks will be scheduled accordingly. 20463 * 20464 * If further execution requests have already been scheduled on the next tick, it can be checked with `hasNextTick`, 20465 * and cancelled with `clearNextTick`. 20466 * 20467 * The task can be scheduled as an interval repeatedly with a period as parameter (see `setInterval`, `clearInterval`). 20468 * 20469 * Sub-classes need to implement the `doTick` method which will effectively have the task execution routine. 20470 * 20471 * Further explanations: 20472 * 20473 * The baseclass has a `tick` method that will schedule the doTick call. It may be called synchroneously 20474 * only for a stack-depth of one. On re-entrant calls, sub-sequent calls are scheduled for next main loop ticks. 20475 * 20476 * When the task execution (`tick` method) is called in re-entrant way this is detected and 20477 * we are limiting the task execution per call stack to exactly one, but scheduling/post-poning further 20478 * task processing on the next main loop iteration (also known as "next tick" in the Node/JS runtime lingo). 20479 */ 20480var TaskLoop = /*#__PURE__*/function () { 20481 function TaskLoop() { 20482 this._boundTick = void 0; 20483 this._tickTimer = null; 20484 this._tickInterval = null; 20485 this._tickCallCount = 0; 20486 this._boundTick = this.tick.bind(this); 20487 } 20488 var _proto = TaskLoop.prototype; 20489 _proto.destroy = function destroy() { 20490 this.onHandlerDestroying(); 20491 this.onHandlerDestroyed(); 20492 }; 20493 _proto.onHandlerDestroying = function onHandlerDestroying() { 20494 // clear all timers before unregistering from event bus 20495 this.clearNextTick(); 20496 this.clearInterval(); 20497 }; 20498 _proto.onHandlerDestroyed = function onHandlerDestroyed() {} 20499 20500 /** 20501 * @returns {boolean} 20502 */; 20503 _proto.hasInterval = function hasInterval() { 20504 return !!this._tickInterval; 20505 } 20506 20507 /** 20508 * @returns {boolean} 20509 */; 20510 _proto.hasNextTick = function hasNextTick() { 20511 return !!this._tickTimer; 20512 } 20513 20514 /** 20515 * @param {number} millis Interval time (ms) 20516 * @returns {boolean} True when interval has been scheduled, false when already scheduled (no effect) 20517 */; 20518 _proto.setInterval = function setInterval(millis) { 20519 if (!this._tickInterval) { 20520 this._tickInterval = self.setInterval(this._boundTick, millis); 20521 return true; 20522 } 20523 return false; 20524 } 20525 20526 /** 20527 * @returns {boolean} True when interval was cleared, false when none was set (no effect) 20528 */; 20529 _proto.clearInterval = function clearInterval() { 20530 if (this._tickInterval) { 20531 self.clearInterval(this._tickInterval); 20532 this._tickInterval = null; 20533 return true; 20534 } 20535 return false; 20536 } 20537 20538 /** 20539 * @returns {boolean} True when timeout was cleared, false when none was set (no effect) 20540 */; 20541 _proto.clearNextTick = function clearNextTick() { 20542 if (this._tickTimer) { 20543 self.clearTimeout(this._tickTimer); 20544 this._tickTimer = null; 20545 return true; 20546 } 20547 return false; 20548 } 20549 20550 /** 20551 * Will call the subclass doTick implementation in this main loop tick 20552 * or in the next one (via setTimeout(,0)) in case it has already been called 20553 * in this tick (in case this is a re-entrant call). 20554 */; 20555 _proto.tick = function tick() { 20556 this._tickCallCount++; 20557 if (this._tickCallCount === 1) { 20558 this.doTick(); 20559 // re-entrant call to tick from previous doTick call stack 20560 // -> schedule a call on the next main loop iteration to process this task processing request 20561 if (this._tickCallCount > 1) { 20562 // make sure only one timer exists at any time at max 20563 this.tickImmediate(); 20564 } 20565 this._tickCallCount = 0; 20566 } 20567 }; 20568 _proto.tickImmediate = function tickImmediate() { 20569 this.clearNextTick(); 20570 this._tickTimer = self.setTimeout(this._boundTick, 0); 20571 } 20572 20573 /** 20574 * For subclass to implement task logic 20575 * @abstract 20576 */; 20577 _proto.doTick = function doTick() {}; 20578 return TaskLoop; 20579}(); 20580 20581 20582/***/ }), 20583 20584/***/ "./src/types/
20584cmcd.ts": 20585/*!***************************!*\ 20586 !*** ./src/types/cmcd.ts ***! 20587 \***************************/ 20588/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 20589 20590"use strict"; 20591__webpack_require__.r(__webpack_exports__); 20592/* harmony export */ __webpack_require__.d(__webpack_exports__, { 20593/* harmony export */ "CMCDObjectType": () => (/* binding */ CMCDObjectType), 20594/* harmony export */ "CMCDStreamType": () => (/* binding */ CMCDStreamType), 20595/* harmony export */ "CMCDStreamingFormat": () => (/* binding */ CMCDStreamingFormat), 20596/* harmony export */ "CMCDVersion": () => (/* binding */ CMCDVersion) 20597/* harmony export */ }); 20598/** 20599 * CMCD spec version 20600 */ 20601var CMCDVersion = 1; 20602 20603/** 20604 * CMCD Object Type 20605 */ 20606var CMCDObjectType; 20607 20608/** 20609 * CMCD Streaming Format 20610 */ 20611(function (CMCDObjectType) { 20612 CMCDObjectType["MANIFEST"] = "m"; 20613 CMCDObjectType["AUDIO"] = "a"; 20614 CMCDObjectType["VIDEO"] = "v"; 20615 CMCDObjectType["MUXED"] = "av"; 20616 CMCDObjectType["INIT"] = "i"; 20617 CMCDObjectType["CAPTION"] = "c"; 20618 CMCDObjectType["TIMED_TEXT"] = "tt"; 20619 CMCDObjectType["KEY"] = "k"; 20620 CMCDObjectType["OTHER"] = "o"; 20621})(CMCDObjectType || (CMCDObjectType = {})); 20622var CMCDStreamingFormat; 20623 20624/** 20625 * CMCD Streaming Type 20626 */ 20627(function (CMCDStreamingFormat) { 20628 CMCDStreamingFormat["DASH"] = "d"; 20629 CMCDStreamingFormat["HLS"] = "h"; 20630 CMCDStreamingFormat["SMOOTH"] = "s"; 20631 CMCDStreamingFormat["OTHER"] = "o"; 20632})(CMCDStreamingFormat || (CMCDStreamingFormat = {})); 20633var CMCDStreamType; 20634 20635/** 20636 * CMCD Headers 20637 */ 20638(function (CMCDStreamType) { 20639 CMCDStreamType["VOD"] = "v"; 20640 CMCDStreamType["LIVE"] = "l"; 20641})(CMCDStreamType || (CMCDStreamType = {}));
vendor: 18,585 bytes, lines 20641-21192
20641 20642 20643/***/ }), 20644 20645/***/ "./src/types/demuxer.ts": 20646/*!******************************!*\ 20647 !*** ./src/types/demuxer.ts ***! 20648 \******************************/ 20649/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 20650 20651"use strict"; 20652__webpack_require__.r(__webpack_exports__); 20653/* harmony export */ __webpack_require__.d(__webpack_exports__, { 20654/* harmony export */ "MetadataSchema": () => (/* binding */ MetadataSchema) 20655/* harmony export */ }); 20656var MetadataSchema; 20657(function (MetadataSchema) { 20658 MetadataSchema["audioId3"] = "org.id3"; 20659 MetadataSchema["dateRange"] = "com.apple.quicktime.HLS"; 20660 MetadataSchema["emsg"] = "https://aomedia.org/emsg/ID3"; 20661})(MetadataSchema || (MetadataSchema = {})); 20662 20663/***/ }), 20664 20665/***/ "./src/types/level.ts": 20666/*!****************************!*\ 20667 !*** ./src/types/level.ts ***! 20668 \****************************/ 20669/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 20670 20671"use strict"; 20672__webpack_require__.r(__webpack_exports__); 20673/* harmony export */ __webpack_require__.d(__webpack_exports__, { 20674/* harmony export */ "HdcpLevels": () => (/* binding */ HdcpLevels), 20675/* harmony export */ "HlsSkip": () => (/* binding */ HlsSkip), 20676/* harmony export */ "HlsUrlParameters": () => (/* binding */ HlsUrlParameters), 20677/* harmony export */ "Level": () => (/* binding */ Level), 20678/* harmony export */ "getSkipValue": () => (/* binding */ getSkipValue) 20679/* harmony export */ }); 20680function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } 20681function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } 20682function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } 20683function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } 20684var HdcpLevels = ['NONE', 'TYPE-0', 'TYPE-1', 'TYPE-2', null]; 20685var HlsSkip; 20686(function (HlsSkip) { 20687 HlsSkip["No"] = ""; 20688 HlsSkip["Yes"] = "YES"; 20689 HlsSkip["v2"] = "v2"; 20690})(HlsSkip || (HlsSkip = {})); 20691function getSkipValue(details, msn) { 20692 var canSkipUntil = details.canSkipUntil, 20693 canSkipDateRanges = details.canSkipDateRanges, 20694 endSN = details.endSN; 20695 var snChangeGoal = msn !== undefined ? msn - endSN : 0; 20696 if (canSkipUntil && snChangeGoal < canSkipUntil) { 20697 if (canSkipDateRanges) { 20698 return HlsSkip.v2; 20699 } 20700 return HlsSkip.Yes; 20701 } 20702 return HlsSkip.No; 20703} 20704var HlsUrlParameters = /*#__PURE__*/function () { 20705 function HlsUrlParameters(msn, part, skip) { 20706 this.msn = void 0; 20707 this.part = void 0; 20708 this.skip = void 0; 20709 this.msn = msn; 20710 this.part = part; 20711 this.skip = skip; 20712 } 20713 var _proto = HlsUrlParameters.prototype; 20714 _proto.addDirectives = function addDirectives(uri) { 20715 var url = new self.URL(uri); 20716 if (this.msn !== undefined) { 20717 url.searchParams.set('_HLS_msn', this.msn.toString()); 20718 } 20719 if (this.part !== undefined) { 20720 url.searchParams.set('_HLS_part', this.part.toString()); 20721 } 20722 if (this.skip) { 20723 url.searchParams.set('_HLS_skip', this.skip); 20724 } 20725 return url.href; 20726 }; 20727 return HlsUrlParameters; 20728}(); 20729var Level = /*#__PURE__*/function () { 20730 function Level(data) { 20731 this.attrs = void 0; 20732 this.audioCodec = void 0; 20733 this.bitrate = void 0; 20734 this.codecSet = void 0; 20735 this.height = void 0; 20736 this.id = void 0; 20737 this.name = void 0; 20738 this.videoCodec = void 0; 20739 this.width = void 0; 20740 this.unknownCodecs = void 0; 20741 this.audioGroupIds = void 0; 20742 this.details = void 0; 20743 this.fragmentError = 0; 20744 this.loadError = 0; 20745 this.loaded = void 0; 20746 this.realBitrate = 0; 20747 this.textGroupIds = void 0; 20748 this.url = void 0; 20749 this._urlId = 0; 20750 this.url = [data.url]; 20751 this.attrs = data.attrs; 20752 this.bitrate = data.bitrate; 20753 if (data.details) { 20754 this.details = data.details; 20755 } 20756 this.id = data.id || 0; 20757 this.name = data.name; 20758 this.width = data.width || 0; 20759 this.height = data.height || 0; 20760 this.audioCodec = data.audioCodec; 20761 this.videoCodec = data.videoCodec; 20762 this.unknownCodecs = data.unknownCodecs; 20763 this.codecSet = [data.videoCodec, data.audioCodec].filter(function (c) { 20764 return c; 20765 }).join(',').replace(/\.[^.,]+/g, ''); 20766 } 20767 _createClass(Level, [{ 20768 key: "maxBitrate", 20769 get: function get() { 20770 return Math.max(this.realBitrate, this.bitrate); 20771 } 20772 }, { 20773 key: "uri", 20774 get: function get() { 20775 return this.url[this._urlId] || ''; 20776 } 20777 }, { 20778 key: "urlId", 20779 get: function get() { 20780 return this._urlId; 20781 }, 20782 set: function set(value) { 20783 var newValue = value % this.url.length; 20784 if (this._urlId !== newValue) { 20785 this.details = undefined; 20786 this._urlId = newValue; 20787 } 20788 } 20789 }]); 20790 return Level; 20791}(); 20792 20793/***/ }), 20794 20795/***/ "./src/types/loader.ts": 20796/*!*****************************!*\ 20797 !*** ./src/types/loader.ts ***! 20798 \*****************************/ 20799/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 20800 20801"use strict"; 20802__webpack_require__.r(__webpack_exports__); 20803/* harmony export */ __webpack_require__.d(__webpack_exports__, { 20804/* harmony export */ "PlaylistContextType": () => (/* binding */ PlaylistContextType), 20805/* harmony export */ "PlaylistLevelType": () => (/* binding */ PlaylistLevelType) 20806/* harmony export */ }); 20807var PlaylistContextType; 20808(function (PlaylistContextType) { 20809 PlaylistContextType["MANIFEST"] = "manifest"; 20810 PlaylistContextType["LEVEL"] = "level"; 20811 PlaylistContextType["AUDIO_TRACK"] = "audioTrack"; 20812 PlaylistContextType["SUBTITLE_TRACK"] = "subtitleTrack"; 20813})(PlaylistContextType || (PlaylistContextType = {})); 20814var PlaylistLevelType; 20815(function (PlaylistLevelType) { 20816 PlaylistLevelType["MAIN"] = "main"; 20817 PlaylistLevelType["AUDIO"] = "audio"; 20818 PlaylistLevelType["SUBTITLE"] = "subtitle"; 20819})(PlaylistLevelType || (PlaylistLevelType = {})); 20820 20821/***/ }), 20822 20823/***/ "./src/types/transmuxer.ts": 20824/*!*********************************!*\ 20825 !*** ./src/types/transmuxer.ts ***! 20826 \*********************************/ 20827/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 20828 20829"use strict"; 20830__webpack_require__.r(__webpack_exports__); 20831/* harmony export */ __webpack_require__.d(__webpack_exports__, { 20832/* harmony export */ "ChunkMetadata": () => (/* binding */ ChunkMetadata) 20833/* harmony export */ }); 20834var ChunkMetadata = function ChunkMetadata(level, sn, id, size, part, partial) { 20835 if (size === void 0) { 20836 size = 0; 20837 } 20838 if (part === void 0) { 20839 part = -1; 20840 } 20841 if (partial === void 0) { 20842 partial = false; 20843 } 20844 this.level = void 0; 20845 this.sn = void 0; 20846 this.part = void 0; 20847 this.id = void 0; 20848 this.size = void 0; 20849 this.partial = void 0; 20850 this.transmuxing = getNewPerformanceTiming(); 20851 this.buffering = { 20852 audio: getNewPerformanceTiming(), 20853 video: getNewPerformanceTiming(), 20854 audiovideo: getNewPerformanceTiming() 20855 }; 20856 this.level = level; 20857 this.sn = sn; 20858 this.id = id; 20859 this.size = size; 20860 this.part = part; 20861 this.partial = partial; 20862}; 20863function getNewPerformanceTiming() { 20864 return { 20865 start: 0, 20866 executeStart: 0, 20867 executeEnd: 0, 20868 end: 0 20869 }; 20870} 20871 20872/***/ }), 20873 20874/***/ "./src/utils/attr-list.ts": 20875/*!********************************!*\ 20876 !*** ./src/utils/attr-list.ts ***! 20877 \********************************/ 20878/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 20879 20880"use strict"; 20881__webpack_require__.r(__webpack_exports__); 20882/* harmony export */ __webpack_require__.d(__webpack_exports__, { 20883/* harmony export */ "AttrList": () => (/* binding */ AttrList) 20884/* harmony export */ }); 20885var DECIMAL_RESOLUTION_REGEX = /^(\d+)x(\d+)$/; // eslint-disable-line no-useless-escape 20886var ATTR_LIST_REGEX = /\s*(.+?)\s*=((?:\".*?\")|.*?)(?:,|$)/g; // eslint-disable-line no-useless-escape 20887 20888// adapted from https://github.com/kanongil/node-m3u8parse/blob/master/attrlist.js 20889var AttrList = /*#__PURE__*/function () { 20890 function AttrList(attrs) { 20891 if (typeof attrs === 'string') { 20892 attrs = AttrList.parseAttrList(attrs); 20893 } 20894 for (var attr in attrs) { 20895 if (attrs.hasOwnProperty(attr)) { 20896 this[attr] = attrs[attr]; 20897 } 20898 } 20899 } 20900 var _proto = AttrList.prototype; 20901 _proto.decimalInteger = function decimalInteger(attrName) { 20902 var intValue = parseInt(this[attrName], 10); 20903 if (intValue > Number.MAX_SAFE_INTEGER) { 20904 return Infinity; 20905 } 20906 return intValue; 20907 }; 20908 _proto.hexadecimalInteger = function hexadecimalInteger(attrName) { 20909 if (this[attrName]) { 20910 var stringValue = (this[attrName] || '0x').slice(2); 20911 stringValue = (stringValue.length & 1 ? '0' : '') + stringValue; 20912 var value = new Uint8Array(stringValue.length / 2); 20913 for (var i = 0; i < stringValue.length / 2; i++) { 20914 value[i] = parseInt(stringValue.slice(i * 2, i * 2 + 2), 16); 20915 } 20916 return value; 20917 } else { 20918 return null; 20919 } 20920 }; 20921 _proto.hexadecimalIntegerAsNumber = function hexadecimalIntegerAsNumber(attrName) { 20922 var intValue = parseInt(this[attrName], 16); 20923 if (intValue > Number.MAX_SAFE_INTEGER) { 20924 return Infinity; 20925 } 20926 return intValue; 20927 }; 20928 _proto.decimalFloatingPoint = function decimalFloatingPoint(attrName) { 20929 return parseFloat(this[attrName]); 20930 }; 20931 _proto.optionalFloat = function optionalFloat(attrName, defaultValue) { 20932 var value = this[attrName]; 20933 return value ? parseFloat(value) : defaultValue; 20934 }; 20935 _proto.enumeratedString = function enumeratedString(attrName) { 20936 return this[attrName]; 20937 }; 20938 _proto.bool = function bool(attrName) { 20939 return this[attrName] === 'YES'; 20940 }; 20941 _proto.decimalResolution = function decimalResolution(attrName) { 20942 var res = DECIMAL_RESOLUTION_REGEX.exec(this[attrName]); 20943 if (res === null) { 20944 return undefined; 20945 } 20946 return { 20947 width: parseInt(res[1], 10), 20948 height: parseInt(res[2], 10) 20949 }; 20950 }; 20951 AttrList.parseAttrList = function parseAttrList(input) { 20952 var match; 20953 var attrs = {}; 20954 var quote = '"'; 20955 ATTR_LIST_REGEX.lastIndex = 0; 20956 while ((match = ATTR_LIST_REGEX.exec(input)) !== null) { 20957 var value = match[2]; 20958 if (value.indexOf(quote) === 0 && value.lastIndexOf(quote) === value.length - 1) { 20959 value = value.slice(1, -1); 20960 } 20961 attrs[match[1]] = value; 20962 } 20963 return attrs; 20964 }; 20965 return AttrList; 20966}(); 20967 20968/***/ }), 20969 20970/***/ "./src/utils/binary-search.ts": 20971/*!************************************!*\ 20972 !*** ./src/utils/binary-search.ts ***! 20973 \************************************/ 20974/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 20975 20976"use strict"; 20977__webpack_require__.r(__webpack_exports__); 20978/* harmony export */ __webpack_require__.d(__webpack_exports__, { 20979/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 20980/* harmony export */ }); 20981var BinarySearch = { 20982 /** 20983 * Searches for an item in an array which matches a certain condition. 20984 * This requires the condition to only match one item in the array, 20985 * and for the array to be ordered. 20986 * 20987 * @param {Array<T>} list The array to search. 20988 * @param {BinarySearchComparison<T>} comparisonFn 20989 * Called and provided a candidate item as the first argument. 20990 * Should return: 20991 * > -1 if the item should be located at a lower index than the provided item. 20992 * > 1 if the item should be located at a higher index than the provided item. 20993 * > 0 if the item is the item you're looking for. 20994 * 20995 * @return {T | null} The object if it is found or null otherwise. 20996 */ 20997 search: function search(list, comparisonFn) { 20998 var minIndex = 0; 20999 var maxIndex = list.length - 1; 21000 var currentIndex = null; 21001 var currentElement = null; 21002 while (minIndex <= maxIndex) { 21003 currentIndex = (minIndex + maxIndex) / 2 | 0; 21004 currentElement = list[currentIndex]; 21005 var comparisonResult = comparisonFn(currentElement); 21006 if (comparisonResult > 0) { 21007 minIndex = currentIndex + 1; 21008 } else if (comparisonResult < 0) { 21009 maxIndex = currentIndex - 1; 21010 } else { 21011 return currentElement; 21012 } 21013 } 21014 return null; 21015 } 21016}; 21017/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BinarySearch); 21018 21019/***/ }), 21020 21021/***/ "./src/utils/buffer-helper.ts": 21022/*!************************************!*\ 21023 !*** ./src/utils/buffer-helper.ts ***! 21024 \************************************/ 21025/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 21026 21027"use strict"; 21028__webpack_require__.r(__webpack_exports__); 21029/* harmony export */ __webpack_require__.d(__webpack_exports__, { 21030/* harmony export */ "BufferHelper": () => (/* binding */ BufferHelper) 21031/* harmony export */ }); 21032/* harmony import */ var _logger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./logger */ "./src/utils/logger.ts"); 21033/** 21034 * @module BufferHelper 21035 * 21036 * Providing methods dealing with buffer length retrieval for example. 21037 * 21038 * In general, a helper around HTML5 MediaElement TimeRanges gathered from `buffered` property. 21039 * 21040 * Also @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/buffered 21041 */ 21042 21043 21044var noopBuffered = { 21045 length: 0, 21046 start: function start() { 21047 return 0; 21048 }, 21049 end: function end() { 21050 return 0; 21051 } 21052}; 21053var BufferHelper = /*#__PURE__*/function () { 21054 function BufferHelper() {} 21055 /** 21056 * Return true if `media`'s buffered include `position` 21057 * @param {Bufferable} media 21058 * @param {number} position 21059 * @returns {boolean} 21060 */ 21061 BufferHelper.isBuffered = function isBuffered(media, position) { 21062 try { 21063 if (media) { 21064 var buffered = BufferHelper.getBuffered(media); 21065 for (var i = 0; i < buffered.length; i++) { 21066 if (position >= buffered.start(i) && position <= buffered.end(i)) { 21067 return true; 21068 } 21069 } 21070 } 21071 } catch (error) { 21072 // this is to catch 21073 // InvalidStateError: Failed to read the 'buffered' property from 'SourceBuffer': 21074 // This SourceBuffer has been removed from the parent media source 21075 } 21076 return false; 21077 }; 21078 BufferHelper.bufferInfo = function bufferInfo(media, pos, maxHoleDuration) { 21079 try { 21080 if (media) { 21081 var vbuffered = BufferHelper.getBuffered(media); 21082 var buffered = []; 21083 var i; 21084 for (i = 0; i < vbuffered.length; i++) { 21085 buffered.push({ 21086 start: vbuffered.start(i), 21087 end: vbuffered.end(i) 21088 }); 21089 } 21090 return this.bufferedInfo(buffered, pos, maxHoleDuration); 21091 } 21092 } catch (error) { 21093 // this is to catch 21094 // InvalidStateError: Failed to read the 'buffered' property from 'SourceBuffer': 21095 // This SourceBuffer has been removed from the parent media source 21096 } 21097 return { 21098 len: 0, 21099 start: pos, 21100 end: pos, 21101 nextStart: undefined 21102 }; 21103 }; 21104 BufferHelper.bufferedInfo = function bufferedInfo(buffered, pos, maxHoleDuration) { 21105 pos = Math.max(0, pos); 21106 // sort on buffer.start/smaller end (IE does not always return sorted buffered range) 21107 buffered.sort(function (a, b) { 21108 var diff = a.start - b.start; 21109 if (diff) { 21110 return diff; 21111 } else { 21112 return b.end - a.end; 21113 } 21114 }); 21115 var buffered2 = []; 21116 if (maxHoleDuration) { 21117 // there might be some small holes between buffer time range 21118 // consider that holes smaller than maxHoleDuration are irrelevant and build another 21119 // buffer time range representations that discards those holes 21120 for (var i = 0; i < buffered.length; i++) { 21121 var buf2len = buffered2.length; 21122 if (buf2len) { 21123 var buf2end = buffered2[buf2len - 1].end; 21124 // if small hole (value between 0 or maxHoleDuration ) or overlapping (negative) 21125 if (buffered[i].start - buf2end < maxHoleDuration) { 21126 // merge overlapping time ranges 21127 // update lastRange.end only if smaller than item.end 21128 // e.g. [ 1, 15] with [ 2,8] => [ 1,15] (no need to modify lastRange.end) 21129 // whereas [ 1, 8] with [ 2,15] => [ 1,15] ( lastRange should switch from [1,8] to [1,15]) 21130 if (buffered[i].end > buf2end) { 21131 buffered2[buf2len - 1].end = buffered[i].end; 21132 } 21133 } else { 21134 // big hole 21135 buffered2.push(buffered[i]); 21136 } 21137 } else { 21138 // first value 21139 buffered2.push(buffered[i]); 21140 } 21141 } 21142 } else { 21143 buffered2 = buffered; 21144 } 21145 var bufferLen = 0; 21146 21147 // bufferStartNext can possibly be undefined based on the conditional logic below 21148 var bufferStartNext; 21149 21150 // bufferStart and bufferEnd are buffer boundaries around current video position 21151 var bufferStart = pos; 21152 var bufferEnd = pos; 21153 for (var _i = 0; _i < buffered2.length; _i++) { 21154 var start = buffered2[_i].start; 21155 var end = buffered2[_i].end; 21156 // logger.log('buf start/end:' + buffered.start(i) + '/' + buffered.end(i)); 21157 if (pos + maxHoleDuration >= start && pos < end) { 21158 // play position is inside this buffer TimeRange, retrieve end of buffer position and buffer length 21159 bufferStart = start; 21160 bufferEnd = end; 21161 bufferLen = bufferEnd - pos; 21162 } else if (pos + maxHoleDuration < start) { 21163 bufferStartNext = start; 21164 break; 21165 } 21166 } 21167 return { 21168 len: bufferLen, 21169 start: bufferStart || 0, 21170 end: bufferEnd || 0, 21171 nextStart: bufferStartNext 21172 }; 21173 } 21174 21175 /** 21176 * Safe method to get buffered property. 21177 * SourceBuffer.buffered may throw if SourceBuffer is removed from it's MediaSource 21178 */; 21179 BufferHelper.getBuffered = function getBuffered(media) { 21180 try { 21181 return media.buffered; 21182 } catch (e) { 21183 _logger__WEBPACK_IMPORTED_MODULE_0__.logger.log('failed to get media.buffered', e); 21184 return noopBuffered; 21185 } 21186 }; 21187 return BufferHelper; 21188}(); 21189 21190/***/ }), 21191 21192/***/ "./src/utils/c
21192ea-608-parser.ts": 21193/*!*************************************!*\ 21194 !*** ./src/utils/cea-608-parser.ts ***! 21195 \*************************************/ 21196/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 21197 21198"use strict"; 21199__webpack_require__.r(__webpack_exports__); 21200/* harmony export */ __webpack_require__.d(__webpack_exports__, { 21201/* harmony export */ "CaptionScreen": () => (/* binding */ CaptionScreen), 21202/* harmony export */ "Row": () => (/* binding */ Row), 21203/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 21204/* harmony export */ }); 21205/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 21206 21207 21208/** 21209 * 21210 * This code was ported from the dash.js project at: 21211 * https://github.com/Dash-Industry-Forum/dash.js/blob/development/externals/cea608-parser.js 21212 * https://github.com/Dash-Industry-Forum/dash.js/commit/8269b26a761e0853bb21d78780ed945144ecdd4d#diff-71bc295a2d6b6b7093a1d3290d53a4b2 21213 * 21214 * The original copyright appears below: 21215 * 21216 * The copyright in this software is being made available under the BSD License, 21217 * included below. This software may be subject to other third party and contributor 21218 * rights, including patent rights, and no such rights are granted under this license. 21219 * 21220 * Copyright (c) 2015-2016, DASH Industry Forum. 21221 * All rights reserved. 21222 * 21223 * Redistribution and use in source and binary forms, with or without modification, 21224 * are permitted provided that the following conditions are met: 21225 * 1. Redistributions of source code must retain the above copyright notice, this 21226 * list of conditions and the following disclaimer. 21227 * * Redistributions in binary form must reproduce the above copyright notice, 21228 * this list of conditions and the following disclaimer in the documentation and/or 21229 * other materials provided with the distribution. 21230 * 2. Neither the name of Dash Industry Forum nor the names of its 21231 * contributors may be used to endorse or promote products derived from this software 21232 * without specific prior written permission. 21233 * 21234 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY 21235 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21236 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21237 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 21238 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21239 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21240 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21241 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 21242 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 21243 * POSSIBILITY OF SUCH DAMAGE. 21244 */ 21245/** 21246 * Exceptions from regular ASCII. CodePoints are mapped to UTF-16 codes 21247 */ 21248 21249var specialCea608CharsCodes = { 21250 0x2a: 0xe1, 21251 // lowercase a, acute accent 21252 0x5c: 0xe9, 21253 // lowercase e, acute accent 21254 0x5e: 0xed, 21255 // lowercase i, acute accent 21256 0x5f: 0xf3, 21257 // lowercase o, acute accent 21258 0x60: 0xfa, 21259 // lowercase u, acute accent 21260 0x7b: 0xe7, 21261 // lowercase c with cedilla 21262 0x7c: 0xf7, 21263 // division symbol 21264 0x7d: 0xd1, 21265 // uppercase N tilde 21266 0x7e: 0xf1, 21267 // lowercase n tilde 21268 0x7f: 0x2588, 21269 // Full block 21270 // THIS BLOCK INCLUDES THE 16 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS 21271 // THAT COME FROM HI BYTE=0x11 AND LOW BETWEEN 0x30 AND 0x3F 21272 // THIS MEANS THAT \x50 MUST BE ADDED TO THE VALUES 21273 0x80: 0xae, 21274 // Registered symbol (R) 21275 0x81: 0xb0, 21276 // degree sign 21277 0x82: 0xbd, 21278 // 1/2 symbol 21279 0x83: 0xbf, 21280 // Inverted (open) question mark 21281 0x84: 0x2122, 21282 // Trademark symbol (TM) 21283 0x85: 0xa2, 21284 // Cents symbol 21285 0x86: 0xa3, 21286 // Pounds sterling 21287 0x87: 0x266a, 21288 // Music 8'th note 21289 0x88: 0xe0, 21290 // lowercase a, grave accent 21291 0x89: 0x20, 21292 // transparent space (regular) 21293 0x8a: 0xe8, 21294 // lowercase e, grave accent 21295 0x8b: 0xe2, 21296 // lowercase a, circumflex accent 21297 0x8c: 0xea, 21298 // lowercase e, circumflex accent 21299 0x8d: 0xee, 21300 // lowercase i, circumflex accent 21301 0x8e: 0xf4, 21302 // lowercase o, circumflex accent 21303 0x8f: 0xfb, 21304 // lowercase u, circumflex accent 21305 // THIS BLOCK INCLUDES THE 32 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS 21306 // THAT COME FROM HI BYTE=0x12 AND LOW BETWEEN 0x20 AND 0x3F 21307 0x90: 0xc1, 21308 // capital letter A with acute
vendor: 10,145 bytes, lines 21309-21692
21309 0x91: 0xc9, 21310 // capital letter E with acute 21311 0x92: 0xd3, 21312 // capital letter O with acute 21313 0x93: 0xda, 21314 // capital letter U with acute 21315 0x94: 0xdc, 21316 // capital letter U with diaresis 21317 0x95: 0xfc, 21318 // lowercase letter U with diaeresis 21319 0x96: 0x2018, 21320 // opening single quote 21321 0x97: 0xa1, 21322 // inverted exclamation mark 21323 0x98: 0x2a, 21324 // asterisk 21325 0x99: 0x2019, 21326 // closing single quote 21327 0x9a: 0x2501, 21328 // box drawings heavy horizontal 21329 0x9b: 0xa9, 21330 // copyright sign 21331 0x9c: 0x2120, 21332 // Service mark 21333 0x9d: 0x2022, 21334 // (round) bullet 21335 0x9e: 0x201c, 21336 // Left double quotation mark 21337 0x9f: 0x201d, 21338 // Right double quotation mark 21339 0xa0: 0xc0, 21340 // uppercase A, grave accent 21341 0xa1: 0xc2, 21342 // uppercase A, circumflex 21343 0xa2: 0xc7, 21344 // uppercase C with cedilla 21345 0xa3: 0xc8, 21346 // uppercase E, grave accent 21347 0xa4: 0xca, 21348 // uppercase E, circumflex 21349 0xa5: 0xcb, 21350 // capital letter E with diaresis 21351 0xa6: 0xeb, 21352 // lowercase letter e with diaresis 21353 0xa7: 0xce, 21354 // uppercase I, circumflex 21355 0xa8: 0xcf, 21356 // uppercase I, with diaresis 21357 0xa9: 0xef, 21358 // lowercase i, with diaresis 21359 0xaa: 0xd4, 21360 // uppercase O, circumflex 21361 0xab: 0xd9, 21362 // uppercase U, grave accent 21363 0xac: 0xf9, 21364 // lowercase u, grave accent 21365 0xad: 0xdb, 21366 // uppercase U, circumflex 21367 0xae: 0xab, 21368 // left-pointing double angle quotation mark 21369 0xaf: 0xbb, 21370 // right-pointing double angle quotation mark 21371 // THIS BLOCK INCLUDES THE 32 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS 21372 // THAT COME FROM HI BYTE=0x13 AND LOW BETWEEN 0x20 AND 0x3F 21373 0xb0: 0xc3, 21374 // Uppercase A, tilde 21375 0xb1: 0xe3, 21376 // Lowercase a, tilde 21377 0xb2: 0xcd, 21378 // Uppercase I, acute accent 21379 0xb3: 0xcc, 21380 // Uppercase I, grave accent 21381 0xb4: 0xec, 21382 // Lowercase i, grave accent 21383 0xb5: 0xd2, 21384 // Uppercase O, grave accent 21385 0xb6: 0xf2, 21386 // Lowercase o, grave accent 21387 0xb7: 0xd5, 21388 // Uppercase O, tilde 21389 0xb8: 0xf5, 21390 // Lowercase o, tilde 21391 0xb9: 0x7b, 21392 // Open curly brace 21393 0xba: 0x7d, 21394 // Closing curly brace 21395 0xbb: 0x5c, 21396 // Backslash 21397 0xbc: 0x5e, 21398 // Caret 21399 0xbd: 0x5f, 21400 // Underscore 21401 0xbe: 0x7c, 21402 // Pipe (vertical line) 21403 0xbf: 0x223c, 21404 // Tilde operator 21405 0xc0: 0xc4, 21406 // Uppercase A, umlaut 21407 0xc1: 0xe4, 21408 // Lowercase A, umlaut 21409 0xc2: 0xd6, 21410 // Uppercase O, umlaut 21411 0xc3: 0xf6, 21412 // Lowercase o, umlaut 21413 0xc4: 0xdf, 21414 // Esszett (sharp S) 21415 0xc5: 0xa5, 21416 // Yen symbol 21417 0xc6: 0xa4, 21418 // Generic currency sign 21419 0xc7: 0x2503, 21420 // Box drawings heavy vertical 21421 0xc8: 0xc5, 21422 // Uppercase A, ring 21423 0xc9: 0xe5, 21424 // Lowercase A, ring 21425 0xca: 0xd8, 21426 // Uppercase O, stroke 21427 0xcb: 0xf8, 21428 // Lowercase o, strok 21429 0xcc: 0x250f, 21430 // Box drawings heavy down and right 21431 0xcd: 0x2513, 21432 // Box drawings heavy down and left 21433 0xce: 0x2517, 21434 // Box drawings heavy up and right 21435 0xcf: 0x251b // Box drawings heavy up and left 21436}; 21437 21438/** 21439 * Utils 21440 */ 21441var getCharForByte = function getCharForByte(_byte) { 21442 var charCode = _byte; 21443 if (specialCea608CharsCodes.hasOwnProperty(_byte)) { 21444 charCode = specialCea608CharsCodes[_byte]; 21445 } 21446 return String.fromCharCode(charCode); 21447}; 21448var NR_ROWS = 15; 21449var NR_COLS = 100; 21450// Tables to look up row from PAC data 21451var rowsLowCh1 = { 21452 0x11: 1, 21453 0x12: 3, 21454 0x15: 5, 21455 0x16: 7, 21456 0x17: 9, 21457 0x10: 11, 21458 0x13: 12, 21459 0x14: 14 21460}; 21461var rowsHighCh1 = { 21462 0x11: 2, 21463 0x12: 4, 21464 0x15: 6, 21465 0x16: 8, 21466 0x17: 10, 21467 0x13: 13, 21468 0x14: 15 21469}; 21470var rowsLowCh2 = { 21471 0x19: 1, 21472 0x1a: 3, 21473 0x1d: 5, 21474 0x1e: 7, 21475 0x1f: 9, 21476 0x18: 11, 21477 0x1b: 12, 21478 0x1c: 14 21479}; 21480var rowsHighCh2 = { 21481 0x19: 2, 21482 0x1a: 4, 21483 0x1d: 6, 21484 0x1e: 8, 21485 0x1f: 10, 21486 0x1b: 13, 21487 0x1c: 15 21488}; 21489var backgroundColors = ['white', 'green', 'blue', 'cyan', 'red', 'yellow', 'magenta', 'black', 'transparent']; 21490var VerboseLevel; 21491(function (VerboseLevel) { 21492 VerboseLevel[VerboseLevel["ERROR"] = 0] = "ERROR"; 21493 VerboseLevel[VerboseLevel["TEXT"] = 1] = "TEXT"; 21494 VerboseLevel[VerboseLevel["WARNING"] = 2] = "WARNING"; 21495 VerboseLevel[VerboseLevel["INFO"] = 2] = "INFO"; 21496 VerboseLevel[VerboseLevel["DEBUG"] = 3] = "DEBUG"; 21497 VerboseLevel[VerboseLevel["DATA"] = 3] = "DATA"; 21498})(VerboseLevel || (VerboseLevel = {})); 21499var CaptionsLogger = /*#__PURE__*/function () { 21500 function CaptionsLogger() { 21501 this.time = null; 21502 this.verboseLevel = VerboseLevel.ERROR; 21503 } 21504 var _proto = CaptionsLogger.prototype; 21505 _proto.log = function log(severity, msg) { 21506 if (this.verboseLevel >= severity) { 21507 var m = typeof msg === 'function' ? msg() : msg; 21508 _utils_logger__WEBPACK_IMPORTED_MODULE_0__.logger.log(this.time + " [" + severity + "] " + m); 21509 } 21510 }; 21511 return CaptionsLogger; 21512}(); 21513var numArrayToHexArray = function numArrayToHexArray(numArray) { 21514 var hexArray = []; 21515 for (var j = 0; j < numArray.length; j++) { 21516 hexArray.push(numArray[j].toString(16)); 21517 } 21518 return hexArray; 21519}; 21520var PenState = /*#__PURE__*/function () { 21521 function PenState(foreground, underline, italics, background, flash) { 21522 this.foreground = void 0; 21523 this.underline = void 0; 21524 this.italics = void 0; 21525 this.background = void 0; 21526 this.flash = void 0; 21527 this.foreground = foreground || 'white'; 21528 this.underline = underline || false; 21529 this.italics = italics || false; 21530 this.background = background || 'black'; 21531 this.flash = flash || false; 21532 } 21533 var _proto2 = PenState.prototype; 21534 _proto2.reset = function reset() { 21535 this.foreground = 'white'; 21536 this.underline = false; 21537 this.italics = false; 21538 this.background = 'black'; 21539 this.flash = false; 21540 }; 21541 _proto2.setStyles = function setStyles(styles) { 21542 var attribs = ['foreground', 'underline', 'italics', 'background', 'flash']; 21543 for (var i = 0; i < attribs.length; i++) { 21544 var style = attribs[i]; 21545 if (styles.hasOwnProperty(style)) { 21546 this[style] = styles[style]; 21547 } 21548 } 21549 }; 21550 _proto2.isDefault = function isDefault() { 21551 return this.foreground === 'white' && !this.underline && !this.italics && this.background === 'black' && !this.flash; 21552 }; 21553 _proto2.equals = function equals(other) { 21554 return this.foreground === other.foreground && this.underline === other.underline && this.italics === other.italics && this.background === other.background && this.flash === other.flash; 21555 }; 21556 _proto2.copy = function copy(newPenState) { 21557 this.foreground = newPenState.foreground; 21558 this.underline = newPenState.underline; 21559 this.italics = newPenState.italics; 21560 this.background = newPenState.background; 21561 this.flash = newPenState.flash; 21562 }; 21563 _proto2.toString = function toString() { 21564 return 'color=' + this.foreground + ', underline=' + this.underline + ', italics=' + this.italics + ', background=' + this.background + ', flash=' + this.flash; 21565 }; 21566 return PenState; 21567}(); 21568/** 21569 * Unicode character with styling and background. 21570 * @constructor 21571 */ 21572var StyledUnicodeChar = /*#__PURE__*/function () { 21573 function StyledUnicodeChar(uchar, foreground, underline, italics, background, flash) { 21574 this.uchar = void 0; 21575 this.penState = void 0; 21576 this.uchar = uchar || ' '; // unicode character 21577 this.penState = new PenState(foreground, underline, italics, background, flash); 21578 } 21579 var _proto3 = StyledUnicodeChar.prototype; 21580 _proto3.reset = function reset() { 21581 this.uchar = ' '; 21582 this.penState.reset(); 21583 }; 21584 _proto3.setChar = function setChar(uchar, newPenState) { 21585 this.uchar = uchar; 21586 this.penState.copy(newPenState); 21587 }; 21588 _proto3.setPenState = function setPenState(newPenState) { 21589 this.penState.copy(newPenState); 21590 }; 21591 _proto3.equals = function equals(other) { 21592 return this.uchar === other.uchar && this.penState.equals(other.penState); 21593 }; 21594 _proto3.copy = function copy(newChar) { 21595 this.uchar = newChar.uchar; 21596 this.penState.copy(newChar.penState); 21597 }; 21598 _proto3.isEmpty = function isEmpty() { 21599 return this.uchar === ' ' && this.penState.isDefault(); 21600 }; 21601 return StyledUnicodeChar; 21602}(); 21603/** 21604 * CEA-608 row consisting of NR_COLS instances of StyledUnicodeChar. 21605 * @constructor 21606 */ 21607var Row = /*#__PURE__*/function () { 21608 function Row(logger) { 21609 this.chars = void 0; 21610 this.pos = void 0; 21611 this.currPenState = void 0; 21612 this.cueStartTime = void 0; 21613 this.logger = void 0; 21614 this.chars = []; 21615 for (var i = 0; i < NR_COLS; i++) { 21616 this.chars.push(new StyledUnicodeChar()); 21617 } 21618 this.logger = logger; 21619 this.pos = 0; 21620 this.currPenState = new PenState(); 21621 } 21622 var _proto4 = Row.prototype; 21623 _proto4.equals = function equals(other) { 21624 var equal = true; 21625 for (var i = 0; i < NR_COLS; i++) { 21626 if (!this.chars[i].equals(other.chars[i])) { 21627 equal = false; 21628 break; 21629 } 21630 } 21631 return equal; 21632 }; 21633 _proto4.copy = function copy(other) { 21634 for (var i = 0; i < NR_COLS; i++) { 21635 this.chars[i].copy(other.chars[i]); 21636 } 21637 }; 21638 _proto4.isEmpty = function isEmpty() { 21639 var empty = true; 21640 for (var i = 0; i < NR_COLS; i++) { 21641 if (!this.chars[i].isEmpty()) { 21642 empty = false; 21643 break; 21644 } 21645 } 21646 return empty; 21647 } 21648 21649 /** 21650 * Set the cursor to a valid column. 21651 */; 21652 _proto4.setCursor = function setCursor(absPos) { 21653 if (this.pos !== absPos) { 21654 this.pos = absPos; 21655 } 21656 if (this.pos < 0) { 21657 this.logger.log(VerboseLevel.DEBUG, 'Negative cursor position ' + this.pos); 21658 this.pos = 0; 21659 } else if (this.pos > NR_COLS) { 21660 this.logger.log(VerboseLevel.DEBUG, 'Too large cursor position ' + this.pos); 21661 this.pos = NR_COLS; 21662 } 21663 } 21664 21665 /** 21666 * Move the cursor relative to current position. 21667 */; 21668 _proto4.moveCursor = function moveCursor(relPos) { 21669 var newPos = this.pos + relPos; 21670 if (relPos > 1) { 21671 for (var i = this.pos + 1; i < newPos + 1; i++) { 21672 this.chars[i].setPenState(this.currPenState); 21673 } 21674 } 21675 this.setCursor(newPos); 21676 } 21677 21678 /** 21679 * Backspace, move one step back and clear character. 21680 */; 21681 _proto4.backSpace = function backSpace() { 21682 this.moveCursor(-1); 21683 this.chars[this.pos].setChar(' ', this.currPenState); 21684 }; 21685 _proto4.insertChar = function insertChar(_byte2) { 21686 var _this = this; 21687 if (_byte2 >= 0x90) { 21688 // Extended char 21689 this.backSpace(); 21690 } 21691 var _char = getCharForByte(_byte2); 21692 if (this.pos >= NR_COLS) {
vendor: 13,146 bytes, lines 21693-22107
21693 this.logger.log(VerboseLevel.ERROR, function () { 21694 return 'Cannot insert ' + _byte2.toString(16) + ' (' + _char + ') at position ' + _this.pos + '. Skipping it!'; 21695 }); 21696 return; 21697 } 21698 this.chars[this.pos].setChar(_char, this.currPenState); 21699 this.moveCursor(1); 21700 }; 21701 _proto4.clearFromPos = function clearFromPos(startPos) { 21702 var i; 21703 for (i = startPos; i < NR_COLS; i++) { 21704 this.chars[i].reset(); 21705 } 21706 }; 21707 _proto4.clear = function clear() { 21708 this.clearFromPos(0); 21709 this.pos = 0; 21710 this.currPenState.reset(); 21711 }; 21712 _proto4.clearToEndOfRow = function clearToEndOfRow() { 21713 this.clearFromPos(this.pos); 21714 }; 21715 _proto4.getTextString = function getTextString() { 21716 var chars = []; 21717 var empty = true; 21718 for (var i = 0; i < NR_COLS; i++) { 21719 var _char2 = this.chars[i].uchar; 21720 if (_char2 !== ' ') { 21721 empty = false; 21722 } 21723 chars.push(_char2); 21724 } 21725 if (empty) { 21726 return ''; 21727 } else { 21728 return chars.join(''); 21729 } 21730 }; 21731 _proto4.setPenStyles = function setPenStyles(styles) { 21732 this.currPenState.setStyles(styles); 21733 var currChar = this.chars[this.pos]; 21734 currChar.setPenState(this.currPenState); 21735 }; 21736 return Row; 21737}(); 21738 21739/** 21740 * Keep a CEA-608 screen of 32x15 styled characters 21741 * @constructor 21742 */ 21743var CaptionScreen = /*#__PURE__*/function () { 21744 function CaptionScreen(logger) { 21745 this.rows = void 0; 21746 this.currRow = void 0; 21747 this.nrRollUpRows = void 0; 21748 this.lastOutputScreen = void 0; 21749 this.logger = void 0; 21750 this.rows = []; 21751 for (var i = 0; i < NR_ROWS; i++) { 21752 this.rows.push(new Row(logger)); 21753 } // Note that we use zero-based numbering (0-14) 21754 21755 this.logger = logger; 21756 this.currRow = NR_ROWS - 1; 21757 this.nrRollUpRows = null; 21758 this.lastOutputScreen = null; 21759 this.reset(); 21760 } 21761 var _proto5 = CaptionScreen.prototype; 21762 _proto5.reset = function reset() { 21763 for (var i = 0; i < NR_ROWS; i++) { 21764 this.rows[i].clear(); 21765 } 21766 this.currRow = NR_ROWS - 1; 21767 }; 21768 _proto5.equals = function equals(other) { 21769 var equal = true; 21770 for (var i = 0; i < NR_ROWS; i++) { 21771 if (!this.rows[i].equals(other.rows[i])) { 21772 equal = false; 21773 break; 21774 } 21775 } 21776 return equal; 21777 }; 21778 _proto5.copy = function copy(other) { 21779 for (var i = 0; i < NR_ROWS; i++) { 21780 this.rows[i].copy(other.rows[i]); 21781 } 21782 }; 21783 _proto5.isEmpty = function isEmpty() { 21784 var empty = true; 21785 for (var i = 0; i < NR_ROWS; i++) { 21786 if (!this.rows[i].isEmpty()) { 21787 empty = false; 21788 break; 21789 } 21790 } 21791 return empty; 21792 }; 21793 _proto5.backSpace = function backSpace() { 21794 var row = this.rows[this.currRow]; 21795 row.backSpace(); 21796 }; 21797 _proto5.clearToEndOfRow = function clearToEndOfRow() { 21798 var row = this.rows[this.currRow]; 21799 row.clearToEndOfRow(); 21800 } 21801 21802 /** 21803 * Insert a character (without styling) in the current row. 21804 */; 21805 _proto5.insertChar = function insertChar(_char3) { 21806 var row = this.rows[this.currRow]; 21807 row.insertChar(_char3); 21808 }; 21809 _proto5.setPen = function setPen(styles) { 21810 var row = this.rows[this.currRow]; 21811 row.setPenStyles(styles); 21812 }; 21813 _proto5.moveCursor = function moveCursor(relPos) { 21814 var row = this.rows[this.currRow]; 21815 row.moveCursor(relPos); 21816 }; 21817 _proto5.setCursor = function setCursor(absPos) { 21818 this.logger.log(VerboseLevel.INFO, 'setCursor: ' + absPos); 21819 var row = this.rows[this.currRow]; 21820 row.setCursor(absPos); 21821 }; 21822 _proto5.setPAC = function setPAC(pacData) { 21823 this.logger.log(VerboseLevel.INFO, function () { 21824 return 'pacData = ' + JSON.stringify(pacData); 21825 }); 21826 var newRow = pacData.row - 1; 21827 if (this.nrRollUpRows && newRow < this.nrRollUpRows - 1) { 21828 newRow = this.nrRollUpRows - 1; 21829 } 21830 21831 // Make sure this only affects Roll-up Captions by checking this.nrRollUpRows 21832 if (this.nrRollUpRows && this.currRow !== newRow) { 21833 // clear all rows first 21834 for (var i = 0; i < NR_ROWS; i++) { 21835 this.rows[i].clear(); 21836 } 21837 21838 // Copy this.nrRollUpRows rows from lastOutputScreen and place it in the newRow location 21839 // topRowIndex - the start of rows to copy (inclusive index) 21840 var topRowIndex = this.currRow + 1 - this.nrRollUpRows; 21841 // We only copy if the last position was already shown. 21842 // We use the cueStartTime value to check this. 21843 var lastOutputScreen = this.lastOutputScreen; 21844 if (lastOutputScreen) { 21845 var prevLineTime = lastOutputScreen.rows[topRowIndex].cueStartTime; 21846 var time = this.logger.time; 21847 if (prevLineTime && time !== null && prevLineTime < time) { 21848 for (var _i = 0; _i < this.nrRollUpRows; _i++) { 21849 this.rows[newRow - this.nrRollUpRows + _i + 1].copy(lastOutputScreen.rows[topRowIndex + _i]); 21850 } 21851 } 21852 } 21853 } 21854 this.currRow = newRow; 21855 var row = this.rows[this.currRow]; 21856 if (pacData.indent !== null) { 21857 var indent = pacData.indent; 21858 var prevPos = Math.max(indent - 1, 0); 21859 row.setCursor(pacData.indent); 21860 pacData.color = row.chars[prevPos].penState.foreground; 21861 } 21862 var styles = { 21863 foreground: pacData.color, 21864 underline: pacData.underline, 21865 italics: pacData.italics, 21866 background: 'black', 21867 flash: false 21868 }; 21869 this.setPen(styles); 21870 } 21871 21872 /** 21873 * Set background/extra foreground, but first do back_space, and then insert space (backwards compatibility). 21874 */; 21875 _proto5.setBkgData = function setBkgData(bkgData) { 21876 this.logger.log(VerboseLevel.INFO, function () { 21877 return 'bkgData = ' + JSON.stringify(bkgData); 21878 }); 21879 this.backSpace(); 21880 this.setPen(bkgData); 21881 this.insertChar(0x20); // Space 21882 }; 21883 _proto5.setRollUpRows = function setRollUpRows(nrRows) { 21884 this.nrRollUpRows = nrRows; 21885 }; 21886 _proto5.rollUp = function rollUp() { 21887 var _this2 = this; 21888 if (this.nrRollUpRows === null) { 21889 this.logger.log(VerboseLevel.DEBUG, 'roll_up but nrRollUpRows not set yet'); 21890 return; // Not properly setup 21891 } 21892 21893 this.logger.log(VerboseLevel.TEXT, function () { 21894 return _this2.getDisplayText(); 21895 }); 21896 var topRowIndex = this.currRow + 1 - this.nrRollUpRows; 21897 var topRow = this.rows.splice(topRowIndex, 1)[0]; 21898 topRow.clear(); 21899 this.rows.splice(this.currRow, 0, topRow); 21900 this.logger.log(VerboseLevel.INFO, 'Rolling up'); 21901 // this.logger.log(VerboseLevel.TEXT, this.get_display_text()) 21902 } 21903 21904 /** 21905 * Get all non-empty rows with as unicode text. 21906 */; 21907 _proto5.getDisplayText = function getDisplayText(asOneRow) { 21908 asOneRow = asOneRow || false; 21909 var displayText = []; 21910 var text = ''; 21911 var rowNr = -1; 21912 for (var i = 0; i < NR_ROWS; i++) { 21913 var rowText = this.rows[i].getTextString(); 21914 if (rowText) { 21915 rowNr = i + 1; 21916 if (asOneRow) { 21917 displayText.push('Row ' + rowNr + ": '" + rowText + "'"); 21918 } else { 21919 displayText.push(rowText.trim()); 21920 } 21921 } 21922 } 21923 if (displayText.length > 0) { 21924 if (asOneRow) { 21925 text = '[' + displayText.join(' | ') + ']'; 21926 } else { 21927 text = displayText.join('\n'); 21928 } 21929 } 21930 return text; 21931 }; 21932 _proto5.getTextAndFormat = function getTextAndFormat() { 21933 return this.rows; 21934 }; 21935 return CaptionScreen; 21936}(); 21937 21938// var modes = ['MODE_ROLL-UP', 'MODE_POP-ON', 'MODE_PAINT-ON', 'MODE_TEXT']; 21939var Cea608Channel = /*#__PURE__*/function () { 21940 function Cea608Channel(channelNumber, outputFilter, logger) { 21941 this.chNr = void 0; 21942 this.outputFilter = void 0; 21943 this.mode = void 0; 21944 this.verbose = void 0; 21945 this.displayedMemory = void 0; 21946 this.nonDisplayedMemory = void 0; 21947 this.lastOutputScreen = void 0; 21948 this.currRollUpRow = void 0; 21949 this.writeScreen = void 0; 21950 this.cueStartTime = void 0; 21951 this.logger = void 0; 21952 this.chNr = channelNumber; 21953 this.outputFilter = outputFilter; 21954 this.mode = null; 21955 this.verbose = 0; 21956 this.displayedMemory = new CaptionScreen(logger); 21957 this.nonDisplayedMemory = new CaptionScreen(logger); 21958 this.lastOutputScreen = new CaptionScreen(logger); 21959 this.currRollUpRow = this.displayedMemory.rows[NR_ROWS - 1]; 21960 this.writeScreen = this.displayedMemory; 21961 this.mode = null; 21962 this.cueStartTime = null; // Keeps track of where a cue started. 21963 this.logger = logger; 21964 } 21965 var _proto6 = Cea608Channel.prototype; 21966 _proto6.reset = function reset() { 21967 this.mode = null; 21968 this.displayedMemory.reset(); 21969 this.nonDisplayedMemory.reset(); 21970 this.lastOutputScreen.reset(); 21971 this.outputFilter.reset(); 21972 this.currRollUpRow = this.displayedMemory.rows[NR_ROWS - 1]; 21973 this.writeScreen = this.displayedMemory; 21974 this.mode = null; 21975 this.cueStartTime = null; 21976 }; 21977 _proto6.getHandler = function getHandler() { 21978 return this.outputFilter; 21979 }; 21980 _proto6.setHandler = function setHandler(newHandler) { 21981 this.outputFilter = newHandler; 21982 }; 21983 _proto6.setPAC = function setPAC(pacData) { 21984 this.writeScreen.setPAC(pacData); 21985 }; 21986 _proto6.setBkgData = function setBkgData(bkgData) { 21987 this.writeScreen.setBkgData(bkgData); 21988 }; 21989 _proto6.setMode = function setMode(newMode) { 21990 if (newMode === this.mode) { 21991 return; 21992 } 21993 this.mode = newMode; 21994 this.logger.log(VerboseLevel.INFO, function () { 21995 return 'MODE=' + newMode; 21996 }); 21997 if (this.mode === 'MODE_POP-ON') { 21998 this.writeScreen = this.nonDisplayedMemory; 21999 } else { 22000 this.writeScreen = this.displayedMemory; 22001 this.writeScreen.reset(); 22002 } 22003 if (this.mode !== 'MODE_ROLL-UP') { 22004 this.displayedMemory.nrRollUpRows = null; 22005 this.nonDisplayedMemory.nrRollUpRows = null; 22006 } 22007 this.mode = newMode; 22008 }; 22009 _proto6.insertChars = function insertChars(chars) { 22010 var _this3 = this; 22011 for (var i = 0; i < chars.length; i++) { 22012 this.writeScreen.insertChar(chars[i]); 22013 } 22014 var screen = this.writeScreen === this.displayedMemory ? 'DISP' : 'NON_DISP'; 22015 this.logger.log(VerboseLevel.INFO, function () { 22016 return screen + ': ' + _this3.writeScreen.getDisplayText(true); 22017 }); 22018 if (this.mode === 'MODE_PAINT-ON' || this.mode === 'MODE_ROLL-UP') { 22019 this.logger.log(VerboseLevel.TEXT, function () { 22020 return 'DISPLAYED: ' + _this3.displayedMemory.getDisplayText(true); 22021 }); 22022 this.outputDataUpdate(); 22023 } 22024 }; 22025 _proto6.ccRCL = function ccRCL() { 22026 // Resume Caption Loading (switch mode to Pop On) 22027 this.logger.log(VerboseLevel.INFO, 'RCL - Resume Caption Loading'); 22028 this.setMode('MODE_POP-ON'); 22029 }; 22030 _proto6.ccBS = function ccBS() { 22031 // BackSpace 22032 this.logger.log(VerboseLevel.INFO, 'BS - BackSpace'); 22033 if (this.mode === 'MODE_TEXT') { 22034 return; 22035 } 22036 this.writeScreen.backSpace(); 22037 if (this.writeScreen === this.displayedMemory) { 22038 this.outputDataUpdate(); 22039 } 22040 }; 22041 _proto6.ccAOF = function ccAOF() { 22042 // Reserved (formerly Alarm Off) 22043 }; 22044 _proto6.ccAON = function ccAON() { 22045 // Reserved (formerly Alarm On) 22046 }; 22047 _proto6.ccDER = function ccDER() { 22048 // Delete to End of Row 22049 this.logger.log(VerboseLevel.INFO, 'DER- Delete to End of Row'); 22050 this.writeScreen.clearToEndOfRow(); 22051 this.outputDataUpdate(); 22052 }; 22053 _proto6.ccRU = function ccRU(nrRows) { 22054 // Roll-Up Captions-2,3,or 4 Rows 22055 this.logger.log(VerboseLevel.INFO, 'RU(' + nrRows + ') - Roll Up'); 22056 this.writeScreen = this.displayedMemory; 22057 this.setMode('MODE_ROLL-UP'); 22058 this.writeScreen.setRollUpRows(nrRows); 22059 }; 22060 _proto6.ccFON = function ccFON() { 22061 // Flash On 22062 this.logger.log(VerboseLevel.INFO, 'FON - Flash On'); 22063 this.writeScreen.setPen({ 22064 flash: true 22065 }); 22066 }; 22067 _proto6.ccRDC = function ccRDC() { 22068 // Resume Direct Captioning (switch mode to PaintOn) 22069 this.logger.log(VerboseLevel.INFO, 'RDC - Resume Direct Captioning'); 22070 this.setMode('MODE_PAINT-ON'); 22071 }; 22072 _proto6.ccTR = function ccTR() { 22073 // Text Restart in text mode (not supported, however) 22074 this.logger.log(VerboseLevel.INFO, 'TR'); 22075 this.setMode('MODE_TEXT'); 22076 }; 22077 _proto6.ccRTD = function ccRTD() { 22078 // Resume Text Display in Text mode (not supported, however) 22079 this.logger.log(VerboseLevel.INFO, 'RTD'); 22080 this.setMode('MODE_TEXT'); 22081 }; 22082 _proto6.ccEDM = function ccEDM() { 22083 // Erase Displayed Memory 22084 this.logger.log(VerboseLevel.INFO, 'EDM - Erase Displayed Memory'); 22085 this.displayedMemory.reset(); 22086 this.outputDataUpdate(true); 22087 }; 22088 _proto6.ccCR = function ccCR() { 22089 // Carriage Return 22090 this.logger.log(VerboseLevel.INFO, 'CR - Carriage Return'); 22091 this.writeScreen.rollUp(); 22092 this.outputDataUpdate(true); 22093 }; 22094 _proto6.ccENM = function ccENM() { 22095 // Erase Non-Displayed Memory 22096 this.logger.log(VerboseLevel.INFO, 'ENM - Erase Non-displayed Memory'); 22097 this.nonDisplayedMemory.reset(); 22098 }; 22099 _proto6.ccEOC = function ccEOC() { 22100 var _this4 = this; 22101 // End of Caption (Flip Memories) 22102 this.logger.log(VerboseLevel.INFO, 'EOC - End Of Caption'); 22103 if (this.mode === 'MODE_POP-ON') { 22104 var tmp = this.displayedMemory; 22105 this.displayedMemory = this.nonDisplayedMemory; 22106 this.nonDisplayedMemory = tmp; 22107 this.writeScreen = this.nonDisplayedMemory;
22108 this.logger.log(VerboseLevel.TEXT, function () { 22109 return 'DISP: ' + _this4.displayedMemory.getDisplayText(); 22110 }); 22111 } 22112 this.outputDataUpdate(true); 22113 }; 22114 _proto6.ccTO = function ccTO(nrCols) { 22115 // Tab Offset 1,2, or 3 columns 22116 this.logger.log(VerboseLevel.INFO, 'TO(' + nrCols + ') - Tab Offset'); 22117 this.writeScreen.moveCursor(nrCols); 22118 }; 22119 _proto6.ccMIDROW = function ccMIDROW(secondByte) { 22120 // Parse MIDROW command 22121 var styles = { 22122 flash: false 22123 }; 22124 styles.underline = secondByte % 2 === 1; 22125 styles.italics = secondByte >= 0x2e; 22126 if (!styles.italics) { 22127 var colorIndex = Math.floor(secondByte / 2) - 0x10; 22128 var colors = ['white', 'green', 'blue', 'cyan', 'red', 'yellow', 'magenta']; 22129 styles.foreground = colors[colorIndex]; 22130 } else { 22131 styles.foreground = 'white'; 22132 } 22133 this.logger.log(VerboseLevel.INFO, 'MIDROW: ' + JSON.stringify(styles)); 22134 this.writeScreen.setPen(styles); 22135 }; 22136 _proto6.outputDataUpdate = function outputDataUpdate(dispatch) { 22137 if (dispatch === void 0) { 22138 dispatch = false; 22139 } 22140 var time = this.logger.time; 22141 if (time === null) { 22142 return; 22143 } 22144 if (this.outputFilter) { 22145 if (this.cueStartTime === null && !this.displayedMemory.isEmpty()) { 22146 // Start of a new cue 22147 this.cueStartTime = time; 22148 } else { 22149 if (!this.displayedMemory.equals(this.lastOutputScreen)) { 22150 this.outputFilter.newCue(this.cueStartTime, time, this.lastOutputScreen); 22151 if (dispatch && this.outputFilter.dispatchCue) { 22152 this.outputFilter.dispatchCue(); 22153 } 22154 this.cueStartTime = this.displayedMemory.isEmpty() ? null : time; 22155 } 22156 } 22157 this.lastOutputScreen.copy(this.displayedMemory); 22158 } 22159 }; 22160 _proto6.cueSplitAtTime = function cueSplitAtTime(t) { 22161 if (this.outputFilter) { 22162 if (!this.displayedMemory.isEmpty()) { 22163 if (this.outputFilter.newCue) { 22164 this.outputFilter.newCue(this.cueStartTime, t, this.displayedMemory); 22165 } 22166 this.cueStartTime = t; 22167 } 22168 } 22169 }; 22170 return Cea608Channel; 22171}(); 22172var Cea608Parser = /*#__PURE__*/function () { 22173 function Cea608Parser(field, out1, out2) { 22174 this.channels = void 0; 22175 this.currentChannel = 0; 22176 this.cmdHistory = void 0; 22177 this.logger = void 0; 22178 var logger = new CaptionsLogger(); 22179 this.channels = [null, new Cea608Channel(field, out1, logger), new Cea608Channel(field + 1, out2, logger)]; 22180 this.cmdHistory = createCmdHistory(); 22181 this.logger = logger; 22182 } 22183 var _proto7 = Cea608Parser.prototype; 22184 _proto7.getHandler = function getHandler(channel) { 22185 return this.channels[channel].getHandler(); 22186 }; 22187 _proto7.setHandler = function setHandler(channel, newHandler) { 22188 this.channels[channel].setHandler(newHandler); 22189 } 22190 22191 /** 22192 * Add data for time t in forms of list of bytes (unsigned ints). The bytes are treated as pairs. 22193 */; 22194 _proto7.addData = function addData(time, byteList) { 22195 var cmdFound; 22196 var a; 22197 var b; 22198 var charsFound = false; 22199 this.logger.time = time; 22200 for (var i = 0; i < byteList.length; i += 2) { 22201 a = byteList[i] & 0x7f; 22202 b = byteList[i + 1] & 0x7f; 22203 if (a === 0 && b === 0) { 22204 continue; 22205 } else { 22206 this.logger.log(VerboseLevel.DATA, '[' + numArrayToHexArray([byteList[i], byteList[i + 1]]) + '] -> (' + numArrayToHexArray([a, b]) + ')'); 22207 } 22208 cmdFound = this.parseCmd(a, b); 22209 if (!cmdFound) { 22210 cmdFound = this.parseMidrow(a, b); 22211 } 22212 if (!cmdFound) { 22213 cmdFound = this.parsePAC(a, b); 22214 } 22215 if (!cmdFound) { 22216 cmdFound = this.parseBackgroundAttributes(a, b); 22217 } 22218 if (!cmdFound) { 22219 charsFound = this.parseChars(a, b); 22220 if (charsFound) { 22221 var currChNr = this.currentChannel; 22222 if (currChNr && currChNr > 0) { 22223 var channel = this.channels[currChNr]; 22224 channel.insertChars(charsFound); 22225 } else { 22226 this.logger.log(VerboseLevel.WARNING, 'No channel found yet. TEXT-MODE?'); 22227 } 22228 } 22229 } 22230 if (!cmdFound && !charsFound) {
vendor: 7,818 bytes, lines 22231-22498
22231 this.logger.log(VerboseLevel.WARNING, "Couldn't parse cleaned data " + numArrayToHexArray([a, b]) + ' orig: ' + numArrayToHexArray([byteList[i], byteList[i + 1]])); 22232 } 22233 } 22234 } 22235 22236 /** 22237 * Parse Command. 22238 * @returns {Boolean} Tells if a command was found 22239 */; 22240 _proto7.parseCmd = function parseCmd(a, b) { 22241 var cmdHistory = this.cmdHistory; 22242 var cond1 = (a === 0x14 || a === 0x1c || a === 0x15 || a === 0x1d) && b >= 0x20 && b <= 0x2f; 22243 var cond2 = (a === 0x17 || a === 0x1f) && b >= 0x21 && b <= 0x23; 22244 if (!(cond1 || cond2)) { 22245 return false; 22246 } 22247 if (hasCmdRepeated(a, b, cmdHistory)) { 22248 setLastCmd(null, null, cmdHistory); 22249 this.logger.log(VerboseLevel.DEBUG, 'Repeated command (' + numArrayToHexArray([a, b]) + ') is dropped'); 22250 return true; 22251 } 22252 var chNr = a === 0x14 || a === 0x15 || a === 0x17 ? 1 : 2; 22253 var channel = this.channels[chNr]; 22254 if (a === 0x14 || a === 0x15 || a === 0x1c || a === 0x1d) { 22255 if (b === 0x20) { 22256 channel.ccRCL(); 22257 } else if (b === 0x21) { 22258 channel.ccBS(); 22259 } else if (b === 0x22) { 22260 channel.ccAOF(); 22261 } else if (b === 0x23) { 22262 channel.ccAON(); 22263 } else if (b === 0x24) { 22264 channel.ccDER(); 22265 } else if (b === 0x25) { 22266 channel.ccRU(2); 22267 } else if (b === 0x26) { 22268 channel.ccRU(3); 22269 } else if (b === 0x27) { 22270 channel.ccRU(4); 22271 } else if (b === 0x28) { 22272 channel.ccFON(); 22273 } else if (b === 0x29) { 22274 channel.ccRDC(); 22275 } else if (b === 0x2a) { 22276 channel.ccTR(); 22277 } else if (b === 0x2b) { 22278 channel.ccRTD(); 22279 } else if (b === 0x2c) { 22280 channel.ccEDM(); 22281 } else if (b === 0x2d) { 22282 channel.ccCR(); 22283 } else if (b === 0x2e) { 22284 channel.ccENM(); 22285 } else if (b === 0x2f) { 22286 channel.ccEOC(); 22287 } 22288 } else { 22289 // a == 0x17 || a == 0x1F 22290 channel.ccTO(b - 0x20); 22291 } 22292 setLastCmd(a, b, cmdHistory); 22293 this.currentChannel = chNr; 22294 return true; 22295 } 22296 22297 /** 22298 * Parse midrow styling command 22299 * @returns {Boolean} 22300 */; 22301 _proto7.parseMidrow = function parseMidrow(a, b) { 22302 var chNr = 0; 22303 if ((a === 0x11 || a === 0x19) && b >= 0x20 && b <= 0x2f) { 22304 if (a === 0x11) { 22305 chNr = 1; 22306 } else { 22307 chNr = 2; 22308 } 22309 if (chNr !== this.currentChannel) { 22310 this.logger.log(VerboseLevel.ERROR, 'Mismatch channel in midrow parsing'); 22311 return false; 22312 } 22313 var channel = this.channels[chNr]; 22314 if (!channel) { 22315 return false; 22316 } 22317 channel.ccMIDROW(b); 22318 this.logger.log(VerboseLevel.DEBUG, 'MIDROW (' + numArrayToHexArray([a, b]) + ')'); 22319 return true; 22320 } 22321 return false; 22322 } 22323 22324 /** 22325 * Parse Preable Access Codes (Table 53). 22326 * @returns {Boolean} Tells if PAC found 22327 */; 22328 _proto7.parsePAC = function parsePAC(a, b) { 22329 var row; 22330 var cmdHistory = this.cmdHistory; 22331 var case1 = (a >= 0x11 && a <= 0x17 || a >= 0x19 && a <= 0x1f) && b >= 0x40 && b <= 0x7f; 22332 var case2 = (a === 0x10 || a === 0x18) && b >= 0x40 && b <= 0x5f; 22333 if (!(case1 || case2)) { 22334 return false; 22335 } 22336 if (hasCmdRepeated(a, b, cmdHistory)) { 22337 setLastCmd(null, null, cmdHistory); 22338 return true; // Repeated commands are dropped (once) 22339 } 22340 22341 var chNr = a <= 0x17 ? 1 : 2; 22342 if (b >= 0x40 && b <= 0x5f) { 22343 row = chNr === 1 ? rowsLowCh1[a] : rowsLowCh2[a]; 22344 } else { 22345 // 0x60 <= b <= 0x7F 22346 row = chNr === 1 ? rowsHighCh1[a] : rowsHighCh2[a]; 22347 } 22348 var channel = this.channels[chNr]; 22349 if (!channel) { 22350 return false; 22351 } 22352 channel.setPAC(this.interpretPAC(row, b)); 22353 setLastCmd(a, b, cmdHistory); 22354 this.currentChannel = chNr; 22355 return true; 22356 } 22357 22358 /** 22359 * Interpret the second byte of the pac, and return the information. 22360 * @returns {Object} pacData with style parameters. 22361 */; 22362 _proto7.interpretPAC = function interpretPAC(row, _byte3) { 22363 var pacIndex; 22364 var pacData = { 22365 color: null, 22366 italics: false, 22367 indent: null, 22368 underline: false, 22369 row: row 22370 }; 22371 if (_byte3 > 0x5f) { 22372 pacIndex = _byte3 - 0x60; 22373 } else { 22374 pacIndex = _byte3 - 0x40; 22375 } 22376 pacData.underline = (pacIndex & 1) === 1; 22377 if (pacIndex <= 0xd) { 22378 pacData.color = ['white', 'green', 'blue', 'cyan', 'red', 'yellow', 'magenta', 'white'][Math.floor(pacIndex / 2)]; 22379 } else if (pacIndex <= 0xf) { 22380 pacData.italics = true; 22381 pacData.color = 'white'; 22382 } else { 22383 pacData.indent = Math.floor((pacIndex - 0x10) / 2) * 4; 22384 } 22385 return pacData; // Note that row has zero offset. The spec uses 1. 22386 } 22387 22388 /** 22389 * Parse characters. 22390 * @returns An array with 1 to 2 codes corresponding to chars, if found. null otherwise. 22391 */; 22392 _proto7.parseChars = function parseChars(a, b) { 22393 var channelNr; 22394 var charCodes = null; 22395 var charCode1 = null; 22396 if (a >= 0x19) { 22397 channelNr = 2; 22398 charCode1 = a - 8; 22399 } else { 22400 channelNr = 1; 22401 charCode1 = a; 22402 } 22403 if (charCode1 >= 0x11 && charCode1 <= 0x13) { 22404 // Special character 22405 var oneCode; 22406 if (charCode1 === 0x11) { 22407 oneCode = b + 0x50; 22408 } else if (charCode1 === 0x12) { 22409 oneCode = b + 0x70; 22410 } else { 22411 oneCode = b + 0x90; 22412 } 22413 this.logger.log(VerboseLevel.INFO, "Special char '" + getCharForByte(oneCode) + "' in channel " + channelNr); 22414 charCodes = [oneCode]; 22415 } else if (a >= 0x20 && a <= 0x7f) { 22416 charCodes = b === 0 ? [a] : [a, b]; 22417 } 22418 if (charCodes) { 22419 var hexCodes = numArrayToHexArray(charCodes); 22420 this.logger.log(VerboseLevel.DEBUG, 'Char codes = ' + hexCodes.join(',')); 22421 setLastCmd(a, b, this.cmdHistory); 22422 } 22423 return charCodes; 22424 } 22425 22426 /** 22427 * Parse extended background attributes as well as new foreground color black. 22428 * @returns {Boolean} Tells if background attributes are found 22429 */; 22430 _proto7.parseBackgroundAttributes = function parseBackgroundAttributes(a, b) { 22431 var case1 = (a === 0x10 || a === 0x18) && b >= 0x20 && b <= 0x2f; 22432 var case2 = (a === 0x17 || a === 0x1f) && b >= 0x2d && b <= 0x2f; 22433 if (!(case1 || case2)) { 22434 return false; 22435 } 22436 var index; 22437 var bkgData = {}; 22438 if (a === 0x10 || a === 0x18) { 22439 index = Math.floor((b - 0x20) / 2); 22440 bkgData.background = backgroundColors[index]; 22441 if (b % 2 === 1) { 22442 bkgData.background = bkgData.background + '_semi'; 22443 } 22444 } else if (b === 0x2d) { 22445 bkgData.background = 'transparent'; 22446 } else { 22447 bkgData.foreground = 'black'; 22448 if (b === 0x2f) { 22449 bkgData.underline = true; 22450 } 22451 } 22452 var chNr = a <= 0x17 ? 1 : 2; 22453 var channel = this.channels[chNr]; 22454 channel.setBkgData(bkgData); 22455 setLastCmd(a, b, this.cmdHistory); 22456 return true; 22457 } 22458 22459 /** 22460 * Reset state of parser and its channels. 22461 */; 22462 _proto7.reset = function reset() { 22463 for (var i = 0; i < Object.keys(this.channels).length; i++) { 22464 var channel = this.channels[i]; 22465 if (channel) { 22466 channel.reset(); 22467 } 22468 } 22469 this.cmdHistory = createCmdHistory(); 22470 } 22471 22472 /** 22473 * Trigger the generation of a cue, and the start of a new one if displayScreens are not empty. 22474 */; 22475 _proto7.cueSplitAtTime = function cueSplitAtTime(t) { 22476 for (var i = 0; i < this.channels.length; i++) { 22477 var channel = this.channels[i]; 22478 if (channel) { 22479 channel.cueSplitAtTime(t); 22480 } 22481 } 22482 }; 22483 return Cea608Parser; 22484}(); 22485function setLastCmd(a, b, cmdHistory) { 22486 cmdHistory.a = a; 22487 cmdHistory.b = b; 22488} 22489function hasCmdRepeated(a, b, cmdHistory) { 22490 return cmdHistory.a === a && cmdHistory.b === b; 22491} 22492function createCmdHistory() { 22493 return { 22494 a: null, 22495 b: null 22496 }; 22497} 22498/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Cea608Parser
vendor: 2,064 bytes, lines 22498-22597
22498); 22499 22500/***/ }), 22501 22502/***/ "./src/utils/codecs.ts": 22503/*!*****************************!*\ 22504 !*** ./src/utils/codecs.ts ***! 22505 \*****************************/ 22506/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 22507 22508"use strict"; 22509__webpack_require__.r(__webpack_exports__); 22510/* harmony export */ __webpack_require__.d(__webpack_exports__, { 22511/* harmony export */ "isCodecSupportedInMp4": () => (/* binding */ isCodecSupportedInMp4), 22512/* harmony export */ "isCodecType": () => (/* binding */ isCodecType) 22513/* harmony export */ }); 22514// from http://mp4ra.org/codecs.html 22515var sampleEntryCodesISO = { 22516 audio: { 22517 a3ds: true, 22518 'ac-3': true, 22519 'ac-4': true, 22520 alac: true, 22521 alaw: true, 22522 dra1: true, 22523 'dts+': true, 22524 'dts-': true, 22525 dtsc: true, 22526 dtse: true, 22527 dtsh: true, 22528 'ec-3': true, 22529 enca: true, 22530 g719: true, 22531 g726: true, 22532 m4ae: true, 22533 mha1: true, 22534 mha2: true, 22535 mhm1: true, 22536 mhm2: true, 22537 mlpa: true, 22538 mp4a: true, 22539 'raw ': true, 22540 Opus: true, 22541 opus: true, 22542 // browsers expect this to be lowercase despite MP4RA says 'Opus' 22543 samr: true, 22544 sawb: true, 22545 sawp: true, 22546 sevc: true, 22547 sqcp: true, 22548 ssmv: true, 22549 twos: true, 22550 ulaw: true 22551 }, 22552 video: { 22553 avc1: true, 22554 avc2: true, 22555 avc3: true, 22556 avc4: true, 22557 avcp: true, 22558 av01: true, 22559 drac: true, 22560 dva1: true, 22561 dvav: true, 22562 dvh1: true, 22563 dvhe: true, 22564 encv: true, 22565 hev1: true, 22566 hvc1: true, 22567 mjp2: true, 22568 mp4v: true, 22569 mvc1: true, 22570 mvc2: true, 22571 mvc3: true, 22572 mvc4: true, 22573 resv: true, 22574 rv60: true, 22575 s263: true, 22576 svc1: true, 22577 svc2: true, 22578 'vc-1': true, 22579 vp08: true, 22580 vp09: true 22581 }, 22582 text: { 22583 stpp: true, 22584 wvtt: true 22585 } 22586}; 22587function isCodecType(codec, type) { 22588 var typeCodes = sampleEntryCodesISO[type]; 22589 return !!typeCodes && typeCodes[codec.slice(0, 4)] === true; 22590} 22591function isCodecSupportedInMp4(codec, type) { 22592 return MediaSource.isTypeSupported((type || 'video') + "/mp4;codecs=\"" + codec + "\""); 22593} 22594 22595/***/ }), 22596 22597/***/ "./src/utils/
22597cues.ts": 22598/*!***************************!*\ 22599 !*** ./src/utils/cues.ts ***! 22600 \***************************/ 22601/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 22602 22603"use strict"; 22604__webpack_require__.r(__webpack_exports__); 22605/* harmony export */ __webpack_require__.d(__webpack_exports__, { 22606/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 22607/* harmony export */ }); 22608/* harmony import */ var _vttparser__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./vttparser */ "./src/utils/vttparser.ts"); 22609/* harmony import */ var _webvtt_parser__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./webvtt-parser */ "./src/utils/webvtt-parser.ts"); 22610/* harmony import */ var _texttrack_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./texttrack-utils */ "./src/utils/texttrack-utils.ts"); 22611 22612 22613 22614var WHITESPACE_CHAR = /\s/; 22615var Cues = { 22616 newCue: function newCue(track, startTime, endTime, captionScreen) { 22617 var result = []; 22618 var row; 22619 // the type data states this is VTTCue, but it can potentially be a TextTrackCue on old browsers 22620 var cue; 22621 var indenting; 22622 var indent; 22623 var text; 22624 var Cue = self.VTTCue || self.TextTrackCue; 22625 for (var r = 0; r < captionScreen.rows.length; r++) { 22626 row = captionScreen.rows[r]; 22627 indenting = true; 22628 indent = 0; 22629 text = ''; 22630 if (!row.isEmpty()) { 22631 for (var c = 0; c < row.chars.length; c++) { 22632 if (WHITESPACE_CHAR.test(row.chars[c].uchar) && indenting) { 22633 indent++; 22634 } else { 22635 text += row.chars[c].uchar; 22636 indenting = false; 22637 } 22638 } 22639 // To be used for cleaning-up orphaned roll-up captions 22640 row.cueStartTime = startTime; 22641 22642 // Give a slight bump to the endTime if it's equal to startTime to avoid a SyntaxError in IE 22643 if (startTime === endTime) { 22644 endTime += 0.0001; 22645 } 22646 if (indent >= 16) { 22647 indent--; 22648 } else { 22649 indent++; 22650 } 22651 var cueText = (0,_vttparser__WEBPACK_IMPORTED_MODULE_0__.fixLineBreaks)(text.trim()); 22652 var id = (0,_webvtt_parser__WEBPACK_IMPORTED_MODULE_1__.generateCueId)(startTime, endTime, cueText); 22653 22654 // If this cue already exists in the track do not push it 22655 if (!track || !track.cues || !track.cues.getCueById(id)) { 22656 cue = new Cue(startTime, endTime, cueText); 22657 cue.id = id; 22658 cue.line = r + 1; 22659 cue.align = 'left'; 22660 // Clamp the position between 10 and 80 percent (CEA-608 PAC indent code) 22661 // https://dvcs.w3.org/hg/text-tracks/raw-file/default/608toVTT/608toVTT.html#positioning-in-cea-608 22662 // Firefox throws an exception and captions break with out of bounds 0-100 values 22663 cue.position = 10 + Math.min(80, Math.floor(indent * 8 / 32) * 10); 22664 result.push(cue); 22665 } 22666 } 22667 } 22668 if (track && result.length) { 22669 // Sort bottom cues in reverse order so that they render in line order when overlapping in Chrome 22670 result.sort(function (cueA, cueB) { 22671 if (cueA.line === 'auto' || cueB.line === 'auto') { 22672 return 0; 22673 } 22674 if (cueA.line > 8 && cueB.line > 8) { 22675 return cueB.line - cueA.line; 22676 } 22677 return cueA.line - cueB.line; 22678 }); 22679 result.forEach(function (cue) { 22680 return (0,_texttrack_utils__WEBPACK_IMPORTED_MODULE_2__.addCueToTrack)(track, cue); 22681 }); 22682 } 22683 return result; 22684 } 22685}; 22686/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Cues);
vendor: 25,719 bytes, lines 22686-23272
22686 22687 22688/***/ }), 22689 22690/***/ "./src/utils/discontinuities.ts": 22691/*!**************************************!*\ 22692 !*** ./src/utils/discontinuities.ts ***! 22693 \**************************************/ 22694/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 22695 22696"use strict"; 22697__webpack_require__.r(__webpack_exports__); 22698/* harmony export */ __webpack_require__.d(__webpack_exports__, { 22699/* harmony export */ "adjustSlidingStart": () => (/* binding */ adjustSlidingStart), 22700/* harmony export */ "alignMediaPlaylistByPDT": () => (/* binding */ alignMediaPlaylistByPDT), 22701/* harmony export */ "alignPDT": () => (/* binding */ alignPDT), 22702/* harmony export */ "alignStream": () => (/* binding */ alignStream), 22703/* harmony export */ "findDiscontinuousReferenceFrag": () => (/* binding */ findDiscontinuousReferenceFrag), 22704/* harmony export */ "findFirstFragWithCC": () => (/* binding */ findFirstFragWithCC), 22705/* harmony export */ "shouldAlignOnDiscontinuities": () => (/* binding */ shouldAlignOnDiscontinuities) 22706/* harmony export */ }); 22707/* harmony import */ var _home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.ts"); 22708/* harmony import */ var _logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./logger */ "./src/utils/logger.ts"); 22709/* harmony import */ var _controller_level_helper__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../controller/level-helper */ "./src/controller/level-helper.ts"); 22710 22711 22712 22713 22714function findFirstFragWithCC(fragments, cc) { 22715 var firstFrag = null; 22716 for (var i = 0, len = fragments.length; i < len; i++) { 22717 var currentFrag = fragments[i]; 22718 if (currentFrag && currentFrag.cc === cc) { 22719 firstFrag = currentFrag; 22720 break; 22721 } 22722 } 22723 return firstFrag; 22724} 22725function shouldAlignOnDiscontinuities(lastFrag, lastLevel, details) { 22726 if (lastLevel.details) { 22727 if (details.endCC > details.startCC || lastFrag && lastFrag.cc < details.startCC) { 22728 return true; 22729 } 22730 } 22731 return false; 22732} 22733 22734// Find the first frag in the previous level which matches the CC of the first frag of the new level 22735function findDiscontinuousReferenceFrag(prevDetails, curDetails, referenceIndex) { 22736 if (referenceIndex === void 0) { 22737 referenceIndex = 0; 22738 } 22739 var prevFrags = prevDetails.fragments; 22740 var curFrags = curDetails.fragments; 22741 if (!curFrags.length || !prevFrags.length) { 22742 _logger__WEBPACK_IMPORTED_MODULE_1__.logger.log('No fragments to align'); 22743 return; 22744 } 22745 var prevStartFrag = findFirstFragWithCC(prevFrags, curFrags[0].cc); 22746 if (!prevStartFrag || prevStartFrag && !prevStartFrag.startPTS) { 22747 _logger__WEBPACK_IMPORTED_MODULE_1__.logger.log('No frag in previous level to align on'); 22748 return; 22749 } 22750 return prevStartFrag; 22751} 22752function adjustFragmentStart(frag, sliding) { 22753 if (frag) { 22754 var start = frag.start + sliding; 22755 frag.start = frag.startPTS = start; 22756 frag.endPTS = start + frag.duration; 22757 } 22758} 22759function adjustSlidingStart(sliding, details) { 22760 // Update segments 22761 var fragments = details.fragments; 22762 for (var i = 0, len = fragments.length; i < len; i++) { 22763 adjustFragmentStart(fragments[i], sliding); 22764 } 22765 // Update LL-HLS parts at the end of the playlist 22766 if (details.fragmentHint) { 22767 adjustFragmentStart(details.fragmentHint, sliding); 22768 } 22769 details.alignedSliding = true; 22770} 22771 22772/** 22773 * Using the parameters of the last level, this function computes PTS' of the new fragments so that they form a 22774 * contiguous stream with the last fragments. 22775 * The PTS of a fragment lets Hls.js know where it fits into a stream - by knowing every PTS, we know which fragment to 22776 * download at any given time. PTS is normally computed when the fragment is demuxed, so taking this step saves us time 22777 * and an extra download. 22778 * @param lastFrag 22779 * @param lastLevel 22780 * @param details 22781 */ 22782function alignStream(lastFrag, lastLevel, details) { 22783 if (!lastLevel) { 22784 return; 22785 } 22786 alignDiscontinuities(lastFrag, details, lastLevel); 22787 if (!details.alignedSliding && lastLevel.details) { 22788 // If the PTS wasn't figured out via discontinuity sequence that means there was no CC increase within the level. 22789 // Aligning via Program Date Time should therefore be reliable, since PDT should be the same within the same 22790 // discontinuity sequence. 22791 alignPDT(details, lastLevel.details); 22792 } 22793 if (!details.alignedSliding && lastLevel.details && !details.skippedSegments) { 22794 // Try to align on sn so that we pick a better start fragment. 22795 // Do not perform this on playlists with delta updates as this is only to align levels on switch 22796 // and adjustSliding only adjusts fragments after skippedSegments. 22797 (0,_controller_level_helper__WEBPACK_IMPORTED_MODULE_2__.adjustSliding)(lastLevel.details, details); 22798 } 22799} 22800 22801/** 22802 * Computes the PTS if a new level's fragments using the PTS of a fragment in the last level which shares the same 22803 * discontinuity sequence. 22804 * @param lastFrag - The last Fragment which shares the same discontinuity sequence 22805 * @param lastLevel - The details of the last loaded level 22806 * @param details - The details of the new level 22807 */ 22808function alignDiscontinuities(lastFrag, details, lastLevel) { 22809 if (shouldAlignOnDiscontinuities(lastFrag, lastLevel, details)) { 22810 var referenceFrag = findDiscontinuousReferenceFrag(lastLevel.details, details); 22811 if (referenceFrag && (0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(referenceFrag.start)) { 22812 _logger__WEBPACK_IMPORTED_MODULE_1__.logger.log("Adjusting PTS using last level due to CC increase within current level " + details.url); 22813 adjustSlidingStart(referenceFrag.start, details); 22814 } 22815 } 22816} 22817 22818/** 22819 * Computes the PTS of a new level's fragments using the difference in Program Date Time from the last level. 22820 * @param details - The details of the new level 22821 * @param lastDetails - The details of the last loaded level 22822 */ 22823function alignPDT(details, lastDetails) { 22824 // This check protects the unsafe "!" usage below for null program date time access. 22825 if (!lastDetails.fragments.length || !details.hasProgramDateTime || !lastDetails.hasProgramDateTime) { 22826 return; 22827 } 22828 // if last level sliding is 1000 and its first frag PROGRAM-DATE-TIME is 2017-08-20 1:10:00 AM 22829 // and if new details first frag PROGRAM DATE-TIME is 2017-08-20 1:10:08 AM 22830 // then we can deduce that playlist B sliding is 1000+8 = 1008s 22831 var lastPDT = lastDetails.fragments[0].programDateTime; // hasProgramDateTime check above makes this safe. 22832 var newPDT = details.fragments[0].programDateTime; 22833 // date diff is in ms. frag.start is in seconds 22834 var sliding = (newPDT - lastPDT) / 1000 + lastDetails.fragments[0].start; 22835 if (sliding && (0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(sliding)) { 22836 _logger__WEBPACK_IMPORTED_MODULE_1__.logger.log("Adjusting PTS using programDateTime delta " + (newPDT - lastPDT) + "ms, sliding:" + sliding.toFixed(3) + " " + details.url + " "); 22837 adjustSlidingStart(sliding, details); 22838 } 22839} 22840 22841/** 22842 * Ensures appropriate time-alignment between renditions based on PDT. Unlike `alignPDT`, which adjusts 22843 * the timeline based on the delta between PDTs of the 0th fragment of two playlists/`LevelDetails`, 22844 * this function assumes the timelines represented in `refDetails` are accurate, including the PDTs, 22845 * and uses the "wallclock"/PDT timeline as a cross-reference to `details`, adjusting the presentation 22846 * times/timelines of `details` accordingly. 22847 * Given the asynchronous nature of fetches and initial loads of live `main` and audio/subtitle tracks, 22848 * the primary purpose of this function is to ensure the "local timelines" of audio/subtitle tracks 22849 * are aligned to the main/video timeline, using PDT as the cross-reference/"anchor" that should 22850 * be consistent across playlists, per the HLS spec. 22851 * @param details - The details of the rendition you'd like to time-align (e.g. an audio rendition). 22852 * @param refDetails - The details of the reference rendition with start and PDT times for alignment. 22853 */ 22854function alignMediaPlaylistByPDT(details, refDetails) { 22855 if (!details.hasProgramDateTime || !refDetails.hasProgramDateTime) { 22856 return; 22857 } 22858 var fragments = details.fragments; 22859 var refFragments = refDetails.fragments; 22860 if (!fragments.length || !refFragments.length) { 22861 return; 22862 } 22863 22864 // Calculate a delta to apply to all fragments according to the delta in PDT times and start times 22865 // of a fragment in the reference details, and a fragment in the target details of the same discontinuity. 22866 // If a fragment of the same discontinuity was not found use the middle fragment of both. 22867 var middleFrag = Math.round(refFragments.length / 2) - 1; 22868 var refFrag = refFragments[middleFrag]; 22869 var frag = findFirstFragWithCC(fragments, refFrag.cc) || fragments[Math.round(fragments.length / 2) - 1]; 22870 var refPDT = refFrag.programDateTime; 22871 var targetPDT = frag.programDateTime; 22872 if (refPDT === null || targetPDT === null) { 22873 return; 22874 } 22875 var delta = (targetPDT - refPDT) / 1000 - (frag.start - refFrag.start); 22876 adjustSlidingStart(delta, details); 22877} 22878 22879/***/ }), 22880 22881/***/ "./src/utils/ewma-bandwidth-estimator.ts": 22882/*!***********************************************!*\ 22883 !*** ./src/utils/ewma-bandwidth-estimator.ts ***! 22884 \***********************************************/ 22885/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 22886 22887"use strict"; 22888__webpack_require__.r(__webpack_exports__); 22889/* harmony export */ __webpack_require__.d(__webpack_exports__, { 22890/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 22891/* harmony export */ }); 22892/* harmony import */ var _utils_ewma__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils/ewma */ "./src/utils/ewma.ts"); 22893/* 22894 * EWMA Bandwidth Estimator 22895 * - heavily inspired from shaka-player 22896 * Tracks bandwidth samples and estimates available bandwidth. 22897 * Based on the minimum of two exponentially-weighted moving averages with 22898 * different half-lives. 22899 */ 22900 22901 22902var EwmaBandWidthEstimator = /*#__PURE__*/function () { 22903 function EwmaBandWidthEstimator(slow, fast, defaultEstimate) { 22904 this.defaultEstimate_ = void 0; 22905 this.minWeight_ = void 0; 22906 this.minDelayMs_ = void 0; 22907 this.slow_ = void 0; 22908 this.fast_ = void 0; 22909 this.defaultEstimate_ = defaultEstimate; 22910 this.minWeight_ = 0.001; 22911 this.minDelayMs_ = 50; 22912 this.slow_ = new _utils_ewma__WEBPACK_IMPORTED_MODULE_0__["default"](slow); 22913 this.fast_ = new _utils_ewma__WEBPACK_IMPORTED_MODULE_0__["default"](fast); 22914 } 22915 var _proto = EwmaBandWidthEstimator.prototype; 22916 _proto.update = function update(slow, fast) { 22917 var slow_ = this.slow_, 22918 fast_ = this.fast_; 22919 if (this.slow_.halfLife !== slow) { 22920 this.slow_ = new _utils_ewma__WEBPACK_IMPORTED_MODULE_0__["default"](slow, slow_.getEstimate(), slow_.getTotalWeight()); 22921 } 22922 if (this.fast_.halfLife !== fast) { 22923 this.fast_ = new _utils_ewma__WEBPACK_IMPORTED_MODULE_0__["default"](fast, fast_.getEstimate(), fast_.getTotalWeight()); 22924 } 22925 }; 22926 _proto.sample = function sample(durationMs, numBytes) { 22927 durationMs = Math.max(durationMs, this.minDelayMs_); 22928 var numBits = 8 * numBytes; 22929 // weight is duration in seconds 22930 var durationS = durationMs / 1000; 22931 // value is bandwidth in bits/s 22932 var bandwidthInBps = numBits / durationS; 22933 this.fast_.sample(durationS, bandwidthInBps); 22934 this.slow_.sample(durationS, bandwidthInBps); 22935 }; 22936 _proto.canEstimate = function canEstimate() { 22937 var fast = this.fast_; 22938 return fast && fast.getTotalWeight() >= this.minWeight_; 22939 }; 22940 _proto.getEstimate = function getEstimate() { 22941 if (this.canEstimate()) { 22942 // console.log('slow estimate:'+ Math.round(this.slow_.getEstimate())); 22943 // console.log('fast estimate:'+ Math.round(this.fast_.getEstimate())); 22944 // Take the minimum of these two estimates. This should have the effect of 22945 // adapting down quickly, but up more slowly. 22946 return Math.min(this.fast_.getEstimate(), this.slow_.getEstimate()); 22947 } else { 22948 return this.defaultEstimate_; 22949 } 22950 }; 22951 _proto.destroy = function destroy() {}; 22952 return EwmaBandWidthEstimator; 22953}(); 22954/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (EwmaBandWidthEstimator); 22955 22956/***/ }), 22957 22958/***/ "./src/utils/ewma.ts": 22959/*!***************************!*\ 22960 !*** ./src/utils/ewma.ts ***! 22961 \***************************/ 22962/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 22963 22964"use strict"; 22965__webpack_require__.r(__webpack_exports__); 22966/* harmony export */ __webpack_require__.d(__webpack_exports__, { 22967/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 22968/* harmony export */ }); 22969/* 22970 * compute an Exponential Weighted moving average 22971 * - https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average 22972 * - heavily inspired from shaka-player 22973 */ 22974var EWMA = /*#__PURE__*/function () { 22975 // About half of the estimated value will be from the last |halfLife| samples by weight. 22976 function EWMA(halfLife, estimate, weight) { 22977 if (estimate === void 0) { 22978 estimate = 0; 22979 } 22980 if (weight === void 0) { 22981 weight = 0; 22982 } 22983 this.halfLife = void 0; 22984 this.alpha_ = void 0; 22985 this.estimate_ = void 0; 22986 this.totalWeight_ = void 0; 22987 this.halfLife = halfLife; 22988 // Larger values of alpha expire historical data more slowly. 22989 this.alpha_ = halfLife ? Math.exp(Math.log(0.5) / halfLife) : 0; 22990 this.estimate_ = estimate; 22991 this.totalWeight_ = weight; 22992 } 22993 var _proto = EWMA.prototype; 22994 _proto.sample = function sample(weight, value) { 22995 var adjAlpha = Math.pow(this.alpha_, weight); 22996 this.estimate_ = value * (1 - adjAlpha) + adjAlpha * this.estimate_; 22997 this.totalWeight_ += weight; 22998 }; 22999 _proto.getTotalWeight = function getTotalWeight() { 23000 return this.totalWeight_; 23001 }; 23002 _proto.getEstimate = function getEstimate() { 23003 if (this.alpha_) { 23004 var zeroFactor = 1 - Math.pow(this.alpha_, this.totalWeight_); 23005 if (zeroFactor) { 23006 return this.estimate_ / zeroFactor; 23007 } 23008 } 23009 return this.estimate_; 23010 }; 23011 return EWMA; 23012}(); 23013/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (EWMA); 23014 23015/***/ }), 23016 23017/***/ "./src/utils/fetch-loader.ts": 23018/*!***********************************!*\ 23019 !*** ./src/utils/fetch-loader.ts ***! 23020 \***********************************/ 23021/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 23022 23023"use strict"; 23024__webpack_require__.r(__webpack_exports__); 23025/* harmony export */ __webpack_require__.d(__webpack_exports__, { 23026/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__), 23027/* harmony export */ "fetchSupported": () => (/* binding */ fetchSupported) 23028/* harmony export */ }); 23029/* harmony import */ var _home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.ts"); 23030/* harmony import */ var _loader_load_stats__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../loader/load-stats */ "./src/loader/load-stats.ts"); 23031/* harmony import */ var _demux_chunk_cache__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../demux/chunk-cache */ "./src/demux/chunk-cache.ts"); 23032 23033 23034function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); } 23035function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); } 23036function _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct.bind(); } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); } 23037function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } 23038function _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; } 23039function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } 23040function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } 23041function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } 23042 23043 23044function fetchSupported() { 23045 if ( 23046 // @ts-ignore 23047 self.fetch && self.AbortController && self.ReadableStream && self.Request) { 23048 try { 23049 new self.ReadableStream({}); // eslint-disable-line no-new 23050 return true; 23051 } catch (e) { 23052 /* noop */ 23053 } 23054 } 23055 return false; 23056} 23057var FetchLoader = /*#__PURE__*/function () { 23058 function FetchLoader(config /* HlsConfig */) { 23059 this.fetchSetup = void 0; 23060 this.requestTimeout = void 0; 23061 this.request = void 0; 23062 this.response = void 0; 23063 this.controller = void 0; 23064 this.context = void 0; 23065 this.config = null; 23066 this.callbacks = null; 23067 this.stats = void 0; 23068 this.loader = null; 23069 this.fetchSetup = config.fetchSetup || getRequest; 23070 this.controller = new self.AbortController(); 23071 this.stats = new _loader_load_stats__WEBPACK_IMPORTED_MODULE_1__.LoadStats(); 23072 } 23073 var _proto = FetchLoader.prototype; 23074 _proto.destroy = function destroy() { 23075 this.loader = this.callbacks = null; 23076 this.abortInternal(); 23077 }; 23078 _proto.abortInternal = function abortInternal() { 23079 var response = this.response; 23080 if (!response || !response.ok) { 23081 this.stats.aborted = true; 23082 this.controller.abort(); 23083 } 23084 }; 23085 _proto.abort = function abort() { 23086 var _this$callbacks; 23087 this.abortInternal(); 23088 if ((_this$callbacks = this.callbacks) !== null && _this$callbacks !== void 0 && _this$callbacks.onAbort) { 23089 this.callbacks.onAbort(this.stats, this.context, this.response); 23090 } 23091 }; 23092 _proto.load = function load(context, config, callbacks) { 23093 var _this = this; 23094 var stats = this.stats; 23095 if (stats.loading.start) { 23096 throw new Error('Loader can only be used once.'); 23097 } 23098 stats.loading.start = self.performance.now(); 23099 var initParams = getRequestParameters(context, this.controller.signal); 23100 var onProgress = callbacks.onProgress; 23101 var isArrayBuffer = context.responseType === 'arraybuffer'; 23102 var LENGTH = isArrayBuffer ? 'byteLength' : 'length'; 23103 this.context = context; 23104 this.config = config; 23105 this.callbacks = callbacks; 23106 this.request = this.fetchSetup(context, initParams); 23107 self.clearTimeout(this.requestTimeout); 23108 this.requestTimeout = self.setTimeout(function () { 23109 _this.abortInternal(); 23110 callbacks.onTimeout(stats, context, _this.response); 23111 }, config.timeout); 23112 self.fetch(this.request).then(function (response) { 23113 _this.response = _this.loader = response; 23114 if (!response.ok) { 23115 var status = response.status, 23116 statusText = response.statusText; 23117 throw new FetchError(statusText || 'fetch, bad network response', status, response); 23118 } 23119 stats.loading.first = Math.max(self.performance.now(), stats.loading.start); 23120 stats.total = parseInt(response.headers.get('Content-Length') || '0'); 23121 if (onProgress && (0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(config.highWaterMark)) { 23122 return _this.loadProgressively(response, stats, context, config.highWaterMark, onProgress); 23123 } 23124 if (isArrayBuffer) { 23125 return response.arrayBuffer(); 23126 } 23127 return response.text(); 23128 }).then(function (responseData) { 23129 var response = _this.response; 23130 self.clearTimeout(_this.requestTimeout); 23131 stats.loading.end = Math.max(self.performance.now(), stats.loading.first); 23132 var total = responseData[LENGTH]; 23133 if (total) { 23134 stats.loaded = stats.total = total; 23135 } 23136 var loaderResponse = { 23137 url: response.url, 23138 data: responseData 23139 }; 23140 if (onProgress && !(0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(config.highWaterMark)) { 23141 onProgress(stats, context, responseData, response); 23142 } 23143 callbacks.onSuccess(loaderResponse, stats, context, response); 23144 }).catch(function (error) { 23145 self.clearTimeout(_this.requestTimeout); 23146 if (stats.aborted) { 23147 return; 23148 } 23149 // CORS errors result in an undefined code. Set it to 0 here to align with XHR's behavior 23150 // when destroying, 'error' itself can be undefined 23151 var code = !error ? 0 : error.code || 0; 23152 var text = !error ? null : error.message; 23153 callbacks.onError({ 23154 code: code, 23155 text: text 23156 }, context, error ? error.details : null); 23157 }); 23158 }; 23159 _proto.getCacheAge = function getCacheAge() { 23160 var result = null; 23161 if (this.response) { 23162 var ageHeader = this.response.headers.get('age'); 23163 result = ageHeader ? parseFloat(ageHeader) : null; 23164 } 23165 return result; 23166 }; 23167 _proto.loadProgressively = function loadProgressively(response, stats, context, highWaterMark, onProgress) { 23168 if (highWaterMark === void 0) { 23169 highWaterMark = 0; 23170 } 23171 var chunkCache = new _demux_chunk_cache__WEBPACK_IMPORTED_MODULE_2__["default"](); 23172 var reader = response.body.getReader(); 23173 var pump = function pump() { 23174 return reader.read().then(function (data) { 23175 if (data.done) { 23176 if (chunkCache.dataLength) { 23177 onProgress(stats, context, chunkCache.flush(), response); 23178 } 23179 return Promise.resolve(new ArrayBuffer(0)); 23180 } 23181 var chunk = data.value; 23182 var len = chunk.length; 23183 stats.loaded += len; 23184 if (len < highWaterMark || chunkCache.dataLength) { 23185 // The current chunk is too small to to be emitted or the cache already has data 23186 // Push it to the cache 23187 chunkCache.push(chunk); 23188 if (chunkCache.dataLength >= highWaterMark) { 23189 // flush in order to join the typed arrays 23190 onProgress(stats, context, chunkCache.flush(), response); 23191 } 23192 } else { 23193 // If there's nothing cached already, and the chache is large enough 23194 // just emit the progress event 23195 onProgress(stats, context, chunk, response); 23196 } 23197 return pump(); 23198 }).catch(function () { 23199 /* aborted */ 23200 return Promise.reject(); 23201 }); 23202 }; 23203 return pump(); 23204 }; 23205 return FetchLoader; 23206}(); 23207function getRequestParameters(context, signal) { 23208 var initParams = { 23209 method: 'GET', 23210 mode: 'cors', 23211 credentials: 'same-origin', 23212 signal: signal, 23213 headers: new self.Headers(_extends({}, context.headers)) 23214 }; 23215 if (context.rangeEnd) { 23216 initParams.headers.set('Range', 'bytes=' + context.rangeStart + '-' + String(context.rangeEnd - 1)); 23217 } 23218 return initParams; 23219} 23220function getRequest(context, initParams) { 23221 return new self.Request(context.url, initParams); 23222} 23223var FetchError = /*#__PURE__*/function (_Error) { 23224 _inheritsLoose(FetchError, _Error); 23225 function FetchError(message, code, details) { 23226 var _this2; 23227 _this2 = _Error.call(this, message) || this; 23228 _this2.code = void 0; 23229 _this2.details = void 0; 23230 _this2.code = code; 23231 _this2.details = details; 23232 return _this2; 23233 } 23234 return FetchError; 23235}( /*#__PURE__*/_wrapNativeSuper(Error)); 23236/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FetchLoader); 23237 23238/***/ }), 23239 23240/***/ "./src/utils/hex.ts": 23241/*!**************************!*\ 23242 !*** ./src/utils/hex.ts ***! 23243 \**************************/ 23244/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 23245 23246"use strict"; 23247__webpack_require__.r(__webpack_exports__); 23248/* harmony export */ __webpack_require__.d(__webpack_exports__, { 23249/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 23250/* harmony export */ }); 23251/** 23252 * hex dump helper class 23253 */ 23254 23255var Hex = { 23256 hexDump: function hexDump(array) { 23257 var str = ''; 23258 for (var i = 0; i < array.length; i++) { 23259 var h = array[i].toString(16); 23260 if (h.length < 2) { 23261 h = '0' + h; 23262 } 23263 str += h; 23264 } 23265 return str; 23266 } 23267}; 23268/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Hex); 23269 23270/***/ }), 23271 23272/***/ "./src/utils/
vendor: 8,453 bytes, lines 23272-23488
23272imsc1-ttml-parser.ts": 23273/*!****************************************!*\ 23274 !*** ./src/utils/imsc1-ttml-parser.ts ***! 23275 \****************************************/ 23276/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 23277 23278"use strict"; 23279__webpack_require__.r(__webpack_exports__); 23280/* harmony export */ __webpack_require__.d(__webpack_exports__, { 23281/* harmony export */ "IMSC1_CODEC": () => (/* binding */ IMSC1_CODEC), 23282/* harmony export */ "parseIMSC1": () => (/* binding */ parseIMSC1) 23283/* harmony export */ }); 23284/* harmony import */ var _mp4_tools__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./mp4-tools */ "./src/utils/mp4-tools.ts"); 23285/* harmony import */ var _vttparser__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./vttparser */ "./src/utils/vttparser.ts"); 23286/* harmony import */ var _vttcue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./vttcue */ "./src/utils/vttcue.ts"); 23287/* harmony import */ var _demux_id3__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../demux/id3 */ "./src/demux/id3.ts"); 23288/* harmony import */ var _timescale_conversion__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./timescale-conversion */ "./src/utils/timescale-conversion.ts"); 23289/* harmony import */ var _webvtt_parser__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./webvtt-parser */ "./src/utils/webvtt-parser.ts"); 23290function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } 23291 23292 23293 23294 23295 23296 23297var IMSC1_CODEC = 'stpp.ttml.im1t'; 23298 23299// Time format: h:m:s:frames(.subframes) 23300var HMSF_REGEX = /^(\d{2,}):(\d{2}):(\d{2}):(\d{2})\.?(\d+)?$/; 23301 23302// Time format: hours, minutes, seconds, milliseconds, frames, ticks 23303var TIME_UNIT_REGEX = /^(\d*(?:\.\d*)?)(h|m|s|ms|f|t)$/; 23304var textAlignToLineAlign = { 23305 left: 'start', 23306 center: 'center', 23307 right: 'end', 23308 start: 'start', 23309 end: 'end' 23310}; 23311function parseIMSC1(payload, initPTS, timescale, callBack, errorCallBack) { 23312 var results = (0,_mp4_tools__WEBPACK_IMPORTED_MODULE_0__.findBox)(new Uint8Array(payload), ['mdat']); 23313 if (results.length === 0) { 23314 errorCallBack(new Error('Could not parse IMSC1 mdat')); 23315 return; 23316 } 23317 var ttmlList = results.map(function (mdat) { 23318 return (0,_demux_id3__WEBPACK_IMPORTED_MODULE_3__.utf8ArrayToStr)(mdat); 23319 }); 23320 var syncTime = (0,_timescale_conversion__WEBPACK_IMPORTED_MODULE_4__.toTimescaleFromScale)(initPTS, 1, timescale); 23321 try { 23322 ttmlList.forEach(function (ttml) { 23323 return callBack(parseTTML(ttml, syncTime)); 23324 }); 23325 } catch (error) { 23326 errorCallBack(error); 23327 } 23328} 23329function parseTTML(ttml, syncTime) { 23330 var parser = new DOMParser(); 23331 var xmlDoc = parser.parseFromString(ttml, 'text/xml'); 23332 var tt = xmlDoc.getElementsByTagName('tt')[0]; 23333 if (!tt) { 23334 throw new Error('Invalid ttml'); 23335 } 23336 var defaultRateInfo = { 23337 frameRate: 30, 23338 subFrameRate: 1, 23339 frameRateMultiplier: 0, 23340 tickRate: 0 23341 }; 23342 var rateInfo = Object.keys(defaultRateInfo).reduce(function (result, key) { 23343 result[key] = tt.getAttribute("ttp:" + key) || defaultRateInfo[key]; 23344 return result; 23345 }, {}); 23346 var trim = tt.getAttribute('xml:space') !== 'preserve'; 23347 var styleElements = collectionToDictionary(getElementCollection(tt, 'styling', 'style')); 23348 var regionElements = collectionToDictionary(getElementCollection(tt, 'layout', 'region')); 23349 var cueElements = getElementCollection(tt, 'body', '[begin]'); 23350 return [].map.call(cueElements, function (cueElement) { 23351 var cueText = getTextContent(cueElement, trim); 23352 if (!cueText || !cueElement.hasAttribute('begin')) { 23353 return null; 23354 } 23355 var startTime = parseTtmlTime(cueElement.getAttribute('begin'), rateInfo); 23356 var duration = parseTtmlTime(cueElement.getAttribute('dur'), rateInfo); 23357 var endTime = parseTtmlTime(cueElement.getAttribute('end'), rateInfo); 23358 if (startTime === null) { 23359 throw timestampParsingError(cueElement); 23360 } 23361 if (endTime === null) { 23362 if (duration === null) { 23363 throw timestampParsingError(cueElement); 23364 } 23365 endTime = startTime + duration; 23366 } 23367 var cue = new _vttcue__WEBPACK_IMPORTED_MODULE_2__["default"](startTime - syncTime, endTime - syncTime, cueText); 23368 cue.id = (0,_webvtt_parser__WEBPACK_IMPORTED_MODULE_5__.generateCueId)(cue.startTime, cue.endTime, cue.text); 23369 var region = regionElements[cueElement.getAttribute('region')]; 23370 var style = styleElements[cueElement.getAttribute('style')]; 23371 23372 // Apply styles to cue 23373 var styles = getTtmlStyles(region, style, styleElements); 23374 var textAlign = styles.textAlign; 23375 if (textAlign) { 23376 // cue.positionAlign not settable in FF~2016 23377 var lineAlign = textAlignToLineAlign[textAlign]; 23378 if (lineAlign) { 23379 cue.lineAlign = lineAlign; 23380 } 23381 cue.align = textAlign; 23382 } 23383 _extends(cue, styles); 23384 return cue; 23385 }).filter(function (cue) { 23386 return cue !== null; 23387 }); 23388} 23389function getElementCollection(fromElement, parentName, childName) { 23390 var parent = fromElement.getElementsByTagName(parentName)[0]; 23391 if (parent) { 23392 return [].slice.call(parent.querySelectorAll(childName)); 23393 } 23394 return []; 23395} 23396function collectionToDictionary(elementsWithId) { 23397 return elementsWithId.reduce(function (dict, element) { 23398 var id = element.getAttribute('xml:id'); 23399 if (id) { 23400 dict[id] = element; 23401 } 23402 return dict; 23403 }, {}); 23404} 23405function getTextContent(element, trim) { 23406 return [].slice.call(element.childNodes).reduce(function (str, node, i) { 23407 var _node$childNodes; 23408 if (node.nodeName === 'br' && i) { 23409 return str + '\n'; 23410 } 23411 if ((_node$childNodes = node.childNodes) !== null && _node$childNodes !== void 0 && _node$childNodes.length) { 23412 return getTextContent(node, trim); 23413 } else if (trim) { 23414 return str + node.textContent.trim().replace(/\s+/g, ' '); 23415 } 23416 return str + node.textContent; 23417 }, ''); 23418} 23419function getTtmlStyles(region, style, styleElements) { 23420 var ttsNs = 'http://www.w3.org/ns/ttml#styling'; 23421 var regionStyle = null; 23422 var styleAttributes = ['displayAlign', 'textAlign', 'color', 'backgroundColor', 'fontSize', 'fontFamily' 23423 // 'fontWeight', 23424 // 'lineHeight', 23425 // 'wrapOption', 23426 // 'fontStyle', 23427 // 'direction', 23428 // 'writingMode' 23429 ]; 23430 23431 var regionStyleName = region !== null && region !== void 0 && region.hasAttribute('style') ? region.getAttribute('style') : null; 23432 if (regionStyleName && styleElements.hasOwnProperty(regionStyleName)) { 23433 regionStyle = styleElements[regionStyleName]; 23434 } 23435 return styleAttributes.reduce(function (styles, name) { 23436 var value = getAttributeNS(style, ttsNs, name) || getAttributeNS(region, ttsNs, name) || getAttributeNS(regionStyle, ttsNs, name); 23437 if (value) { 23438 styles[name] = value; 23439 } 23440 return styles; 23441 }, {}); 23442} 23443function getAttributeNS(element, ns, name) { 23444 if (!element) { 23445 return null; 23446 } 23447 return element.hasAttributeNS(ns, name) ? element.getAttributeNS(ns, name) : null; 23448} 23449function timestampParsingError(node) { 23450 return new Error("Could not parse ttml timestamp " + node); 23451} 23452function parseTtmlTime(timeAttributeValue, rateInfo) { 23453 if (!timeAttributeValue) { 23454 return null; 23455 } 23456 var seconds = (0,_vttparser__WEBPACK_IMPORTED_MODULE_1__.parseTimeStamp)(timeAttributeValue); 23457 if (seconds === null) { 23458 if (HMSF_REGEX.test(timeAttributeValue)) { 23459 seconds = parseHoursMinutesSecondsFrames(timeAttributeValue, rateInfo); 23460 } else if (TIME_UNIT_REGEX.test(timeAttributeValue)) { 23461 seconds = parseTimeUnits(timeAttributeValue, rateInfo); 23462 } 23463 } 23464 return seconds; 23465} 23466function parseHoursMinutesSecondsFrames(timeAttributeValue, rateInfo) { 23467 var m = HMSF_REGEX.exec(timeAttributeValue); 23468 var frames = (m[4] | 0) + (m[5] | 0) / rateInfo.subFrameRate; 23469 return (m[1] | 0) * 3600 + (m[2] | 0) * 60 + (m[3] | 0) + frames / rateInfo.frameRate; 23470} 23471function parseTimeUnits(timeAttributeValue, rateInfo) { 23472 var m = TIME_UNIT_REGEX.exec(timeAttributeValue); 23473 var value = Number(m[1]); 23474 var unit = m[2]; 23475 switch (unit) { 23476 case 'h': 23477 return value * 3600; 23478 case 'm': 23479 return value * 60; 23480 case 'ms': 23481 return value * 1000; 23482 case 'f': 23483 return value / rateInfo.frameRate; 23484 case 't': 23485 return value / rateInfo.tickRate; 23486 } 23487 return value; 23488}
vendor: 47,325 bytes, lines 23488-24834
23488 23489 23490/***/ }), 23491 23492/***/ "./src/utils/keysystem-util.ts": 23493/*!*************************************!*\ 23494 !*** ./src/utils/keysystem-util.ts ***! 23495 \*************************************/ 23496/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 23497 23498"use strict"; 23499__webpack_require__.r(__webpack_exports__); 23500/* harmony export */ __webpack_require__.d(__webpack_exports__, { 23501/* harmony export */ "changeEndianness": () => (/* binding */ changeEndianness), 23502/* harmony export */ "convertDataUriToArrayBytes": () => (/* binding */ convertDataUriToArrayBytes), 23503/* harmony export */ "strToUtf8array": () => (/* binding */ strToUtf8array) 23504/* harmony export */ }); 23505/* harmony import */ var _numeric_encoding_utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./numeric-encoding-utils */ "./src/utils/numeric-encoding-utils.ts"); 23506 23507function getKeyIdBytes(str) { 23508 var keyIdbytes = strToUtf8array(str).subarray(0, 16); 23509 var paddedkeyIdbytes = new Uint8Array(16); 23510 paddedkeyIdbytes.set(keyIdbytes, 16 - keyIdbytes.length); 23511 return paddedkeyIdbytes; 23512} 23513function changeEndianness(keyId) { 23514 var swap = function swap(array, from, to) { 23515 var cur = array[from]; 23516 array[from] = array[to]; 23517 array[to] = cur; 23518 }; 23519 swap(keyId, 0, 3); 23520 swap(keyId, 1, 2); 23521 swap(keyId, 4, 5); 23522 swap(keyId, 6, 7); 23523} 23524function convertDataUriToArrayBytes(uri) { 23525 // data:[<media type][;attribute=value][;base64],<data> 23526 var colonsplit = uri.split(':'); 23527 var keydata = null; 23528 if (colonsplit[0] === 'data' && colonsplit.length === 2) { 23529 var semicolonsplit = colonsplit[1].split(';'); 23530 var commasplit = semicolonsplit[semicolonsplit.length - 1].split(','); 23531 if (commasplit.length === 2) { 23532 var isbase64 = commasplit[0] === 'base64'; 23533 var data = commasplit[1]; 23534 if (isbase64) { 23535 semicolonsplit.splice(-1, 1); // remove from processing 23536 keydata = (0,_numeric_encoding_utils__WEBPACK_IMPORTED_MODULE_0__.base64Decode)(data); 23537 } else { 23538 keydata = getKeyIdBytes(data); 23539 } 23540 } 23541 } 23542 return keydata; 23543} 23544function strToUtf8array(str) { 23545 return Uint8Array.from(unescape(encodeURIComponent(str)), function (c) { 23546 return c.charCodeAt(0); 23547 }); 23548} 23549 23550/***/ }), 23551 23552/***/ "./src/utils/logger.ts": 23553/*!*****************************!*\ 23554 !*** ./src/utils/logger.ts ***! 23555 \*****************************/ 23556/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 23557 23558"use strict"; 23559__webpack_require__.r(__webpack_exports__); 23560/* harmony export */ __webpack_require__.d(__webpack_exports__, { 23561/* harmony export */ "enableLogs": () => (/* binding */ enableLogs), 23562/* harmony export */ "logger": () => (/* binding */ logger) 23563/* harmony export */ }); 23564var noop = function noop() {}; 23565var fakeLogger = { 23566 trace: noop, 23567 debug: noop, 23568 log: noop, 23569 warn: noop, 23570 info: noop, 23571 error: noop 23572}; 23573var exportedLogger = fakeLogger; 23574 23575// let lastCallTime; 23576// function formatMsgWithTimeInfo(type, msg) { 23577// const now = Date.now(); 23578// const diff = lastCallTime ? '+' + (now - lastCallTime) : '0'; 23579// lastCallTime = now; 23580// msg = (new Date(now)).toISOString() + ' | [' + type + '] > ' + msg + ' ( ' + diff + ' ms )'; 23581// return msg; 23582// } 23583 23584function consolePrintFn(type) { 23585 var func = self.console[type]; 23586 if (func) { 23587 return func.bind(self.console, "[" + type + "] >"); 23588 } 23589 return noop; 23590} 23591function exportLoggerFunctions(debugConfig) { 23592 for (var _len = arguments.length, functions = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 23593 functions[_key - 1] = arguments[_key]; 23594 } 23595 functions.forEach(function (type) { 23596 exportedLogger[type] = debugConfig[type] ? debugConfig[type].bind(debugConfig) : consolePrintFn(type); 23597 }); 23598} 23599function enableLogs(debugConfig, id) { 23600 // check that console is available 23601 if (self.console && debugConfig === true || typeof debugConfig === 'object') { 23602 exportLoggerFunctions(debugConfig, 23603 // Remove out from list here to hard-disable a log-level 23604 // 'trace', 23605 'debug', 'log', 'info', 'warn', 'error'); 23606 // Some browsers don't allow to use bind on console object anyway 23607 // fallback to default if needed 23608 try { 23609 exportedLogger.log("Debug logs enabled for \"" + id + "\""); 23610 } catch (e) { 23611 exportedLogger = fakeLogger; 23612 } 23613 } else { 23614 exportedLogger = fakeLogger; 23615 } 23616} 23617var logger = exportedLogger; 23618 23619/***/ }), 23620 23621/***/ "./src/utils/mediakeys-helper.ts": 23622/*!***************************************!*\ 23623 !*** ./src/utils/mediakeys-helper.ts ***! 23624 \***************************************/ 23625/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 23626 23627"use strict"; 23628__webpack_require__.r(__webpack_exports__); 23629/* harmony export */ __webpack_require__.d(__webpack_exports__, { 23630/* harmony export */ "KeySystemFormats": () => (/* binding */ KeySystemFormats), 23631/* harmony export */ "KeySystemIds": () => (/* binding */ KeySystemIds), 23632/* harmony export */ "KeySystems": () => (/* binding */ KeySystems), 23633/* harmony export */ "getKeySystemsForConfig": () => (/* binding */ getKeySystemsForConfig), 23634/* harmony export */ "getSupportedMediaKeySystemConfigurations": () => (/* binding */ getSupportedMediaKeySystemConfigurations), 23635/* harmony export */ "keySystemDomainToKeySystemFormat": () => (/* binding */ keySystemDomainToKeySystemFormat), 23636/* harmony export */ "keySystemFormatToKeySystemDomain": () => (/* binding */ keySystemFormatToKeySystemDomain), 23637/* harmony export */ "keySystemIdToKeySystemDomain": () => (/* binding */ keySystemIdToKeySystemDomain), 23638/* harmony export */ "requestMediaKeySystemAccess": () => (/* binding */ requestMediaKeySystemAccess) 23639/* harmony export */ }); 23640/** 23641 * @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/requestMediaKeySystemAccess 23642 */ 23643var KeySystems; 23644 23645// Playlist #EXT-X-KEY KEYFORMAT values 23646(function (KeySystems) { 23647 KeySystems["CLEARKEY"] = "org.w3.clearkey"; 23648 KeySystems["FAIRPLAY"] = "com.apple.fps"; 23649 KeySystems["PLAYREADY"] = "com.microsoft.playready"; 23650 KeySystems["WIDEVINE"] = "com.widevine.alpha"; 23651})(KeySystems || (KeySystems = {})); 23652var KeySystemFormats; 23653(function (KeySystemFormats) { 23654 KeySystemFormats["CLEARKEY"] = "org.w3.clearkey"; 23655 KeySystemFormats["FAIRPLAY"] = "com.apple.streamingkeydelivery"; 23656 KeySystemFormats["PLAYREADY"] = "com.microsoft.playready"; 23657 KeySystemFormats["WIDEVINE"] = "urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"; 23658})(KeySystemFormats || (KeySystemFormats = {})); 23659function keySystemFormatToKeySystemDomain(format) { 23660 switch (format) { 23661 case KeySystemFormats.FAIRPLAY: 23662 return KeySystems.FAIRPLAY; 23663 case KeySystemFormats.PLAYREADY: 23664 return KeySystems.PLAYREADY; 23665 case KeySystemFormats.WIDEVINE: 23666 return KeySystems.WIDEVINE; 23667 case KeySystemFormats.CLEARKEY: 23668 return KeySystems.CLEARKEY; 23669 } 23670} 23671 23672// System IDs for which we can extract a key ID from "encrypted" event PSSH 23673var KeySystemIds; 23674(function (KeySystemIds) { 23675 KeySystemIds["WIDEVINE"] = "edef8ba979d64acea3c827dcd51d21ed"; 23676})(KeySystemIds || (KeySystemIds = {})); 23677function keySystemIdToKeySystemDomain(systemId) { 23678 if (systemId === KeySystemIds.WIDEVINE) { 23679 return KeySystems.WIDEVINE; 23680 // } else if (systemId === KeySystemIds.PLAYREADY) { 23681 // return KeySystems.PLAYREADY; 23682 // } else if (systemId === KeySystemIds.CENC || systemId === KeySystemIds.CLEARKEY) { 23683 // return KeySystems.CLEARKEY; 23684 } 23685} 23686 23687function keySystemDomainToKeySystemFormat(keySystem) { 23688 switch (keySystem) { 23689 case KeySystems.FAIRPLAY: 23690 return KeySystemFormats.FAIRPLAY; 23691 case KeySystems.PLAYREADY: 23692 return KeySystemFormats.PLAYREADY; 23693 case KeySystems.WIDEVINE: 23694 return KeySystemFormats.WIDEVINE; 23695 case KeySystems.CLEARKEY: 23696 return KeySystemFormats.CLEARKEY; 23697 } 23698} 23699function getKeySystemsForConfig(config) { 23700 var drmSystems = config.drmSystems, 23701 widevineLicenseUrl = config.widevineLicenseUrl; 23702 var keySystemsToAttempt = drmSystems ? [KeySystems.FAIRPLAY, KeySystems.WIDEVINE, KeySystems.PLAYREADY, KeySystems.CLEARKEY].filter(function (keySystem) { 23703 return !!drmSystems[keySystem]; 23704 }) : []; 23705 if (!keySystemsToAttempt[KeySystems.WIDEVINE] && widevineLicenseUrl) { 23706 keySystemsToAttempt.push(KeySystems.WIDEVINE); 23707 } 23708 return keySystemsToAttempt; 23709} 23710var requestMediaKeySystemAccess = function () { 23711 if (typeof self !== 'undefined' && self.navigator && self.navigator.requestMediaKeySystemAccess) { 23712 return self.navigator.requestMediaKeySystemAccess.bind(self.navigator); 23713 } else { 23714 return null; 23715 } 23716}(); 23717 23718/** 23719 * @see https://developer.mozilla.org/en-US/docs/Web/API/MediaKeySystemConfiguration 23720 */ 23721function getSupportedMediaKeySystemConfigurations(keySystem, audioCodecs, videoCodecs, drmSystemOptions) { 23722 var initDataTypes; 23723 switch (keySystem) { 23724 case KeySystems.FAIRPLAY: 23725 initDataTypes = ['cenc', 'sinf']; 23726 break; 23727 case KeySystems.WIDEVINE: 23728 case KeySystems.PLAYREADY: 23729 initDataTypes = ['cenc']; 23730 break; 23731 case KeySystems.CLEARKEY: 23732 initDataTypes = ['cenc', 'keyids']; 23733 break; 23734 default: 23735 throw new Error("Unknown key-system: " + keySystem); 23736 } 23737 return createMediaKeySystemConfigurations(initDataTypes, audioCodecs, videoCodecs, drmSystemOptions); 23738} 23739function createMediaKeySystemConfigurations(initDataTypes, audioCodecs, videoCodecs, drmSystemOptions) { 23740 var baseConfig = { 23741 initDataTypes: initDataTypes, 23742 persistentState: drmSystemOptions.persistentState || 'not-allowed', 23743 distinctiveIdentifier: drmSystemOptions.distinctiveIdentifier || 'not-allowed', 23744 sessionTypes: drmSystemOptions.sessionTypes || [drmSystemOptions.sessionType || 'temporary'], 23745 audioCapabilities: audioCodecs.map(function (codec) { 23746 return { 23747 contentType: "audio/mp4; codecs=\"" + codec + "\"", 23748 robustness: drmSystemOptions.audioRobustness || '', 23749 encryptionScheme: drmSystemOptions.audioEncryptionScheme || null 23750 }; 23751 }), 23752 videoCapabilities: videoCodecs.map(function (codec) { 23753 return { 23754 contentType: "video/mp4; codecs=\"" + codec + "\"", 23755 robustness: drmSystemOptions.videoRobustness || '', 23756 encryptionScheme: drmSystemOptions.videoEncryptionScheme || null 23757 }; 23758 }) 23759 }; 23760 return [baseConfig]; 23761} 23762 23763/***/ }), 23764 23765/***/ "./src/utils/mediasource-helper.ts": 23766/*!*****************************************!*\ 23767 !*** ./src/utils/mediasource-helper.ts ***! 23768 \*****************************************/ 23769/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 23770 23771"use strict"; 23772__webpack_require__.r(__webpack_exports__); 23773/* harmony export */ __webpack_require__.d(__webpack_exports__, { 23774/* harmony export */ "getMediaSource": () => (/* binding */ getMediaSource) 23775/* harmony export */ }); 23776/** 23777 * MediaSource helper 23778 */ 23779 23780function getMediaSource() { 23781 return self.MediaSource || self.WebKitMediaSource; 23782} 23783 23784/***/ }), 23785 23786/***/ "./src/utils/mp4-tools.ts": 23787/*!********************************!*\ 23788 !*** ./src/utils/mp4-tools.ts ***! 23789 \********************************/ 23790/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 23791 23792"use strict"; 23793__webpack_require__.r(__webpack_exports__); 23794/* harmony export */ __webpack_require__.d(__webpack_exports__, { 23795/* harmony export */ "RemuxerTrackIdConfig": () => (/* binding */ RemuxerTrackIdConfig), 23796/* harmony export */ "appendUint8Array": () => (/* binding */ appendUint8Array), 23797/* harmony export */ "bin2str": () => (/* binding */ bin2str), 23798/* harmony export */ "computeRawDurationFromSamples": () => (/* binding */ computeRawDurationFromSamples), 23799/* harmony export */ "discardEPB": () => (/* binding */ discardEPB), 23800/* harmony export */ "findBox": () => (/* binding */ findBox), 23801/* harmony export */ "getDuration": () => (/* binding */ getDuration), 23802/* harmony export */ "getStartDTS": () => (/* binding */ getStartDTS), 23803/* harmony export */ "mp4Box": () => (/* binding */ mp4Box), 23804/* harmony export */ "mp4pssh": () => (/* binding */ mp4pssh), 23805/* harmony export */ "offsetStartDTS": () => (/* binding */ offsetStartDTS), 23806/* harmony export */ "parseEmsg": () => (/* binding */ parseEmsg), 23807/* harmony export */ "parseInitSegment": () => (/* binding */ parseInitSegment), 23808/* harmony export */ "parsePssh": () => (/* binding */ parsePssh), 23809/* harmony export */ "parseSEIMessageFromNALu": () => (/* binding */ parseSEIMessageFromNALu), 23810/* harmony export */ "parseSamples": () => (/* binding */ parseSamples), 23811/* harmony export */ "parseSegmentIndex": () => (/* binding */ parseSegmentIndex), 23812/* harmony export */ "parseSinf": () => (/* binding */ parseSinf), 23813/* harmony export */ "patchEncyptionData": () => (/* binding */ patchEncyptionData), 23814/* harmony export */ "readSint32": () => (/* binding */ readSint32), 23815/* harmony export */ "readUint16": () => (/* binding */ readUint16), 23816/* harmony export */ "readUint32": () => (/* binding */ readUint32), 23817/* harmony export */ "segmentValidRange": () => (/* binding */ segmentValidRange), 23818/* harmony export */ "writeUint32": () => (/* binding */ writeUint32) 23819/* harmony export */ }); 23820/* harmony import */ var _loader_fragment__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../loader/fragment */ "./src/loader/fragment.ts"); 23821/* harmony import */ var _typed_array__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./typed-array */ "./src/utils/typed-array.ts"); 23822/* harmony import */ var _demux_id3__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../demux/id3 */ "./src/demux/id3.ts"); 23823/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 23824/* harmony import */ var _hex__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./hex */ "./src/utils/hex.ts"); 23825 23826 23827 23828 23829 23830var UINT32_MAX = Math.pow(2, 32) - 1; 23831var push = [].push; 23832 23833// We are using fixed track IDs for driving the MP4 remuxer 23834// instead of following the TS PIDs. 23835// There is no reason not to do this and some browsers/SourceBuffer-demuxers 23836// may not like if there are TrackID "switches" 23837// See https://github.com/video-dev/hls.js/issues/1331 23838// Here we are mapping our internal track types to constant MP4 track IDs 23839// With MSE currently one can only have one track of each, and we are muxing 23840// whatever video/audio rendition in them. 23841var RemuxerTrackIdConfig = { 23842 video: 1, 23843 audio: 2, 23844 id3: 3, 23845 text: 4 23846}; 23847function bin2str(data) { 23848 return String.fromCharCode.apply(null, data); 23849} 23850function readUint16(buffer, offset) { 23851 var val = buffer[offset] << 8 | buffer[offset + 1]; 23852 return val < 0 ? 65536 + val : val; 23853} 23854function readUint32(buffer, offset) { 23855 var val = readSint32(buffer, offset); 23856 return val < 0 ? 4294967296 + val : val; 23857} 23858function readSint32(buffer, offset) { 23859 return buffer[offset] << 24 | buffer[offset + 1] << 16 | buffer[offset + 2] << 8 | buffer[offset + 3]; 23860} 23861function writeUint32(buffer, offset, value) { 23862 buffer[offset] = value >> 24; 23863 buffer[offset + 1] = value >> 16 & 0xff; 23864 buffer[offset + 2] = value >> 8 & 0xff; 23865 buffer[offset + 3] = value & 0xff; 23866} 23867 23868// Find the data for a box specified by its path 23869function findBox(data, path) { 23870 var results = []; 23871 if (!path.length) { 23872 // short-circuit the search for empty paths 23873 return results; 23874 } 23875 var end = data.byteLength; 23876 for (var i = 0; i < end;) { 23877 var size = readUint32(data, i); 23878 var type = bin2str(data.subarray(i + 4, i + 8)); 23879 var endbox = size > 1 ? i + size : end; 23880 if (type === path[0]) { 23881 if (path.length === 1) { 23882 // this is the end of the path and we've found the box we were 23883 // looking for 23884 results.push(data.subarray(i + 8, endbox)); 23885 } else { 23886 // recursively search for the next box along the path 23887 var subresults = findBox(data.subarray(i + 8, endbox), path.slice(1)); 23888 if (subresults.length) { 23889 push.apply(results, subresults); 23890 } 23891 } 23892 } 23893 i = endbox; 23894 } 23895 23896 // we've finished searching all of data 23897 return results; 23898} 23899function parseSegmentIndex(sidx) { 23900 var references = []; 23901 var version = sidx[0]; 23902 23903 // set initial offset, we skip the reference ID (not needed) 23904 var index = 8; 23905 var timescale = readUint32(sidx, index); 23906 index += 4; 23907 23908 // TODO: parse earliestPresentationTime and firstOffset 23909 // usually zero in our case 23910 var earliestPresentationTime = 0; 23911 var firstOffset = 0; 23912 if (version === 0) { 23913 index += 8; 23914 } else { 23915 index += 16; 23916 } 23917 23918 // skip reserved 23919 index += 2; 23920 var startByte = sidx.length + firstOffset; 23921 var referencesCount = readUint16(sidx, index); 23922 index += 2; 23923 for (var i = 0; i < referencesCount; i++) { 23924 var referenceIndex = index; 23925 var referenceInfo = readUint32(sidx, referenceIndex); 23926 referenceIndex += 4; 23927 var referenceSize = referenceInfo & 0x7fffffff; 23928 var referenceType = (referenceInfo & 0x80000000) >>> 31; 23929 if (referenceType === 1) { 23930 // eslint-disable-next-line no-console 23931 console.warn('SIDX has hierarchical references (not supported)'); 23932 return null; 23933 } 23934 var subsegmentDuration = readUint32(sidx, referenceIndex); 23935 referenceIndex += 4; 23936 references.push({ 23937 referenceSize: referenceSize, 23938 subsegmentDuration: subsegmentDuration, 23939 // unscaled 23940 info: { 23941 duration: subsegmentDuration / timescale, 23942 start: startByte, 23943 end: startByte + referenceSize - 1 23944 } 23945 }); 23946 startByte += referenceSize; 23947 23948 // Skipping 1 bit for |startsWithSap|, 3 bits for |sapType|, and 28 bits 23949 // for |sapDelta|. 23950 referenceIndex += 4; 23951 23952 // skip to next ref 23953 index = referenceIndex; 23954 } 23955 return { 23956 earliestPresentationTime: earliestPresentationTime, 23957 timescale: timescale, 23958 version: version, 23959 referencesCount: referencesCount, 23960 references: references 23961 }; 23962} 23963 23964/** 23965 * Parses an MP4 initialization segment and extracts stream type and 23966 * timescale values for any declared tracks. Timescale values indicate the 23967 * number of clock ticks per second to assume for time-based values 23968 * elsewhere in the MP4. 23969 * 23970 * To determine the start time of an MP4, you need two pieces of 23971 * information: the timescale unit and the earliest base media decode 23972 * time. Multiple timescales can be specified within an MP4 but the 23973 * base media decode time is always expressed in the timescale from 23974 * the media header box for the track: 23975 * ``` 23976 * moov > trak > mdia > mdhd.timescale 23977 * moov > trak > mdia > hdlr 23978 * ``` 23979 * @param initSegment {Uint8Array} the bytes of the init segment 23980 * @return {InitData} a hash of track type to timescale values or null if 23981 * the init segment is malformed. 23982 */ 23983 23984function parseInitSegment(initSegment) { 23985 var result = []; 23986 var traks = findBox(initSegment, ['moov', 'trak']); 23987 for (var i = 0; i < traks.length; i++) { 23988 var trak = traks[i]; 23989 var tkhd = findBox(trak, ['tkhd'])[0]; 23990 if (tkhd) { 23991 var version = tkhd[0]; 23992 var _index = version === 0 ? 12 : 20; 23993 var trackId = readUint32(tkhd, _index); 23994 var mdhd = findBox(trak, ['mdia', 'mdhd'])[0]; 23995 if (mdhd) { 23996 version = mdhd[0]; 23997 _index = version === 0 ? 12 : 20; 23998 var timescale = readUint32(mdhd, _index); 23999 var hdlr = findBox(trak, ['mdia', 'hdlr'])[0]; 24000 if (hdlr) { 24001 var hdlrType = bin2str(hdlr.subarray(8, 12)); 24002 var type = { 24003 soun: _loader_fragment__WEBPACK_IMPORTED_MODULE_0__.ElementaryStreamTypes.AUDIO, 24004 vide: _loader_fragment__WEBPACK_IMPORTED_MODULE_0__.ElementaryStreamTypes.VIDEO 24005 }[hdlrType]; 24006 if (type) { 24007 // Parse codec details 24008 var stsd = findBox(trak, ['mdia', 'minf', 'stbl', 'stsd'])[0]; 24009 var codec = void 0; 24010 if (stsd) { 24011 codec = bin2str(stsd.subarray(12, 16)); 24012 // TODO: Parse codec details to be able to build MIME type. 24013 // stsd.start += 8; 24014 // const codecBox = findBox(stsd, [codec])[0]; 24015 // if (codecBox) { 24016 // TODO: Codec parsing support for avc1, mp4a, hevc, av01... 24017 // } 24018 } 24019 24020 result[trackId] = { 24021 timescale: timescale, 24022 type: type 24023 }; 24024 result[type] = { 24025 timescale: timescale, 24026 id: trackId, 24027 codec: codec 24028 }; 24029 } 24030 } 24031 } 24032 } 24033 } 24034 var trex = findBox(initSegment, ['moov', 'mvex', 'trex']); 24035 trex.forEach(function (trex) { 24036 var trackId = readUint32(trex, 4); 24037 var track = result[trackId]; 24038 if (track) { 24039 track.default = { 24040 duration: readUint32(trex, 12), 24041 flags: readUint32(trex, 20) 24042 }; 24043 } 24044 }); 24045 return result; 24046} 24047function patchEncyptionData(initSegment, decryptdata) { 24048 if (!initSegment || !decryptdata) { 24049 return initSegment; 24050 } 24051 var keyId = decryptdata.keyId; 24052 if (keyId && decryptdata.isCommonEncryption) { 24053 var traks = findBox(initSegment, ['moov', 'trak']); 24054 traks.forEach(function (trak) { 24055 var stsd = findBox(trak, ['mdia', 'minf', 'stbl', 'stsd'])[0]; 24056 24057 // skip the sample entry count 24058 var sampleEntries = stsd.subarray(8); 24059 var encBoxes = findBox(sampleEntries, ['enca']); 24060 var isAudio = encBoxes.length > 0; 24061 if (!isAudio) { 24062 encBoxes = findBox(sampleEntries, ['encv']); 24063 } 24064 encBoxes.forEach(function (enc) { 24065 var encBoxChildren = isAudio ? enc.subarray(28) : enc.subarray(78); 24066 var sinfBoxes = findBox(encBoxChildren, ['sinf']); 24067 sinfBoxes.forEach(function (sinf) { 24068 var tenc = parseSinf(sinf); 24069 if (tenc) { 24070 // Look for default key id (keyID offset is always 8 within the tenc box): 24071 var tencKeyId = tenc.subarray(8, 24); 24072 if (!tencKeyId.some(function (b) { 24073 return b !== 0; 24074 })) { 24075 _utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger.log("[eme] Patching keyId in 'enc" + (isAudio ? 'a' : 'v') + ">sinf>>tenc' box: " + _hex__WEBPACK_IMPORTED_MODULE_4__["default"].hexDump(tencKeyId) + " -> " + _hex__WEBPACK_IMPORTED_MODULE_4__["default"].hexDump(keyId)); 24076 tenc.set(keyId, 8); 24077 } 24078 } 24079 }); 24080 }); 24081 }); 24082 } 24083 return initSegment; 24084} 24085function parseSinf(sinf) { 24086 var schm = findBox(sinf, ['schm'])[0]; 24087 if (schm) { 24088 var scheme = bin2str(schm.subarray(4, 8)); 24089 if (scheme === 'cbcs' || scheme === 'cenc') { 24090 return findBox(sinf, ['schi', 'tenc'])[0]; 24091 } 24092 } 24093 _utils_logger__WEBPACK_IMPORTED_MODULE_3__.logger.error("[eme] missing 'schm' box"); 24094 return null; 24095} 24096 24097/** 24098 * Determine the base media decode start time, in seconds, for an MP4 24099 * fragment. If multiple fragments are specified, the earliest time is 24100 * returned. 24101 * 24102 * The base media decode time can be parsed from track fragment 24103 * metadata: 24104 * ``` 24105 * moof > traf > tfdt.baseMediaDecodeTime 24106 * ``` 24107 * It requires the timescale value from the mdhd to interpret. 24108 * 24109 * @param initData {InitData} a hash of track type to timescale values 24110 * @param fmp4 {Uint8Array} the bytes of the mp4 fragment 24111 * @return {number} the earliest base media decode start time for the 24112 * fragment, in seconds 24113 */ 24114function getStartDTS(initData, fmp4) { 24115 // we need info from two children of each track fragment box 24116 return findBox(fmp4, ['moof', 'traf']).reduce(function (result, traf) { 24117 var tfdt = findBox(traf, ['tfdt'])[0]; 24118 var version = tfdt[0]; 24119 var start = findBox(traf, ['tfhd']).reduce(function (result, tfhd) { 24120 // get the track id from the tfhd 24121 var id = readUint32(tfhd, 4); 24122 var track = initData[id]; 24123 if (track) { 24124 var baseTime = readUint32(tfdt, 4); 24125 if (version === 1) { 24126 baseTime *= Math.pow(2, 32); 24127 baseTime += readUint32(tfdt, 8); 24128 } 24129 // assume a 90kHz clock if no timescale was specified 24130 var scale = track.timescale || 90e3; 24131 // convert base time to seconds 24132 var startTime = baseTime / scale; 24133 if (isFinite(startTime) && (result === null || startTime < result)) { 24134 return startTime; 24135 } 24136 } 24137 return result; 24138 }, null); 24139 if (start !== null && isFinite(start) && (result === null || start < result)) { 24140 return start; 24141 } 24142 return result; 24143 }, null) || 0; 24144} 24145 24146/* 24147 For Reference: 24148 aligned(8) class TrackFragmentHeaderBox 24149 extends FullBox(‘tfhd’, 0, tf_flags){ 24150 unsigned int(32) track_ID; 24151 // all the following are optional fields 24152 unsigned int(64) base_data_offset; 24153 unsigned int(32) sample_description_index; 24154 unsigned int(32) default_sample_duration; 24155 unsigned int(32) default_sample_size; 24156 unsigned int(32) default_sample_flags 24157 } 24158 */ 24159function getDuration(data, initData) { 24160 var rawDuration = 0; 24161 var videoDuration = 0; 24162 var audioDuration = 0; 24163 var trafs = findBox(data, ['moof', 'traf']); 24164 for (var i = 0; i < trafs.length; i++) { 24165 var traf = trafs[i]; 24166 // There is only one tfhd & trun per traf 24167 // This is true for CMAF style content, and we should perhaps check the ftyp 24168 // and only look for a single trun then, but for ISOBMFF we should check 24169 // for multiple track runs. 24170 var tfhd = findBox(traf, ['tfhd'])[0]; 24171 // get the track id from the tfhd 24172 var id = readUint32(tfhd, 4); 24173 var track = initData[id]; 24174 if (!track) { 24175 continue; 24176 } 24177 var trackDefault = track.default; 24178 var tfhdFlags = readUint32(tfhd, 0) | (trackDefault === null || trackDefault === void 0 ? void 0 : trackDefault.flags); 24179 var sampleDuration = trackDefault === null || trackDefault === void 0 ? void 0 : trackDefault.duration; 24180 if (tfhdFlags & 0x000008) { 24181 // 0x000008 indicates the presence of the default_sample_duration field 24182 if (tfhdFlags & 0x000002) { 24183 // 0x000002 indicates the presence of the sample_description_index field, which precedes default_sample_duration 24184 // If present, the default_sample_duration exists at byte offset 12 24185 sampleDuration = readUint32(tfhd, 12); 24186 } else { 24187 // Otherwise, the duration is at byte offset 8 24188 sampleDuration = readUint32(tfhd, 8); 24189 } 24190 } 24191 // assume a 90kHz clock if no timescale was specified 24192 var timescale = track.timescale || 90e3; 24193 var truns = findBox(traf, ['trun']); 24194 for (var j = 0; j < truns.length; j++) { 24195 rawDuration = computeRawDurationFromSamples(truns[j]); 24196 if (!rawDuration && sampleDuration) { 24197 var sampleCount = readUint32(truns[j], 4); 24198 rawDuration = sampleDuration * sampleCount; 24199 } 24200 if (track.type === _loader_fragment__WEBPACK_IMPORTED_MODULE_0__.ElementaryStreamTypes.VIDEO) { 24201 videoDuration += rawDuration / timescale; 24202 } else if (track.type === _loader_fragment__WEBPACK_IMPORTED_MODULE_0__.ElementaryStreamTypes.AUDIO) { 24203 audioDuration += rawDuration / timescale; 24204 } 24205 } 24206 } 24207 if (videoDuration === 0 && audioDuration === 0) { 24208 // If duration samples are not available in the traf use sidx subsegment_duration 24209 var sidxDuration = 0; 24210 var sidxs = findBox(data, ['sidx']); 24211 for (var _i = 0; _i < sidxs.length; _i++) { 24212 var sidx = parseSegmentIndex(sidxs[_i]); 24213 if (sidx !== null && sidx !== void 0 && sidx.references) { 24214 sidxDuration += sidx.references.reduce(function (dur, ref) { 24215 return dur + ref.info.duration || 0; 24216 }, 0); 24217 } 24218 } 24219 return sidxDuration; 24220 } 24221 if (videoDuration) { 24222 return videoDuration; 24223 } 24224 return audioDuration; 24225} 24226 24227/* 24228 For Reference: 24229 aligned(8) class TrackRunBox 24230 extends FullBox(‘trun’, version, tr_flags) { 24231 unsigned int(32) sample_count; 24232 // the following are optional fields 24233 signed int(32) data_offset; 24234 unsigned int(32) first_sample_flags; 24235 // all fields in the following array are optional 24236 { 24237 unsigned int(32) sample_duration; 24238 unsigned int(32) sample_size; 24239 unsigned int(32) sample_flags 24240 if (version == 0) 24241 { unsigned int(32) 24242 else 24243 { signed int(32) 24244 }[ sample_count ] 24245 } 24246 */ 24247function computeRawDurationFromSamples(trun) { 24248 var flags = readUint32(trun, 0); 24249 // Flags are at offset 0, non-optional sample_count is at offset 4. Therefore we start 8 bytes in. 24250 // Each field is an int32, which is 4 bytes 24251 var offset = 8; 24252 // data-offset-present flag 24253 if (flags & 0x000001) { 24254 offset += 4; 24255 } 24256 // first-sample-flags-present flag 24257 if (flags & 0x000004) { 24258 offset += 4; 24259 } 24260 var duration = 0; 24261 var sampleCount = readUint32(trun, 4); 24262 for (var i = 0; i < sampleCount; i++) { 24263 // sample-duration-present flag 24264 if (flags & 0x000100) { 24265 var sampleDuration = readUint32(trun, offset); 24266 duration += sampleDuration; 24267 offset += 4; 24268 } 24269 // sample-size-present flag 24270 if (flags & 0x000200) { 24271 offset += 4; 24272 } 24273 // sample-flags-present flag 24274 if (flags & 0x000400) { 24275 offset += 4; 24276 } 24277 // sample-composition-time-offsets-present flag 24278 if (flags & 0x000800) { 24279 offset += 4; 24280 } 24281 } 24282 return duration; 24283} 24284function offsetStartDTS(initData, fmp4, timeOffset) { 24285 findBox(fmp4, ['moof', 'traf']).forEach(function (traf) { 24286 findBox(traf, ['tfhd']).forEach(function (tfhd) { 24287 // get the track id from the tfhd 24288 var id = readUint32(tfhd, 4); 24289 var track = initData[id]; 24290 if (!track) { 24291 return; 24292 } 24293 // assume a 90kHz clock if no timescale was specified 24294 var timescale = track.timescale || 90e3; 24295 // get the base media decode time from the tfdt 24296 findBox(traf, ['tfdt']).forEach(function (tfdt) { 24297 var version = tfdt[0]; 24298 var baseMediaDecodeTime = readUint32(tfdt, 4); 24299 if (version === 0) { 24300 baseMediaDecodeTime -= timeOffset * timescale; 24301 baseMediaDecodeTime = Math.max(baseMediaDecodeTime, 0); 24302 writeUint32(tfdt, 4, baseMediaDecodeTime); 24303 } else { 24304 baseMediaDecodeTime *= Math.pow(2, 32); 24305 baseMediaDecodeTime += readUint32(tfdt, 8); 24306 baseMediaDecodeTime -= timeOffset * timescale; 24307 baseMediaDecodeTime = Math.max(baseMediaDecodeTime, 0); 24308 var upper = Math.floor(baseMediaDecodeTime / (UINT32_MAX + 1)); 24309 var lower = Math.floor(baseMediaDecodeTime % (UINT32_MAX + 1)); 24310 writeUint32(tfdt, 4, upper); 24311 writeUint32(tfdt, 8, lower); 24312 } 24313 }); 24314 }); 24315 }); 24316} 24317 24318// TODO: Check if the last moof+mdat pair is part of the valid range 24319function segmentValidRange(data) { 24320 var segmentedRange = { 24321 valid: null, 24322 remainder: null 24323 }; 24324 var moofs = findBox(data, ['moof']); 24325 if (!moofs) { 24326 return segmentedRange; 24327 } else if (moofs.length < 2) { 24328 segmentedRange.remainder = data; 24329 return segmentedRange; 24330 } 24331 var last = moofs[moofs.length - 1]; 24332 // Offset by 8 bytes; findBox offsets the start by as much 24333 segmentedRange.valid = (0,_typed_array__WEBPACK_IMPORTED_MODULE_1__.sliceUint8)(data, 0, last.byteOffset - 8); 24334 segmentedRange.remainder = (0,_typed_array__WEBPACK_IMPORTED_MODULE_1__.sliceUint8)(data, last.byteOffset - 8); 24335 return segmentedRange; 24336} 24337function appendUint8Array(data1, data2) { 24338 var temp = new Uint8Array(data1.length + data2.length); 24339 temp.set(data1); 24340 temp.set(data2, data1.length); 24341 return temp; 24342} 24343function parseSamples(timeOffset, track) { 24344 var seiSamples = []; 24345 var videoData = track.samples; 24346 var timescale = track.timescale; 24347 var trackId = track.id; 24348 var isHEVCFlavor = false; 24349 var moofs = findBox(videoData, ['moof']); 24350 moofs.map(function (moof) { 24351 var moofOffset = moof.byteOffset - 8; 24352 var trafs = findBox(moof, ['traf']); 24353 trafs.map(function (traf) { 24354 // get the base media decode time from the tfdt 24355 var baseTime = findBox(traf, ['tfdt']).map(function (tfdt) { 24356 var version = tfdt[0]; 24357 var result = readUint32(tfdt, 4); 24358 if (version === 1) { 24359 result *= Math.pow(2, 32); 24360 result += readUint32(tfdt, 8); 24361 } 24362 return result / timescale; 24363 })[0]; 24364 if (baseTime !== undefined) { 24365 timeOffset = baseTime; 24366 } 24367 return findBox(traf, ['tfhd']).map(function (tfhd) { 24368 var id = readUint32(tfhd, 4); 24369 var tfhdFlags = readUint32(tfhd, 0) & 0xffffff; 24370 var baseDataOffsetPresent = (tfhdFlags & 0x000001) !== 0; 24371 var sampleDescriptionIndexPresent = (tfhdFlags & 0x000002) !== 0; 24372 var defaultSampleDurationPresent = (tfhdFlags & 0x000008) !== 0; 24373 var defaultSampleDuration = 0; 24374 var defaultSampleSizePresent = (tfhdFlags & 0x000010) !== 0; 24375 var defaultSampleSize = 0; 24376 var defaultSampleFlagsPresent = (tfhdFlags & 0x000020) !== 0; 24377 var tfhdOffset = 8; 24378 if (id === trackId) { 24379 if (baseDataOffsetPresent) { 24380 tfhdOffset += 8; 24381 } 24382 if (sampleDescriptionIndexPresent) { 24383 tfhdOffset += 4; 24384 } 24385 if (defaultSampleDurationPresent) { 24386 defaultSampleDuration = readUint32(tfhd, tfhdOffset); 24387 tfhdOffset += 4; 24388 } 24389 if (defaultSampleSizePresent) { 24390 defaultSampleSize = readUint32(tfhd, tfhdOffset); 24391 tfhdOffset += 4; 24392 } 24393 if (defaultSampleFlagsPresent) { 24394 tfhdOffset += 4; 24395 } 24396 if (track.type === 'video') { 24397 isHEVCFlavor = isHEVC(track.codec); 24398 } 24399 findBox(traf, ['trun']).map(function (trun) { 24400 var version = trun[0]; 24401 var flags = readUint32(trun, 0) & 0xffffff; 24402 var dataOffsetPresent = (flags & 0x000001) !== 0; 24403 var dataOffset = 0; 24404 var firstSampleFlagsPresent = (flags & 0x000004) !== 0; 24405 var sampleDurationPresent = (flags & 0x000100) !== 0; 24406 var sampleDuration = 0; 24407 var sampleSizePresent = (flags & 0x000200) !== 0; 24408 var sampleSize = 0; 24409 var sampleFlagsPresent = (flags & 0x000400) !== 0; 24410 var sampleCompositionOffsetsPresent = (flags & 0x000800) !== 0; 24411 var compositionOffset = 0; 24412 var sampleCount = readUint32(trun, 4); 24413 var trunOffset = 8; // past version, flags, and sample count 24414 24415 if (dataOffsetPresent) { 24416 dataOffset = readUint32(trun, trunOffset); 24417 trunOffset += 4; 24418 } 24419 if (firstSampleFlagsPresent) { 24420 trunOffset += 4; 24421 } 24422 var sampleOffset = dataOffset + moofOffset; 24423 for (var ix = 0; ix < sampleCount; ix++) { 24424 if (sampleDurationPresent) { 24425 sampleDuration = readUint32(trun, trunOffset); 24426 trunOffset += 4; 24427 } else { 24428 sampleDuration = defaultSampleDuration; 24429 } 24430 if (sampleSizePresent) { 24431 sampleSize = readUint32(trun, trunOffset); 24432 trunOffset += 4; 24433 } else { 24434 sampleSize = defaultSampleSize; 24435 } 24436 if (sampleFlagsPresent) { 24437 trunOffset += 4; 24438 } 24439 if (sampleCompositionOffsetsPresent) { 24440 if (version === 0) { 24441 compositionOffset = readUint32(trun, trunOffset); 24442 } else { 24443 compositionOffset = readSint32(trun, trunOffset); 24444 } 24445 trunOffset += 4; 24446 } 24447 if (track.type === _loader_fragment__WEBPACK_IMPORTED_MODULE_0__.ElementaryStreamTypes.VIDEO) { 24448 var naluTotalSize = 0; 24449 while (naluTotalSize < sampleSize) { 24450 var naluSize = readUint32(videoData, sampleOffset); 24451 sampleOffset += 4; 24452 if (isSEIMessage(isHEVCFlavor, videoData[sampleOffset])) { 24453 var data = videoData.subarray(sampleOffset, sampleOffset + naluSize); 24454 parseSEIMessageFromNALu(data, isHEVCFlavor ? 2 : 1, timeOffset + compositionOffset / timescale, seiSamples); 24455 } 24456 sampleOffset += naluSize; 24457 naluTotalSize += naluSize + 4; 24458 } 24459 } 24460 timeOffset += sampleDuration / timescale; 24461 } 24462 }); 24463 } 24464 }); 24465 }); 24466 }); 24467 return seiSamples; 24468} 24469function isHEVC(codec) { 24470 if (!codec) { 24471 return false; 24472 } 24473 var delimit = codec.indexOf('.'); 24474 var baseCodec = delimit < 0 ? codec : codec.substring(0, delimit); 24475 return baseCodec === 'hvc1' || baseCodec === 'hev1' || 24476 // Dolby Vision 24477 baseCodec === 'dvh1' || baseCodec === 'dvhe'; 24478} 24479function isSEIMessage(isHEVCFlavor, naluHeader) { 24480 if (isHEVCFlavor) { 24481 var naluType = naluHeader >> 1 & 0x3f; 24482 return naluType === 39 || naluType === 40; 24483 } else { 24484 var _naluType = naluHeader & 0x1f; 24485 return _naluType === 6; 24486 } 24487} 24488function parseSEIMessageFromNALu(unescapedData, headerSize, pts, samples) { 24489 var data = discardEPB(unescapedData); 24490 var seiPtr = 0; 24491 // skip nal header 24492 seiPtr += headerSize; 24493 var payloadType = 0; 24494 var payloadSize = 0; 24495 var endOfCaptions = false; 24496 var b = 0; 24497 while (seiPtr < data.length) { 24498 payloadType = 0; 24499 do { 24500 if (seiPtr >= data.length) { 24501 break; 24502 } 24503 b = data[seiPtr++]; 24504 payloadType += b; 24505 } while (b === 0xff); 24506 24507 // Parse payload size. 24508 payloadSize = 0; 24509 do { 24510 if (seiPtr >= data.length) { 24511 break; 24512 } 24513 b = data[seiPtr++]; 24514 payloadSize += b; 24515 } while (b === 0xff); 24516 var leftOver = data.length - seiPtr; 24517 if (!endOfCaptions && payloadType === 4 && seiPtr < data.length) { 24518 endOfCaptions = true; 24519 var countryCode = data[seiPtr++]; 24520 if (countryCode === 181) { 24521 var providerCode = readUint16(data, seiPtr); 24522 seiPtr += 2; 24523 if (providerCode === 49) { 24524 var userStructure = readUint32(data, seiPtr); 24525 seiPtr += 4; 24526 if (userStructure === 0x47413934) { 24527 var userDataType = data[seiPtr++]; 24528 24529 // Raw CEA-608 bytes wrapped in CEA-708 packet 24530 if (userDataType === 3) { 24531 var firstByte = data[seiPtr++]; 24532 var totalCCs = 0x1f & firstByte; 24533 var enabled = 0x40 & firstByte; 24534 var totalBytes = enabled ? 2 + totalCCs * 3 : 0; 24535 var byteArray = new Uint8Array(totalBytes); 24536 if (enabled) { 24537 byteArray[0] = firstByte; 24538 for (var i = 1; i < totalBytes; i++) { 24539 byteArray[i] = data[seiPtr++]; 24540 } 24541 } 24542 samples.push({ 24543 type: userDataType, 24544 payloadType: payloadType, 24545 pts: pts, 24546 bytes: byteArray 24547 }); 24548 } 24549 } 24550 } 24551 } 24552 } else if (payloadType === 5 && payloadSize < leftOver) { 24553 endOfCaptions = true; 24554 if (payloadSize > 16) { 24555 var uuidStrArray = []; 24556 for (var _i2 = 0; _i2 < 16; _i2++) { 24557 var _b = data[seiPtr++].toString(16); 24558 uuidStrArray.push(_b.length == 1 ? '0' + _b : _b); 24559 if (_i2 === 3 || _i2 === 5 || _i2 === 7 || _i2 === 9) { 24560 uuidStrArray.push('-'); 24561 } 24562 } 24563 var length = payloadSize - 16; 24564 var userDataBytes = new Uint8Array(length); 24565 for (var _i3 = 0; _i3 < length; _i3++) { 24566 userDataBytes[_i3] = data[seiPtr++]; 24567 } 24568 samples.push({ 24569 payloadType: payloadType, 24570 pts: pts, 24571 uuid: uuidStrArray.join(''), 24572 userData: (0,_demux_id3__WEBPACK_IMPORTED_MODULE_2__.utf8ArrayToStr)(userDataBytes), 24573 userDataBytes: userDataBytes 24574 }); 24575 } 24576 } else if (payloadSize < leftOver) { 24577 seiPtr += payloadSize; 24578 } else if (payloadSize > leftOver) { 24579 break; 24580 } 24581 } 24582} 24583 24584/** 24585 * remove Emulation Prevention bytes from a RBSP 24586 */ 24587function discardEPB(data) { 24588 var length = data.byteLength; 24589 var EPBPositions = []; 24590 var i = 1; 24591 24592 // Find all `Emulation Prevention Bytes` 24593 while (i < length - 2) { 24594 if (data[i] === 0 && data[i + 1] === 0 && data[i + 2] === 0x03) { 24595 EPBPositions.push(i + 2); 24596 i += 2; 24597 } else { 24598 i++; 24599 } 24600 } 24601 24602 // If no Emulation Prevention Bytes were found just return the original 24603 // array 24604 if (EPBPositions.length === 0) { 24605 return data; 24606 } 24607 24608 // Create a new array to hold the NAL unit data 24609 var newLength = length - EPBPositions.length; 24610 var newData = new Uint8Array(newLength); 24611 var sourceIndex = 0; 24612 for (i = 0; i < newLength; sourceIndex++, i++) { 24613 if (sourceIndex === EPBPositions[0]) { 24614 // Skip this byte 24615 sourceIndex++; 24616 // Remove this position index 24617 EPBPositions.shift(); 24618 } 24619 newData[i] = data[sourceIndex]; 24620 } 24621 return newData; 24622} 24623function parseEmsg(data) { 24624 var version = data[0]; 24625 var schemeIdUri = ''; 24626 var value = ''; 24627 var timeScale = 0; 24628 var presentationTimeDelta = 0; 24629 var presentationTime = 0; 24630 var eventDuration = 0; 24631 var id = 0; 24632 var offset = 0; 24633 if (version === 0) { 24634 while (bin2str(data.subarray(offset, offset + 1)) !== '\0') { 24635 schemeIdUri += bin2str(data.subarray(offset, offset + 1)); 24636 offset += 1; 24637 } 24638 schemeIdUri += bin2str(data.subarray(offset, offset + 1)); 24639 offset += 1; 24640 while (bin2str(data.subarray(offset, offset + 1)) !== '\0') { 24641 value += bin2str(data.subarray(offset, offset + 1)); 24642 offset += 1; 24643 } 24644 value += bin2str(data.subarray(offset, offset + 1)); 24645 offset += 1; 24646 timeScale = readUint32(data, 12); 24647 presentationTimeDelta = readUint32(data, 16); 24648 eventDuration = readUint32(data, 20); 24649 id = readUint32(data, 24); 24650 offset = 28; 24651 } else if (version === 1) { 24652 offset += 4; 24653 timeScale = readUint32(data, offset); 24654 offset += 4; 24655 var leftPresentationTime = readUint32(data, offset); 24656 offset += 4; 24657 var rightPresentationTime = readUint32(data, offset); 24658 offset += 4; 24659 presentationTime = Math.pow(2, 32) * leftPresentationTime + rightPresentationTime; 24660 if (!Number.isSafeInteger(presentationTime)) { 24661 presentationTime = Number.MAX_SAFE_INTEGER; 24662 // eslint-disable-next-line no-console 24663 console.warn('Presentation time exceeds safe integer limit and wrapped to max safe integer in parsing emsg box'); 24664 } 24665 eventDuration = readUint32(data, offset); 24666 offset += 4; 24667 id = readUint32(data, offset); 24668 offset += 4; 24669 while (bin2str(data.subarray(offset, offset + 1)) !== '\0') { 24670 schemeIdUri += bin2str(data.subarray(offset, offset + 1)); 24671 offset += 1; 24672 } 24673 schemeIdUri += bin2str(data.subarray(offset, offset + 1)); 24674 offset += 1; 24675 while (bin2str(data.subarray(offset, offset + 1)) !== '\0') { 24676 value += bin2str(data.subarray(offset, offset + 1)); 24677 offset += 1; 24678 } 24679 value += bin2str(data.subarray(offset, offset + 1)); 24680 offset += 1; 24681 } 24682 var payload = data.subarray(offset, data.byteLength); 24683 return { 24684 schemeIdUri: schemeIdUri, 24685 value: value, 24686 timeScale: timeScale, 24687 presentationTime: presentationTime, 24688 presentationTimeDelta: presentationTimeDelta, 24689 eventDuration: eventDuration, 24690 id: id, 24691 payload: payload 24692 }; 24693} 24694function mp4Box(type) { 24695 for (var _len = arguments.length, payload = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 24696 payload[_key - 1] = arguments[_key]; 24697 } 24698 var len = payload.length; 24699 var size = 8; 24700 var i = len; 24701 while (i--) { 24702 size += payload[i].byteLength; 24703 } 24704 var result = new Uint8Array(size); 24705 result[0] = size >> 24 & 0xff; 24706 result[1] = size >> 16 & 0xff; 24707 result[2] = size >> 8 & 0xff; 24708 result[3] = size & 0xff; 24709 result.set(type, 4); 24710 for (i = 0, size = 8; i < len; i++) { 24711 result.set(payload[i], size); 24712 size += payload[i].byteLength; 24713 } 24714 return result; 24715} 24716function mp4pssh(systemId, keyids, data) { 24717 if (systemId.byteLength !== 16) { 24718 throw new RangeError('Invalid system id'); 24719 } 24720 var version; 24721 var kids; 24722 if (keyids) { 24723 version = 1; 24724 kids = new Uint8Array(keyids.length * 16); 24725 for (var ix = 0; ix < keyids.length; ix++) { 24726 var k = keyids[ix]; // uint8array 24727 if (k.byteLength !== 16) { 24728 throw new RangeError('Invalid key'); 24729 } 24730 kids.set(k, ix * 16); 24731 } 24732 } else { 24733 version = 0; 24734 kids = new Uint8Array(); 24735 } 24736 var kidCount; 24737 if (version > 0) { 24738 kidCount = new Uint8Array(4); 24739 if (keyids.length > 0) { 24740 new DataView(kidCount.buffer).setUint32(0, keyids.length, false); 24741 } 24742 } else { 24743 kidCount = new Uint8Array(); 24744 } 24745 var dataSize = new Uint8Array(4); 24746 if (data && data.byteLength > 0) { 24747 new DataView(dataSize.buffer).setUint32(0, data.byteLength, false); 24748 } 24749 return mp4Box([112, 115, 115, 104], new Uint8Array([version, 0x00, 0x00, 0x00 // Flags 24750 ]), systemId, 24751 // 16 bytes 24752 kidCount, kids, dataSize, data || new Uint8Array()); 24753} 24754function parsePssh(initData) { 24755 if (!(initData instanceof ArrayBuffer) || initData.byteLength < 32) { 24756 return null; 24757 } 24758 var result = { 24759 version: 0, 24760 systemId: '', 24761 kids: null, 24762 data: null 24763 }; 24764 var view = new DataView(initData); 24765 var boxSize = view.getUint32(0); 24766 if (initData.byteLength !== boxSize && boxSize > 44) { 24767 return null; 24768 } 24769 var type = view.getUint32(4); 24770 if (type !== 0x70737368) { 24771 return null; 24772 } 24773 result.version = view.getUint32(8) >>> 24; 24774 if (result.version > 1) { 24775 return null; 24776 } 24777 result.systemId = _hex__WEBPACK_IMPORTED_MODULE_4__["default"].hexDump(new Uint8Array(initData, 12, 16)); 24778 var dataSizeOrKidCount = view.getUint32(28); 24779 if (result.version === 0) { 24780 if (boxSize - 32 < dataSizeOrKidCount) { 24781 return null; 24782 } 24783 result.data = new Uint8Array(initData, 32, dataSizeOrKidCount); 24784 } else if (result.version === 1) { 24785 result.kids = []; 24786 for (var i = 0; i < dataSizeOrKidCount; i++) { 24787 result.kids.push(new Uint8Array(initData, 32 + i * 16, 16)); 24788 } 24789 } 24790 return result; 24791} 24792 24793/***/ }), 24794 24795/***/ "./src/utils/numeric-encoding-utils.ts": 24796/*!*********************************************!*\ 24797 !*** ./src/utils/numeric-encoding-utils.ts ***! 24798 \*********************************************/ 24799/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 24800 24801"use strict"; 24802__webpack_require__.r(__webpack_exports__); 24803/* harmony export */ __webpack_require__.d(__webpack_exports__, { 24804/* harmony export */ "base64Decode": () => (/* binding */ base64Decode), 24805/* harmony export */ "base64DecodeToStr": () => (/* binding */ base64DecodeToStr), 24806/* harmony export */ "base64Encode": () => (/* binding */ base64Encode), 24807/* harmony export */ "base64ToBase64Url": () => (/* binding */ base64ToBase64Url), 24808/* harmony export */ "base64UrlEncode": () => (/* binding */ base64UrlEncode), 24809/* harmony export */ "strToBase64Encode": () => (/* binding */ strToBase64Encode) 24810/* harmony export */ }); 24811function base64ToBase64Url(base64encodedStr) { 24812 return base64encodedStr.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); 24813} 24814function strToBase64Encode(str) { 24815 return btoa(str); 24816} 24817function base64DecodeToStr(str) { 24818 return atob(str); 24819} 24820function base64Encode(input) { 24821 return btoa(String.fromCharCode.apply(String, input)); 24822} 24823function base64UrlEncode(input) { 24824 return base64ToBase64Url(base64Encode(input)); 24825} 24826function base64Decode(base64encodedStr) { 24827 return Uint8Array.from(atob(base64encodedStr), function (c) { 24828 return c.charCodeAt(0); 24829 }); 24830} 24831 24832/***/ }), 24833 24834/***/ "./src/utils/
vendor: 1,500 bytes, lines 24834-24877
24834output-filter.ts": 24835/*!************************************!*\ 24836 !*** ./src/utils/output-filter.ts ***! 24837 \************************************/ 24838/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 24839 24840"use strict"; 24841__webpack_require__.r(__webpack_exports__); 24842/* harmony export */ __webpack_require__.d(__webpack_exports__, { 24843/* harmony export */ "default": () => (/* binding */ OutputFilter) 24844/* harmony export */ }); 24845var OutputFilter = /*#__PURE__*/function () { 24846 function OutputFilter(timelineController, trackName) { 24847 this.timelineController = void 0; 24848 this.cueRanges = []; 24849 this.trackName = void 0; 24850 this.startTime = null; 24851 this.endTime = null; 24852 this.screen = null; 24853 this.timelineController = timelineController; 24854 this.trackName = trackName; 24855 } 24856 var _proto = OutputFilter.prototype; 24857 _proto.dispatchCue = function dispatchCue() { 24858 if (this.startTime === null) { 24859 return; 24860 } 24861 this.timelineController.addCues(this.trackName, this.startTime, this.endTime, this.screen, this.cueRanges); 24862 this.startTime = null; 24863 }; 24864 _proto.newCue = function newCue(startTime, endTime, screen) { 24865 if (this.startTime === null || this.startTime > startTime) { 24866 this.startTime = startTime; 24867 } 24868 this.endTime = endTime; 24869 this.screen = screen; 24870 this.timelineController.createCaptionsTrack(this.trackName); 24871 }; 24872 _proto.reset = function reset() { 24873 this.cueRanges = []; 24874 this.startTime = null; 24875 }; 24876 return OutputFilter; 24877}();
vendor: 7,782 bytes, lines 24878-25115
24878 24879 24880/***/ }), 24881 24882/***/ "./src/utils/texttrack-utils.ts": 24883/*!**************************************!*\ 24884 !*** ./src/utils/texttrack-utils.ts ***! 24885 \**************************************/ 24886/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 24887 24888"use strict"; 24889__webpack_require__.r(__webpack_exports__); 24890/* harmony export */ __webpack_require__.d(__webpack_exports__, { 24891/* harmony export */ "addCueToTrack": () => (/* binding */ addCueToTrack), 24892/* harmony export */ "clearCurrentCues": () => (/* binding */ clearCurrentCues), 24893/* harmony export */ "getCuesInRange": () => (/* binding */ getCuesInRange), 24894/* harmony export */ "removeCuesInRange": () => (/* binding */ removeCuesInRange), 24895/* harmony export */ "sendAddTrackEvent": () => (/* binding */ sendAddTrackEvent) 24896/* harmony export */ }); 24897/* harmony import */ var _logger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./logger */ "./src/utils/logger.ts"); 24898 24899function sendAddTrackEvent(track, videoEl) { 24900 var event; 24901 try { 24902 event = new Event('addtrack'); 24903 } catch (err) { 24904 // for IE11 24905 event = document.createEvent('Event'); 24906 event.initEvent('addtrack', false, false); 24907 } 24908 event.track = track; 24909 videoEl.dispatchEvent(event); 24910} 24911function addCueToTrack(track, cue) { 24912 // Sometimes there are cue overlaps on segmented vtts so the same 24913 // cue can appear more than once in different vtt files. 24914 // This avoid showing duplicated cues with same timecode and text. 24915 var mode = track.mode; 24916 if (mode === 'disabled') { 24917 track.mode = 'hidden'; 24918 } 24919 if (track.cues && !track.cues.getCueById(cue.id)) { 24920 try { 24921 track.addCue(cue); 24922 if (!track.cues.getCueById(cue.id)) { 24923 throw new Error("addCue is failed for: " + cue); 24924 } 24925 } catch (err) { 24926 _logger__WEBPACK_IMPORTED_MODULE_0__.logger.debug("[texttrack-utils]: " + err); 24927 var textTrackCue = new self.TextTrackCue(cue.startTime, cue.endTime, cue.text); 24928 textTrackCue.id = cue.id; 24929 track.addCue(textTrackCue); 24930 } 24931 } 24932 if (mode === 'disabled') { 24933 track.mode = mode; 24934 } 24935} 24936function clearCurrentCues(track) { 24937 // When track.mode is disabled, track.cues will be null. 24938 // To guarantee the removal of cues, we need to temporarily 24939 // change the mode to hidden 24940 var mode = track.mode; 24941 if (mode === 'disabled') { 24942 track.mode = 'hidden'; 24943 } 24944 if (track.cues) { 24945 for (var i = track.cues.length; i--;) { 24946 track.removeCue(track.cues[i]); 24947 } 24948 } 24949 if (mode === 'disabled') { 24950 track.mode = mode; 24951 } 24952} 24953function removeCuesInRange(track, start, end, predicate) { 24954 var mode = track.mode; 24955 if (mode === 'disabled') { 24956 track.mode = 'hidden'; 24957 } 24958 if (track.cues && track.cues.length > 0) { 24959 var cues = getCuesInRange(track.cues, start, end); 24960 for (var i = 0; i < cues.length; i++) { 24961 if (!predicate || predicate(cues[i])) { 24962 track.removeCue(cues[i]); 24963 } 24964 } 24965 } 24966 if (mode === 'disabled') { 24967 track.mode = mode; 24968 } 24969} 24970 24971// Find first cue starting after given time. 24972// Modified version of binary search O(log(n)). 24973function getFirstCueIndexAfterTime(cues, time) { 24974 // If first cue starts after time, start there 24975 if (time < cues[0].startTime) { 24976 return 0; 24977 } 24978 // If the last cue ends before time there is no overlap 24979 var len = cues.length - 1; 24980 if (time > cues[len].endTime) { 24981 return -1; 24982 } 24983 var left = 0; 24984 var right = len; 24985 while (left <= right) { 24986 var mid = Math.floor((right + left) / 2); 24987 if (time < cues[mid].startTime) { 24988 right = mid - 1; 24989 } else if (time > cues[mid].startTime && left < len) { 24990 left = mid + 1; 24991 } else { 24992 // If it's not lower or higher, it must be equal. 24993 return mid; 24994 } 24995 } 24996 // At this point, left and right have swapped. 24997 // No direct match was found, left or right element must be the closest. Check which one has the smallest diff. 24998 return cues[left].startTime - time < time - cues[right].startTime ? left : right; 24999} 25000function getCuesInRange(cues, start, end) { 25001 var cuesFound = []; 25002 var firstCueInRange = getFirstCueIndexAfterTime(cues, start); 25003 if (firstCueInRange > -1) { 25004 for (var i = firstCueInRange, len = cues.length; i < len; i++) { 25005 var _cue = cues[i]; 25006 if (_cue.startTime >= start && _cue.endTime <= end) { 25007 cuesFound.push(_cue); 25008 } else if (_cue.startTime > end) { 25009 return cuesFound; 25010 } 25011 } 25012 } 25013 return cuesFound; 25014} 25015 25016/***/ }), 25017 25018/***/ "./src/utils/time-ranges.ts": 25019/*!**********************************!*\ 25020 !*** ./src/utils/time-ranges.ts ***! 25021 \**********************************/ 25022/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 25023 25024"use strict"; 25025__webpack_require__.r(__webpack_exports__); 25026/* harmony export */ __webpack_require__.d(__webpack_exports__, { 25027/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 25028/* harmony export */ }); 25029/** 25030 * TimeRanges to string helper 25031 */ 25032 25033var TimeRanges = { 25034 toString: function toString(r) { 25035 var log = ''; 25036 var len = r.length; 25037 for (var i = 0; i < len; i++) { 25038 log += "[" + r.start(i).toFixed(3) + "-" + r.end(i).toFixed(3) + "]"; 25039 } 25040 return log; 25041 } 25042}; 25043/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TimeRanges); 25044 25045/***/ }), 25046 25047/***/ "./src/utils/timescale-conversion.ts": 25048/*!*******************************************!*\ 25049 !*** ./src/utils/timescale-conversion.ts ***! 25050 \*******************************************/ 25051/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 25052 25053"use strict"; 25054__webpack_require__.r(__webpack_exports__); 25055/* harmony export */ __webpack_require__.d(__webpack_exports__, { 25056/* harmony export */ "toMpegTsClockFromTimescale": () => (/* binding */ toMpegTsClockFromTimescale), 25057/* harmony export */ "toMsFromMpegTsClock": () => (/* binding */ toMsFromMpegTsClock), 25058/* harmony export */ "toTimescaleFromBase": () => (/* binding */ toTimescaleFromBase), 25059/* harmony export */ "toTimescaleFromScale": () => (/* binding */ toTimescaleFromScale) 25060/* harmony export */ }); 25061var MPEG_TS_CLOCK_FREQ_HZ = 90000; 25062function toTimescaleFromBase(value, destScale, srcBase, round) { 25063 if (srcBase === void 0) { 25064 srcBase = 1; 25065 } 25066 if (round === void 0) { 25067 round = false; 25068 } 25069 var result = value * destScale * srcBase; // equivalent to `(value * scale) / (1 / base)` 25070 return round ? Math.round(result) : result; 25071} 25072function toTimescaleFromScale(value, destScale, srcScale, round) { 25073 if (srcScale === void 0) { 25074 srcScale = 1; 25075 } 25076 if (round === void 0) { 25077 round = false; 25078 } 25079 return toTimescaleFromBase(value, destScale, 1 / srcScale, round); 25080} 25081function toMsFromMpegTsClock(value, round) { 25082 if (round === void 0) { 25083 round = false; 25084 } 25085 return toTimescaleFromBase(value, 1000, 1 / MPEG_TS_CLOCK_FREQ_HZ, round); 25086} 25087function toMpegTsClockFromTimescale(value, srcScale) { 25088 if (srcScale === void 0) { 25089 srcScale = 1; 25090 } 25091 return toTimescaleFromBase(value, MPEG_TS_CLOCK_FREQ_HZ, 1 / srcScale); 25092} 25093 25094/***/ }), 25095 25096/***/ "./src/utils/typed-array.ts": 25097/*!**********************************!*\ 25098 !*** ./src/utils/typed-array.ts ***! 25099 \**********************************/ 25100/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 25101 25102"use strict"; 25103__webpack_require__.r(__webpack_exports__); 25104/* harmony export */ __webpack_require__.d(__webpack_exports__, { 25105/* harmony export */ "sliceUint8": () => (/* binding */ sliceUint8) 25106/* harmony export */ }); 25107function sliceUint8(array, start, end) { 25108 // @ts-expect-error This polyfills IE11 usage of Uint8Array slice. 25109 // It always exists in the TypeScript definition so fails, but it fails at runtime on IE11. 25110 return Uint8Array.prototype.slice ? array.slice(start, end) : new Uint8Array(Array.prototype.slice.call(array, start, end)); 25111} 25112 25113/***/ }), 25114 25115/***/ "./src/utils/
vendor: 23,094 bytes, lines 25115-25844
25115vttcue.ts": 25116/*!*****************************!*\ 25117 !*** ./src/utils/vttcue.ts ***! 25118 \*****************************/ 25119/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 25120 25121"use strict"; 25122__webpack_require__.r(__webpack_exports__); 25123/* harmony export */ __webpack_require__.d(__webpack_exports__, { 25124/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 25125/* harmony export */ }); 25126/** 25127 * Copyright 2013 vtt.js Contributors 25128 * 25129 * Licensed under the Apache License, Version 2.0 (the 'License'); 25130 * you may not use this file except in compliance with the License. 25131 * You may obtain a copy of the License at 25132 * 25133 * http://www.apache.org/licenses/LICENSE-2.0 25134 * 25135 * Unless required by applicable law or agreed to in writing, software 25136 * distributed under the License is distributed on an 'AS IS' BASIS, 25137 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 25138 * See the License for the specific language governing permissions and 25139 * limitations under the License. 25140 */ 25141 25142/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ((function () { 25143 if (typeof self !== 'undefined' && self.VTTCue) { 25144 return self.VTTCue; 25145 } 25146 var AllowedDirections = ['', 'lr', 'rl']; 25147 var AllowedAlignments = ['start', 'middle', 'end', 'left', 'right']; 25148 function isAllowedValue(allowed, value) { 25149 if (typeof value !== 'string') { 25150 return false; 25151 } 25152 // necessary for assuring the generic conforms to the Array interface 25153 if (!Array.isArray(allowed)) { 25154 return false; 25155 } 25156 // reset the type so that the next narrowing works well 25157 var lcValue = value.toLowerCase(); 25158 // use the allow list to narrow the type to a specific subset of strings 25159 if (~allowed.indexOf(lcValue)) { 25160 return lcValue; 25161 } 25162 return false; 25163 } 25164 function findDirectionSetting(value) { 25165 return isAllowedValue(AllowedDirections, value); 25166 } 25167 function findAlignSetting(value) { 25168 return isAllowedValue(AllowedAlignments, value); 25169 } 25170 function extend(obj) { 25171 for (var _len = arguments.length, rest = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 25172 rest[_key - 1] = arguments[_key]; 25173 } 25174 var i = 1; 25175 for (; i < arguments.length; i++) { 25176 var cobj = arguments[i]; 25177 for (var p in cobj) { 25178 obj[p] = cobj[p]; 25179 } 25180 } 25181 return obj; 25182 } 25183 function VTTCue(startTime, endTime, text) { 25184 var cue = this; 25185 var baseObj = { 25186 enumerable: true 25187 }; 25188 /** 25189 * Shim implementation specific properties. These properties are not in 25190 * the spec. 25191 */ 25192 25193 // Lets us know when the VTTCue's data has changed in such a way that we need 25194 // to recompute its display state. This lets us compute its display state 25195 // lazily. 25196 cue.hasBeenReset = false; 25197 25198 /** 25199 * VTTCue and TextTrackCue properties 25200 * http://dev.w3.org/html5/webvtt/#vttcue-interface 25201 */ 25202 25203 var _id = ''; 25204 var _pauseOnExit = false; 25205 var _startTime = startTime; 25206 var _endTime = endTime; 25207 var _text = text; 25208 var _region = null; 25209 var _vertical = ''; 25210 var _snapToLines = true; 25211 var _line = 'auto'; 25212 var _lineAlign = 'start'; 25213 var _position = 50; 25214 var _positionAlign = 'middle'; 25215 var _size = 50; 25216 var _align = 'middle'; 25217 Object.defineProperty(cue, 'id', extend({}, baseObj, { 25218 get: function get() { 25219 return _id; 25220 }, 25221 set: function set(value) { 25222 _id = '' + value; 25223 } 25224 })); 25225 Object.defineProperty(cue, 'pauseOnExit', extend({}, baseObj, { 25226 get: function get() { 25227 return _pauseOnExit; 25228 }, 25229 set: function set(value) { 25230 _pauseOnExit = !!value; 25231 } 25232 })); 25233 Object.defineProperty(cue, 'startTime', extend({}, baseObj, { 25234 get: function get() { 25235 return _startTime; 25236 }, 25237 set: function set(value) { 25238 if (typeof value !== 'number') { 25239 throw new TypeError('Start time must be set to a number.'); 25240 } 25241 _startTime = value; 25242 this.hasBeenReset = true; 25243 } 25244 })); 25245 Object.defineProperty(cue, 'endTime', extend({}, baseObj, { 25246 get: function get() { 25247 return _endTime; 25248 }, 25249 set: function set(value) { 25250 if (typeof value !== 'number') { 25251 throw new TypeError('End time must be set to a number.'); 25252 } 25253 _endTime = value; 25254 this.hasBeenReset = true; 25255 } 25256 })); 25257 Object.defineProperty(cue, 'text', extend({}, baseObj, { 25258 get: function get() { 25259 return _text; 25260 }, 25261 set: function set(value) { 25262 _text = '' + value; 25263 this.hasBeenReset = true; 25264 } 25265 })); 25266 25267 // todo: implement VTTRegion polyfill? 25268 Object.defineProperty(cue, 'region', extend({}, baseObj, { 25269 get: function get() { 25270 return _region; 25271 }, 25272 set: function set(value) { 25273 _region = value; 25274 this.hasBeenReset = true; 25275 } 25276 })); 25277 Object.defineProperty(cue, 'vertical', extend({}, baseObj, { 25278 get: function get() { 25279 return _vertical; 25280 }, 25281 set: function set(value) { 25282 var setting = findDirectionSetting(value); 25283 // Have to check for false because the setting an be an empty string. 25284 if (setting === false) { 25285 throw new SyntaxError('An invalid or illegal string was specified.'); 25286 } 25287 _vertical = setting; 25288 this.hasBeenReset = true; 25289 } 25290 })); 25291 Object.defineProperty(cue, 'snapToLines', extend({}, baseObj, { 25292 get: function get() { 25293 return _snapToLines; 25294 }, 25295 set: function set(value) { 25296 _snapToLines = !!value; 25297 this.hasBeenReset = true; 25298 } 25299 })); 25300 Object.defineProperty(cue, 'line', extend({}, baseObj, { 25301 get: function get() { 25302 return _line; 25303 }, 25304 set: function set(value) { 25305 if (typeof value !== 'number' && value !== 'auto') { 25306 throw new SyntaxError('An invalid number or illegal string was specified.'); 25307 } 25308 _line = value; 25309 this.hasBeenReset = true; 25310 } 25311 })); 25312 Object.defineProperty(cue, 'lineAlign', extend({}, baseObj, { 25313 get: function get() { 25314 return _lineAlign; 25315 }, 25316 set: function set(value) { 25317 var setting = findAlignSetting(value); 25318 if (!setting) { 25319 throw new SyntaxError('An invalid or illegal string was specified.'); 25320 } 25321 _lineAlign = setting; 25322 this.hasBeenReset = true; 25323 } 25324 })); 25325 Object.defineProperty(cue, 'position', extend({}, baseObj, { 25326 get: function get() { 25327 return _position; 25328 }, 25329 set: function set(value) { 25330 if (value < 0 || value > 100) { 25331 throw new Error('Position must be between 0 and 100.'); 25332 } 25333 _position = value; 25334 this.hasBeenReset = true; 25335 } 25336 })); 25337 Object.defineProperty(cue, 'positionAlign', extend({}, baseObj, { 25338 get: function get() { 25339 return _positionAlign; 25340 }, 25341 set: function set(value) { 25342 var setting = findAlignSetting(value); 25343 if (!setting) { 25344 throw new SyntaxError('An invalid or illegal string was specified.'); 25345 } 25346 _positionAlign = setting; 25347 this.hasBeenReset = true; 25348 } 25349 })); 25350 Object.defineProperty(cue, 'size', extend({}, baseObj, { 25351 get: function get() { 25352 return _size; 25353 }, 25354 set: function set(value) { 25355 if (value < 0 || value > 100) { 25356 throw new Error('Size must be between 0 and 100.'); 25357 } 25358 _size = value; 25359 this.hasBeenReset = true; 25360 } 25361 })); 25362 Object.defineProperty(cue, 'align', extend({}, baseObj, { 25363 get: function get() { 25364 return _align; 25365 }, 25366 set: function set(value) { 25367 var setting = findAlignSetting(value); 25368 if (!setting) { 25369 throw new SyntaxError('An invalid or illegal string was specified.'); 25370 } 25371 _align = setting; 25372 this.hasBeenReset = true; 25373 } 25374 })); 25375 25376 /** 25377 * Other <track> spec defined properties 25378 */ 25379 25380 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#text-track-cue-display-state 25381 cue.displayState = undefined; 25382 } 25383 25384 /** 25385 * VTTCue methods 25386 */ 25387 25388 VTTCue.prototype.getCueAsHTML = function () { 25389 // Assume WebVTT.convertCueToDOMTree is on the global. 25390 var WebVTT = self.WebVTT; 25391 return WebVTT.convertCueToDOMTree(self, this.text); 25392 }; 25393 // this is a polyfill hack 25394 return VTTCue; 25395})()); 25396 25397/***/ }), 25398 25399/***/ "./src/utils/vttparser.ts": 25400/*!********************************!*\ 25401 !*** ./src/utils/vttparser.ts ***! 25402 \********************************/ 25403/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 25404 25405"use strict"; 25406__webpack_require__.r(__webpack_exports__); 25407/* harmony export */ __webpack_require__.d(__webpack_exports__, { 25408/* harmony export */ "VTTParser": () => (/* binding */ VTTParser), 25409/* harmony export */ "fixLineBreaks": () => (/* binding */ fixLineBreaks), 25410/* harmony export */ "parseTimeStamp": () => (/* binding */ parseTimeStamp) 25411/* harmony export */ }); 25412/* harmony import */ var _vttcue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./vttcue */ "./src/utils/vttcue.ts"); 25413/* 25414 * Source: https://github.com/mozilla/vtt.js/blob/master/dist/vtt.js 25415 */ 25416 25417 25418var StringDecoder = /*#__PURE__*/function () { 25419 function StringDecoder() {} 25420 var _proto = StringDecoder.prototype; 25421 // eslint-disable-next-line @typescript-eslint/no-unused-vars 25422 _proto.decode = function decode(data, options) { 25423 if (!data) { 25424 return ''; 25425 } 25426 if (typeof data !== 'string') { 25427 throw new Error('Error - expected string data.'); 25428 } 25429 return decodeURIComponent(encodeURIComponent(data)); 25430 }; 25431 return StringDecoder; 25432}(); // Try to parse input as a time stamp. 25433function parseTimeStamp(input) { 25434 function computeSeconds(h, m, s, f) { 25435 return (h | 0) * 3600 + (m | 0) * 60 + (s | 0) + parseFloat(f || 0); 25436 } 25437 var m = input.match(/^(?:(\d+):)?(\d{2}):(\d{2})(\.\d+)?/); 25438 if (!m) { 25439 return null; 25440 } 25441 if (parseFloat(m[2]) > 59) { 25442 // Timestamp takes the form of [hours]:[minutes].[milliseconds] 25443 // First position is hours as it's over 59. 25444 return computeSeconds(m[2], m[3], 0, m[4]); 25445 } 25446 // Timestamp takes the form of [hours (optional)]:[minutes]:[seconds].[milliseconds] 25447 return computeSeconds(m[1], m[2], m[3], m[4]); 25448} 25449 25450// A settings object holds key/value pairs and will ignore anything but the first 25451// assignment to a specific key. 25452var Settings = /*#__PURE__*/function () { 25453 function Settings() { 25454 this.values = Object.create(null); 25455 } 25456 var _proto2 = Settings.prototype; 25457 // Only accept the first assignment to any key. 25458 _proto2.set = function set(k, v) { 25459 if (!this.get(k) && v !== '') { 25460 this.values[k] = v; 25461 } 25462 } 25463 // Return the value for a key, or a default value. 25464 // If 'defaultKey' is passed then 'dflt' is assumed to be an object with 25465 // a number of possible default values as properties where 'defaultKey' is 25466 // the key of the property that will be chosen; otherwise it's assumed to be 25467 // a single value. 25468 ; 25469 _proto2.get = function get(k, dflt, defaultKey) { 25470 if (defaultKey) { 25471 return this.has(k) ? this.values[k] : dflt[defaultKey]; 25472 } 25473 return this.has(k) ? this.values[k] : dflt; 25474 } 25475 // Check whether we have a value for a key. 25476 ; 25477 _proto2.has = function has(k) { 25478 return k in this.values; 25479 } 25480 // Accept a setting if its one of the given alternatives. 25481 ; 25482 _proto2.alt = function alt(k, v, a) { 25483 for (var n = 0; n < a.length; ++n) { 25484 if (v === a[n]) { 25485 this.set(k, v); 25486 break; 25487 } 25488 } 25489 } 25490 // Accept a setting if its a valid (signed) integer. 25491 ; 25492 _proto2.integer = function integer(k, v) { 25493 if (/^-?\d+$/.test(v)) { 25494 // integer 25495 this.set(k, parseInt(v, 10)); 25496 } 25497 } 25498 // Accept a setting if its a valid percentage. 25499 ; 25500 _proto2.percent = function percent(k, v) { 25501 if (/^([\d]{1,3})(\.[\d]*)?%$/.test(v)) { 25502 var percent = parseFloat(v); 25503 if (percent >= 0 && percent <= 100) { 25504 this.set(k, percent); 25505 return true; 25506 } 25507 } 25508 return false; 25509 }; 25510 return Settings; 25511}(); // Helper function to parse input into groups separated by 'groupDelim', and 25512// interpret each group as a key/value pair separated by 'keyValueDelim'. 25513function parseOptions(input, callback, keyValueDelim, groupDelim) { 25514 var groups = groupDelim ? input.split(groupDelim) : [input]; 25515 for (var i in groups) { 25516 if (typeof groups[i] !== 'string') { 25517 continue; 25518 } 25519 var kv = groups[i].split(keyValueDelim); 25520 if (kv.length !== 2) { 25521 continue; 25522 } 25523 var _k = kv[0]; 25524 var _v = kv[1]; 25525 callback(_k, _v); 25526 } 25527} 25528var defaults = new _vttcue__WEBPACK_IMPORTED_MODULE_0__["default"](0, 0, ''); 25529// 'middle' was changed to 'center' in the spec: https://github.com/w3c/webvtt/pull/244 25530// Safari doesn't yet support this change, but FF and Chrome do. 25531var center = defaults.align === 'middle' ? 'middle' : 'center'; 25532function parseCue(input, cue, regionList) { 25533 // Remember the original input if we need to throw an error. 25534 var oInput = input; 25535 // 4.1 WebVTT timestamp 25536 function consumeTimeStamp() { 25537 var ts = parseTimeStamp(input); 25538 if (ts === null) { 25539 throw new Error('Malformed timestamp: ' + oInput); 25540 } 25541 25542 // Remove time stamp from input. 25543 input = input.replace(/^[^\sa-zA-Z-]+/, ''); 25544 return ts; 25545 } 25546 25547 // 4.4.2 WebVTT cue settings 25548 function consumeCueSettings(input, cue) { 25549 var settings = new Settings(); 25550 parseOptions(input, function (k, v) { 25551 var vals; 25552 switch (k) { 25553 case 'region': 25554 // Find the last region we parsed with the same region id. 25555 for (var i = regionList.length - 1; i >= 0; i--) { 25556 if (regionList[i].id === v) { 25557 settings.set(k, regionList[i].region); 25558 break; 25559 } 25560 } 25561 break; 25562 case 'vertical': 25563 settings.alt(k, v, ['rl', 'lr']); 25564 break; 25565 case 'line': 25566 vals = v.split(','); 25567 settings.integer(k, vals[0]); 25568 if (settings.percent(k, vals[0])) { 25569 settings.set('snapToLines', false); 25570 } 25571 settings.alt(k, vals[0], ['auto']); 25572 if (vals.length === 2) { 25573 settings.alt('lineAlign', vals[1], ['start', center, 'end']); 25574 } 25575 break; 25576 case 'position': 25577 vals = v.split(','); 25578 settings.percent(k, vals[0]); 25579 if (vals.length === 2) { 25580 settings.alt('positionAlign', vals[1], ['start', center, 'end', 'line-left', 'line-right', 'auto']); 25581 } 25582 break; 25583 case 'size': 25584 settings.percent(k, v); 25585 break; 25586 case 'align': 25587 settings.alt(k, v, ['start', center, 'end', 'left', 'right']); 25588 break; 25589 } 25590 }, /:/, /\s/); 25591 25592 // Apply default values for any missing fields. 25593 cue.region = settings.get('region', null); 25594 cue.vertical = settings.get('vertical', ''); 25595 var line = settings.get('line', 'auto'); 25596 if (line === 'auto' && defaults.line === -1) { 25597 // set numeric line number for Safari 25598 line = -1; 25599 } 25600 cue.line = line; 25601 cue.lineAlign = settings.get('lineAlign', 'start'); 25602 cue.snapToLines = settings.get('snapToLines', true); 25603 cue.size = settings.get('size', 100); 25604 cue.align = settings.get('align', center); 25605 var position = settings.get('position', 'auto'); 25606 if (position === 'auto' && defaults.position === 50) { 25607 // set numeric position for Safari 25608 position = cue.align === 'start' || cue.align === 'left' ? 0 : cue.align === 'end' || cue.align === 'right' ? 100 : 50; 25609 } 25610 cue.position = position; 25611 } 25612 function skipWhitespace() { 25613 input = input.replace(/^\s+/, ''); 25614 } 25615 25616 // 4.1 WebVTT cue timings. 25617 skipWhitespace(); 25618 cue.startTime = consumeTimeStamp(); // (1) collect cue start time 25619 skipWhitespace(); 25620 if (input.slice(0, 3) !== '-->') { 25621 // (3) next characters must match '-->' 25622 throw new Error("Malformed time stamp (time stamps must be separated by '-->'): " + oInput); 25623 } 25624 input = input.slice(3); 25625 skipWhitespace(); 25626 cue.endTime = consumeTimeStamp(); // (5) collect cue end time 25627 25628 // 4.1 WebVTT cue settings list. 25629 skipWhitespace(); 25630 consumeCueSettings(input, cue); 25631} 25632function fixLineBreaks(input) { 25633 return input.replace(/<br(?: \/)?>/gi, '\n'); 25634} 25635var VTTParser = /*#__PURE__*/function () { 25636 function VTTParser() { 25637 this.state = 'INITIAL'; 25638 this.buffer = ''; 25639 this.decoder = new StringDecoder(); 25640 this.regionList = []; 25641 this.cue = null; 25642 this.oncue = void 0; 25643 this.onparsingerror = void 0; 25644 this.onflush = void 0; 25645 } 25646 var _proto3 = VTTParser.prototype; 25647 _proto3.parse = function parse(data) { 25648 var _this = this; 25649 25650 // If there is no data then we won't decode it, but will just try to parse 25651 // whatever is in buffer already. This may occur in circumstances, for 25652 // example when flush() is called. 25653 if (data) { 25654 // Try to decode the data that we received. 25655 _this.buffer += _this.decoder.decode(data, { 25656 stream: true 25657 }); 25658 } 25659 function collectNextLine() { 25660 var buffer = _this.buffer; 25661 var pos = 0; 25662 buffer = fixLineBreaks(buffer); 25663 while (pos < buffer.length && buffer[pos] !== '\r' && buffer[pos] !== '\n') { 25664 ++pos; 25665 } 25666 var line = buffer.slice(0, pos); 25667 // Advance the buffer early in case we fail below. 25668 if (buffer[pos] === '\r') { 25669 ++pos; 25670 } 25671 if (buffer[pos] === '\n') { 25672 ++pos; 25673 } 25674 _this.buffer = buffer.slice(pos); 25675 return line; 25676 } 25677 25678 // 3.2 WebVTT metadata header syntax 25679 function parseHeader(input) { 25680 parseOptions(input, function (k, v) { 25681 // switch (k) { 25682 // case 'region': 25683 // 3.3 WebVTT region metadata header syntax 25684 // console.log('parse region', v); 25685 // parseRegion(v); 25686 // break; 25687 // } 25688 }, /:/); 25689 } 25690 25691 // 5.1 WebVTT file parsing. 25692 try { 25693 var line = ''; 25694 if (_this.state === 'INITIAL') { 25695 // We can't start parsing until we have the first line. 25696 if (!/\r\n|\n/.test(_this.buffer)) { 25697 return this; 25698 } 25699 line = collectNextLine(); 25700 // strip of UTF-8 BOM if any 25701 // https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8 25702 var m = line.match(/^()?WEBVTT([ \t].*)?$/); 25703 if (!m || !m[0]) { 25704 throw new Error('Malformed WebVTT signature.'); 25705 } 25706 _this.state = 'HEADER'; 25707 } 25708 var alreadyCollectedLine = false; 25709 while (_this.buffer) { 25710 // We can't parse a line until we have the full line. 25711 if (!/\r\n|\n/.test(_this.buffer)) { 25712 return this; 25713 } 25714 if (!alreadyCollectedLine) { 25715 line = collectNextLine(); 25716 } else { 25717 alreadyCollectedLine = false; 25718 } 25719 switch (_this.state) { 25720 case 'HEADER': 25721 // 13-18 - Allow a header (metadata) under the WEBVTT line. 25722 if (/:/.test(line)) { 25723 parseHeader(line); 25724 } else if (!line) { 25725 // An empty line terminates the header and starts the body (cues). 25726 _this.state = 'ID'; 25727 } 25728 continue; 25729 case 'NOTE': 25730 // Ignore NOTE blocks. 25731 if (!line) { 25732 _this.state = 'ID'; 25733 } 25734 continue; 25735 case 'ID': 25736 // Check for the start of NOTE blocks. 25737 if (/^NOTE($|[ \t])/.test(line)) { 25738 _this.state = 'NOTE'; 25739 break; 25740 } 25741 // 19-29 - Allow any number of line terminators, then initialize new cue values. 25742 if (!line) { 25743 continue; 25744 } 25745 _this.cue = new _vttcue__WEBPACK_IMPORTED_MODULE_0__["default"](0, 0, ''); 25746 _this.state = 'CUE'; 25747 // 30-39 - Check if self line contains an optional identifier or timing data. 25748 if (line.indexOf('-->') === -1) { 25749 _this.cue.id = line; 25750 continue; 25751 } 25752 // Process line as start of a cue. 25753 /* falls through */ 25754 case 'CUE': 25755 // 40 - Collect cue timings and settings. 25756 if (!_this.cue) { 25757 _this.state = 'BADCUE'; 25758 continue; 25759 } 25760 try { 25761 parseCue(line, _this.cue, _this.regionList); 25762 } catch (e) { 25763 // In case of an error ignore rest of the cue. 25764 _this.cue = null; 25765 _this.state = 'BADCUE'; 25766 continue; 25767 } 25768 _this.state = 'CUETEXT'; 25769 continue; 25770 case 'CUETEXT': 25771 { 25772 var hasSubstring = line.indexOf('-->') !== -1; 25773 // 34 - If we have an empty line then report the cue. 25774 // 35 - If we have the special substring '-->' then report the cue, 25775 // but do not collect the line as we need to process the current 25776 // one as a new cue. 25777 if (!line || hasSubstring && (alreadyCollectedLine = true)) { 25778 // We are done parsing self cue. 25779 if (_this.oncue && _this.cue) { 25780 _this.oncue(_this.cue); 25781 } 25782 _this.cue = null; 25783 _this.state = 'ID'; 25784 continue; 25785 } 25786 if (_this.cue === null) { 25787 continue; 25788 } 25789 if (_this.cue.text) { 25790 _this.cue.text += '\n'; 25791 } 25792 _this.cue.text += line; 25793 } 25794 continue; 25795 case 'BADCUE': 25796 // 54-62 - Collect and discard the remaining cue. 25797 if (!line) { 25798 _this.state = 'ID'; 25799 } 25800 } 25801 } 25802 } catch (e) { 25803 // If we are currently parsing a cue, report what we have. 25804 if (_this.state === 'CUETEXT' && _this.cue && _this.oncue) { 25805 _this.oncue(_this.cue); 25806 } 25807 _this.cue = null; 25808 // Enter BADWEBVTT state if header was not parsed correctly otherwise 25809 // another exception occurred so enter BADCUE state. 25810 _this.state = _this.state === 'INITIAL' ? 'BADWEBVTT' : 'BADCUE'; 25811 } 25812 return this; 25813 }; 25814 _proto3.flush = function flush() { 25815 var _this = this; 25816 try { 25817 // Finish decoding the stream. 25818 // _this.buffer += _this.decoder.decode(); 25819 // Synthesize the end of the current cue or region. 25820 if (_this.cue || _this.state === 'HEADER') { 25821 _this.buffer += '\n\n'; 25822 _this.parse(); 25823 } 25824 // If we've flushed, parsed, and we're still on the INITIAL state then 25825 // that means we don't have enough of the stream to parse the first 25826 // line. 25827 if (_this.state === 'INITIAL' || _this.state === 'BADWEBVTT') { 25828 throw new Error('Malformed WebVTT signature.'); 25829 } 25830 } catch (e) { 25831 if (_this.onparsingerror) { 25832 _this.onparsingerror(e); 25833 } 25834 } 25835 if (_this.onflush) { 25836 _this.onflush(); 25837 } 25838 return this; 25839 }; 25840 return VTTParser; 25841}(); 25842 25843/***/ }), 25844
vendor: 6,785 bytes, lines 25845-26000
25845/***/ "./src/utils/webvtt-parser.ts": 25846/*!************************************!*\ 25847 !*** ./src/utils/webvtt-parser.ts ***! 25848 \************************************/ 25849/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 25850 25851"use strict"; 25852__webpack_require__.r(__webpack_exports__); 25853/* harmony export */ __webpack_require__.d(__webpack_exports__, { 25854/* harmony export */ "generateCueId": () => (/* binding */ generateCueId), 25855/* harmony export */ "parseWebVTT": () => (/* binding */ parseWebVTT) 25856/* harmony export */ }); 25857/* harmony import */ var _home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.ts"); 25858/* harmony import */ var _vttparser__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./vttparser */ "./src/utils/vttparser.ts"); 25859/* harmony import */ var _demux_id3__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../demux/id3 */ "./src/demux/id3.ts"); 25860/* harmony import */ var _timescale_conversion__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./timescale-conversion */ "./src/utils/timescale-conversion.ts"); 25861/* harmony import */ var _remux_mp4_remuxer__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../remux/mp4-remuxer */ "./src/remux/mp4-remuxer.ts"); 25862 25863 25864 25865 25866 25867 25868 25869 25870var LINEBREAKS = /\r\n|\n\r|\n|\r/g; 25871 25872// String.prototype.startsWith is not supported in IE11 25873var startsWith = function startsWith(inputString, searchString, position) { 25874 if (position === void 0) { 25875 position = 0; 25876 } 25877 return inputString.slice(position, position + searchString.length) === searchString; 25878}; 25879var cueString2millis = function cueString2millis(timeString) { 25880 var ts = parseInt(timeString.slice(-3)); 25881 var secs = parseInt(timeString.slice(-6, -4)); 25882 var mins = parseInt(timeString.slice(-9, -7)); 25883 var hours = timeString.length > 9 ? parseInt(timeString.substring(0, timeString.indexOf(':'))) : 0; 25884 if (!(0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(ts) || !(0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(secs) || !(0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(mins) || !(0,_home_runner_work_hls_js_hls_js_src_polyfills_number__WEBPACK_IMPORTED_MODULE_0__.isFiniteNumber)(hours)) { 25885 throw Error("Malformed X-TIMESTAMP-MAP: Local:" + timeString); 25886 } 25887 ts += 1000 * secs; 25888 ts += 60 * 1000 * mins; 25889 ts += 60 * 60 * 1000 * hours; 25890 return ts; 25891}; 25892 25893// From https://github.com/darkskyapp/string-hash 25894var hash = function hash(text) { 25895 var hash = 5381; 25896 var i = text.length; 25897 while (i) { 25898 hash = hash * 33 ^ text.charCodeAt(--i); 25899 } 25900 return (hash >>> 0).toString(); 25901}; 25902 25903// Create a unique hash id for a cue based on start/end times and text. 25904// This helps timeline-controller to avoid showing repeated captions. 25905function generateCueId(startTime, endTime, text) { 25906 return hash(startTime.toString()) + hash(endTime.toString()) + hash(text); 25907} 25908var calculateOffset = function calculateOffset(vttCCs, cc, presentationTime) { 25909 var currCC = vttCCs[cc]; 25910 var prevCC = vttCCs[currCC.prevCC]; 25911 25912 // This is the first discontinuity or cues have been processed since the last discontinuity 25913 // Offset = current discontinuity time 25914 if (!prevCC || !prevCC.new && currCC.new) { 25915 vttCCs.ccOffset = vttCCs.presentationOffset = currCC.start; 25916 currCC.new = false; 25917 return; 25918 } 25919 25920 // There have been discontinuities since cues were last parsed. 25921 // Offset = time elapsed 25922 while ((_prevCC = prevCC) !== null && _prevCC !== void 0 && _prevCC.new) { 25923 var _prevCC; 25924 vttCCs.ccOffset += currCC.start - prevCC.start; 25925 currCC.new = false; 25926 currCC = prevCC; 25927 prevCC = vttCCs[currCC.prevCC]; 25928 } 25929 vttCCs.presentationOffset = presentationTime; 25930}; 25931function parseWebVTT(vttByteArray, initPTS, timescale, vttCCs, cc, timeOffset, callBack, errorCallBack) { 25932 var parser = new _vttparser__WEBPACK_IMPORTED_MODULE_1__.VTTParser(); 25933 // Convert byteArray into string, replacing any somewhat exotic linefeeds with "\n", then split on that character. 25934 // Uint8Array.prototype.reduce is not implemented in IE11 25935 var vttLines = (0,_demux_id3__WEBPACK_IMPORTED_MODULE_2__.utf8ArrayToStr)(new Uint8Array(vttByteArray)).trim().replace(LINEBREAKS, '\n').split('\n'); 25936 var cues = []; 25937 var initPTS90Hz = (0,_timescale_conversion__WEBPACK_IMPORTED_MODULE_3__.toMpegTsClockFromTimescale)(initPTS, timescale); 25938 var cueTime = '00:00.000'; 25939 var timestampMapMPEGTS = 0; 25940 var timestampMapLOCAL = 0; 25941 var parsingError; 25942 var inHeader = true; 25943 parser.oncue = function (cue) { 25944 // Adjust cue timing; clamp cues to start no earlier than - and drop cues that don't end after - 0 on timeline. 25945 var currCC = vttCCs[cc]; 25946 var cueOffset = vttCCs.ccOffset; 25947 25948 // Calculate subtitle PTS offset 25949 var webVttMpegTsMapOffset = (timestampMapMPEGTS - initPTS90Hz) / 90000; 25950 25951 // Update offsets for new discontinuities 25952 if (currCC !== null && currCC !== void 0 && currCC.new) { 25953 if (timestampMapLOCAL !== undefined) { 25954 // When local time is provided, offset = discontinuity start time - local time 25955 cueOffset = vttCCs.ccOffset = currCC.start; 25956 } else { 25957 calculateOffset(vttCCs, cc, webVttMpegTsMapOffset); 25958 } 25959 } 25960 if (webVttMpegTsMapOffset) { 25961 // If we have MPEGTS, offset = presentation time + discontinuity offset 25962 cueOffset = webVttMpegTsMapOffset - vttCCs.presentationOffset; 25963 } 25964 var duration = cue.endTime - cue.startTime; 25965 var startTime = (0,_remux_mp4_remuxer__WEBPACK_IMPORTED_MODULE_4__.normalizePts)((cue.startTime + cueOffset - timestampMapLOCAL) * 90000, timeOffset * 90000) / 90000; 25966 cue.startTime = Math.max(startTime, 0); 25967 cue.endTime = Math.max(startTime + duration, 0); 25968 25969 //trim trailing webvtt block whitespaces 25970 var text = cue.text.trim(); 25971 25972 // Fix encoding of special characters 25973 cue.text = decodeURIComponent(encodeURIComponent(text)); 25974 25975 // If the cue was not assigned an id from the VTT file (line above the content), create one. 25976 if (!cue.id) { 25977 cue.id = generateCueId(cue.startTime, cue.endTime, text); 25978 } 25979 if (cue.endTime > 0) { 25980 cues.push(cue); 25981 } 25982 }; 25983 parser.onparsingerror = function (error) { 25984 parsingError = error; 25985 }; 25986 parser.onflush = function () { 25987 if (parsingError) { 25988 errorCallBack(parsingError); 25989 return; 25990 } 25991 callBack(cues); 25992 }; 25993 25994 // Go through contents line by line. 25995 vttLines.forEach(function (line) { 25996 if (inHeader) { 25997 // Look for X-TIMESTAMP-MAP in header. 25998 if (startsWith(line, 'X-TIMESTAMP-MAP=')) { 25999 // Once found, no more are allowed anyway, so stop searching. 26000 inHeader = false;
26001 // Extract LOCAL and MPEGTS. 26002 line.slice(16).split(',').forEach(function (timestamp) { 26003 if (startsWith(timestamp, 'LOCAL:')) { 26004 cueTime = timestamp.slice(6); 26005 } else if (startsWith(timestamp, 'MPEGTS:')) { 26006 timestampMapMPEGTS = parseInt(timestamp.slice(7)); 26007 } 26008 }); 26009 try { 26010 // Convert cue time to seconds 26011 timestampMapLOCAL = cueString2millis(cueTime) / 1000; 26012 } catch (error) { 26013 parsingError = error; 26014 } 26015 // Return without parsing X-TIMESTAMP-MAP line. 26016 return; 26017 } else if (line === '') { 26018 inHeader = false; 26019 } 26020 } 26021 // Parse line by default. 26022 parser.parse(line + '\n'); 26023 }); 26024 parser.flush(
vendor: 8,404 bytes, lines 26024-26260
26024); 26025} 26026 26027/***/ }), 26028 26029/***/ "./src/utils/xhr-loader.ts": 26030/*!*********************************!*\ 26031 !*** ./src/utils/xhr-loader.ts ***! 26032 \*********************************/ 26033/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 26034 26035"use strict"; 26036__webpack_require__.r(__webpack_exports__); 26037/* harmony export */ __webpack_require__.d(__webpack_exports__, { 26038/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 26039/* harmony export */ }); 26040/* harmony import */ var _utils_logger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.ts"); 26041/* harmony import */ var _loader_load_stats__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../loader/load-stats */ "./src/loader/load-stats.ts"); 26042 26043 26044var AGE_HEADER_LINE_REGEX = /^age:\s*[\d.]+\s*$/m; 26045var XhrLoader = /*#__PURE__*/function () { 26046 function XhrLoader(config /* HlsConfig */) { 26047 this.xhrSetup = void 0; 26048 this.requestTimeout = void 0; 26049 this.retryTimeout = void 0; 26050 this.retryDelay = void 0; 26051 this.config = null; 26052 this.callbacks = null; 26053 this.context = void 0; 26054 this.loader = null; 26055 this.stats = void 0; 26056 this.xhrSetup = config ? config.xhrSetup : null; 26057 this.stats = new _loader_load_stats__WEBPACK_IMPORTED_MODULE_1__.LoadStats(); 26058 this.retryDelay = 0; 26059 } 26060 var _proto = XhrLoader.prototype; 26061 _proto.destroy = function destroy() { 26062 this.callbacks = null; 26063 this.abortInternal(); 26064 this.loader = null; 26065 this.config = null; 26066 }; 26067 _proto.abortInternal = function abortInternal() { 26068 var loader = this.loader; 26069 self.clearTimeout(this.requestTimeout); 26070 self.clearTimeout(this.retryTimeout); 26071 if (loader) { 26072 loader.onreadystatechange = null; 26073 loader.onprogress = null; 26074 if (loader.readyState !== 4) { 26075 this.stats.aborted = true; 26076 loader.abort(); 26077 } 26078 } 26079 }; 26080 _proto.abort = function abort() { 26081 var _this$callbacks; 26082 this.abortInternal(); 26083 if ((_this$callbacks = this.callbacks) !== null && _this$callbacks !== void 0 && _this$callbacks.onAbort) { 26084 this.callbacks.onAbort(this.stats, this.context, this.loader); 26085 } 26086 }; 26087 _proto.load = function load(context, config, callbacks) { 26088 if (this.stats.loading.start) { 26089 throw new Error('Loader can only be used once.'); 26090 } 26091 this.stats.loading.start = self.performance.now(); 26092 this.context = context; 26093 this.config = config; 26094 this.callbacks = callbacks; 26095 this.retryDelay = config.retryDelay; 26096 this.loadInternal(); 26097 }; 26098 _proto.loadInternal = function loadInternal() { 26099 var config = this.config, 26100 context = this.context; 26101 if (!config) { 26102 return; 26103 } 26104 var xhr = this.loader = new self.XMLHttpRequest(); 26105 var stats = this.stats; 26106 stats.loading.first = 0; 26107 stats.loaded = 0; 26108 var xhrSetup = this.xhrSetup; 26109 try { 26110 if (xhrSetup) { 26111 try { 26112 xhrSetup(xhr, context.url); 26113 } catch (e) { 26114 // fix xhrSetup: (xhr, url) => {xhr.setRequestHeader("Content-Language", "test");} 26115 // not working, as xhr.setRequestHeader expects xhr.readyState === OPEN 26116 xhr.open('GET', context.url, true); 26117 xhrSetup(xhr, context.url); 26118 } 26119 } 26120 if (!xhr.readyState) { 26121 xhr.open('GET', context.url, true); 26122 } 26123 var headers = this.context.headers; 26124 if (headers) { 26125 for (var header in headers) { 26126 xhr.setRequestHeader(header, headers[header]); 26127 } 26128 } 26129 } catch (e) { 26130 // IE11 throws an exception on xhr.open if attempting to access an HTTP resource over HTTPS 26131 this.callbacks.onError({ 26132 code: xhr.status, 26133 text: e.message 26134 }, context, xhr); 26135 return; 26136 } 26137 if (context.rangeEnd) { 26138 xhr.setRequestHeader('Range', 'bytes=' + context.rangeStart + '-' + (context.rangeEnd - 1)); 26139 } 26140 xhr.onreadystatechange = this.readystatechange.bind(this); 26141 xhr.onprogress = this.loadprogress.bind(this); 26142 xhr.responseType = context.responseType; 26143 // setup timeout before we perform request 26144 self.clearTimeout(this.requestTimeout); 26145 this.requestTimeout = self.setTimeout(this.loadtimeout.bind(this), config.timeout); 26146 xhr.send(); 26147 }; 26148 _proto.readystatechange = function readystatechange() { 26149 var context = this.context, 26150 xhr = this.loader, 26151 stats = this.stats; 26152 if (!context || !xhr) { 26153 return; 26154 } 26155 var readyState = xhr.readyState; 26156 var config = this.config; 26157 26158 // don't proceed if xhr has been aborted 26159 if (stats.aborted) { 26160 return; 26161 } 26162 26163 // >= HEADERS_RECEIVED 26164 if (readyState >= 2) { 26165 // clear xhr timeout and rearm it if readyState less than 4 26166 self.clearTimeout(this.requestTimeout); 26167 if (stats.loading.first === 0) { 26168 stats.loading.first = Math.max(self.performance.now(), stats.loading.start); 26169 } 26170 if (readyState === 4) { 26171 xhr.onreadystatechange = null; 26172 xhr.onprogress = null; 26173 var status = xhr.status; 26174 // http status between 200 to 299 are all successful 26175 var isArrayBuffer = xhr.responseType === 'arraybuffer'; 26176 if (status >= 200 && status < 300 && (isArrayBuffer && xhr.response || xhr.responseText !== null)) { 26177 stats.loading.end = Math.max(self.performance.now(), stats.loading.first); 26178 var data; 26179 var len; 26180 if (isArrayBuffer) { 26181 data = xhr.response; 26182 len = data.byteLength; 26183 } else { 26184 data = xhr.responseText; 26185 len = data.length; 26186 } 26187 stats.loaded = stats.total = len; 26188 if (!this.callbacks) { 26189 return; 26190 } 26191 var onProgress = this.callbacks.onProgress; 26192 if (onProgress) { 26193 onProgress(stats, context, data, xhr); 26194 } 26195 if (!this.callbacks) { 26196 return; 26197 } 26198 var response = { 26199 url: xhr.responseURL, 26200 data: data 26201 }; 26202 this.callbacks.onSuccess(response, stats, context, xhr); 26203 } else { 26204 // if max nb of retries reached or if http status between 400 and 499 (such error cannot be recovered, retrying is useless), return error 26205 if (stats.retry >= config.maxRetry || status >= 400 && status < 499) { 26206 _utils_logger__WEBPACK_IMPORTED_MODULE_0__.logger.error(status + " while loading " + context.url); 26207 this.callbacks.onError({ 26208 code: status, 26209 text: xhr.statusText 26210 }, context, xhr); 26211 } else { 26212 // retry 26213 _utils_logger__WEBPACK_IMPORTED_MODULE_0__.logger.warn(status + " while loading " + context.url + ", retrying in " + this.retryDelay + "..."); 26214 // abort and reset internal state 26215 this.abortInternal(); 26216 this.loader = null; 26217 // schedule retry 26218 self.clearTimeout(this.retryTimeout); 26219 this.retryTimeout = self.setTimeout(this.loadInternal.bind(this), this.retryDelay); 26220 // set exponential backoff 26221 this.retryDelay = Math.min(2 * this.retryDelay, config.maxRetryDelay); 26222 stats.retry++; 26223 } 26224 } 26225 } else { 26226 // readyState >= 2 AND readyState !==4 (readyState = HEADERS_RECEIVED || LOADING) rearm timeout as xhr not finished yet 26227 self.clearTimeout(this.requestTimeout); 26228 this.requestTimeout = self.setTimeout(this.loadtimeout.bind(this), config.timeout); 26229 } 26230 } 26231 }; 26232 _proto.loadtimeout = function loadtimeout() { 26233 _utils_logger__WEBPACK_IMPORTED_MODULE_0__.logger.warn("timeout while loading " + this.context.url); 26234 var callbacks = this.callbacks; 26235 if (callbacks) { 26236 this.abortInternal(); 26237 callbacks.onTimeout(this.stats, this.context, this.loader); 26238 } 26239 }; 26240 _proto.loadprogress = function loadprogress(event) { 26241 var stats = this.stats; 26242 stats.loaded = event.loaded; 26243 if (event.lengthComputable) { 26244 stats.total = event.total; 26245 } 26246 }; 26247 _proto.getCacheAge = function getCacheAge() { 26248 var result = null; 26249 if (this.loader && AGE_HEADER_LINE_REGEX.test(this.loader.getAllResponseHeaders())) { 26250 var ageHeader = this.loader.getResponseHeader('age'); 26251 result = ageHeader ? parseFloat(ageHeader) : null; 26252 } 26253 return result; 26254 }; 26255 return XhrLoader; 26256}(); 26257/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (XhrLoader); 26258 26259/***/ }), 26260
vendor: 9,351 bytes, lines 26261-26607
26261/***/ "./node_modules/eventemitter3/index.js": 26262/*!*********************************************!*\ 26263 !*** ./node_modules/eventemitter3/index.js ***! 26264 \*********************************************/ 26265/***/ ((module) => { 26266 26267"use strict"; 26268 26269 26270var has = Object.prototype.hasOwnProperty 26271 , prefix = '~'; 26272 26273/** 26274 * Constructor to create a storage for our `EE` objects. 26275 * An `Events` instance is a plain object whose properties are event names. 26276 * 26277 * @constructor 26278 * @private 26279 */ 26280function Events() {} 26281 26282// 26283// We try to not inherit from `Object.prototype`. In some engines creating an 26284// instance in this way is faster than calling `Object.create(null)` directly. 26285// If `Object.create(null)` is not supported we prefix the event names with a 26286// character to make sure that the built-in object properties are not 26287// overridden or used as an attack vector. 26288// 26289if (Object.create) { 26290 Events.prototype = Object.create(null); 26291 26292 // 26293 // This hack is needed because the `__proto__` property is still inherited in 26294 // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5. 26295 // 26296 if (!new Events().__proto__) prefix = false; 26297} 26298 26299/** 26300 * Representation of a single event listener. 26301 * 26302 * @param {Function} fn The listener function. 26303 * @param {*} context The context to invoke the listener with. 26304 * @param {Boolean} [once=false] Specify if the listener is a one-time listener. 26305 * @constructor 26306 * @private 26307 */ 26308function EE(fn, context, once) { 26309 this.fn = fn; 26310 this.context = context; 26311 this.once = once || false; 26312} 26313 26314/** 26315 * Add a listener for a given event. 26316 * 26317 * @param {EventEmitter} emitter Reference to the `EventEmitter` instance. 26318 * @param {(String|Symbol)} event The event name. 26319 * @param {Function} fn The listener function. 26320 * @param {*} context The context to invoke the listener with. 26321 * @param {Boolean} once Specify if the listener is a one-time listener. 26322 * @returns {EventEmitter} 26323 * @private 26324 */ 26325function addListener(emitter, event, fn, context, once) { 26326 if (typeof fn !== 'function') { 26327 throw new TypeError('The listener must be a function'); 26328 } 26329 26330 var listener = new EE(fn, context || emitter, once) 26331 , evt = prefix ? prefix + event : event; 26332 26333 if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++; 26334 else if (!emitter._events[evt].fn) emitter._events[evt].push(listener); 26335 else emitter._events[evt] = [emitter._events[evt], listener]; 26336 26337 return emitter; 26338} 26339 26340/** 26341 * Clear event by name. 26342 * 26343 * @param {EventEmitter} emitter Reference to the `EventEmitter` instance. 26344 * @param {(String|Symbol)} evt The Event name. 26345 * @private 26346 */ 26347function clearEvent(emitter, evt) { 26348 if (--emitter._eventsCount === 0) emitter._events = new Events(); 26349 else delete emitter._events[evt]; 26350} 26351 26352/** 26353 * Minimal `EventEmitter` interface that is molded against the Node.js 26354 * `EventEmitter` interface. 26355 * 26356 * @constructor 26357 * @public 26358 */ 26359function EventEmitter() { 26360 this._events = new Events(); 26361 this._eventsCount = 0; 26362} 26363 26364/** 26365 * Return an array listing the events for which the emitter has registered 26366 * listeners. 26367 * 26368 * @returns {Array} 26369 * @public 26370 */ 26371EventEmitter.prototype.eventNames = function eventNames() { 26372 var names = [] 26373 , events 26374 , name; 26375 26376 if (this._eventsCount === 0) return names; 26377 26378 for (name in (events = this._events)) { 26379 if (has.call(events, name)) names.push(prefix ? name.slice(1) : name); 26380 } 26381 26382 if (Object.getOwnPropertySymbols) { 26383 return names.concat(Object.getOwnPropertySymbols(events)); 26384 } 26385 26386 return names; 26387}; 26388 26389/** 26390 * Return the listeners registered for a given event. 26391 * 26392 * @param {(String|Symbol)} event The event name. 26393 * @returns {Array} The registered listeners. 26394 * @public 26395 */ 26396EventEmitter.prototype.listeners = function listeners(event) { 26397 var evt = prefix ? prefix + event : event 26398 , handlers = this._events[evt]; 26399 26400 if (!handlers) return []; 26401 if (handlers.fn) return [handlers.fn]; 26402 26403 for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) { 26404 ee[i] = handlers[i].fn; 26405 } 26406 26407 return ee; 26408}; 26409 26410/** 26411 * Return the number of listeners listening to a given event. 26412 * 26413 * @param {(String|Symbol)} event The event name. 26414 * @returns {Number} The number of listeners. 26415 * @public 26416 */ 26417EventEmitter.prototype.listenerCount = function listenerCount(event) { 26418 var evt = prefix ? prefix + event : event 26419 , listeners = this._events[evt]; 26420 26421 if (!listeners) return 0; 26422 if (listeners.fn) return 1; 26423 return listeners.length; 26424}; 26425 26426/** 26427 * Calls each of the listeners registered for a given event. 26428 * 26429 * @param {(String|Symbol)} event The event name. 26430 * @returns {Boolean} `true` if the event had listeners, else `false`. 26431 * @public 26432 */ 26433EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) { 26434 var evt = prefix ? prefix + event : event; 26435 26436 if (!this._events[evt]) return false; 26437 26438 var listeners = this._events[evt] 26439 , len = arguments.length 26440 , args 26441 , i; 26442 26443 if (listeners.fn) { 26444 if (listeners.once) this.removeListener(event, listeners.fn, undefined, true); 26445 26446 switch (len) { 26447 case 1: return listeners.fn.call(listeners.context), true; 26448 case 2: return listeners.fn.call(listeners.context, a1), true; 26449 case 3: return listeners.fn.call(listeners.context, a1, a2), true; 26450 case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true; 26451 case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true; 26452 case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true; 26453 } 26454 26455 for (i = 1, args = new Array(len -1); i < len; i++) { 26456 args[i - 1] = arguments[i]; 26457 } 26458 26459 listeners.fn.apply(listeners.context, args); 26460 } else { 26461 var length = listeners.length 26462 , j; 26463 26464 for (i = 0; i < length; i++) { 26465 if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true); 26466 26467 switch (len) { 26468 case 1: listeners[i].fn.call(listeners[i].context); break; 26469 case 2: listeners[i].fn.call(listeners[i].context, a1); break; 26470 case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break; 26471 case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break; 26472 default: 26473 if (!args) for (j = 1, args = new Array(len -1); j < len; j++) { 26474 args[j - 1] = arguments[j]; 26475 } 26476 26477 listeners[i].fn.apply(listeners[i].context, args); 26478 } 26479 } 26480 } 26481 26482 return true; 26483}; 26484 26485/** 26486 * Add a listener for a given event. 26487 * 26488 * @param {(String|Symbol)} event The event name. 26489 * @param {Function} fn The listener function. 26490 * @param {*} [context=this] The context to invoke the listener with. 26491 * @returns {EventEmitter} `this`. 26492 * @public 26493 */ 26494EventEmitter.prototype.on = function on(event, fn, context) { 26495 return addListener(this, event, fn, context, false); 26496}; 26497 26498/** 26499 * Add a one-time listener for a given event. 26500 * 26501 * @param {(String|Symbol)} event The event name. 26502 * @param {Function} fn The listener function. 26503 * @param {*} [context=this] The context to invoke the listener with. 26504 * @returns {EventEmitter} `this`. 26505 * @public 26506 */ 26507EventEmitter.prototype.once = function once(event, fn, context) { 26508 return addListener(this, event, fn, context, true); 26509}; 26510 26511/** 26512 * Remove the listeners of a given event. 26513 * 26514 * @param {(String|Symbol)} event The event name. 26515 * @param {Function} fn Only remove the listeners that match this function. 26516 * @param {*} context Only remove the listeners that have this context. 26517 * @param {Boolean} once Only remove one-time listeners. 26518 * @returns {EventEmitter} `this`. 26519 * @public 26520 */ 26521EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) { 26522 var evt = prefix ? prefix + event : event; 26523 26524 if (!this._events[evt]) return this; 26525 if (!fn) { 26526 clearEvent(this, evt); 26527 return this; 26528 } 26529 26530 var listeners = this._events[evt]; 26531 26532 if (listeners.fn) { 26533 if ( 26534 listeners.fn === fn && 26535 (!once || listeners.once) && 26536 (!context || listeners.context === context) 26537 ) { 26538 clearEvent(this, evt); 26539 } 26540 } else { 26541 for (var i = 0, events = [], length = listeners.length; i < length; i++) { 26542 if ( 26543 listeners[i].fn !== fn || 26544 (once && !listeners[i].once) || 26545 (context && listeners[i].context !== context) 26546 ) { 26547 events.push(listeners[i]); 26548 } 26549 } 26550 26551 // 26552 // Reset the array, or remove it completely if we have no more listeners. 26553 // 26554 if (events.length) this._events[evt] = events.length === 1 ? events[0] : events; 26555 else clearEvent(this, evt); 26556 } 26557 26558 return this; 26559}; 26560 26561/** 26562 * Remove all listeners, or those of the specified event. 26563 * 26564 * @param {(String|Symbol)} [event] The event name. 26565 * @returns {EventEmitter} `this`. 26566 * @public 26567 */ 26568EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) { 26569 var evt; 26570 26571 if (event) { 26572 evt = prefix ? prefix + event : event; 26573 if (this._events[evt]) clearEvent(this, evt); 26574 } else { 26575 this._events = new Events(); 26576 this._eventsCount = 0; 26577 } 26578 26579 return this; 26580}; 26581 26582// 26583// Alias methods names because people roll like that. 26584// 26585EventEmitter.prototype.off = EventEmitter.prototype.removeListener; 26586EventEmitter.prototype.addListener = EventEmitter.prototype.on; 26587 26588// 26589// Expose the prefix. 26590// 26591EventEmitter.prefixed = prefix; 26592 26593// 26594// Allow `EventEmitter` to be imported as module namespace. 26595// 26596EventEmitter.EventEmitter = EventEmitter; 26597 26598// 26599// Expose the module. 26600// 26601if (true) { 26602 module.exports = EventEmitter; 26603} 26604 26605 26606/***/ }), 26607
vendor: 7,126 bytes, lines 26608-26785
26608/***/ "./node_modules/url-toolkit/src/url-toolkit.js": 26609/*!*****************************************************!*\ 26610 !*** ./node_modules/url-toolkit/src/url-toolkit.js ***! 26611 \*****************************************************/ 26612/***/ (function(module) { 26613 26614// see https://tools.ietf.org/html/rfc1808 26615 26616(function (root) { 26617 var URL_REGEX = 26618 /^(?=((?:[a-zA-Z0-9+\-.]+:)?))\1(?=((?:\/\/[^\/?#]*)?))\2(?=((?:(?:[^?#\/]*\/)*[^;?#\/]*)?))\3((?:;[^?#]*)?)(\?[^#]*)?(#[^]*)?$/; 26619 var FIRST_SEGMENT_REGEX = /^(?=([^\/?#]*))\1([^]*)$/; 26620 var SLASH_DOT_REGEX = /(?:\/|^)\.(?=\/)/g; 26621 var SLASH_DOT_DOT_REGEX = /(?:\/|^)\.\.\/(?!\.\.\/)[^\/]*(?=\/)/g; 26622 26623 var URLToolkit = { 26624 // If opts.alwaysNormalize is true then the path will always be normalized even when it starts with / or // 26625 // E.g 26626 // With opts.alwaysNormalize = false (default, spec compliant) 26627 // http://a.com/b/cd + /e/f/../g => http://a.com/e/f/../g 26628 // With opts.alwaysNormalize = true (not spec compliant) 26629 // http://a.com/b/cd + /e/f/../g => http://a.com/e/g 26630 buildAbsoluteURL: function (baseURL, relativeURL, opts) { 26631 opts = opts || {}; 26632 // remove any remaining space and CRLF 26633 baseURL = baseURL.trim(); 26634 relativeURL = relativeURL.trim(); 26635 if (!relativeURL) { 26636 // 2a) If the embedded URL is entirely empty, it inherits the 26637 // entire base URL (i.e., is set equal to the base URL) 26638 // and we are done. 26639 if (!opts.alwaysNormalize) { 26640 return baseURL; 26641 } 26642 var basePartsForNormalise = URLToolkit.parseURL(baseURL); 26643 if (!basePartsForNormalise) { 26644 throw new Error('Error trying to parse base URL.'); 26645 } 26646 basePartsForNormalise.path = URLToolkit.normalizePath( 26647 basePartsForNormalise.path 26648 ); 26649 return URLToolkit.buildURLFromParts(basePartsForNormalise); 26650 } 26651 var relativeParts = URLToolkit.parseURL(relativeURL); 26652 if (!relativeParts) { 26653 throw new Error('Error trying to parse relative URL.'); 26654 } 26655 if (relativeParts.scheme) { 26656 // 2b) If the embedded URL starts with a scheme name, it is 26657 // interpreted as an absolute URL and we are done. 26658 if (!opts.alwaysNormalize) { 26659 return relativeURL; 26660 } 26661 relativeParts.path = URLToolkit.normalizePath(relativeParts.path); 26662 return URLToolkit.buildURLFromParts(relativeParts); 26663 } 26664 var baseParts = URLToolkit.parseURL(baseURL); 26665 if (!baseParts) { 26666 throw new Error('Error trying to parse base URL.'); 26667 } 26668 if (!baseParts.netLoc && baseParts.path && baseParts.path[0] !== '/') { 26669 // If netLoc missing and path doesn't start with '/', assume everthing before the first '/' is the netLoc 26670 // This causes 'example.com/a' to be handled as '//example.com/a' instead of '/example.com/a' 26671 var pathParts = FIRST_SEGMENT_REGEX.exec(baseParts.path); 26672 baseParts.netLoc = pathParts[1]; 26673 baseParts.path = pathParts[2]; 26674 } 26675 if (baseParts.netLoc && !baseParts.path) { 26676 baseParts.path = '/'; 26677 } 26678 var builtParts = { 26679 // 2c) Otherwise, the embedded URL inherits the scheme of 26680 // the base URL. 26681 scheme: baseParts.scheme, 26682 netLoc: relativeParts.netLoc, 26683 path: null, 26684 params: relativeParts.params, 26685 query: relativeParts.query, 26686 fragment: relativeParts.fragment, 26687 }; 26688 if (!relativeParts.netLoc) { 26689 // 3) If the embedded URL's <net_loc> is non-empty, we skip to 26690 // Step 7. Otherwise, the embedded URL inherits the <net_loc> 26691 // (if any) of the base URL. 26692 builtParts.netLoc = baseParts.netLoc; 26693 // 4) If the embedded URL path is preceded by a slash "/", the 26694 // path is not relative and we skip to Step 7. 26695 if (relativeParts.path[0] !== '/') { 26696 if (!relativeParts.path) { 26697 // 5) If the embedded URL path is empty (and not preceded by a 26698 // slash), then the embedded URL inherits the base URL path 26699 builtParts.path = baseParts.path; 26700 // 5a) if the embedded URL's <params> is non-empty, we skip to 26701 // step 7; otherwise, it inherits the <params> of the base 26702 // URL (if any) and 26703 if (!relativeParts.params) { 26704 builtParts.params = baseParts.params; 26705 // 5b) if the embedded URL's <query> is non-empty, we skip to 26706 // step 7; otherwise, it inherits the <query> of the base 26707 // URL (if any) and we skip to step 7. 26708 if (!relativeParts.query) { 26709 builtParts.query = baseParts.query; 26710 } 26711 } 26712 } else { 26713 // 6) The last segment of the base URL's path (anything 26714 // following the rightmost slash "/", or the entire path if no 26715 // slash is present) is removed and the embedded URL's path is 26716 // appended in its place. 26717 var baseURLPath = baseParts.path; 26718 var newPath = 26719 baseURLPath.substring(0, baseURLPath.lastIndexOf('/') + 1) + 26720 relativeParts.path; 26721 builtParts.path = URLToolkit.normalizePath(newPath); 26722 } 26723 } 26724 } 26725 if (builtParts.path === null) { 26726 builtParts.path = opts.alwaysNormalize 26727 ? URLToolkit.normalizePath(relativeParts.path) 26728 : relativeParts.path; 26729 } 26730 return URLToolkit.buildURLFromParts(builtParts); 26731 }, 26732 parseURL: function (url) { 26733 var parts = URL_REGEX.exec(url); 26734 if (!parts) { 26735 return null; 26736 } 26737 return { 26738 scheme: parts[1] || '', 26739 netLoc: parts[2] || '', 26740 path: parts[3] || '', 26741 params: parts[4] || '', 26742 query: parts[5] || '', 26743 fragment: parts[6] || '', 26744 }; 26745 }, 26746 normalizePath: function (path) { 26747 // The following operations are 26748 // then applied, in order, to the new path: 26749 // 6a) All occurrences of "./", where "." is a complete path 26750 // segment, are removed. 26751 // 6b) If the path ends with "." as a complete path segment, 26752 // that "." is removed. 26753 path = path.split('').reverse().join('').replace(SLASH_DOT_REGEX, ''); 26754 // 6c) All occurrences of "<segment>/../", where <segment> is a 26755 // complete path segment not equal to "..", are removed. 26756 // Removal of these path segments is performed iteratively, 26757 // removing the leftmost matching pattern on each iteration, 26758 // until no matching pattern remains. 26759 // 6d) If the path ends with "<segment>/..", where <segment> is a 26760 // complete path segment not equal to "..", that 26761 // "<segment>/.." is removed. 26762 while ( 26763 path.length !== (path = path.replace(SLASH_DOT_DOT_REGEX, '')).length 26764 ) {} 26765 return path.split('').reverse().join(''); 26766 }, 26767 buildURLFromParts: function (parts) { 26768 return ( 26769 parts.scheme + 26770 parts.netLoc + 26771 parts.path + 26772 parts.params + 26773 parts.query + 26774 parts.fragment 26775 ); 26776 }, 26777 }; 26778 26779 if (true) 26780 module.exports = URLToolkit; 26781 else {} 26782})(this); 26783 26784 26785/***/ })
vendor: 3,261 bytes, lines 26785-26869
26785 26786 26787/******/ }); 26788/************************************************************************/ 26789/******/ // The module cache 26790/******/ var __webpack_module_cache__ = {}; 26791/******/ 26792/******/ // The require function 26793/******/ function __webpack_require__(moduleId) { 26794/******/ // Check if module is in cache 26795/******/ var cachedModule = __webpack_module_cache__[moduleId]; 26796/******/ if (cachedModule !== undefined) { 26797/******/ return cachedModule.exports; 26798/******/ } 26799/******/ // Create a new module (and put it into the cache) 26800/******/ var module = __webpack_module_cache__[moduleId] = { 26801/******/ // no module.id needed 26802/******/ // no module.loaded needed 26803/******/ exports: {} 26804/******/ }; 26805/******/ 26806/******/ // Execute the module function 26807/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__); 26808/******/ 26809/******/ // Return the exports of the module 26810/******/ return module.exports; 26811/******/ } 26812/******/ 26813/******/ // expose the modules object (__webpack_modules__) 26814/******/ __webpack_require__.m = __webpack_modules__; 26815/******/ 26816/************************************************************************/ 26817/******/ /* webpack/runtime/compat get default export */ 26818/******/ (() => { 26819/******/ // getDefaultExport function for compatibility with non-harmony modules 26820/******/ __webpack_require__.n = (module) => { 26821/******/ var getter = module && module.__esModule ? 26822/******/ () => (module['default']) : 26823/******/ () => (module); 26824/******/ __webpack_require__.d(getter, { a: getter }); 26825/******/ return getter; 26826/******/ }; 26827/******/ })(); 26828/******/ 26829/******/ /* webpack/runtime/define property getters */ 26830/******/ (() => { 26831/******/ // define getter functions for harmony exports 26832/******/ __webpack_require__.d = (exports, definition) => { 26833/******/ for(var key in definition) { 26834/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { 26835/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); 26836/******/ } 26837/******/ } 26838/******/ }; 26839/******/ })(); 26840/******/ 26841/******/ /* webpack/runtime/hasOwnProperty shorthand */ 26842/******/ (() => { 26843/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) 26844/******/ })(); 26845/******/ 26846/******/ /* webpack/runtime/make namespace object */ 26847/******/ (() => { 26848/******/ // define __esModule on exports 26849/******/ __webpack_require__.r = (exports) => { 26850/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 26851/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 26852/******/ } 26853/******/ Object.defineProperty(exports, '__esModule', { value: true }); 26854/******/ }; 26855/******/ })(); 26856/******/ 26857/************************************************************************/ 26858/******/ 26859/******/ // module factories are used so entry inlining is disabled 26860/******/ // startup 26861/******/ // Load entry module and return exports 26862/******/ var __webpack_exports__ = __webpack_require__("./src/hls.ts"); 26863/******/ __webpack_exports__ = __webpack_exports__["default"]; 26864/******/ 26865/******/ return __webpack_exports__; 26866/******/ })() 26867; 26868}); 26869//# sourceMappingURL=hls.js.map
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.