PageSourceSearch

https://tv5.ir/assets/js/hls.js

js tv5.ir collected 2026-10-02 22:09:52 UTC 790,932 bytes, 18,209 lines download raw bytes

vendor: 4,005 bytes, lines 1-99
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, function() {
12return /******/ (function(modules) { // webpackBootstrap
13/******/ 	// The module cache
14/******/ 	var installedModules = {};
15/******/
16/******/ 	// The require function
17/******/ 	function __webpack_require__(moduleId) {
18/******/
19/******/ 		// Check if module is in cache
20/******/ 		if(installedModules[moduleId]) {
21/******/ 			return installedModules[moduleId].exports;
22/******/ 		}
23/******/ 		// Create a new module (and put it into the cache)
24/******/ 		var module = installedModules[moduleId] = {
25/******/ 			i: moduleId,
26/******/ 			l: false,
27/******/ 			exports: {}
28/******/ 		};
29/******/
30/******/ 		// Execute the module function
31/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
32/******/
33/******/ 		// Flag the module as loaded
34/******/ 		module.l = true;
35/******/
36/******/ 		// Return the exports of the module
37/******/ 		return module.exports;
38/******/ 	}
39/******/
40/******/
41/******/ 	// expose the modules object (__webpack_modules__)
42/******/ 	__webpack_require__.m = modules;
43/******/
44/******/ 	// expose the module cache
45/******/ 	__webpack_require__.c = installedModules;
46/******/
47/******/ 	// define getter function for harmony exports
48/******/ 	__webpack_require__.d = function(exports, name, getter) {
49/******/ 		if(!__webpack_require__.o(exports, name)) {
50/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
51/******/ 		}
52/******/ 	};
53/******/
54/******/ 	// define __esModule on exports
55/******/ 	__webpack_require__.r = function(exports) {
56/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
57/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
58/******/ 		}
59/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
60/******/ 	};
61/******/
62/******/ 	// create a fake namespace object
63/******/ 	// mode & 1: value is a module id, require it
64/******/ 	// mode & 2: merge all properties of value into the ns
65/******/ 	// mode & 4: return value when already ns object
66/******/ 	// mode & 8|1: behave like require
67/******/ 	__webpack_require__.t = function(value, mode) {
68/******/ 		if(mode & 1) value = __webpack_require__(value);
69/******/ 		if(mode & 8) return value;
70/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
71/******/ 		var ns = Object.create(null);
72/******/ 		__webpack_require__.r(ns);
73/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
74/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
75/******/ 		return ns;
76/******/ 	};
77/******/
78/******/ 	// getDefaultExport function for compatibility with non-harmony modules
79/******/ 	__webpack_require__.n = function(module) {
80/******/ 		var getter = module && module.__esModule ?
81/******/ 			function getDefault() { return module['default']; } :
82/******/ 			function getModuleExports() { return module; };
83/******/ 		__webpack_require__.d(getter, 'a', getter);
84/******/ 		return getter;
85/******/ 	};
86/******/
87/******/ 	// Object.prototype.hasOwnProperty.call
88/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
89/******/
90/******/ 	// __webpack_public_path__
91/******/ 	__webpack_require__.p = "/dist/";
92/******/
93/******/
94/******/ 	// Load entry module and return exports
95/******/ 	return __webpack_require__(__webpack_require__.s = "./src/hls.js");
96/******/ })
97/************************************************************************/
98/******/ ({
99
vendor: 9,488 bytes, lines 100-448
100/***/ "./node_modules/eventemitter3/index.js":
101/*!*********************************************!*\
102  !*** ./node_modules/eventemitter3/index.js ***!
103  \*********************************************/
104/*! no static exports found */
105/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
106/***/ (function(module, exports, __webpack_require__) {
107
108"use strict";
109
110
111var has = Object.prototype.hasOwnProperty
112  , prefix = '~';
113
114/**
115 * Constructor to create a storage for our `EE` objects.
116 * An `Events` instance is a plain object whose properties are event names.
117 *
118 * @constructor
119 * @private
120 */
121function Events() {}
122
123//
124// We try to not inherit from `Object.prototype`. In some engines creating an
125// instance in this way is faster than calling `Object.create(null)` directly.
126// If `Object.create(null)` is not supported we prefix the event names with a
127// character to make sure that the built-in object properties are not
128// overridden or used as an attack vector.
129//
130if (Object.create) {
131  Events.prototype = Object.create(null);
132
133  //
134  // This hack is needed because the `__proto__` property is still inherited in
135  // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.
136  //
137  if (!new Events().__proto__) prefix = false;
138}
139
140/**
141 * Representation of a single event listener.
142 *
143 * @param {Function} fn The listener function.
144 * @param {*} context The context to invoke the listener with.
145 * @param {Boolean} [once=false] Specify if the listener is a one-time listener.
146 * @constructor
147 * @private
148 */
149function EE(fn, context, once) {
150  this.fn = fn;
151  this.context = context;
152  this.once = once || false;
153}
154
155/**
156 * Add a listener for a given event.
157 *
158 * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
159 * @param {(String|Symbol)} event The event name.
160 * @param {Function} fn The listener function.
161 * @param {*} context The context to invoke the listener with.
162 * @param {Boolean} once Specify if the listener is a one-time listener.
163 * @returns {EventEmitter}
164 * @private
165 */
166function addListener(emitter, event, fn, context, once) {
167  if (typeof fn !== 'function') {
168    throw new TypeError('The listener must be a function');
169  }
170
171  var listener = new EE(fn, context || emitter, once)
172    , evt = prefix ? prefix + event : event;
173
174  if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;
175  else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);
176  else emitter._events[evt] = [emitter._events[evt], listener];
177
178  return emitter;
179}
180
181/**
182 * Clear event by name.
183 *
184 * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
185 * @param {(String|Symbol)} evt The Event name.
186 * @private
187 */
188function clearEvent(emitter, evt) {
189  if (--emitter._eventsCount === 0) emitter._events = new Events();
190  else delete emitter._events[evt];
191}
192
193/**
194 * Minimal `EventEmitter` interface that is molded against the Node.js
195 * `EventEmitter` interface.
196 *
197 * @constructor
198 * @public
199 */
200function EventEmitter() {
201  this._events = new Events();
202  this._eventsCount = 0;
203}
204
205/**
206 * Return an array listing the events for which the emitter has registered
207 * listeners.
208 *
209 * @returns {Array}
210 * @public
211 */
212EventEmitter.prototype.eventNames = function eventNames() {
213  var names = []
214    , events
215    , name;
216
217  if (this._eventsCount === 0) return names;
218
219  for (name in (events = this._events)) {
220    if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
221  }
222
223  if (Object.getOwnPropertySymbols) {
224    return names.concat(Object.getOwnPropertySymbols(events));
225  }
226
227  return names;
228};
229
230/**
231 * Return the listeners registered for a given event.
232 *
233 * @param {(String|Symbol)} event The event name.
234 * @returns {Array} The registered listeners.
235 * @public
236 */
237EventEmitter.prototype.listeners = function listeners(event) {
238  var evt = prefix ? prefix + event : event
239    , handlers = this._events[evt];
240
241  if (!handlers) return [];
242  if (handlers.fn) return [handlers.fn];
243
244  for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
245    ee[i] = handlers[i].fn;
246  }
247
248  return ee;
249};
250
251/**
252 * Return the number of listeners listening to a given event.
253 *
254 * @param {(String|Symbol)} event The event name.
255 * @returns {Number} The number of listeners.
256 * @public
257 */
258EventEmitter.prototype.listenerCount = function listenerCount(event) {
259  var evt = prefix ? prefix + event : event
260    , listeners = this._events[evt];
261
262  if (!listeners) return 0;
263  if (listeners.fn) return 1;
264  return listeners.length;
265};
266
267/**
268 * Calls each of the listeners registered for a given event.
269 *
270 * @param {(String|Symbol)} event The event name.
271 * @returns {Boolean} `true` if the event had listeners, else `false`.
272 * @public
273 */
274EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
275  var evt = prefix ? prefix + event : event;
276
277  if (!this._events[evt]) return false;
278
279  var listeners = this._events[evt]
280    , len = arguments.length
281    , args
282    , i;
283
284  if (listeners.fn) {
285    if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);
286
287    switch (len) {
288      case 1: return listeners.fn.call(listeners.context), true;
289      case 2: return listeners.fn.call(listeners.context, a1), true;
290      case 3: return listeners.fn.call(listeners.context, a1, a2), true;
291      case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;
292      case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
293      case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
294    }
295
296    for (i = 1, args = new Array(len -1); i < len; i++) {
297      args[i - 1] = arguments[i];
298    }
299
300    listeners.fn.apply(listeners.context, args);
301  } else {
302    var length = listeners.length
303      , j;
304
305    for (i = 0; i < length; i++) {
306      if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);
307
308      switch (len) {
309        case 1: listeners[i].fn.call(listeners[i].context); break;
310        case 2: listeners[i].fn.call(listeners[i].context, a1); break;
311        case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;
312        case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;
313        default:
314          if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {
315            args[j - 1] = arguments[j];
316          }
317
318          listeners[i].fn.apply(listeners[i].context, args);
319      }
320    }
321  }
322
323  return true;
324};
325
326/**
327 * Add a listener for a given event.
328 *
329 * @param {(String|Symbol)} event The event name.
330 * @param {Function} fn The listener function.
331 * @param {*} [context=this] The context to invoke the listener with.
332 * @returns {EventEmitter} `this`.
333 * @public
334 */
335EventEmitter.prototype.on = function on(event, fn, context) {
336  return addListener(this, event, fn, context, false);
337};
338
339/**
340 * Add a one-time listener for a given event.
341 *
342 * @param {(String|Symbol)} event The event name.
343 * @param {Function} fn The listener function.
344 * @param {*} [context=this] The context to invoke the listener with.
345 * @returns {EventEmitter} `this`.
346 * @public
347 */
348EventEmitter.prototype.once = function once(event, fn, context) {
349  return addListener(this, event, fn, context, true);
350};
351
352/**
353 * Remove the listeners of a given event.
354 *
355 * @param {(String|Symbol)} event The event name.
356 * @param {Function} fn Only remove the listeners that match this function.
357 * @param {*} context Only remove the listeners that have this context.
358 * @param {Boolean} once Only remove one-time listeners.
359 * @returns {EventEmitter} `this`.
360 * @public
361 */
362EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
363  var evt = prefix ? prefix + event : event;
364
365  if (!this._events[evt]) return this;
366  if (!fn) {
367    clearEvent(this, evt);
368    return this;
369  }
370
371  var listeners = this._events[evt];
372
373  if (listeners.fn) {
374    if (
375      listeners.fn === fn &&
376      (!once || listeners.once) &&
377      (!context || listeners.context === context)
378    ) {
379      clearEvent(this, evt);
380    }
381  } else {
382    for (var i = 0, events = [], length = listeners.length; i < length; i++) {
383      if (
384        listeners[i].fn !== fn ||
385        (once && !listeners[i].once) ||
386        (context && listeners[i].context !== context)
387      ) {
388        events.push(listeners[i]);
389      }
390    }
391
392    //
393    // Reset the array, or remove it completely if we have no more listeners.
394    //
395    if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;
396    else clearEvent(this, evt);
397  }
398
399  return this;
400};
401
402/**
403 * Remove all listeners, or those of the specified event.
404 *
405 * @param {(String|Symbol)} [event] The event name.
406 * @returns {EventEmitter} `this`.
407 * @public
408 */
409EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
410  var evt;
411
412  if (event) {
413    evt = prefix ? prefix + event : event;
414    if (this._events[evt]) clearEvent(this, evt);
415  } else {
416    this._events = new Events();
417    this._eventsCount = 0;
418  }
419
420  return this;
421};
422
423//
424// Alias methods names because people roll like that.
425//
426EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
427EventEmitter.prototype.addListener = EventEmitter.prototype.on;
428
429//
430// Expose the prefix.
431//
432EventEmitter.prefixed = prefix;
433
434//
435// Allow `EventEmitter` to be imported as module namespace.
436//
437EventEmitter.EventEmitter = EventEmitter;
438
439//
440// Expose the module.
441//
442if (true) {
443  module.exports = EventEmitter;
444}
445
446
447/***/ }),
448
vendor: 8,778 bytes, lines 449-762
449/***/ "./node_modules/node-libs-browser/node_modules/events/events.js":
450/*!**********************************************************************!*\
451  !*** ./node_modules/node-libs-browser/node_modules/events/events.js ***!
452  \**********************************************************************/
453/*! no static exports found */
454/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
455/***/ (function(module, exports) {
456
457// Copyright Joyent, Inc. and other Node contributors.
458//
459// Permission is hereby granted, free of charge, to any person obtaining a
460// copy of this software and associated documentation files (the
461// "Software"), to deal in the Software without restriction, including
462// without limitation the rights to use, copy, modify, merge, publish,
463// distribute, sublicense, and/or sell copies of the Software, and to permit
464// persons to whom the Software is furnished to do so, subject to the
465// following conditions:
466//
467// The above copyright notice and this permission notice shall be included
468// in all copies or substantial portions of the Software.
469//
470// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
471// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
472// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
473// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
474// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
475// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
476// USE OR OTHER DEALINGS IN THE SOFTWARE.
477
478function EventEmitter() {
479  this._events = this._events || {};
480  this._maxListeners = this._maxListeners || undefined;
481}
482module.exports = EventEmitter;
483
484// Backwards-compat with node 0.10.x
485EventEmitter.EventEmitter = EventEmitter;
486
487EventEmitter.prototype._events = undefined;
488EventEmitter.prototype._maxListeners = undefined;
489
490// By default EventEmitters will print a warning if more than 10 listeners are
491// added to it. This is a useful default which helps finding memory leaks.
492EventEmitter.defaultMaxListeners = 10;
493
494// Obviously not all Emitters should be limited to 10. This function allows
495// that to be increased. Set to zero for unlimited.
496EventEmitter.prototype.setMaxListeners = function(n) {
497  if (!isNumber(n) || n < 0 || isNaN(n))
498    throw TypeError('n must be a positive number');
499  this._maxListeners = n;
500  return this;
501};
502
503EventEmitter.prototype.emit = function(type) {
504  var er, handler, len, args, i, listeners;
505
506  if (!this._events)
507    this._events = {};
508
509  // If there is no 'error' event listener then throw.
510  if (type === 'error') {
511    if (!this._events.error ||
512        (isObject(this._events.error) && !this._events.error.length)) {
513      er = arguments[1];
514      if (er instanceof Error) {
515        throw er; // Unhandled 'error' event
516      } else {
517        // At least give some kind of context to the user
518        var err = new Error('Uncaught, unspecified "error" event. (' + er + ')');
519        err.context = er;
520        throw err;
521      }
522    }
523  }
524
525  handler = this._events[type];
526
527  if (isUndefined(handler))
528    return false;
529
530  if (isFunction(handler)) {
531    switch (arguments.length) {
532      // fast cases
533      case 1:
534        handler.call(this);
535        break;
536      case 2:
537        handler.call(this, arguments[1]);
538        break;
539      case 3:
540        handler.call(this, arguments[1], arguments[2]);
541        break;
542      // slower
543      default:
544        args = Array.prototype.slice.call(arguments, 1);
545        handler.apply(this, args);
546    }
547  } else if (isObject(handler)) {
548    args = Array.prototype.slice.call(arguments, 1);
549    listeners = handler.slice();
550    len = listeners.length;
551    for (i = 0; i < len; i++)
552      listeners[i].apply(this, args);
553  }
554
555  return true;
556};
557
558EventEmitter.prototype.addListener = function(type, listener) {
559  var m;
560
561  if (!isFunction(listener))
562    throw TypeError('listener must be a function');
563
564  if (!this._events)
565    this._events = {};
566
567  // To avoid recursion in the case that type === "newListener"! Before
568  // adding it to the listeners, first emit "newListener".
569  if (this._events.newListener)
570    this.emit('newListener', type,
571              isFunction(listener.listener) ?
572              listener.listener : listener);
573
574  if (!this._events[type])
575    // Optimize the case of one listener. Don't need the extra array object.
576    this._events[type] = listener;
577  else if (isObject(this._events[type]))
578    // If we've already got an array, just append.
579    this._events[type].push(listener);
580  else
581    // Adding the second element, need to change to array.
582    this._events[type] = [this._events[type], listener];
583
584  // Check for listener leak
585  if (isObject(this._events[type]) && !this._events[type].warned) {
586    if (!isUndefined(this._maxListeners)) {
587      m = this._maxListeners;
588    } else {
589      m = EventEmitter.defaultMaxListeners;
590    }
591
592    if (m && m > 0 && this._events[type].length > m) {
593      this._events[type].warned = true;
594      console.error('(node) warning: possible EventEmitter memory ' +
595                    'leak detected. %d listeners added. ' +
596                    'Use emitter.setMaxListeners() to increase limit.',
597                    this._events[type].length);
598      if (typeof console.trace === 'function') {
599        // not supported in IE 10
600        console.trace();
601      }
602    }
603  }
604
605  return this;
606};
607
608EventEmitter.prototype.on = EventEmitter.prototype.addListener;
609
610EventEmitter.prototype.once = function(type, listener) {
611  if (!isFunction(listener))
612    throw TypeError('listener must be a function');
613
614  var fired = false;
615
616  function g() {
617    this.removeListener(type, g);
618
619    if (!fired) {
620      fired = true;
621      listener.apply(this, arguments);
622    }
623  }
624
625  g.listener = listener;
626  this.on(type, g);
627
628  return this;
629};
630
631// emits a 'removeListener' event iff the listener was removed
632EventEmitter.prototype.removeListener = function(type, listener) {
633  var list, position, length, i;
634
635  if (!isFunction(listener))
636    throw TypeError('listener must be a function');
637
638  if (!this._events || !this._events[type])
639    return this;
640
641  list = this._events[type];
642  length = list.length;
643  position = -1;
644
645  if (list === listener ||
646      (isFunction(list.listener) && list.listener === listener)) {
647    delete this._events[type];
648    if (this._events.removeListener)
649      this.emit('removeListener', type, listener);
650
651  } else if (isObject(list)) {
652    for (i = length; i-- > 0;) {
653      if (list[i] === listener ||
654          (list[i].listener && list[i].listener === listener)) {
655        position = i;
656        break;
657      }
658    }
659
660    if (position < 0)
661      return this;
662
663    if (list.length === 1) {
664      list.length = 0;
665      delete this._events[type];
666    } else {
667      list.splice(position, 1);
668    }
669
670    if (this._events.removeListener)
671      this.emit('removeListener', type, listener);
672  }
673
674  return this;
675};
676
677EventEmitter.prototype.removeAllListeners = function(type) {
678  var key, listeners;
679
680  if (!this._events)
681    return this;
682
683  // not listening for removeListener, no need to emit
684  if (!this._events.removeListener) {
685    if (arguments.length === 0)
686      this._events = {};
687    else if (this._events[type])
688      delete this._events[type];
689    return this;
690  }
691
692  // emit removeListener for all listeners on all events
693  if (arguments.length === 0) {
694    for (key in this._events) {
695      if (key === 'removeListener') continue;
696      this.removeAllListeners(key);
697    }
698    this.removeAllListeners('removeListener');
699    this._events = {};
700    return this;
701  }
702
703  listeners = this._events[type];
704
705  if (isFunction(listeners)) {
706    this.removeListener(type, listeners);
707  } else if (listeners) {
708    // LIFO order
709    while (listeners.length)
710      this.removeListener(type, listeners[listeners.length - 1]);
711  }
712  delete this._events[type];
713
714  return this;
715};
716
717EventEmitter.prototype.listeners = function(type) {
718  var ret;
719  if (!this._events || !this._events[type])
720    ret = [];
721  else if (isFunction(this._events[type]))
722    ret = [this._events[type]];
723  else
724    ret = this._events[type].slice();
725  return ret;
726};
727
728EventEmitter.prototype.listenerCount = function(type) {
729  if (this._events) {
730    var evlistener = this._events[type];
731
732    if (isFunction(evlistener))
733      return 1;
734    else if (evlistener)
735      return evlistener.length;
736  }
737  return 0;
738};
739
740EventEmitter.listenerCount = function(emitter, type) {
741  return emitter.listenerCount(type);
742};
743
744function isFunction(arg) {
745  return typeof arg === 'function';
746}
747
748function isNumber(arg) {
749  return typeof arg === 'number';
750}
751
752function isObject(arg) {
753  return typeof arg === 'object' && arg !== null;
754}
755
756function isUndefined(arg) {
757  return arg === void 0;
758}
759
760
761/***/ }),
762
vendor: 7,201 bytes, lines 763-932
763/***/ "./node_modules/url-toolkit/src/url-toolkit.js":
764/*!*****************************************************!*\
765  !*** ./node_modules/url-toolkit/src/url-toolkit.js ***!
766  \*****************************************************/
767/*! no static exports found */
768/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
769/***/ (function(module, exports, __webpack_require__) {
770
771// see https://tools.ietf.org/html/rfc1808
772
773/* jshint ignore:start */
774(function(root) { 
775/* jshint ignore:end */
776
777  var URL_REGEX = /^((?:[a-zA-Z0-9+\-.]+:)?)(\/\/[^\/?#]*)?((?:[^\/\?#]*\/)*.*?)??(;.*?)?(\?.*?)?(#.*?)?$/;
778  var FIRST_SEGMENT_REGEX = /^([^\/?#]*)(.*)$/;
779  var SLASH_DOT_REGEX = /(?:\/|^)\.(?=\/)/g;
780  var SLASH_DOT_DOT_REGEX = /(?:\/|^)\.\.\/(?!\.\.\/).*?(?=\/)/g;
781
782  var URLToolkit = { // jshint ignore:line
783    // If opts.alwaysNormalize is true then the path will always be normalized even when it starts with / or //
784    // E.g
785    // With opts.alwaysNormalize = false (default, spec compliant)
786    // http://a.com/b/cd + /e/f/../g => http://a.com/e/f/../g
787    // With opts.alwaysNormalize = true (not spec compliant)
788    // http://a.com/b/cd + /e/f/../g => http://a.com/e/g
789    buildAbsoluteURL: function(baseURL, relativeURL, opts) {
790      opts = opts || {};
791      // remove any remaining space and CRLF
792      baseURL = baseURL.trim();
793      relativeURL = relativeURL.trim();
794      if (!relativeURL) {
795        // 2a) If the embedded URL is entirely empty, it inherits the
796        // entire base URL (i.e., is set equal to the base URL)
797        // and we are done.
798        if (!opts.alwaysNormalize) {
799          return baseURL;
800        }
801        var basePartsForNormalise = URLToolkit.parseURL(baseURL);
802        if (!basePartsForNormalise) {
803          throw new Error('Error trying to parse base URL.');
804        }
805        basePartsForNormalise.path = URLToolkit.normalizePath(basePartsForNormalise.path);
806        return URLToolkit.buildURLFromParts(basePartsForNormalise);
807      }
808      var relativeParts = URLToolkit.parseURL(relativeURL);
809      if (!relativeParts) {
810        throw new Error('Error trying to parse relative URL.');
811      }
812      if (relativeParts.scheme) {
813        // 2b) If the embedded URL starts with a scheme name, it is
814        // interpreted as an absolute URL and we are done.
815        if (!opts.alwaysNormalize) {
816          return relativeURL;
817        }
818        relativeParts.path = URLToolkit.normalizePath(relativeParts.path);
819        return URLToolkit.buildURLFromParts(relativeParts);
820      }
821      var baseParts = URLToolkit.parseURL(baseURL);
822      if (!baseParts) {
823        throw new Error('Error trying to parse base URL.');
824      }
825      if (!baseParts.netLoc && baseParts.path && baseParts.path[0] !== '/') {
826        // If netLoc missing and path doesn't start with '/', assume everthing before the first '/' is the netLoc
827        // This causes 'example.com/a' to be handled as '//example.com/a' instead of '/example.com/a'
828        var pathParts = FIRST_SEGMENT_REGEX.exec(baseParts.path);
829        baseParts.netLoc = pathParts[1];
830        baseParts.path = pathParts[2];
831      }
832      if (baseParts.netLoc && !baseParts.path) {
833        baseParts.path = '/';
834      }
835      var builtParts = {
836        // 2c) Otherwise, the embedded URL inherits the scheme of
837        // the base URL.
838        scheme: baseParts.scheme,
839        netLoc: relativeParts.netLoc,
840        path: null,
841        params: relativeParts.params,
842        query: relativeParts.query,
843        fragment: relativeParts.fragment
844      };
845      if (!relativeParts.netLoc) {
846        // 3) If the embedded URL's <net_loc> is non-empty, we skip to
847        // Step 7.  Otherwise, the embedded URL inherits the <net_loc>
848        // (if any) of the base URL.
849        builtParts.netLoc = baseParts.netLoc;
850        // 4) If the embedded URL path is preceded by a slash "/", the
851        // path is not relative and we skip to Step 7.
852        if (relativeParts.path[0] !== '/') {
853          if (!relativeParts.path) {
854            // 5) If the embedded URL path is empty (and not preceded by a
855            // slash), then the embedded URL inherits the base URL path
856            builtParts.path = baseParts.path;
857            // 5a) if the embedded URL's <params> is non-empty, we skip to
858            // step 7; otherwise, it inherits the <params> of the base
859            // URL (if any) and
860            if (!relativeParts.params) {
861              builtParts.params = baseParts.params;
862              // 5b) if the embedded URL's <query> is non-empty, we skip to
863              // step 7; otherwise, it inherits the <query> of the base
864              // URL (if any) and we skip to step 7.
865              if (!relativeParts.query) {
866                builtParts.query = baseParts.query;
867              }
868            }
869          } else {
870            // 6) The last segment of the base URL's path (anything
871            // following the rightmost slash "/", or the entire path if no
872            // slash is present) is removed and the embedded URL's path is
873            // appended in its place.
874            var baseURLPath = baseParts.path;
875            var newPath = baseURLPath.substring(0, baseURLPath.lastIndexOf('/') + 1) + relativeParts.path;
876            builtParts.path = URLToolkit.normalizePath(newPath);
877          }
878        }
879      }
880      if (builtParts.path === null) {
881        builtParts.path = opts.alwaysNormalize ? URLToolkit.normalizePath(relativeParts.path) : relativeParts.path;
882      }
883      return URLToolkit.buildURLFromParts(builtParts);
884    },
885    parseURL: function(url) {
886      var parts = URL_REGEX.exec(url);
887      if (!parts) {
888        return null;
889      }
890      return {
891        scheme: parts[1] || '',
892        netLoc: parts[2] || '',
893        path: parts[3] || '',
894        params: parts[4] || '',
895        query: parts[5] || '',
896        fragment: parts[6] || ''
897      };
898    },
899    normalizePath: function(path) {
900      // The following operations are
901      // then applied, in order, to the new path:
902      // 6a) All occurrences of "./", where "." is a complete path
903      // segment, are removed.
904      // 6b) If the path ends with "." as a complete path segment,
905      // that "." is removed.
906      path = path.split('').reverse().join('').replace(SLASH_DOT_REGEX, '');
907      // 6c) All occurrences of "<segment>/../", where <segment> is a
908      // complete path segment not equal to "..", are removed.
909      // Removal of these path segments is performed iteratively,
910      // removing the leftmost matching pattern on each iteration,
911      // until no matching pattern remains.
912      // 6d) If the path ends with "<segment>/..", where <segment> is a
913      // complete path segment not equal to "..", that
914      // "<segment>/.." is removed.
915      while (path.length !== (path = path.replace(SLASH_DOT_DOT_REGEX, '')).length) {} // jshint ignore:line
916      return path.split('').reverse().join('');
917    },
918    buildURLFromParts: function(parts) {
919      return parts.scheme + parts.netLoc + parts.path + parts.params + parts.query + parts.fragment;
920    }
921  };
922
923/* jshint ignore:start */
924  if(true)
925    module.exports = URLToolkit;
926  else {}
927})(this);
928/* jshint ignore:end */
929
930
931/***/ }),
932
vendor: 7,825 bytes, lines 933-1146
933/***/ "./node_modules/webworkify-webpack/index.js":
934/*!**************************************************!*\
935  !*** ./node_modules/webworkify-webpack/index.js ***!
936  \**************************************************/
937/*! no static exports found */
938/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
939/***/ (function(module, exports, __webpack_require__) {
940
941function webpackBootstrapFunc (modules) {
942/******/  // The module cache
943/******/  var installedModules = {};
944
945/******/  // The require function
946/******/  function __webpack_require__(moduleId) {
947
948/******/    // Check if module is in cache
949/******/    if(installedModules[moduleId])
950/******/      return installedModules[moduleId].exports;
951
952/******/    // Create a new module (and put it into the cache)
953/******/    var module = installedModules[moduleId] = {
954/******/      i: moduleId,
955/******/      l: false,
956/******/      exports: {}
957/******/    };
958
959/******/    // Execute the module function
960/******/    modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
961
962/******/    // Flag the module as loaded
963/******/    module.l = true;
964
965/******/    // Return the exports of the module
966/******/    return module.exports;
967/******/  }
968
969/******/  // expose the modules object (__webpack_modules__)
970/******/  __webpack_require__.m = modules;
971
972/******/  // expose the module cache
973/******/  __webpack_require__.c = installedModules;
974
975/******/  // identity function for calling harmony imports with the correct context
976/******/  __webpack_require__.i = function(value) { return value; };
977
978/******/  // define getter function for harmony exports
979/******/  __webpack_require__.d = function(exports, name, getter) {
980/******/    if(!__webpack_require__.o(exports, name)) {
981/******/      Object.defineProperty(exports, name, {
982/******/        configurable: false,
983/******/        enumerable: true,
984/******/        get: getter
985/******/      });
986/******/    }
987/******/  };
988
989/******/  // define __esModule on exports
990/******/  __webpack_require__.r = function(exports) {
991/******/    Object.defineProperty(exports, '__esModule', { value: true });
992/******/  };
993
994/******/  // getDefaultExport function for compatibility with non-harmony modules
995/******/  __webpack_require__.n = function(module) {
996/******/    var getter = module && module.__esModule ?
997/******/      function getDefault() { return module['default']; } :
998/******/      function getModuleExports() { return module; };
999/******/    __webpack_require__.d(getter, 'a', getter);
1000/******/    return getter;
1001/******/  };
1002
1003/******/  // Object.prototype.hasOwnProperty.call
1004/******/  __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
1005
1006/******/  // __webpack_public_path__
1007/******/  __webpack_require__.p = "/";
1008
1009/******/  // on error function for async loading
1010/******/  __webpack_require__.oe = function(err) { console.error(err); throw err; };
1011
1012  var f = __webpack_require__(__webpack_require__.s = ENTRY_MODULE)
1013  return f.default || f // try to call default if defined to also support babel esmodule exports
1014}
1015
1016var moduleNameReqExp = '[\\.|\\-|\\+|\\w|\/|@]+'
1017var dependencyRegExp = '\\((\/\\*.*?\\*\/)?\s?.*?(' + moduleNameReqExp + ').*?\\)' // additional chars when output.pathinfo is true
1018
1019// http://stackoverflow.com/a/2593661/130442
1020function quoteRegExp (str) {
1021  return (str + '').replace(/[.?*+^$[\]\\(){}|-]/g, '\\$&')
1022}
1023
1024function isNumeric(n) {
1025  return !isNaN(1 * n); // 1 * n converts integers, integers as string ("123"), 1e3 and "1e3" to integers and strings to NaN
1026}
1027
1028function getModuleDependencies (sources, module, queueName) {
1029  var retval = {}
1030  retval[queueName] = []
1031
1032  var fnString = module.toString()
1033  var wrapperSignature = fnString.match(/^function\s?\(\w+,\s*\w+,\s*(\w+)\)/)
1034  if (!wrapperSignature) return retval
1035  var webpackRequireName = wrapperSignature[1]
1036
1037  // main bundle deps
1038  var re = new RegExp('(\\\\n|\\W)' + quoteRegExp(webpackRequireName) + dependencyRegExp, 'g')
1039  var match
1040  while ((match = re.exec(fnString))) {
1041    if (match[3] === 'dll-reference') continue
1042    retval[queueName].push(match[3])
1043  }
1044
1045  // dll deps
1046  re = new RegExp('\\(' + quoteRegExp(webpackRequireName) + '\\("(dll-reference\\s(' + moduleNameReqExp + '))"\\)\\)' + dependencyRegExp, 'g')
1047  while ((match = re.exec(fnString))) {
1048    if (!sources[match[2]]) {
1049      retval[queueName].push(match[1])
1050      sources[match[2]] = __webpack_require__(match[1]).m
1051    }
1052    retval[match[2]] = retval[match[2]] || []
1053    retval[match[2]].push(match[4])
1054  }
1055
1056  // convert 1e3 back to 1000 - this can be important after uglify-js converted 1000 to 1e3
1057  var keys = Object.keys(retval);
1058  for (var i = 0; i < keys.length; i++) {
1059    for (var j = 0; j < retval[keys[i]].length; j++) {
1060      if (isNumeric(retval[keys[i]][j])) {
1061        retval[keys[i]][j] = 1 * retval[keys[i]][j];
1062      }
1063    }
1064  }
1065
1066  return retval
1067}
1068
1069function hasValuesInQueues (queues) {
1070  var keys = Object.keys(queues)
1071  return keys.reduce(function (hasValues, key) {
1072    return hasValues || queues[key].length > 0
1073  }, false)
1074}
1075
1076function getRequiredModules (sources, moduleId) {
1077  var modulesQueue = {
1078    main: [moduleId]
1079  }
1080  var requiredModules = {
1081    main: []
1082  }
1083  var seenModules = {
1084    main: {}
1085  }
1086
1087  while (hasValuesInQueues(modulesQueue)) {
1088    var queues = Object.keys(modulesQueue)
1089    for (var i = 0; i < queues.length; i++) {
1090      var queueName = queues[i]
1091      var queue = modulesQueue[queueName]
1092      var moduleToCheck = queue.pop()
1093      seenModules[queueName] = seenModules[queueName] || {}
1094      if (seenModules[queueName][moduleToCheck] || !sources[queueName][moduleToCheck]) continue
1095      seenModules[queueName][moduleToCheck] = true
1096      requiredModules[queueName] = requiredModules[queueName] || []
1097      requiredModules[queueName].push(moduleToCheck)
1098      var newModules = getModuleDependencies(sources, sources[queueName][moduleToCheck], queueName)
1099      var newModulesKeys = Object.keys(newModules)
1100      for (var j = 0; j < newModulesKeys.length; j++) {
1101        modulesQueue[newModulesKeys[j]] = modulesQueue[newModulesKeys[j]] || []
1102        modulesQueue[newModulesKeys[j]] = modulesQueue[newModulesKeys[j]].concat(newModules[newModulesKeys[j]])
1103      }
1104    }
1105  }
1106
1107  return requiredModules
1108}
1109
1110module.exports = function (moduleId, options) {
1111  options = options || {}
1112  var sources = {
1113    main: __webpack_require__.m
1114  }
1115
1116  var requiredModules = options.all ? { main: Object.keys(sources.main) } : getRequiredModules(sources, moduleId)
1117
1118  var src = ''
1119
1120  Object.keys(requiredModules).filter(function (m) { return m !== 'main' }).forEach(function (module) {
1121    var entryModule = 0
1122    while (requiredModules[module][entryModule]) {
1123      entryModule++
1124    }
1125    requiredModules[module].push(entryModule)
1126    sources[module][entryModule] = '(function(module, exports, __webpack_require__) { module.exports = __webpack_require__; })'
1127    src = src + 'var ' + module + ' = (' + webpackBootstrapFunc.toString().replace('ENTRY_MODULE', JSON.stringify(entryModule)) + ')({' + requiredModules[module].map(function (id) { return '' + JSON.stringify(id) + ': ' + sources[module][id].toString() }).join(',') + '});\n'
1128  })
1129
1130  src = src + 'new ((' + webpackBootstrapFunc.toString().replace('ENTRY_MODULE', JSON.stringify(moduleId)) + ')({' + requiredModules.main.map(function (id) { return '' + JSON.stringify(id) + ': ' + sources.main[id].toString() }).join(',') + '}))(self);'
1131
1132  var blob = new window.Blob([src], { type: 'text/javascript' })
1133  if (options.bare) { return blob }
1134
1135  var URL = window.URL || window.webkitURL || window.mozURL || window.msURL
1136
1137  var workerUrl = URL.createObjectURL(blob)
1138  var worker = new window.Worker(workerUrl)
1139  worker.objectURL = workerUrl
1140
1141  return worker
1142}
1143
1144
1145/***/ }),
1146
1147/***/ "./src/config.js":
1148/*!***********************!*\
1149  !*** ./src/config.js ***!
1150  \***********************/
1151/*! no static exports found */
1152/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
1153/***/ (function(module, exports, __webpack_require__) {
1154
1155"use strict";
1156
1157/**
1158 * HLS config
1159 */
1160Object.defineProperty(exports, "__esModule", { value: true });
1161var abr_controller_1 = __webpack_require__(/*! ./controller/abr-controller */ "./src/controller/abr-controller.js");
1162var buffer_controller_1 = __webpack_require__(/*! ./controller/buffer-controller */ "./src/controller/buffer-controller.js");
1163var cap_level_controller_1 = __webpack_require__(/*! ./controller/cap-level-controller */ "./src/controller/cap-level-controller.js");
1164var fps_controller_1 = __webpack_require__(/*! ./controller/fps-controller */ "./src/controller/fps-controller.js");
1165var xhr_loader_1 = __webpack_require__(/*! ./utils/xhr-loader */ "./src/utils/xhr-loader.js");
1166// import FetchLoader from './utils/fetch-loader';
1167var audio_track_controller_1 = __webpack_require__(/*! ./controller/audio-track-controller */ "./src/controller/audio-track-controller.js");
1168var audio_stream_controller_1 = __webpack_require__(/*! ./controller/audio-stream-controller */ "./src/controller/audio-stream-controller.js");
1169var Cues = __webpack_require__(/*! ./utils/cues */ "./src/utils/cues.js");
1170var timeline_controller_1 = __webpack_require__(/*! ./controller/timeline-controller */ "./src/controller/timeline-controller.js");
1171var subtitle_track_controller_1 = __webpack_require__(/*! ./controller/subtitle-track-controller */ "./src/controller/subtitle-track-controller.js");
1172var subtitle_stream_controller_1 = __webpack_require__(/*! ./controller/subtitle-stream-controller */ "./src/controller/subtitle-stream-controller.js");
1173var eme_controller_1 = __webpack_require__(/*! ./controller/eme-controller */ "./src/controller/eme-controller.js");
1174var mediakeys_helper_1 = __webpack_require__(/*! ./utils/mediakeys-helper */ "./src/utils/mediakeys-helper.js");
1175exports.hlsDefaultConfig = {
1176    autoStartLoad: true,
1177    startPosition: -1,
1178    defaultAudioCodec: undefined,
1179    debug: false,
1180    capLevelOnFPSDrop: false,
1181    capLevelToPlayerSize: false,
1182    initialLiveManifestSize: 1,
1183    maxBufferLength: 30,
1184    maxBufferSize: 60 * 1000 * 1000,
1185    maxBufferHole: 0.5,
1186    lowBufferWatchdogPeriod: 0.5,
1187    highBufferWatchdogPeriod: 3,
1188    nudgeOffset: 0.1,
1189    nudgeMaxRetry: 3,
1190    maxFragLookUpTolerance: 0.25,
1191    liveSyncDurationCount: 3,
1192    liveMaxLatencyDurationCount: Infinity,
1193    liveSyncDuration: undefined,
1194    liveMaxLatencyDuration: undefined,
1195    liveDurationInfinity: false,
1196    liveBackBufferLength: Infinity,
1197    maxMaxBufferLength: 600,
1198    enableWorker: true,
1199    enableSoftwareAES: true,
1200    manifestLoadingTimeOut: 10000,
1201    manifestLoadingMaxRetry: 1,
1202    manifestLoadingRetryDelay: 1000,
1203    manifestLoadingMaxRetryTimeout: 64000,
1204    startLevel: undefined,
1205    levelLoadingTimeOut: 10000,
1206    levelLoadingMaxRetry: 4,
1207    levelLoadingRetryDelay: 1000,
1208    levelLoadingMaxRetryTimeout: 64000,
1209    fragLoadingTimeOut: 20000,
1210    fragLoadingMaxRetry: 6,
1211    fragLoadingRetryDelay: 1000,
1212    fragLoadingMaxRetryTimeout: 64000,
1213    startFragPrefetch: false,
1214    fpsDroppedMonitoringPeriod: 5000,
1215    fpsDroppedMonitoringThreshold: 0.2,
1216    appendErrorMaxRetry: 3,
1217    loader: xhr_loader_1.default,
1218    // loader: FetchLoader,
1219    fLoader: undefined,
1220    pLoader: undefined,
1221    xhrSetup: undefined,
1222    licenseXhrSetup: undefined,
1223    // fetchSetup: undefined,
1224    abrController: abr_controller_1.default,
1225    bufferController: buffer_controller_1.default,
1226    capLevelController: cap_level_controller_1.default,
1227    fpsController: fps_controller_1.default,
1228    stretchShortVideoTrack: false,
1229    maxAudioFramesDrift: 1,
1230    forceKeyFrameOnDiscontinuity: true,
1231    abrEwmaFastLive: 3,
1232    abrEwmaSlowLive: 9,
1233    abrEwmaFastVoD: 3,
1234    abrEwmaSlowVoD: 9,
1235    abrEwmaDefaultEstimate: 5e5,
1236    abrBandWidthFactor: 0.95,
1237    abrBandWidthUpFactor: 0.7,
1238    abrMaxWithRealBitrate: false,
1239    maxStarvationDelay: 4,
1240    maxLoadingDelay: 4,
1241    minAutoBitrate: 0,
1242    emeEnabled: false,
1243    widevineLicenseUrl: undefined,
1244    requestMediaKeySystemAccessFunc: mediakeys_helper_1.requestMediaKeySystemAccess // used by eme-controller
1245};
1246if (true) {
1247    exports.hlsDefaultConfig.subtitleStreamController = subtitle_stream_controller_1.SubtitleStreamController;
1248    exports.hlsDefaultConfig.subtitleTrackController = subtitle_track_controller_1.default;
1249    exports.hlsDefaultConfig.timelineController = timeline_controller_1.default;
1250    exports.hlsDefaultConfig.cueHandler = Cues; // used by timeline-controller
1251    exports.hlsDefaultConfig.enableCEA708Captions = true; // used by timeline-controller
1252    exports.hlsDefaultConfig.enableWebVTT = true; // used by timeline-controller
1253    exports.hlsDefaultConfig.captionsTextTrack1Label = 'English'; // used by timeline-controller
1254    exports.hlsDefaultConfig.captionsTextTrack1LanguageCode = 'en'; // used by timeline-controller
1255    exports.hlsDefaultConfig.captionsTextTrack2Label = 'Spanish'; // used by timeline-controller
1256    exports.hlsDefaultConfig.captionsTextTrack2LanguageCode = 'es'; // used by timeline-controller
1257}
1258if (true) {
1259    exports.hlsDefaultConfig.audioStreamController = audio_stream_controller_1.default;
1260    exports.hlsDefaultConfig.audioTrackController = audio_track_controller_1.default;
1261}
1262if (true) {
1263    exports.hlsDefaultConfig.emeController = eme_controller_1.default;
1264}
1265
1266
1267/***/ }),
1268
1269/***/ "./src/controller/abr-controller.js":
1270/*!******************************************!*\
1271  !*** ./src/controller/abr-controller.js ***!
1272  \******************************************/
1273/*! no static exports found */
1274/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
1275/***/ (function(module, exports, __webpack_require__) {
1276
1277"use strict";
1278/* WEBPACK VAR INJECTION */(function(Number) {
1279/*
1280 * simple ABR Controller
1281 *  - compute next level based on last fragment bw heuristics
1282 *  - implement an abandon rules triggered if we have less than 2 frag buffered and if computed bw shows that we risk buffer stalling
1283 */
1284var __extends = (this && this.__extends) || (function () {
1285    var extendStatics = Object.setPrototypeOf ||
1286        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
1287        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
1288    return function (d, b) {
1289        extendStatics(d, b);
1290        function __() { this.constructor = d; }
1291        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
1292    };
1293})();
1294Object.defineProperty(exports, "__esModule", { value: true });
1295var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
1296var event_handler_1 = __webpack_require__(/*! ../event-handler */ "./src/event-handler.js");
1297var buffer_helper_1 = __webpack_require__(/*! ../utils/buffer-helper */ "./src/utils/buffer-helper.js");
1298var errors_1 = __webpack_require__(/*! ../errors */ "./src/errors.js");
1299var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
1300var ewma_bandwidth_estimator_1 = __webpack_require__(/*! ../utils/ewma-bandwidth-estimator */ "./src/utils/ewma-bandwidth-estimator.js");
1301var performance = window.performance;
1302var AbrController = /** @class */ (function (_super) {
1303    __extends(AbrController, _super);
1304    function AbrController(hls) {
1305        var _this = _super.call(this, hls, events_1.default.FRAG_LOADING, events_1.default.FRAG_LOADED, events_1.default.FRAG_BUFFERED, events_1.default.ERROR) || this;
1306        _this.lastLoadedFragLevel = 0;
1307        _this._nextAutoLevel = -1;
1308        _this.hls = hls;
1309        _this.timer = null;
1310        _this._bwEstimator = null;
1311        _this.onCheck = _this._abandonRulesCheck.bind(_this);
1312        return _this;
1313    }
1314    AbrController.prototype.destroy = function () {
1315        this.clearTimer();
1316        event_handler_1.default.prototype.destroy.call(this);
1317    };
1318    AbrController.prototype.onFragLoading = function (data) {
1319        var frag = data.frag;
1320        if (frag.type === 'main') {
1321            if (!this.timer) {
1322                this.fragCurrent = frag;
1323                this.timer = setInterval(this.onCheck, 100);
1324            }
1325            // lazy init of BwEstimator, rationale is that we use different params for Live/VoD
1326            // so we need to wait for stream manifest / playlist type to instantiate it.
1327            if (!this._bwEstimator) {
1328                var hls_1 = this.hls;
1329                var config = hls_1.config;
1330                var level = frag.level;
1331                var isLive = hls_1.levels[level].details.live;
1332                var ewmaFast = void 0, ewmaSlow = void 0;
1333                if (isLive) {
1334                    ewmaFast = config.abrEwmaFastLive;
1335                    ewmaSlow = config.abrEwmaSlowLive;
1336                }
1337                else {
1338                    ewmaFast = config.abrEwmaFastVoD;
1339                    ewmaSlow = config.abrEwmaSlowVoD;
1340                }
1341                this._bwEstimator = new ewma_bandwidth_estimator_1.default(hls_1, ewmaSlow, ewmaFast, config.abrEwmaDefaultEstimate);
1342            }
1343        }
1344    };
1345    AbrController.prototype._abandonRulesCheck = function () {
1346        /*
1347          monitor fragment retrieval time...
1348          we compute expected time of arrival of the complete fragment.
1349          we compare it to expected time of buffer starvation
1350        */
1351        var hls = this.hls;
1352        var video = hls.media;
1353        var frag = this.fragCurrent;
1354        if (!frag) {
1355            return;
1356        }
1357        var loader = frag.loader;
1358        var minAutoLevel = hls.minAutoLevel;
1359        // if loader has been destroyed or loading has been aborted, stop timer and return
1360        if (!loader || (loader.stats && loader.stats.aborted)) {
1361            logger_1.logger.warn('frag loader destroy or aborted, disarm abandonRules');
1362            this.clearTimer();
1363            // reset forced auto level value so that next level will be selected
1364            this._nextAutoLevel = -1;
1365            return;
1366        }
1367        var stats = loader.stats;
1368        /* only monitor frag retrieval time if
1369        (video not paused OR first fragment being loaded(ready state === HAVE_NOTHING = 0)) AND autoswitching enabled AND not lowest level (=> means that we have several levels) */
1370        if (video && stats && ((!video.paused && (video.playbackRate !== 0)) || !video.readyState) && frag.autoLevel && frag.level) {
1371            var requestDelay = performance.now() - stats.trequest, playbackRate = Math.abs(video.playbackRate);
1372            // monitor fragment load progress after half of expected fragment duration,to stabilize bitrate
1373            if (requestDelay > (500 * frag.duration / playbackRate)) {
1374                var levels = hls.levels, loadRate = Math.max(1, stats.bw ? stats.bw / 8 : stats.loaded * 1000 / requestDelay), // byte/s; at least 1 byte/s to avoid division by zero
1375                // compute expected fragment length using frag duration and level bitrate. also ensure that expected len is gte than already loaded size
1376                level = levels[frag.level], levelBitrate = level.realBitrate ? Math.max(level.realBitrate, level.bitrate) : level.bitrate, expectedLen = stats.total ? stats.total : Math.max(stats.loaded, Math.round(frag.duration * levelBitrate / 8)), pos = video.currentTime, fragLoadedDelay = (expectedLen - stats.loaded) / loadRate, bufferStarvationDelay = (buffer_helper_1.BufferHelper.bufferInfo(video, pos, hls.config.maxBufferHole).end - pos) / playbackRate;
1377                // consider emergency switch down only if we have less than 2 frag buffered AND
1378                // time to finish loading current fragment is bigger than buffer starvation delay
1379                // ie if we risk buffer starvation if bw does not increase quickly
1380                if ((bufferStarvationDelay < (2 * frag.duration / playbackRate)) && (fragLoadedDelay > bufferStarvationDelay)) {
1381                    var fragLevelNextLoadedDelay = void 0, nextLoadLevel = void 0;
1382                    // lets iterate through lower level and try to find the biggest one that could avoid rebuffering
1383                    // we start from current level - 1 and we step down , until we find a matching level
1384                    for (nextLoadLevel = frag.level - 1; nextLoadLevel > minAutoLevel; nextLoadLevel--) {
1385                        // compute time to load next fragment at lower level
1386                        // 0.8 : consider only 80% of current bw to be conservative
1387                        // 8 = bits per byte (bps/Bps)
1388                        var levelNextBitrate = levels[nextLoadLevel].realBitrate ? Math.max(levels[nextLoadLevel].realBitrate, levels[nextLoadLevel].bitrate) : levels[nextLoadLevel].bitrate;
1389                        fragLevelNextLoadedDelay = frag.duration * levelNextBitrate / (8 * 0.8 * loadRate);
1390                        if (fragLevelNextLoadedDelay < bufferStarvationDelay) {
1391                            // we found a lower level that be rebuffering free with current estimated bw !
1392                            break;
1393                        }
1394                    }
1395                    // only emergency switch down if it takes less time to load new fragment at lowest level instead
1396                    // of finishing loading current one ...
1397                    if (fragLevelNextLoadedDelay < fragLoadedDelay) {
1398                        logger_1.logger.warn("loading too slow, abort fragment loading and switch to level " + nextLoadLevel + ":fragLoadedDelay[" + nextLoadLevel + "]<fragLoadedDelay[" + (frag.level - 1) + "];bufferStarvationDelay:" + fragLevelNextLoadedDelay.toFixed(1) + "<" + fragLoadedDelay.toFixed(1) + ":" + bufferStarvationDelay.toFixed(1));
1399                        // force next load level in auto mode
1400                        hls.nextLoadLevel = nextLoadLevel;
1401                        // update bw estimate for this fragment before cancelling load (this will help reducing the bw)
1402                        this._bwEstimator.sample(requestDelay, stats.loaded);
1403                        // abort fragment loading
1404                        loader.abort();
1405                        // stop abandon rules timer
1406                        this.clearTimer();
1407                        hls.trigger(events_1.default.FRAG_LOAD_EMERGENCY_ABORTED, { frag: frag, stats: stats });
1408                    }
1409                }
1410            }
1411        }
1412    };
1413    AbrController.prototype.onFragLoaded = function (data) {
1414        var frag = data.frag;
1415        if (frag.type === 'main' && Number.isFinite(frag.sn)) {
1416            // stop monitoring bw once frag loaded
1417            this.clearTimer();
1418            // store level id after successful fragment load
1419            this.lastLoadedFragLevel = frag.level;
1420            // reset forced auto level value so that next level will be selected
1421            this._nextAutoLevel = -1;
1422            // compute level average bitrate
1423            if (this.hls.config.abrMaxWithRealBitrate) {
1424                var level = this.hls.levels[frag.level];
1425                var loadedBytes = (level.loaded ? level.loaded.bytes : 0) + data.stats.loaded;
1426                var loadedDuration = (level.loaded ? level.loaded.duration : 0) + data.frag.duration;
1427                level.loaded = { bytes: loadedBytes, duration: loadedDuration };
1428                level.realBitrate = Math.round(8 * loadedBytes / loadedDuration);
1429            }
1430            // if fragment has been loaded to perform a bitrate test,
1431            if (data.frag.bitrateTest) {
1432                var stats = data.stats;
1433                stats.tparsed = stats.tbuffered = stats.tload;
1434                this.onFragBuffered(data);
1435            }
1436        }
1437    };
1438    AbrController.prototype.onFragBuffered = function (data) {
1439        var stats = data.stats;
1440        var frag = data.frag;
1441        // only update stats on first frag buffering
1442        // if same frag is loaded multiple times, it might be in browser cache, and loaded quickly
1443        // and leading to wrong bw estimation
1444        // on bitrate test, also only update stats once (if tload = tbuffered == on FRAG_LOADED)
1445        if (stats.aborted !== true && frag.type === 'main' && Number.isFinite(frag.sn) && ((!frag.bitrateTest || stats.tload === stats.tbuffered))) {
1446            // use tparsed-trequest instead of tbuffered-trequest to compute fragLoadingProcessing; rationale is that  buffer appending only happens once media is attached
1447            // in case we use config.startFragPrefetch while media is not attached yet, fragment might be parsed while media not attached yet, but it will only be buffered on media attached
1448            // as a consequence it could happen really late in the process. meaning that appending duration might appears huge ... leading to underestimated throughput estimation
1449            var fragLoadingProcessingMs = stats.tparsed - stats.trequest;
1450            logger_1.logger.log("latency/loading/parsing/append/kbps:" + Math.round(stats.tfirst - stats.trequest) + "/" + Math.round(stats.tload - stats.tfirst) + "/" + Math.round(stats.tparsed - stats.tload) + "/" + Math.round(stats.tbuffered - stats.tparsed) + "/" + Math.round(8 * stats.loaded / (stats.tbuffered - stats.trequest)));
1451            this._bwEstimator.sample(fragLoadingProcessingMs, stats.loaded);
1452            stats.bwEstimate = this._bwEstimator.getEstimate();
1453            // if fragment has been loaded to perform a bitrate test, (hls.startLevel = -1), store bitrate test delay duration
1454            if (frag.bitrateTest) {
1455                this.bitrateTestDelay = fragLoadingProcessingMs / 1000;
1456            }
1457            else {
1458                this.bitrateTestDelay = 0;
1459            }
1460        }
1461    };
1462    AbrController.prototype.onError = function (data) {
1463        // stop timer in case of frag loading error
1464        switch (data.details) {
1465            case errors_1.ErrorDetails.FRAG_LOAD_ERROR:
1466            case errors_1.ErrorDetails.FRAG_LOAD_TIMEOUT:
1467                this.clearTimer();
1468                break;
1469            default:
1470                break;
1471        }
1472    };
1473    AbrController.prototype.clearTimer = function () {
1474        clearInterval(this.timer);
1475        this.timer = null;
1476    };
1477    Object.defineProperty(AbrController.prototype, "nextAutoLevel", {
1478        // return next auto level
1479        get: function () {
1480            var forcedAutoLevel = this._nextAutoLevel;
1481            var bwEstimator = this._bwEstimator;
1482            // in case next auto level has been forced, and bw not available or not reliable, return forced value
1483            if (forcedAutoLevel !== -1 && (!bwEstimator || !bwEstimator.canEstimate())) {
1484                return forcedAutoLevel;
1485            }
1486            // compute next level using ABR logic
1487            var nextABRAutoLevel = this._nextABRAutoLevel;
1488            // if forced auto level has been defined, use it to cap ABR computed quality level
1489            if (forcedAutoLevel !== -1) {
1490                nextABRAutoLevel = Math.min(forcedAutoLevel, nextABRAutoLevel);
1491            }
1492            return nextABRAutoLevel;
1493        },
1494        set: function (nextLevel) {
1495            this._nextAutoLevel = nextLevel;
1496        },
1497        enumerable: true,
1498        configurable: true
1499    });
1500    Object.defineProperty(AbrController.prototype, "_nextABRAutoLevel", {
1501        get: function () {
1502            var hls = this.hls, maxAutoLevel = hls.maxAutoLevel, levels = hls.levels, config = hls.config, minAutoLevel = hls.minAutoLevel;
1503            var video = hls.media, currentLevel = this.lastLoadedFragLevel, currentFragDuration = this.fragCurrent ? this.fragCurrent.duration : 0, pos = (video ? video.currentTime : 0), 
1504            // playbackRate is the absolute value of the playback rate; if video.playbackRate is 0, we use 1 to load as
1505            // if we're playing back at the normal rate.
1506            playbackRate = ((video && (video.playbackRate !== 0)) ? Math.abs(video.playbackRate) : 1.0), avgbw = this._bwEstimator ? this._bwEstimator.getEstimate() : config.abrEwmaDefaultEstimate, 
1507            // bufferStarvationDelay is the wall-clock time left until the playback buffer is exhausted.
1508            bufferStarvationDelay = (buffer_helper_1.BufferHelper.bufferInfo(video, pos, config.maxBufferHole).end - pos) / playbackRate;
1509            // First, look to see if we can find a level matching with our avg bandwidth AND that could also guarantee no rebuffering at all
1510            var bestLevel = this._findBestLevel(currentLevel, currentFragDuration, avgbw, minAutoLevel, maxAutoLevel, bufferStarvationDelay, config.abrBandWidthFactor, config.abrBandWidthUpFactor, levels);
1511            if (bestLevel >= 0) {
1512                return bestLevel;
1513            }
1514            else {
1515                logger_1.logger.trace('rebuffering expected to happen, lets try to find a quality level minimizing the rebuffering');
1516                // not possible to get rid of rebuffering ... let's try to find level that will guarantee less than maxStarvationDelay of rebuffering
1517                // if no matching level found, logic will return 0
1518                var maxStarvationDelay = currentFragDuration ? Math.min(currentFragDuration, config.maxStarvationDelay) : config.maxStarvationDelay, bwFactor = config.abrBandWidthFactor, bwUpFactor = config.abrBandWidthUpFactor;
1519                if (bufferStarvationDelay === 0) {
1520                    // in case buffer is empty, let's check if previous fragment was loaded to perform a bitrate test
1521                    var bitrateTestDelay = this.bitrateTestDelay;
1522                    if (bitrateTestDelay) {
1523                        // if it is the case, then we need to adjust our max starvation delay using maxLoadingDelay config value
1524                        // max video loading delay used in  automatic start level selection :
1525                        // in that mode ABR controller will ensure that video loading time (ie the time to fetch the first fragment at lowest quality level +
1526                        // the time to fetch the fragment at the appropriate quality level is less than ```maxLoadingDelay``` )
1527                        // cap maxLoadingDelay and ensure it is not bigger 'than bitrate test' frag duration
1528                        var maxLoadingDelay = currentFragDuration ? Math.min(currentFragDuration, config.maxLoadingDelay) : config.maxLoadingDelay;
1529                        maxStarvationDelay = maxLoadingDelay - bitrateTestDelay;
1530                        logger_1.logger.trace("bitrate test took " + Math.round(1000 * bitrateTestDelay) + "ms, set first fragment max fetchDuration to " + Math.round(1000 * maxStarvationDelay) + " ms");
1531                        // don't use conservative factor on bitrate test
1532                        bwFactor = bwUpFactor = 1;
1533                    }
1534                }
1535                bestLevel = this._findBestLevel(currentLevel, currentFragDuration, avgbw, minAutoLevel, maxAutoLevel, bufferStarvationDelay + maxStarvationDelay, bwFactor, bwUpFactor, levels);
1536                return Math.max(bestLevel, 0);
1537            }
1538        },
1539        enumerable: true,
1540        configurable: true
1541    });
1542    AbrController.prototype._findBestLevel = function (currentLevel, currentFragDuration, currentBw, minAutoLevel, maxAutoLevel, maxFetchDuration, bwFactor, bwUpFactor, levels) {
1543        for (var i = maxAutoLevel; i >= minAutoLevel; i--) {
1544            var levelInfo = levels[i];
1545            if (!levelInfo) {
1546                continue;
1547            }
1548            var levelDetails = levelInfo.details, avgDuration = levelDetails ? levelDetails.totalduration / levelDetails.fragments.length : currentFragDuration, live = levelDetails ? levelDetails.live : false, adjustedbw = void 0;
1549            // follow algorithm captured from stagefright :
1550            // https://android.googlesource.com/platform/frameworks/av/+/master/media/libstagefright/httplive/LiveSession.cpp
1551            // Pick the highest bandwidth stream below or equal to estimated bandwidth.
1552            // consider only 80% of the available bandwidth, but if we are switching up,
1553            // be even more conservative (70%) to avoid overestimating and immediately
1554            // switching back.
1555            if (i <= currentLevel) {
1556                adjustedbw = bwFactor * currentBw;
1557            }
1558            else {
1559                adjustedbw = bwUpFactor * currentBw;
1560            }
1561            var bitrate = levels[i].realBitrate ? Math.max(levels[i].realBitrate, levels[i].bitrate) : levels[i].bitrate, fetchDuration = bitrate * avgDuration / adjustedbw;
1562            logger_1.logger.trace("level/adjustedbw/bitrate/avgDuration/maxFetchDuration/fetchDuration: " + i + "/" + Math.round(adjustedbw) + "/" + bitrate + "/" + avgDuration + "/" + maxFetchDuration + "/" + fetchDuration);
1563            // if adjusted bw is greater than level bitrate AND
1564            if (adjustedbw > bitrate &&
1565                // fragment fetchDuration unknown OR live stream OR fragment fetchDuration less than max allowed fetch duration, then this level matches
1566                // 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 ...
1567                // special case to support startLevel = -1 (bitrateTest) on live streams : in that case we should not exit loop so that _findBestLevel will return -1
1568                (!fetchDuration || (live && !this.bitrateTestDelay) || fetchDuration < maxFetchDuration)) {
1569                // as we are looping from highest to lowest, this will return the best achievable quality level
1570                return i;
1571            }
1572        }
1573        // not enough time budget even with quality level 0 ... rebuffering might happen
1574        return -1;
1575    };
1576    return AbrController;
1577}(event_handler_1.default));
1578exports.default = AbrController;
1579
1580/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.js")["Number"]))
1581
1582/***/ }),
1583
1584/***/ "./src/controller/audio-stream-controller.js":
1585/*!***************************************************!*\
1586  !*** ./src/controller/audio-stream-controller.js ***!
1587  \***************************************************/
1588/*! no static exports found */
1589/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
1590/***/ (function(module, exports, __webpack_require__) {
1591
1592"use strict";
1593/* WEBPACK VAR INJECTION */(function(Number) {
1594/*
1595 * Audio Stream Controller
1596*/
1597var __extends = (this && this.__extends) || (function () {
1598    var extendStatics = Object.setPrototypeOf ||
1599        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
1600        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
1601    return function (d, b) {
1602        extendStatics(d, b);
1603        function __() { this.constructor = d; }
1604        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
1605    };
1606})();
1607Object.defineProperty(exports, "__esModule", { value: true });
1608var binary_search_1 = __webpack_require__(/*! ../utils/binary-search */ "./src/utils/binary-search.js");
1609var buffer_helper_1 = __webpack_require__(/*! ../utils/buffer-helper */ "./src/utils/buffer-helper.js");
1610var demuxer_1 = __webpack_require__(/*! ../demux/demuxer */ "./src/demux/demuxer.js");
1611var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
1612var LevelHelper = __webpack_require__(/*! ./level-helper */ "./src/controller/level-helper.js");
1613var time_ranges_1 = __webpack_require__(/*! ../utils/time-ranges */ "./src/utils/time-ranges.js");
1614var errors_1 = __webpack_require__(/*! ../errors */ "./src/errors.js");
1615var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
1616var discontinuities_1 = __webpack_require__(/*! ../utils/discontinuities */ "./src/utils/discontinuities.js");
1617var fragment_tracker_1 = __webpack_require__(/*! ./fragment-tracker */ "./src/controller/fragment-tracker.js");
1618var fragment_1 = __webpack_require__(/*! ../loader/fragment */ "./src/loader/fragment.js");
1619var base_stream_controller_1 = __webpack_require__(/*! ./base-stream-controller */ "./src/controller/base-stream-controller.js");
1620var performance = window.performance;
1621var TICK_INTERVAL = 100; // how often to tick in ms
1622var AudioStreamController = /** @class */ (function (_super) {
1623    __extends(AudioStreamController, _super);
1624    function AudioStreamController(hls, fragmentTracker) {
1625        var _this = _super.call(this, hls, events_1.default.MEDIA_ATTA
1625CHED, events_1.default.MEDIA_DETACHING, events_1.default.AUDIO_TRACKS_UPDATED, events_1.default.AUDIO_TRACK_SWITCHING, events_1.default.AUDIO_TRACK_LOADED, events_1.default.KEY_LOADED, events_1.default.FRAG_LOADED, events_1.default.FRAG_PARSING_INIT_SEGMENT, events_1.default.FRAG_PARSING_DATA, events_1.default.FRAG_PARSED, events_1.default.ERROR, events_1.default.BUFFER_RESET, events_1.default.BUFFER_CREATED, events_1.default.BUFFER_APPENDED, events_1.default.BUFFER_FLUSHED, events_1.default.INIT_PTS_FOUND) || this;
1626        _this.fragmentTracker = fragmentTracker;
1627        _this.config = hls.config;
1628        _this.audioCodecSwap = false;
1629        _this._state = base_stream_controller_1.State.STOPPED;
1630        _this.initPTS = [];
1631        _this.waitingFragment = null;
1632        _this.videoTrackCC = null;
1633        return _this;
1634    }
1635    // Signal that video PTS was found
1636    AudioStreamController.prototype.onInitPtsFound = function (data) {
1637        var demuxerId = data.id, cc = data.frag.cc, initPTS = data.initPTS;
1638        if (demuxerId === 'main') {
1639            // Always update the new INIT PTS
1640            // Can change due level switch
1641            this.initPTS[cc] = initPTS;
1642            this.videoTrackCC = cc;
1643            logger_1.logger.log("InitPTS for cc: " + cc + " found from video track: " + initPTS);
1644            // If we are waiting we need to demux/remux the waiting frag
1645            // With the new initPTS
1646            if (this.state === base_stream_controller_1.State.WAITING_INIT_PTS) {
1647                this.tick();
1648            }
1649        }
1650    };
1651    AudioStreamController.prototype.startLoad = function (startPosition) {
1652        if (this.tracks) {
1653            var lastCurrentTime = this.lastCurrentTime;
1654            this.stopLoad();
1655            this.setInterval(TICK_INTERVAL);
1656            this.fragLoadError = 0;
1657            if (lastCurrentTime > 0 && startPosition === -1) {
1658                logger_1.logger.log("audio:override startPosition with lastCurrentTime @" + lastCurrentTime.toFixed(3));
1659                this.state = base_stream_controller_1.State.IDLE;
1660            }
1661            else {
1662                this.lastCurrentTime = this.startPosition ? this.startPosition : startPosition;
1663                this.state = base_stream_controller_1.State.STARTING;
1664            }
1665            this.nextLoadPosition = this.startPosition = this.lastCurrentTime;
1666            this.tick();
1667        }
1668        else {
1669            this.startPosition = startPosition;
1670            this.state = base_stream_controller_1.State.STOPPED;
1671        }
1672    };
1673    Object.defineProperty(AudioStreamController.prototype, "state", {
1674        get: function () {
1675            return this._state;
1676        },
1677        set: function (nextState) {
1678            if (this.state !== nextState) {
1679                var previousState = this.state;
1680                this._state = nextState;
1681                logger_1.logger.log("audio stream:" + previousState + "->" + nextState);
1682            }
1683        },
1684        enumerable: true,
1685        configurable: true
1686    });
1687    AudioStreamController.prototype.doTick = function () {
1688        var pos, track, trackDetails, hls = this.hls, config = hls.config;
1689        // logger.log('audioStream:' + this.state);
1690        switch (this.state) {
1691            case base_stream_controller_1.State.ERROR:
1692            // don't do anything in error state to avoid breaking further ...
1693            case base_stream_controller_1.State.PAUSED:
1694            // don't do anything in paused state either ...
1695            case base_stream_controller_1.State.BUFFER_FLUSHING:
1696                break;
1697            case base_stream_controller_1.State.STARTING:
1698                this.state = base_stream_controller_1.State.WAITING_TRACK;
1699                this.loadedmetadata = false;
1700                break;
1701            case base_stream_controller_1.State.IDLE:
1702                var tracks = this.tracks;
1703                // audio tracks not received => exit loop
1704                if (!tracks) {
1705                    break;
1706                }
1707                // if video not attached AND
1708                // start fragment already requested OR start frag prefetch disable
1709                // exit loop
1710                // => if media not attached but start frag prefetch is enabled and start frag not requested yet, we will not exit loop
1711                if (!this.media &&
1712                    (this.startFragRequested || !config.startFragPrefetch)) {
1713                    break;
1714                }
1715                // determine next candidate fragment to be loaded, based on current position and
1716                //  end of buffer position
1717                // if we have not yet loaded any fragment, start loading from start position
1718                if (this.loadedmetadata) {
1719                    pos = this.media.currentTime;
1720                }
1721                else {
1722                    pos = this.nextLoadPosition;
1723                    if (pos === undefined) {
1724                        break;
1725                    }
1726                }
1727                var media = this.mediaBuffer ? this.mediaBuffer : this.media, videoBuffer = this.videoBuffer ? this.videoBuffer : this.media, bufferInfo = buffer_helper_1.BufferHelper.bufferInfo(media, pos, config.maxBufferHole), mainBufferInfo = buffer_helper_1.BufferHelper.bufferInfo(videoBuffer, pos, config.maxBufferHole), bufferLen = bufferInfo.len, bufferEnd_1 = bufferInfo.end, fragPrevious = this.fragPrevious, 
1728                // ensure we buffer at least config.maxBufferLength (default 30s) or config.max
vendor: 5,304 bytes, lines 1728-1800
1728MaxBufferLength (default: 600s)
1729                // whichever is smaller.
1730                // once we reach that threshold, don't buffer more than video (mainBufferInfo.len)
1731                maxConfigBuffer = Math.min(config.maxBufferLength, config.maxMaxBufferLength), maxBufLen = Math.max(maxConfigBuffer, mainBufferInfo.len), audioSwitch = this.audioSwitch, trackId = this.trackId;
1732                // if buffer length is less than maxBufLen try to load a new fragment
1733                if ((bufferLen < maxBufLen || audioSwitch) && trackId < tracks.length) {
1734                    trackDetails = tracks[trackId].details;
1735                    // if track info not retrieved yet, switch state and wait for track retrieval
1736                    if (typeof trackDetails === 'undefined') {
1737                        this.state = base_stream_controller_1.State.WAITING_TRACK;
1738                        break;
1739                    }
1740                    if (!audioSwitch && this._streamEnded(bufferInfo, trackDetails)) {
1741                        this.hls.trigger(events_1.default.BUFFER_EOS, { type: 'audio' });
1742                        this.state = base_stream_controller_1.State.ENDED;
1743                        return;
1744                    }
1745                    // find fragment index, contiguous with end of buffer position
1746                    var fragments = trackDetails.fragments, fragLen = fragments.length, start = fragments[0].start, end = fragments[fragLen - 1].start + fragments[fragLen - 1].duration, frag = void 0;
1747                    // When switching audio track, reload audio as close as possible to currentTime
1748                    if (audioSwitch) {
1749                        if (trackDetails.live && !trackDetails.PTSKnown) {
1750                            logger_1.logger.log('switching audiotrack, live stream, unknown PTS,load first fragment');
1751                            bufferEnd_1 = 0;
1752                        }
1753                        else {
1754                            bufferEnd_1 = pos;
1755                            // if currentTime (pos) is less than alt audio playlist start time, it means that alt audio is ahead of currentTime
1756                            if (trackDetails.PTSKnown && pos < start) {
1757                                // if everything is buffered from pos to start or if audio buffer upfront, let's seek to start
1758                                if (bufferInfo.end > start || bufferInfo.nextStart) {
1759                                    logger_1.logger.log('alt audio track ahead of main track, seek to start of alt audio track');
1760                                    this.media.currentTime = start + 0.05;
1761                                }
1762                                else {
1763                                    return;
1764                                }
1765                            }
1766                        }
1767                    }
1768                    if (trackDetails.initSegment && !trackDetails.initSegment.data) {
1769                        frag = trackDetails.initSegment;
1770                    } // eslint-disable-line brace-style
1771                    // if bufferEnd before start of playlist, load first fragment
1772                    else if (bufferEnd_1 <= start) {
1773                        frag = fragments[0];
1774                        if (this.videoTrackCC !== null && frag.cc !== this.videoTrackCC) {
1775                            // Ensure we find a fragment which matches the continuity of the video track
1776                            frag = discontinuities_1.findFragWithCC(fragments, this.videoTrackCC);
1777                        }
1778                        if (trackDetails.live && frag.loadIdx && frag.loadIdx === this.fragLoadIdx) {
1779                            // we just loaded this first fragment, and we are still lagging behind the start of the live playlist
1780                            // let's force seek to start
1781                            var nextBuffered = bufferInfo.nextStart ? bufferInfo.nextStart : start;
1782                            logger_1.logger.log("no alt audio available @currentTime:" + this.media.currentTime + ", seeking @" + (nextBuffered + 0.05));
1783                            this.media.currentTime = nextBuffered + 0.05;
1784                            return;
1785                        }
1786                    }
1787                    else {
1788                        var foundFrag = void 0;
1789                        var maxFragLookUpTolerance_1 = config.maxFragLookUpTolerance;
1790                        var fragNext = fragPrevious ? fragments[fragPrevious.sn - fragments[0].sn + 1] : undefined;
1791                        var fragmentWithinToleranceTest = function (candidate) {
1792                            // offset should be within fragment boundary - config.maxFragLookUpTolerance
1793                            // this is to cope with situations like
1794                            // bufferEnd = 9.991
1795                            // frag[Ø] : [0,10]
1796                            // frag[1] : [10,20]
1797                            // bufferEnd is within frag[0] range ... although what we are expecting is to return frag[1] here
1798                            //              frag start               frag start+duration
1799                            //                  |-----------------------------|
1800                            //              <--->                         <--->
1801                            //  ...--------><-----------------------------><---------....
1802                            // previous frag         matching fragment         next frag
1803                            //  return -1             return 0                 return 1
1804                            // logger.log(`level/sn/start/end/bufEnd:${level}/${candidate.sn}/${candidate.start}/${(candidate.start+candidate.duration)}/${bufferEnd}`);
1805                            // Set the lookup tolerance to be small enough to detect the current segment - ensures we don't skip over very small segments
1806                            var candidateLookupTolerance = Math.min(maxFragLookUpTolerance_1, candidate.duration);
1807                            if ((candidate.start + candidate.duration - candidateLookupTolerance) <= bufferEnd_1) {
1808                                return 1;
1809                            }
1810                            else if (candidate.start - candidateLookupTolerance > bufferEnd_1 && candidate.start) {
1811                                // if maxFragLookUpTolerance will have negative value then don't return -1 for first element
1812                                return -1;
1813                            }
1814                            return 0;
1815                        };
1816                        if (bufferEnd_1 < end) {
1817                            if (bufferEnd_1 > end - maxFragLookUpTolerance_1) {
1818                                maxFragLookUpTolerance_1 = 0;
1819                            }
1820                            // Prefer the next fragment if it's within tolerance
1821                            if (fragNext && !fragmentWithinToleranceTest(fragNext)) {
1822                                foundFrag = fragNext;
1823                            }
1824                            else {
1825                                foundFrag = binary_search_1.default.search(fragments, fragmentWithinToleranceTest);
1826                            }
1827                        }
1828                        else {
1829                            // reach end of playlist
1830                            foundFrag = fragments[fragLen - 1];
1831                        }
1832                        if (foundFrag) {
1833                            frag = foundFrag;
1834                            start = foundFrag.start;
1835                            // logger.log('find SN matching with pos:' +  bufferEnd + ':' + frag.sn);
1836                            if (fragPrevious && frag.level === fragPrevious.level && frag.sn === fragPrevious.sn) {
1837                                if (frag.sn < trackDetails.endSN) {
1838                                    frag = fragments[frag.sn + 1 - trackDetails.startSN];
1839                                    logger_1.logger.log("SN just loaded, load next one: " + frag.sn);
1840                                }
1841                                else {
1842                                    frag = null;
1843                                }
1844                            }
1845                        }
1846                    }
1847                    if (frag) {
1848                        // logger.log('      loading frag ' + i +',pos/bufEnd:' + pos.toFixed(3) + '/' + bufferEnd.toFixed(3));
1849                        if (frag.encrypted) {
1850                            logger_1.logger.log("Loading key for " + frag.sn + " of [" + trackDetails.startSN + " ," + trackDetails.endSN + "],track " + trackId);
1851                            this.state = base_stream_controller_1.State.KEY_LOADING;
1852                            hls.trigger(events_1.default.KEY_LOADING, { frag: frag });
1853                        }
1854                        else {
1855                            logger_1.logger.log("Loading " + frag.sn + ", cc: " + frag.cc + " of [" + trackDetails.startSN + " ," + trackDetails.endSN + "],track " + trackId + ", currentTime:" + pos + ",bufferEnd:" + bufferEnd_1.toFixed(3));
1856                            // only load if fragment is not loaded or if in audio switch
1857                            // we force a frag loading in audio switch as fragment tracker might not have evicted previous frags in case of quick audio switch
1858                            this.fragCurrent = frag;
1859                            if (audioSwitch || this.fragmentTracker.getState(frag) === fragment_tracker_1.FragmentState.NOT_LOADED) {
1860                                this.startFragRequested = true;
1861                                if (Number.isFinite(frag.sn)) {
1862                                    this.nextLoadPosition = frag.start + frag.duration;
1863                                }
1864                                hls.trigger(events_1.default.FRAG_LOADING, { frag: frag });
1865                                this.state = base_stream_controller_1.State.FRAG_LOADING;
1866                            }
1867                        }
1868                    }
1869                }
1870                break;
1871            case base_stream_controller_1.State.WAITING_TRACK:
1872                track = this.tracks[this.trackId];
1873                // check if playlist is already loaded
1874                if (track && track.details) {
1875                    this.state = base_stream_controller_1.State.IDLE;
1876                }
1877                break;
1878            case base_stream_controller_1.State.FRAG_LOADING_WAITING_RETRY:
1879                var now = performance.now();
1880                var retryDate = this.retryDate;
1881                media = this.media;
1882                var isSeeking = media && media.seeking;
1883                // if current time is gt than retryDate, or if media seeking let's switch to IDLE state to retry loading
1884                if (!retryDate || (now >= retryDate) || isSeeking) {
1885                    logger_1.logger.log('audioStreamController: retryDate reached, switch back to IDLE state');
1886                    this.state = base_stream_controller_1.State.IDLE;
1887                }
1888                break;
1889            case base_stream_controller_1.State.WAITING_INIT_PTS:
1890                var videoTrackCC = this.videoTrackCC;
1891                if (this.initPTS[videoTrackCC] === undefined) {
1892                    break;
1893                }
1894                // Ensure we don't get stuck in the WAITING_INIT_PTS state if the waiting frag CC doesn't match any initPTS
1895                var waitingFrag = this.waitingFragment;
1896                if (waitingFrag) {
1897                    var waitingFragCC = waitingFrag.frag.cc;
1898                    if (videoTrackCC !== waitingFragCC) {
1899                        track = this.tracks[this.trackId];
1900                        if (track.details && track.details.live) {
1901                            logger_1.logger.warn("Waiting fragment CC (" + waitingFragCC + ") does not match video track CC (" + videoTrackCC + ")");
1902                            this.waitingFragment = null;
1903                            this.state = base_stream_controller_1.State.IDLE;
1904                        }
1905                    }
1906                    else {
1907                        this.state = base_stream_controller_1.State.FRAG_LOADING;
1908                        this.onFragLoaded(this.waitingFragment);
1909                        this.waitingFragment = null;
1910                    }
1911                }
1912                else {
1913                    this.state = base_stream_controller_1.State.IDLE;
1914                }
1915                break;
1916            case base_stream_controller_1.State.STOPPED:
1917            case base_stream_controller_1.State.FRAG_LOADING:
1918            case base_stream_controller_1.State.PARSING:
1919            case base_stream_controller_1.State.PARSED:
1920            case base_stream_controller_1.State.ENDED:
1921                break;
1922            default:
1923                break;
1924        }
1925    };
1926    AudioStreamController.prototype.onMediaAttached = function (data) {
1927        var media = this.media = this.mediaBuffer = data.media;
1928        this.onvseeking = this.onMediaSeeking.bind(this);
1929        this.onvended = this.onMediaEnded.bind(this);
1930        media.addEventListener('seeking', this.onvseeking);
1931        media.addEventListener('ended', this.onvended);
1932        var config = this.config;
1933        if (this.tracks && config.autoStartLoad) {
1934            this.startLoad(config.startPosition);
1935        }
1936    };
1937    AudioStreamController.prototype.onMediaDetaching = function () {
1938        var media = this.media;
1939        if (media && media.ended) {
1940            logger_1.logger.log('MSE detaching and video ended, reset startPosition');
1941            this.startPosition = this.lastCurrentTime = 0;
1942        }
1943        // remove video listeners
1944        if (media) {
1945            media.removeEventListener('seeking', this.onvseeking);
1946            media.removeEventListener('ended', this.onvended);
1947            this.onvseeking = this.onvseeked = this.onvended = null;
1948        }
1949        this.media = this.mediaBuffer = this.videoBuffer = null;
1950        this.loadedmetadata = false;
1951        this.stopLoad();
1952    };
1953    AudioStreamController.prototype.onAudioTracksUpdated = function (data) {
1954        logger_1.logger.log('audio tracks updated');
1955        this.tracks = data.audioTracks;
1956    };
1957    AudioStreamController.prototype.onAudioTrackSwitching = function (data) {
1958        // if any URL found on new audio track, it is an alternate audio track
1959        var altAudio = !!data.url;
1960        this.trackId = data.id;
1961        this.fragCurrent = null;
1962        this.state = base_stream_controller_1.State.PAUSED;
1963        this.waitingFragment = null;
1964        // destroy useless demuxer when switching audio to main
1965        if (!altAudio) {
1966            if (this.demuxer) {
1967                this.demuxer.destroy();
1968                this.demuxer = null;
1969            }
1970        }
1971        else {
1972            // switching to audio track, start timer if not already started
1973            this.setInterval(TICK_INTERVAL);
1974        }
1975        // should we switch tracks ?
1976        if (altAudio) {
1977            this.audioSwitch = true;
1978            // main audio track are handled by stream-controller, just do something if switching to alt audio track
1979            this.state = base_stream_controller_1.State.IDLE;
1980        }
1981        this.tick();
1982    };
1983    AudioStreamController.prototype.onAudioTrackLoaded = function (data) {
1984        var newDetails = data.details, trackId = data.id, track = this.tracks[trackId], duration = newDetails.totalduration, sliding = 0;
1985        logger_1.logger.log("track " + trackId + " loaded [" + newDetails.startSN + "," + newDetails.endSN + "],duration:" + duration);
1986        if (newDetails.live) {
1987            var curDetails = track.details;
1988            if (curDetails && newDetails.fragments.length > 0) {
1989                // we already have details for that level, merge them
1990                LevelHelper.mergeDetails(curDetails, newDetails);
1991                sliding = newDetails.fragments[0].start;
1992                // TODO
1993                // this.liveSyncPosition = this.computeLivePosition(sliding, curDetails);
1994                if (newDetails.PTSKnown) {
1995                    logger_1.logger.log("live audio playlist sliding:" + sliding.toFixed(3));
1996                }
1997                else {
1998                    logger_1.logger.log('live audio playlist - outdated PTS, unknown sliding');
1999                }
2000            }
2001            else {
2002                newDetails.PTSKnown = false;
2003                logger_1.logger.log('live audio playlist - first load, unknown sliding');
2004            }
2005        }
2006        else {
2007            newDetails.PTSKnown = false;
2008        }
2009        track.details = newDetails;
2010        // compute start position
2011        if (!this.startFragRequested) {
2012            // compute start position if set to -1. use it straight away if value is defined
2013            if (this.startPosition === -1) {
2014                // first, check if start time offset has been set in playlist, if yes, use this value
2015                var startTimeOffset = newDetails.startTimeOffset;
2016                if (Number.isFinite(startTimeOffset)) {
2017                    logger_1.logger.log("start time offset found in playlist, adjust startPosition to " + startTimeOffset);
2018                    this.startPosition = startTimeOffset;
2019                }
2020                else {
2021                    this.startPosition = 0;
2022                }
2023            }
2024            this.nextLoadPosition = this.startPosition;
2025        }
2026        // only switch batck to IDLE state if we were waiting for track to start downloading a new fragment
2027        if (this.state === base_stream_controller_1.State.WAITING_TRACK) {
2028            this.state = base_stream_controller_1.State.IDLE;
2029        }
2030        // trigger handler right now
2031        this.tick();
2032    };
2033    AudioStreamController.prototype.onKeyLoaded = function () {
2034        if (this.state === base_stream_controller_1.State.KEY_LOADING) {
2035            this.state = base_stream_controller_1.State.IDLE;
2036            this.tick();
2037        }
2038    };
2039    AudioStreamController.prototype.onFragLoaded = function (data) {
2040        var fragCurrent = this.fragCurrent, fragLoaded = data.frag;
2041        if (this.state === base_stream_controller_1.State.FRAG_LOADING &&
2042            fragCurrent &&
2043            fragLoaded.type === 'audio' &&
2044            fragLoaded.level === fragCurrent.level &&
2045            fragLoaded.sn === fragCurrent.sn) {
2046            var track = this.tracks[this.trackId], details = track.details, duration = details.totalduration, trackId = fragCurrent.level, sn = fragCurrent.sn, cc = fragCurrent.cc, audioCodec = this.config.defaultAudioCodec || track.audioCodec || 'mp4a.40.2', stats = this.stats = data.stats;
2047            if (sn === 'initSegment') {
2048                this.state = base_stream_controller_1.State.IDLE;
2049                stats.tparsed = stats.tbuffered = performance.now();
2050                details.initSegment.data = data.payload;
2051                this.hls.trigger(events_1.default.FRAG_BUFFERED, { stats: stats, frag: fragCurrent, id: 'audio' });
2052                this.tick();
2053            }
2054            else {
2055                this.state = base_stream_controller_1.State.PARSING;
2056                // transmux the MPEG-TS data to ISO-BMFF segments
2057                this.appended = false;
2058                if (!this.demuxer) {
2059                    this.demuxer = new demuxer_1.default(this.hls, 'audio');
2060                }
2061                // Check if we have video initPTS
2062                // If not we need to wait for it
2063                var initPTS = this.initPTS[cc];
2064                var initSegmentData = details.initSegment ? details.initSegment.data : [];
2065                if (details.initSegment || initPTS !== undefined) {
2066                    this.pendingBuffering = true;
2067                    logger_1.logger.log("Demuxing " + sn + " of [" + details.startSN + " ," + details.endSN + "],track " + trackId);
2068                    // time Offset is accurate if level PTS is known, or if playlist is not sliding (not live)
2069                    var accurateTimeOffset = false; // details.PTSKnown || !details.live;
2070                    this.demuxer.push(data.payload, initSegmentData, audioCodec, null, fragCurrent, duration, accurateTimeOffset, initPTS);
2071                }
2072                else {
2073                    logger_1.logger.log("unknown video PTS for continuity counter " + cc + ", waiting for video PTS before demuxing audio frag " + sn + " of [" + details.startSN + " ," + details.endSN + "],track " + trackId);
2074                    this.waitingFragment = data;
2075                    this.state = base_stream_controller_1.State.WAITING_INIT_PTS;
2076                }
2077            }
2078        }
2079        this.fragLoadError = 0;
2080    };
2081    AudioStreamController.prototype.onFragParsingInitSegment = function (data) {
2082        var fragCurrent = this.fragCurrent;
2083        var fragNew = data.frag;
2084        if (fragCurrent &&
2085            data.id === 'audio' &&
2086            fragNew.sn === fragCurrent.sn &&
2087            fragNew.level === fragCurrent.level &&
2088            this.state === base_stream_controller_1.State.PARSING) {
2089            var tracks = data.tracks, track = void 0;
2090            // delete any video track found on audio demuxer
2091            if (tracks.video) {
2092                delete tracks.video;
2093            }
2094            // include levelCodec in audio and video tracks
2095            track = tracks.audio;
2096            if (track) {
2097                track.levelCodec = track.codec;
2098                track.id = data.id;
2099                this.hls.trigger(events_1.default.BUFFER_CODECS, tracks);
2100                logger_1.logger.log("audio track:audio,container:" + track.container + ",codecs[level/parsed]=[" + track.levelCodec + "/" + track.codec + "]");
2101                var initSegment = track.initSegment;
2102                if (initSegment) {
2103                    var appendObj = { type: 'audio', data: initSegment, parent: 'audio', content: 'initSegment' };
2104                    if (this.audioSwitch) {
2105                        this.pendingData = [appendObj];
2106                    }
2107                    else {
2108                        this.appended = true;
2109                        // arm pending Buffering flag before appending a segment
2110                        this.pendingBuffering = true;
2111                        this.hls.trigger(events_1.default.BUFFER_APPENDING, appendObj);
2112                    }
2113                }
2114                // trigger handler right now
2115                this.tick();
2116            }
2117        }
2118    };
2119    AudioStreamController.prototype.onFragParsingData = function (data) {
2120        var _this = this;
2121        var fragCurrent = this.fragCurrent;
2122        var fragNew = data.frag;
2123        if (fragCurrent &&
2124            data.id === 'audio' &&
2125            data.type === 'audio' &&
2126            fragNew.sn === fragCurrent.sn &&
2127            fragNew.level === fragCurrent.level &&
2128            this.state === base_stream_controller_1.State.PARSING) {
2129            var trackId = this.trackId, track = this.tracks[trackId], hls_1 = this.hls;
2130            if (!Number.isFinite(data.endPTS)) {
2131                data.endPTS = data.startPTS + fragCurrent.duration;
2132                data.endDTS = data.startDTS + fragCurrent.duration;
2133            }
2134            fragCurrent.addElementaryStream(fragment_1.default.ElementaryStreamTypes.AUDIO);
2135            logger_1.logger.log("parsed " + data.type + ",PTS:[" + data.startPTS.toFixed(3) + "," + data.endPTS.toFixed(3) + "],DTS:[" + data.startDTS.toFixed(3) + "/" + data.endDTS.toFixed(3) + "],nb:" + data.nb);
2136            LevelHelper.updateFragPTSDTS(track.details, fragCurrent, data.startPTS, data.endPTS);
2137            var audioSwitch = this.audioSwitch, media = this.media, appendOnBufferFlush = false;
2138            // Only flush audio from old audio tracks when PTS is known on new audio track
2139            if (audioSwitch && media) {
2140                if (media.readyState) {
2141                    var currentTime = media.currentTime;
2142                    logger_1.logger.log('switching audio track : currentTime:' + currentTime);
2143                    if (currentTime >= data.startPTS) {
2144                        logger_1.logger.log('switching audio track : flushing all audio');
2145                        this.state = base_stream_controller_1.State.BUFFER_FLUSHING;
2146                        hls_1.trigger(events_1.default.BUFFER_FLUSHING, { startOffset: 0, endOffset: Number.POSITIVE_INFINITY, type: 'audio' });
2147                        appendOnBufferFlush = true;
2148                        // Lets announce that the initial audio track switch flush occur
2149                        this.audioSwitch = false;
2150                        hls_1.trigger(events_1.default.AUDIO_TRACK_SWITCHED, { id: trackId });
2151                    }
2152                }
2153                else {
2154                    // Lets announce that the initial audio track switch flush occur
2155                    this.audioSwitch = false;
2156                    hls_1.trigger(events_1.default.AUDIO_TRACK_SWITCHED, { id: trackId });
2157                }
2158            }
2159            var pendingData_1 = this.pendingData;
2160            if (!pendingData_1) {
2161                logger_1.logger.warn('Apparently attempt to enqueue media payload without codec initialization data upfront');
2162                hls_1.trigger(events_1.default.ERROR, { type: errors_1.ErrorTypes.MEDIA_ERROR, details: null, fatal: true });
2163                return;
2164            }
2165            if (!this.audioSwitch) {
2166                [data.data1, data.data2].forEach(function (buffer) {
2167                    if (buffer && buffer.length) {
2168                        pendingData_1.push({ type: data.type, data: buffer, parent: 'audio', content: 'data' });
2169                    }
2170                });
2171                if (!appendOnBufferFlush && pendingData_1.length) {
2172                    pendingData_1.forEach(function (appendObj) {
2173                        // only append in PARSING state (rationale is that an appending error could happen synchronously on first segment appending)
2174                        // in that case it is useless to append following segments
2175                        if (_this.state === base_stream_controller_1.State.PARSING) {
2176                            // arm pending Buffering flag before appending a segment
2177                            _this.pendingBuffering = true;
2178                            _this.hls.trigger(events_1.default.BUFFER_APPENDING, appendObj);
2179                        }
2180                    });
2181                    this.pendingData = [];
2182                    this.appended = true;
2183                }
2184            }
2185            // trigger handler right now
2186            this.tick();
2187        }
2188    };
2189    AudioStreamController.prototype.onFragParsed = function (data) {
2190        var fragCurrent = this.fragCurrent;
2191        var fragNew = data.frag;
2192        if (fragCurrent &&
2193            data.id === 'audio' &&
2194            fragNew.sn === fragCurrent.sn &&
2195            fragNew.level === fragCurrent.level &&
2196            this.state === base_stream_controller_1.State.PARSING) {
2197            this.stats.tparsed = performance.now();
2198            this.state = base_stream_controller_1.State.PARSED;
2199            this._checkAppendedParsed();
2200        }
2201    };
2202    AudioStreamController.prototype.onBufferReset = function () {
2203        // reset reference to sourcebuffers
2204        this.mediaBuffer = this.videoBuffer = null;
2205        this.loadedmetadata = false;
2206    };
2207    AudioStreamController.prototype.onBufferCreated = function (data) {
2208        var audioTrack = data.tracks.audio;
2209        if (audioTrack) {
2210            this.mediaBuffer = audioTrack.buffer;
2211            this.loadedmetadata = true;
2212        }
2213        if (data.tracks.video) {
2214            this.videoBuffer = data.tracks.video.buffer;
2215        }
2216    };
2217    AudioStreamController.prototype.onBufferAppended = function (data) {
2218        if (data.parent === 'audio') {
2219            var state = this.state;
2220            if (state === base_stream_controller_1.State.PARSING || state === base_stream_controller_1.State.PARSED) {
2221                // check if all buffers have been appended
2222                this.pendingBuffering = (data.pending > 0);
2223                this._checkAppendedParsed();
2224            }
2225        }
2226    };
2227    AudioStreamController.prototype._checkAppendedParsed = function () {
2228        // trigger handler right now
2229        if (this.state === base_stream_controller_1.State.PARSED && (!this.appended || !this.pendingBuffering)) {
2230            var frag = this.fragCurrent, stats = this.stats, hls_2 = this.hls;
2231            if (frag) {
2232                this.fragPrevious = frag;
2233                stats.tbuffered = performance.now();
2234                hls_2.trigger(events_1.default.FRAG_BUFFERED, { stats: stats, frag: frag, id: 'audio' });
2235                var media = this.mediaBuffer ? this.mediaBuffer : this.media;
2236                logger_1.logger.log("audio buffered : " + time_ranges_1.default.toString(media.buffered));
2237                if (this.audioSwitch && this.appended) {
2238                    this.audioSwitch = false;
2239                    hls_2.trigger(events_1.default.AUDIO_TRACK_SWITCHED, { id: this.trackId });
2240                }
2241                this.state = base_stream_controller_1.State.IDLE;
2242            }
2243            this.tick();
2244        }
2245    };
2246    AudioStreamController.prototype.onError = function (data) {
2247        var frag = data.frag;
2248        // don't handle frag error not related to audio fragment
2249        if (frag && frag.type !== 'audio') {
2250            return;
2251        }
2252        switch (data.details) {
2253            case errors_1.ErrorDetails.FRAG_LOAD_ERROR:
2254            case errors_1.ErrorDetails.FRAG_LOAD_TIMEOUT:
2255                var frag_1 = data.frag;
2256                // don't handle frag error not related to audio fragment
2257                if (frag_1 && frag_1.type !== 'audio') {
2258                    break;
2259                }
2260                if (!data.fatal) {
2261                    var loadError = this.fragLoadError;
2262                    if (loadError) {
2263                        loadError++;
2264                    }
2265                    else {
2266                        loadError = 1;
2267                    }
2268                    var config = this.config;
2269                    if (loadError <= config.fragLoadingMaxRetry) {
2270                        this.fragLoadError = loadError;
2271                        // exponential backoff capped to config.fragLoadingMaxRetryTimeout
2272                        var delay = Math.min(Math.pow(2, loadError - 1) * config.fragLoadingRetryDelay, config.fragLoadingMaxRetryTimeout);
2273                        logger_1.logger.warn("AudioStreamController: frag loading failed, retry in " + delay + " ms");
2274                        this.retryDate = performance.now() + delay;
2275                        // retry loading state
2276                        this.state = base_stream_controller_1.State.FRAG_LOADING_WAITING_RETRY;
2277                    }
2278                    else {
2279                        logger_1.logger.error("AudioStreamController: " + data.details + " reaches max retry, redispatch as fatal ...");
2280                        // switch error to fatal
2281                        data.fatal = true;
2282                        this.state = base_stream_controller_1.State.ERROR;
2283                    }
2284                }
2285                break;
2286            case errors_1.ErrorDetails.AUDIO_TRACK_LOAD_ERROR:
2287            case errors_1.ErrorDetails.AUDIO_TRACK_LOAD_TIMEOUT:
2288            case errors_1.ErrorDetails.KEY_LOAD_ERROR:
2289            case errors_1.ErrorDetails.KEY_LOAD_TIMEOUT:
2290                //  when in ERROR state, don't switch back to IDLE state in case a non-fatal error is received
2291                if (this.state !== base_stream_controller_1.State.ERROR) {
2292                    // if fatal error, stop processing, otherwise move to IDLE to retry loading
2293                    this.state = data.fatal ? base_stream_controller_1.State.ERROR : base_stream_controller_1.State.IDLE;
2294                    logger_1.logger.warn("AudioStreamController: " + data.details + " while loading frag, now switching to " + this.state + " state ...");
2295                }
2296                break;
2297            case errors_1.ErrorDetails.BUFFER_FULL_ERROR:
2298                // if in appending state
2299                if (data.parent === 'audio' && (this.state === base_stream_controller_1.State.PARSING || this.state === base_stream_controller_1.State.PARSED)) {
2300                    var media = this.mediaBuffer, currentTime = this.media.currentTime, mediaBuffered = media && buffer_helper_1.BufferHelper.isBuffered(media, currentTime) && buffer_helper_1.BufferHelper.isBuffered(media, currentTime + 0.5);
2301                    // reduce max buf len if current position is buffered
2302                    if (mediaBuffered) {
2303                        var config = this.config;
2304                        if (config.maxMaxBufferLength >= config.maxBufferLength) {
2305                            // reduce max buffer length as it might be too high. we do this to avoid loop flushing ...
2306                            config.maxMaxBufferLength /= 2;
2307                            logger_1.logger.warn("AudioStreamController: reduce max buffer length to " + config.max
2307MaxBufferLength + "s");
2308                        }
2309                        this.state = base_stream_controller_1.State.IDLE;
2310                    }
2311                    else {
2312                        // current position is not buffered, but browser is still complaining about buffer full error
2313                        // this happens on IE/Edge, refer to https://github.com/video-dev/hls.js/pull/708
2314                        // in that case flush the whole audio buffer to recover
2315                        logger_1.logger.warn('AudioStreamController: buffer full error also media.currentTime is not buffered, flush audio buffer');
2316                        this.fragCurrent = null;
2317                        // flush everything
2318                        this.state = base_stream_controller_1.State.BUFFER_FLUSHING;
2319                        this.hls.trigger(events_1.default.BUFFER_FLUSHING, { startOffset: 0, endOffset: Number.POSITIVE_INFINITY, type: 'audio' });
2320                    }
2321                }
2322                break;
2323            default:
2324                break;
2325        }
2326    };
2327    AudioStreamController.prototype.onBufferFlushed = function () {
2328        var _this = this;
2329        var pendingData = this.pendingData;
2330        if (pendingData && pendingData.length) {
2331            logger_1.logger.log('AudioStreamController: appending pending audio data after buffer flushed');
2332            pendingData.forEach(function (appendObj) {
2333                _this.hls.trigger(events_1.default.BUFFER_APPENDING, appendObj);
2334            });
2335            this.appended = true;
2336            this.pendingData = [];
2337            this.state = base_stream_controller_1.State.PARSED;
2338        }
2339        else {
2340            // move to IDLE once flush complete. this should trigger new fragment loading
2341            this.state = base_stream_controller_1.State.IDLE;
2342            // reset reference to frag
2343            this.fragPrevious = null;
2344            this.tick();
2345        }
2346    };
2347    return AudioStreamController;
2348}(base_stream_controller_1.default));
2349exports.default = AudioStreamController;
2350
2351/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.js")["Number"]))
2352
2353/***/ }),
2354
2355/***/ "./src/controller/audio-track-controller.js":
2356/*!**************************************************!*\
2357  !*** ./src/controller/audio-track-controller.js ***!
2358  \**************************************************/
2359/*! no static exports found */
2360/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
2361/***/ (function(module, exports, __webpack_require__) {
2362
2363"use strict";
2364
2365var __extends = (this && this.__extends) || (function () {
2366    var extendStatics = Object.setPrototypeOf ||
2367        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
2368        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
2369    return function (d, b) {
2370        extendStatics(d, b);
2371        function __() { this.constructor = d; }
2372        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
2373    };
2374})();
2375Object.defineProperty(exports, "__esModule", { value: true });
2376var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
2377var task_loop_1 = __webpack_require__(/*! ../task-loop */ "./src/task-loop.js");
2378var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
2379var errors_1 = __webpack_require__(/*! ../errors */ "./src/errors.js");
2380/**
2381 * @class AudioTrackController
2382 * @implements {EventHandler}
2383 *
2384 * Handles main manifest and audio-track metadata loaded,
2385 * owns and exposes the selectable audio-tracks data-models.
2386 *
2387 * Exposes internal interface to select available audio-tracks.
2388 *
2389 * Handles errors on loading audio-track playlists. Manages fallback mechanism
2390 * with redundants tracks (group-IDs).
2391 *
2392 * Handles level-loading and group-ID switches for video (fallback on video levels),
2393 * and eventually adapts the audio-track group-ID to match.
2394 *
2395 * @fires AUDIO_TRACK_LOADING
2396 * @fires AUDIO_TRACK_SWITCHING
2397 * @fires AUDIO_TRACKS_UPDATED
2398 * @fires ERROR
2399 *
2400 */
2401var AudioTrackController = /** @class */ (function (_super) {
2402    __extends(AudioTrackController, _super);
2403    function AudioTrackController(hls) {
2404        var _this = _super.call(this, hls, events_1.default.MANIFEST_LOADING, events_1.default.MANIFEST_PARSED, events_1.default.AUDIO_TRACK_LOADED, events_1.default.AUDIO_TRACK_SWITCHED, events_1.default.LEVEL_LOADED, events_1.default.ERROR) || this;
2405        /**
2406         * @private
2407         * Currently selected index in `tracks`
2408         * @member {number} trackId
2409         */
2410        _this._trackId = -1;
2411        /**
2412         * @private
2413         * If should select tracks according to default track attribute
2414         * @member {boolean} _selectDefaultTrack
2415         */
2416        _this._selectDefaultTrack = true;
2417        /**
2418         * @public
2419         * All tracks available
2420         * @member {AudioTrack[]}
2421         */
2422        _this.tracks = [];
2423        /**
2424         * @public
2425         * List of blacklisted audio track IDs (that have caused failure)
2426         * @member {number[]}
2427         */
2428        _this.trackIdBlacklist = Object.create(null);
2429        /**
2430         * @public
2431         * The currently running group ID for audio
2432         * (we grab this on manifest-parsed and new level-loaded)
2433         * @member {string}
2434         */
2435        _this.audioGroupId = null;
2436        return _this;
2437    }
2438    /**
2439     * Reset audio tracks on new manifest loading.
2440     */
2441    AudioTrackController.prototype.onManifestLoading = function () {
2442        this.tracks = [];
2443        this._trackId = -1;
2444        this._selectDefaultTrack = true;
2445    };
2446    /**
2447     * Store tracks data from manifest parsed data.
2448     *
2449     * Trigger AUDIO_TRACKS_UPDATED event.
2450     *
2451     * @param {*} data
2452     */
2453    AudioTrackController.prototype.onManifestParsed = function (data) {
2454        var tracks = this.tracks = data.audioTracks || [];
2455        this.hls.trigger(events_1.default.AUDIO_TRACKS_UPDATED, { audioTracks: tracks });
2456    };
2457    /**
2458     * Store track details of loaded track in our data-model.
2459     *
2460     * Set-up metadata update interval task for live-mode streams.
2461     *
2462     * @param {} data
2463     */
2464    AudioTrackController.prototype.onAudioTrackLoaded = function (data) {
2465        if (data.id >= this.tracks.length) {
2466            logger_1.logger.warn('Invalid audio track id:', data.id);
2467            return;
2468        }
2469        logger_1.logger.log("audioTrack " + data.id + " loaded");
2470        this.tracks[data.id].details = data.details;
2471        // check if current playlist is a live playlist
2472        // and if we have already our reload interval setup
2473        if (data.details.live && !this.hasInterval()) {
2474            // if live playlist we will have to reload it periodically
2475            // set reload period to playlist target duration
2476            var updatePeriodMs = data.details.targetduration * 1000;
2477            this.setInterval(updatePeriodMs);
2478        }
2479        if (!data.details.live && this.hasInterval()) {
2480            // playlist is not live and timer is scheduled: cancel it
2481            this.clearInterval();
2482        }
2483    };
2484    /**
2485     * Update the internal group ID to any audio-track we may have set manually
2486     * or because of a failure-handling fallback.
2487     *
2488     * Quality-levels should update to that group ID in this case.
2489     *
2490     * @param {*} data
2491     */
2492    AudioTrackController.prototype.onAudioTrackSwitched = function (data) {
2493        var audioGroupId = this.tracks[data.id].groupId;
2494        if (audioGroupId && (this.audioGroupId !== audioGroupId)) {
2495            this.audioGroupId = audioGroupId;
2496        }
2497    };
2498    /**
2499     * When a level gets loaded, if it has redundant audioGroupIds (in the same ordinality as it's redundant URLs)
2500     * we are setting our audio-group ID internally to the one set, if it is different from the group ID currently set.
2501     *
2502     * If group-ID got update, we re-select the appropriate audio-track with this group-ID matching the currently
2503     * selected one (based on NAME property).
2504     *
2505     * @param {*} data
2506     */
2507    AudioTrackController.prototype.onLevelLoaded = function (data) {
2508        // FIXME: crashes because currentLevel is undefined
2509        // const levelInfo = this.hls.levels[this.hls.currentLevel];
2510        var levelInfo = this.hls.levels[data.level];
2511        if (!levelInfo.audioGroupIds) {
2512            return;
2513        }
2514        var audioGroupId = levelInfo.audioGroupIds[levelInfo.urlId];
2515        if (this.audioGroupId !== audioGroupId) {
2516            this.audioGroupId = audioGroupId;
2517            this._selectInitialAudioTrack();
2518        }
2519    };
2520    /**
2521     * Handle network errors loading audio track manifests
2522     * and also pausing on any netwok errors.
2523     *
2524     * @param {ErrorEventData} data
2525     */
2526    AudioTrackController.prototype.onError = function (data) {
2527        // Only handle network errors
2528        if (data.type !== errors_1.ErrorTypes.NETWORK_ERROR) {
2529            return;
2530        }
2531        // If fatal network error, cancel update task
2532        if (data.fatal) {
2533            this.clearInterval();
2534        }
2535        // If not an audio-track loading error don't handle further
2536        if (data.details !== errors_1.ErrorDetails.AUDIO_TRACK_LOAD_ERROR) {
2537            return;
2538        }
2539        logger_1.logger.warn('Network failure on audio-track id:', data.context.id);
2540        this._handleLoadError();
2541    };
2542    Object.defineProperty(AudioTrackController.prototype, "audioTracks", {
2543        /**
2544         * @type {AudioTrack[]} Audio-track list we own
2545         */
2546        get: function () {
2547            return this.tracks;
2548        },
2549        enumerable: true,
2550        configurable: true
2551    });
2552    Object.defineProperty(AudioTrackController.prototype, "audioTrack", {
2553        /**
2554         * @type {number} Index into audio-tracks list of currently selected track.
2555         */
2556        get: function () {
2557            return this._trackId;
2558        },
2559        /**
2560         * Select current track by index
2561         */
2562        set: function (newId) {
2563            this._setAudioTrack(newId);
2564            // If audio track is selected from API then don't choose from the manifest default track
2565            this._selectDefaultTrack = false;
2566        },
2567        enumerable: true,
2568        configurable: true
2569    });
2570    /**
2571     * @private
2572     * @param {number} newId
2573     */
2574    AudioTrackController.prototype._setAudioTrack = function (newId) {
2575        // noop on same audio track id as already set
2576        if (this._trackId === newId && this.tracks[this._trackId].details) {
2577            logger_1.logger.debug('Same id as current audio-track passed, and track details available -> no-op');
2578            return;
2579        }
2580        // check if level idx is valid
2581        if (newId < 0 || newId >= this.tracks.length) {
2582            logger_1.logger.warn('Invalid id passed to audio-track controller');
2583            return;
2584        }
2585        var audioTrack = this.tracks[newId];
2586        logger_1.logger.log("Now switching to audio-track index " + newId);
2587        // stopping live reloading timer if any
2588        this.clearInterval();
2589        this._trackId = newId;
2590        var url = audioTrack.url, type = audioTrack.type, id = audioTrack.id;
2591        this.hls.trigger(events_1.default.AUDIO_TRACK_SWITCHING, { id: id, type: type, url: url });
2592        this._loadTrackDetailsIfNeeded(audioTrack);
2593    };
2594    /**
2595     * @override
2596     */
2597    AudioTrackController.prototype.doTick = function () {
2598        this._updateTrack(this._trackId);
2599    };
2600    /**
2601     * Select initial track
2602     * @private
2603     */
2604    AudioTrackController.prototype._selectInitialAudioTrack = function () {
2605        var _this = this;
2606        var tracks = this.tracks;
2607        if (!tracks.length) {
2608            return;
2609        }
2610        var currentAudioTrack = this.tracks[this._trackId];
2611        var name = null;
2612        if (currentAudioTrack) {
2613            name = currentAudioTrack.name;
2614        }
2615        // Pre-select default tracks if there are any
2616        if (this._selectDefaultTrack) {
2617            var defaultTracks = tracks.filter(function (track) { return track.default; });
2618            if (defaultTracks.length) {
2619                tracks = defaultTracks;
2620            }
2621            else {
2622                logger_1.logger.warn('No default audio tracks defined');
2623            }
2624        }
2625        var trackFound = false;
2626        var traverseTracks = function () {
2627            // Select track with right group ID
2628            tracks.forEach(function (track) {
2629                if (trackFound) {
2630                    return;
2631                }
2632                // We need to match the (pre-)selected group ID
2633                // and the NAME of the current track.
2634                if ((!_this.audioGroupId || track.groupId === _this.audioGroupId) &&
2635                    (!name || name === track.name)) {
2636                    // If there was a previous track try to stay with the same `NAME`.
2637                    // It should be unique across tracks of same group, and consistent through redundant track groups.
2638                    _this._setAudioTrack(track.id);
2639                    trackFound = true;
2640                }
2641            });
2642        };
2643        traverseTracks();
2644        if (!trackFound) {
2645            name = null;
2646            traverseTracks();
2647        }
2648        if (!trackFound) {
2649            logger_1.logger.error("No track found for running audio group-ID: " + this.audioGroupId);
2650            this.hls.trigger(events_1.default.ERROR, {
2651                type: errors_1.ErrorTypes.MEDIA_ERROR,
2652                details: errors_1.ErrorDetails.AUDIO_TRACK_LOAD_ERROR,
2653                fatal: true
2654            });
2655        }
2656    };
2657    /**
2658     * @private
2659     * @param {AudioTrack} audioTrack
2660     * @returns {boolean}
2661     */
2662    AudioTrackController.prototype._needsTrackLoading = function (audioTrack) {
2663        var details = audioTrack.details, url = audioTrack.url;
2664        if (!details || details.live) {
2665            // check if we face an audio track embedded in main playlist (audio track without URI attribute)
2666            return !!url;
2667        }
2668        return false;
2669    };
2670    /**
2671     * @private
2672     * @param {AudioTrack} audioTrack
2673     */
2674    AudioTrackController.prototype._loadTrackDetailsIfNeeded = function (audioTrack) {
2675        if (this._needsTrackLoading(audioTrack)) {
2676            var url = audioTrack.url, id = audioTrack.id;
2677            // track not retrieved yet, or live playlist we need to (re)load it
2678            logger_1.logger.log("loading audio-track playlist for id: " + id);
2679            this.hls.trigger(events_1.default.AUDIO_TRACK_LOADING, { url: url, id: id });
2680        }
2681    };
2682    /**
2683     * @private
2684     * @param {number} newId
2685     */
2686    AudioTrackController.prototype._updateTrack = function (newId) {
2687        // check if level idx is valid
2688        if (newId < 0 || newId >= this.tracks.length) {
2689            return;
2690        }
2691        // stopping live reloading timer if any
2692        this.clearInterval();
2693        this._trackId = newId;
2694        logger_1.logger.log("trying to update audio-track " + newId);
2695        var audioTrack = this.tracks[newId];
2696        this._loadTrackDetailsIfNeeded(audioTrack);
2697    };
2698    /**
2699     * @private
2700     */
2701    AudioTrackController.prototype._handleLoadError = function () {
2702        // First, let's black list current track id
2703        this.trackIdBlacklist[this._trackId] = true;
2704        // Let's try to fall back on a functional audio-track with the same group ID
2705        var previousId = this._trackId;
2706        var _a = this.tracks[previousId], name = _a.name, language = _a.language, groupId = _a.groupId;
2707        logger_1.logger.warn("Loading failed on audio track id: " + previousId + ", group-id: " + groupId + ", name/language: \"" + name + "\" / \"" + language + "\"");
2708        // Find a non-blacklisted track ID with the same NAME
2709        // At least a track that is not blacklisted, thus on another group-ID.
2710        var newId = previousId;
2711        for (var i = 0; i < this.tracks.length; i++) {
2712            if (this.trackIdBlacklist[i]) {
2713                continue;
2714            }
2715            var newTrack = this.tracks[i];
2716            if (newTrack.name === name) {
2717                newId = i;
2718                break;
2719            }
2720        }
2721        if (newId === previousId) {
2722            logger_1.logger.warn("No fallback audio-track found for name/language: \"" + name + "\" / \"" + language + "\"");
2723            return;
2724        }
2725        logger_1.logger.log('Attempting audio-track fallback id:', newId, 'group-id:', this.tracks[newId].groupId);
2726        this._setAudioTrack(newId);
2727    };
2728    return AudioTrackController;
2729}(task_loop_1.default));
2730exports.default = AudioTrackController;
2731
2732
2733/***/ }),
2734
2735/***/ "./src/controller/base-stream-controller.js":
2736/*!**************************************************!*\
2737  !*** ./src/controller/base-stream-controller.js ***!
2738  \**************************************************/
2739/*! no static exports found */
2740/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
2741/***/ (function(module, exports, __webpack_require__) {
2742
2743"use strict";
2744/* WEBPACK VAR INJECTION */(function(Number) {
2745var __extends = (this && this.__extends) || (function () {
2746    var extendStatics = Object.setPrototypeOf ||
2747        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
2748        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
2749    return function (d, b) {
2750        extendStatics(d, b);
2751        function __() { this.constructor = d; }
2752        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
2753    };
2754})();
2755Object.defineProperty(exports, "__esModule", { value: true });
2756var task_loop_1 = __webpack_require__(/*! ../task-loop */ "./src/task-loop.js");
2757var fragment_tracker_1 = __webpack_require__(/*! ./fragment-tracker */ "./src/controller/fragment-tracker.js");
2758var buffer_helper_1 = __webpack_require__(/*! ../utils/buffer-helper */ "./src/utils/buffer-helper.js");
2759var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
2760exports.State = {
2761    STOPPED: 'STOPPED',
2762    STARTING: 'STARTING',
2763    IDLE: 'IDLE',
2764    PAUSED: 'PAUSED',
2765    KEY_LOADING: 'KEY_LOADING',
2766    FRAG_LOADING: 'FRAG_LOADING',
2767    FRAG_LOADING_WAITING_RETRY: 'FRAG_LOADING_WAITING_RETRY',
2768    WAITING_TRACK: 'WAITING_TRACK',
2769    PARSING: 'PARSING',
2770    PARSED: 'PARSED',
2771    BUFFER_FLUSHING: 'BUFFER_FLUSHING',
2772    ENDED: 'ENDED',
2773    ERROR: 'ERROR',
2774    WAITING_INIT_PTS: 'WAITING_INIT_PTS',
2775    WAITING_LEVEL: 'WAITING_LEVEL'
2776};
2777var BaseStreamController = /** @class */ (function (_super) {
2778    __extends(BaseStreamController, _super);
2779    function BaseStreamController() {
2780        return _super !== null && _super.apply(this, arguments) || this;
2781    }
2782    BaseStreamController.prototype.doTick = function () { };
2783    BaseStreamController.prototype.startLoad = function () { };
2784    BaseStreamController.prototype.stopLoad = function () {
2785        var frag = this.fragCurrent;
2786        if (frag) {
2787            if (frag.loader) {
2788                frag.loader.abort();
2789            }
2790            this.fragmentTracker.removeFragment(frag);
2791        }
2792        if (this.demuxer) {
2793            this.demuxer.destroy();
2794            this.demuxer = null;
2795        }
2796        this.fragCurrent = null;
2797        this.fragPrevious = null;
2798        this.clearInterval();
2799        this.clearNextTick();
2800        this.state = exports.State.STOPPED;
2801    };
2802    BaseStreamController.prototype._streamEnded = function (bufferInfo, levelDetails) {
2803        var _a = this, fragCurrent = _a.fragCurrent, fragmentTracker = _a.fragmentTracker;
2804        // we just got done loading the final fragment and there is no other buffered range after ...
2805        // rationale is that in case there are any buffered ranges after, it means that there are unbuffered portion in between
2806        // so we should not switch to ENDED in that case, to be able to buffer them
2807        // dont switch to ENDED if we need to backtrack last fragment
2808        if (!levelDetails.live && fragCurrent && !fragCurrent.backtracked && fragCurrent.sn === levelDetails.endSN && !bufferInfo.nextStart) {
2809            var fragState = fragmentTracker.getState(fragCurrent);
2810            return fragState === fragment_tracker_1.FragmentState.PARTIAL || fragState === fragment_tracker_1.FragmentState.OK;
2811        }
2812        return false;
2813    };
2814    BaseStreamController.prototype.onMediaSeeking = function () {
2815        var _a = this, config = _a.config, media = _a.media, mediaBuffer = _a.mediaBuffer, state = _a.state;
2816        var currentTime = media ? media.currentTime : null;
2817        var bufferInfo = buffer_helper_1.BufferHelper.bufferInfo(mediaBuffer || media, currentTime, this.config.maxBufferHole);
2818        if (Number.isFinite(currentTime)) {
2819            logger_1.logger.log("media seeking to " + currentTime.toFixed(3));
2820        }
2821        if (state === exports.State.FRAG_LOADING) {
2822            var fragCurrent = this.fragCurrent;
2823            // check if we are seeking to a unbuffered area AND if frag loading is in progress
2824            if (bufferInfo.len === 0 && fragCurrent) {
2825                var tolerance = config.maxFragLookUpTolerance;
2826                var fragStartOffset = fragCurrent.start - tolerance;
2827                var fragEndOffset = fragCurrent.start + fragCurrent.duration + tolerance;
2828                // check if we seek position will be out of currently loaded frag range : if out cancel frag load, if in, don't do anything
2829                if (currentTime < fragStartOffset || currentTime > fragEndOffset) {
2830                    if (fragCurrent.loader) {
2831                        logger_1.logger.log('seeking outside of buffer while fragment load in progress, cancel fragment load');
2832                        fragCurrent.loader.abort();
2833                    }
2834                    this.fragCurrent = null;
2835                    this.fragPrevious = null;
2836                    // switch to IDLE state to load new fragment
2837                    this.state = exports.State.IDLE;
2838                }
2839                else {
2840                    logger_1.logger.log('seeking outside of buffer but within currently loaded fragment range');
2841                }
2842            }
2843        }
2844        else if (state === exports.State.ENDED) {
2845            // if seeking to unbuffered area, clean up fragPrevious
2846            if (bufferInfo.len === 0) {
2847                this.fragPrevious = null;
2848                this.fragCurrent = null;
2849            }
2850            // switch to IDLE state to check for potential new fragment
2851            this.state = exports.State.IDLE;
2852        }
2853        if (media) {
2854            this.lastCurrentTime = currentTime;
2855        }
2856        // in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target
2857        if (!this.loadedmetadata) {
2858            this.nextLoadPosition = this.startPosition = currentTime;
2859        }
2860        // tick to speed up processing
2861        this.tick();
2862    };
2863    BaseStreamController.prototype.onMediaEnded = function () {
2864        // reset startPosition and lastCurrentTime to restart playback @ stream beginning
2865        this.startPosition = this.lastCurrentTime = 0;
2866    };
2867    BaseStreamController.prototype.onHandlerDestroying = function () {
2868        this.stopLoad();
2869        _super.prototype.onHandlerDestroying.call(this);
2870    };
2871    BaseStreamController.prototype.onHandlerDestroyed = function () {
2872        this.state = exports.State.STOPPED;
2873        this.fragmentTracker = null;
2874    };
2875    return BaseStreamController;
2876}(task_loop_1.default));
2877exports.default = BaseStreamController;
2878
2879/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.js")["Number"]))
2880
2881/***/ }),
2882
2883/***/ "./src/controller/buffer-controller.js":
2884/*!*********************************************!*\
2885  !*** ./src/controller/buffer-controller.js ***!
2886  \*********************************************/
2887/*! no static exports found */
2888/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
2889/***/ (function(module, exports, __webpack_require__) {
2890
2891"use strict";
2892/* WEBPACK VAR INJECTION */(function(Number) {
2893/*
2894 * Buffer Controller
2895*/
2896var __extends = (this && this.__extends) || (function () {
2897    var extendStatics = Object.setPrototypeOf ||
2898        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
2899        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
2900    return function (d, b) {
2901        extendStatics(d, b);
2902        function __() { this.constructor = d; }
2903        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
2904    };
2905})();
2906Object.defineProperty(exports, "__esModule", { value: true });
2907var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
2908var event_handler_1 = __webpack_require__(/*! ../event-handler */ "./src/event-handler.js");
2909var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
2910var errors_1 = __webpack_require__(/*! ../errors */ "./src/errors.js");
2911var mediasource_helper_1 = __webpack_require__(/*! ../utils/mediasource-helper */ "./src/utils/mediasource-helper.js");
2912var MediaSource = mediasource_helper_1.getMediaSource();
2913var BufferController = /** @class */ (function (_super) {
2914    __extends(BufferController, _super);
2915    function BufferController(hls) {
2916        var _this = _super.call(this, hls, events_1.default.MEDIA_ATTA
2916CHING, events_1.default.MEDIA_DETACHING, events_1.default.MANIFEST_PARSED, events_1.default.BUFFER_RESET, events_1.default.BUFFER_APPENDING, events_1.default.BUFFER_CODECS, events_1.default.BUFFER_EOS, events_1.default.BUFFER_FLUSHING, events_1.default.LEVEL_PTS_UPDATED, events_1.default.LEVEL_UPDATED) || this;
2917        // the value that we have set mediasource.duration to
2918        // (the actual duration may be tweaked slighly by the browser)
2919        _this._msDuration = null;
2920        // the value that we want to set mediaSource.duration to
2921        _this._levelDuration = null;
2922        // the target duration of the current media playlist
2923        _this._levelTargetDuration = 10;
2924        // current stream state: true - for live broadcast, false - for VoD content
2925        _this._live = null;
2926        // cache the self generated object url to detect hijack of video tag
2927        _this._objectUrl = null;
2928        // The number of BUFFER_CODEC events received before any sourceBuffers are created
2929        _this.bufferCodecEventsExpected = 0;
2930        // Source Buffer listeners
2931        _this.onsbue = _this.onSBUpdateEnd.bind(_this);
2932        _this.onsbe = _this.onSBUpdateError.bind(_this);
2933        _this.pendingTracks = {};
2934        _this.tracks = {};
2935        return _this;
2936    }
2937    BufferController.prototype.destroy = function () {
2938        event_handler_1.default.prototype.destroy.call(this);
2939    };
2940    BufferController.prototype.onLevelPtsUpdated = function (data) {
2941        var type = data.type;
2942        var audioTrack = this.tracks.audio;
2943        // Adjusting `SourceBuffer.timestampOffset` (desired point in the timeline where the next frames should be appended)
2944        // in Chrome browser when we detect MPEG audio container and time delta between level PTS and `SourceBuffer.timestampOffset`
2945        // is greater than 100ms (this is enough to handle seek for VOD or level change for LIVE videos). At the time of change we issue
2946        // `SourceBuffer.abort()` and adjusting `SourceBuffer.timestampOffset` if `SourceBuffer.updating` is false or awaiting `updateend`
2947        // event if SB is in updating state.
2948        // More info here: https://github.com/video-dev/hls.js/issues/332#issuecomment-257986486
2949        if (type === 'audio' && audioTrack && audioTrack.container === 'audio/mpeg') { // Chrome audio mp3 track
2950            var audioBuffer = this.sourceBuffer.audio;
2951            var delta = Math.abs(audioBuffer.timestampOffset - data.start);
2952            // adjust timestamp offset if time delta is greater than 100ms
2953            if (delta > 0.1) {
2954                var updating = audioBuffer.updating;
2955                try {
2956                    audioBuffer.abort();
2957                }
2958                catch (err) {
2959                    logger_1.logger.warn('can not abort audio buffer: ' + err);
2960                }
2961                if (!updating) {
2962                    logger_1.logger.warn('change mpeg audio timestamp offset from ' + audioBuffer.timestampOffset + ' to ' + data.start);
2963                    audioBuffer.timestampOffset = data.start;
2964                }
2965                else {
2966                    this.audioTimestampOffset = data.start;
2967                }
2968            }
2969        }
2970    };
2971    BufferController.prototype.onManifestParsed = function (data) {
2972        // in case of alt audio 2 BUFFER_CODECS events will be triggered, one per stream controller
2973        // sourcebuffers will be created all at once when the expected nb of tracks will be reached
2974        // in case alt audio is not used, only one BUFFER_CODEC event will be fired from main stream controller
2975        // it will contain the expected nb of source buffers, no need to compute it
2976        this.bufferCodecEventsExpected = data.altAudio ? 2 : 1;
2977        logger_1.logger.log(this.bufferCodecEventsExpected + " bufferCodec event(s) expected");
2978    };
2979    BufferController.prototype.onMediaAttaching = function (data) {
2980        var media = this.media = data.media;
2981        if (media) {
2982            // setup the media source
2983            var ms = this.mediaSource = new MediaSource();
2984            // Media Source listeners
2985            this.onmso = this.onMediaSourceOpen.bind(this);
2986            this.onmse = this.onMediaSourceEnded.bind(this);
2987            this.onmsc = this.onMediaSourceClose.bind(this);
2988            ms.addEventListener('sourceopen', this.onmso);
2989            ms.addEventListener('sourceended', this.onmse);
2990            ms.addEventListener('sourceclose', this.onmsc);
2991            // link video and media Source
2992            media.src = window.URL.createObjectURL(ms);
2993            // cache the locally generated object url
2994            this._objectUrl = media.src;
2995        }
2996    };
2997    BufferController.prototype.onMediaDetaching = function () {
2998        logger_1.logger.log('media source detaching');
2999        var ms = this.mediaSource;
3000        if (ms) {
3001            if (ms.readyState === 'open') {
3002                try {
3003                    // endOfStream could trigger exception if any sourcebuffer is in updating state
3004                    // we don't really care about checking sourcebuffer state here,
3005                    // as we are anyway detaching the MediaSource
3006                    // let's just avoid this exception to propagate
3007                    ms.endOfStream();
3008                }
3009                catch (err) {
3010                    logger_1.logger.warn("onMediaDetaching:" + err.message + " while calling endOfStream");
3011                }
3012            }
3013            ms.removeEventListener('sourceopen', this.onmso);
3014            ms.removeEventListener('sourceended', this.onmse);
3015            ms.removeEventListener('sourceclose', this.onmsc);
3016            // Detach properly the MediaSource from the HTMLMediaElement as
3017            // suggested in https://github.com/w3c/media-source/issues/53.
3018            if (this.media) {
3019                window.URL.revokeObjectURL(this._objectUrl);
3020                // clean up video tag src only if it's our own url. some external libraries might
3021                // hijack the video tag and change its 'src' without destroying the Hls instance first
3022                if (this.media.src === this._objectUrl) {
3023                    this.media.removeAttribute('src');
3024                    this.media.load();
3025                }
3026                else {
3027                    logger_1.logger.warn('media.src was changed by a third party - skip cleanup');
3028                }
3029            }
3030            this.mediaSource = null;
3031            this.media = null;
3032            this._objectUrl = null;
3033            this.pendingTracks = {};
3034            this.tracks = {};
3035            this.sourceBuffer = {};
3036            this.flushRange = [];
3037            this.segments = [];
3038            this.appended = 0;
3039        }
3040        this.onmso = this.onmse = this.onmsc = null;
3041        this.hls.trigger(events_1.default.MEDIA_DETACHED);
3042    };
3043    BufferController.prototype.onMediaSourceOpen = function () {
3044        logger_1.logger.log('media source opened');
3045        this.hls.trigger(events_1.default.MEDIA_ATTACHED, { media: this.media });
3046        var mediaSource = this.mediaSource;
3047        if (mediaSource) {
3048            // once received, don't listen anymore to sourceopen event
3049            mediaSource.removeEventListener('sourceopen', this.onmso);
3050        }
3051        this.checkPendingTracks();
3052    };
3053    BufferController.prototype.checkPendingTracks = function () {
3054        var _a = this, bufferCodecEventsExpected = _a.bufferCodecEventsExpected, pendingTracks = _a.pendingTracks;
3055        // Check if we've received all of the expected bufferCodec events. When none remain, create all the sourceBuffers at once.
3056        // This is important because the MSE spec allows implementations to throw QuotaExceededErrors if creating new sourceBuffers after
3057        // data has been appended to existing ones.
3058        // 2 tracks is the max (one for audio, one for video). If we've reach this max go ahead and create the buffers.
3059        var pendingTracksCount = Object.keys(pendingTracks).length;
3060        if ((pendingTracksCount && !bufferCodecEventsExpected) || pendingTracksCount === 2) {
3061            // ok, let's create them now !
3062            this.createSourceBuffers(pendingTracks);
3063            this.pendingTracks = {};
3064            // append any pending segments now !
3065            this.doAppending();
3066        }
3067    };
3068    BufferController.prototype.onMediaSourceClose = function () {
3069        logger_1.logger.log('media source closed');
3070    };
3071    BufferController.prototype.onMediaSourceEnded = function () {
3072        logger_1.logger.log('media source ended');
3073    };
3074    BufferController.prototype.onSBUpdateEnd = function () {
3075        // update timestampOffset
3076        if (this.audioTimestampOffset) {
3077            var audioBuffer = this.sourceBuffer.audio;
3078            logger_1.logger.warn("change mpeg audio timestamp offset from " + audioBuffer.timestampOffset + " to " + this.audioTimestampOffset);
3079            audioBuffer.timestampOffset = this.audioTimestampOffset;
3080            delete this.audioTimestampOffset;
3081        }
3082        if (this._needsFlush) {
3083            this.doFlush();
3084        }
3085        if (this._needsEos) {
3086            this.checkEos();
3087        }
3088        this.appending = false;
3089        var parent = this.parent;
3090        // count nb of pending segments waiting for appending on this sourcebuffer
3091        var pending = this.segments.reduce(function (counter, segment) { return (segment.parent === parent) ? counter + 1 : counter; }, 0);
3092        // this.sourceBuffer is better to use than media.buffered as it is closer to the PTS data from the fragments
3093        var timeRanges = {};
3094        var sourceBuffer = this.sourceBuffer;
3095        for (var streamType in sourceBuffer) {
3096            timeRanges[streamType] = sourceBuffer[streamType].buffered;
3097        }
3098        this.hls.trigger(events_1.default.BUFFER_APPENDED, { parent: parent, pending: pending, timeRanges: timeRanges });
3099        // don't append in flushing mode
3100        if (!this._needsFlush) {
3101            this.doAppending();
3102        }
3103        this.updateMediaElementDuration();
3104        // appending goes first
3105        if (pending === 0) {
3106            this.flushLiveBackBuffer();
3107        }
3108    };
3109    BufferController.prototype.onSBUpdateError = function (event) {
3110        logger_1.logger.error('sourceBuffer error:', event);
3111        // according to http://www.w3.org/TR/media-source/#sourcebuffer-append-error
3112        // this error might not always be fatal (it is fatal if decode error is set, in that case
3113        // it will be followed by a mediaElement error ...)
3114        this.hls.trigger(events_1.default.ERROR, { type: errors_1.ErrorTypes.MEDIA_ERROR, details: errors_1.ErrorDetails.BUFFER_APPENDING_ERROR, fatal: false });
3115        // we don't need to do more than that, as accordin to the spec, updateend will be fired just after
3116    };
3117    BufferController.prototype.onBufferReset = function () {
3118        var sourceBuffer = this.sourceBuffer;
3119        for (var type in sourceBuffer) {
3120            var sb = sourceBuffer[type];
3121            try {
3122                this.mediaSource.removeSourceBuffer(sb);
3123                sb.removeEventListener('updateend', this.onsbue);
3124                sb.removeEventListener('error', this.onsbe);
3125            }
3126            catch (err) {
3127            }
3128        }
3129        this.sourceBuffer = {};
3130        this.flushRange = [];
3131        this.segments = [];
3132        this.appended = 0;
3133    };
3134    BufferController.prototype.onBufferCodecs = function (tracks) {
3135        var _this = this;
3136        // if source buffer(s) not created yet, appended buffer tracks in this.pendingTracks
3137        // if sourcebuffers already created, do nothing ...
3138        if (Object.keys(this.sourceBuffer).length) {
3139            return;
3140        }
3141        Object.keys(tracks).forEach(function (trackName) {
3142            _this.pendingTracks[trackName] = tracks[trackName];
3143        });
3144        var mediaSource = this.mediaSource;
3145        this.bufferCodecEventsExpected = Math.max(this.bufferCodecEventsExpected - 1, 0);
3146        if (mediaSource && mediaSource.readyState === 'open') {
3147            this.checkPendingTracks();
3148        }
3149    };
3150    BufferController.prototype.createSourceBuffers = function (tracks) {
3151        var sourceBuffer = this.sourceBuffer, mediaSource = this.mediaSource;
3152        for (var trackName in tracks) {
3153            if (!sourceBuffer[trackName]) {
3154                var track = tracks[trackName];
3155                // use levelCodec as first priority
3156                var codec = track.levelCodec || track.codec;
3157                var mimeType = track.container + ";codecs=" + codec;
3158                logger_1.logger.log("creating sourceBuffer(" + mimeType + ")");
3159                try {
3160                    var sb = sourceBuffer[trackName] = mediaSource.addSourceBuffer(mimeType);
3161                    sb.addEventListener('updateend', this.onsbue);
3162                    sb.addEventListener('error', this.onsbe);
3163                    this.tracks[trackName] = { codec: codec, container: track.container };
3164                    track.buffer = sb;
3165                }
3166                catch (err) {
3167                    logger_1.logger.error("error while trying to add sourceBuffer:" + err.message);
3168                    this.hls.trigger(events_1.default.ERROR, { type: errors_1.ErrorTypes.MEDIA_ERROR, details: errors_1.ErrorDetails.BUFFER_ADD_CODEC_ERROR, fatal: false, err: err, mimeType: mimeType });
3169                }
3170            }
3171        }
3172        this.hls.trigger(events_1.default.BUFFER_CREATED, { tracks: tracks });
3173    };
3174    BufferController.prototype.onBufferAppending = function (data) {
3175        if (!this._needsFlush) {
3176            if (!this.segments) {
3177                this.segments = [data];
3178            }
3179            else {
3180                this.segments.push(data);
3181            }
3182            this.doAppending();
3183        }
3184    };
3185    BufferController.prototype.onBufferAppendFail = function (data) {
3186        logger_1.logger.error('sourceBuffer error:', data.event);
3187        // according to http://www.w3.org/TR/media-source/#sourcebuffer-append-error
3188        // this error might not always be fatal (it is fatal if decode error is set, in that case
3189        // it will be followed by a mediaElement error ...)
3190        this.hls.trigger(events_1.default.ERROR, { type: errors_1.ErrorTypes.MEDIA_ERROR, details: errors_1.ErrorDetails.BUFFER_APPENDING_ERROR, fatal: false });
3191    };
3192    // on BUFFER_EOS mark matching sourcebuffer(s) as ended and trigger checkEos()
3193    BufferController.prototype.onBufferEos = function (data) {
3194        var sb = this.sourceBuffer;
3195        var dataType = data.type;
3196        for (var type in sb) {
3197            if (!dataType || type === dataType) {
3198                if (!sb[type].ended) {
3199                    sb[type].ended = true;
3200                    logger_1.logger.log(type + " sourceBuffer now EOS");
3201                }
3202            }
3203        }
3204        this.checkEos();
3205    };
3206    // if all source buffers are marked as ended, signal endOfStream() to MediaSource.
3207    BufferController.prototype.checkEos = function () {
3208        var sb = this.sourceBuffer, mediaSource = this.mediaSource;
3209        if (!mediaSource || mediaSource.readyState !== 'open') {
3210            this._needsEos = false;
3211            return;
3212        }
3213        for (var type in sb) {
3214            var sbobj = sb[type];
3215            if (!sbobj.ended) {
3216                return;
3217            }
3218            if (sbobj.updating) {
3219                this._needsEos = true;
3220                return;
3221            }
3222        }
3223        logger_1.logger.log('all media data are available, signal endOfStream() to MediaSource and stop loading fragment');
3224        // Notify the media element that it now has all of the media data
3225        try {
3226            mediaSource.endOfStream();
3227        }
3228        catch (e) {
3229            logger_1.logger.warn('exception while calling mediaSource.endOfStream()');
3230        }
3231        this._needsEos = false;
3232    };
3233    BufferController.prototype.onBufferFlushing = function (data) {
3234        this.flushRange.push({ start: data.startOffset, end: data.endOffset, type: data.type });
3235        // attempt flush immediately
3236        this.flushBufferCounter = 0;
3237        this.doFlush();
3238    };
3239    BufferController.prototype.flushLiveBackBuffer = function () {
3240        // clear back buffer for live only
3241        if (!this._live) {
3242            return;
3243        }
3244        var liveBackBufferLength = this.hls.config.liveBackBufferLength;
3245        if (!isFinite(liveBackBufferLength) || liveBackBufferLength < 0) {
3246            return;
3247        }
3248        var currentTime = this.media.currentTime;
3249        var sourceBuffer = this.sourceBuffer;
3250        var bufferTypes = Object.keys(sourceBuffer);
3251        var targetBackBufferPosition = currentTime - Math.max(liveBackBufferLength, this._levelTargetDuration);
3252        for (var index = bufferTypes.length - 1; index >= 0; index--) {
3253            var bufferType = bufferTypes[index], buffered = sourceBuffer[bufferType].buffered;
3254            // when target buffer start exceeds actual buffer start
3255            if (buffered.length > 0 && targetBackBufferPosition > buffered.start(0)) {
3256                // remove buffer up until current time minus minimum back buffer length (removing buffer too close to current
3257                // time will lead to playback freezing)
3258                // credits for level target duration - https://github.com/videojs/http-streaming/blob/3132933b6aa99ddefab29c10447624efd6fd6e52/src/segment-loader.js#L91
3259                this.removeBufferRange(bufferType, sourceBuffer[bufferType], 0, targetBackBufferPosition);
3260            }
3261        }
3262    };
3263    BufferController.prototype.onLevelUpdated = function (_a) {
3264        var details = _a.details;
3265        if (details.fragments.length > 0) {
3266            this._levelDuration = details.totalduration + details.fragments[0].start;
3267            this._levelTargetDuration = details.averagetargetduration || details.targetduration || 10;
3268            this._live = details.live;
3269            this.updateMediaElementDuration();
3270        }
3271    };
3272    /**
3273     * Update Media Source duration to current level duration or override to Infinity if configuration parameter
3274     * 'liveDurationInfinity` is set to `true`
3275     * More details: https://github.com/video-dev/hls.js/issues/355
3276     */
3277    BufferController.prototype.updateMediaElementDuration = function () {
3278        var config = this.hls.config;
3279        var duration;
3280        if (this._levelDuration === null ||
3281            !this.media ||
3282            !this.mediaSource ||
3283            !this.sourceBuffer ||
3284            this.media.readyState === 0 ||
3285            this.mediaSource.readyState !== 'open') {
3286            return;
3287        }
3288        for (var type in this.sourceBuffer) {
3289            if (this.sourceBuffer[type].updating === true) {
3290                // can't set duration whilst a buffer is updating
3291                return;
3292            }
3293        }
3294        duration = this.media.duration;
3295        // initialise to the value that the media source is reporting
3296        if (this._msDuration === null) {
3297            this._msDuration = this.mediaSource.duration;
3298        }
3299        if (this._live === true && config.liveDurationInfinity === true) {
3300            // Override duration to Infinity
3301            logger_1.logger.log('Media Source duration is set to Infinity');
3302            this._msDuration = this.mediaSource.duration = Infinity;
3303        }
3304        else if ((this._levelDuration > this._msDuration && this._levelDuration > duration) || !Number.isFinite(duration)) {
3305            // levelDuration was the last value we set.
3306            // not using mediaSource.duration as the browser may tweak this value
3307            // only update Media Source duration if its value increase, this is to avoid
3308            // flushing already buffered portion when switching between quality level
3309            logger_1.logger.log("Updating Media Source duration to " + this._levelDuration.toFixed(3));
3310            this._msDuration = this.mediaSource.duration = this._levelDuration;
3311        }
3312    };
3313    BufferController.prototype.doFlush = function () {
3314        // loop through all buffer ranges to flush
3315        while (this.flushRange.length) {
3316            var range = this.flushRange[0];
3317            // flushBuffer will abort any buffer append in progress and flush Audio/Video Buffer
3318            if (this.flushBuffer(range.start, range.end, range.type)) {
3319                // range flushed, remove from flush array
3320                this.flushRange.shift();
3321                this.flushBufferCounter = 0;
3322            }
3323            else {
3324                this._needsFlush = true;
3325                // avoid looping, wait for SB update end to retrigger a flush
3326                return;
3327            }
3328        }
3329        if (this.flushRange.length === 0) {
3330            // everything flushed
3331            this._needsFlush = false;
3332            // let's recompute this.appended, which is used to avoid flush looping
3333            var appended = 0;
3334            var sourceBuffer = this.sourceBuffer;
3335            try {
3336                for (var type in sourceBuffer) {
3337                    appended += sourceBuffer[type].buffered.length;
3338                }
3339            }
3340            catch (error) {
3341                // error could be thrown while accessing buffered, in case sourcebuffer has already been removed from MediaSource
3342                // this is harmess at this stage, catch this to avoid reporting an internal exception
3343                logger_1.logger.error('error while accessing sourceBuffer.buffered');
3344            }
3345            this.appended = appended;
3346            this.hls.trigger(events_1.default.BUFFER_FLUSHED);
3347        }
3348    };
3349    BufferController.prototype.doAppending = function () {
3350        var _a = this, hls = _a.hls, segments = _a.segments, sourceBuffer = _a.sourceBuffer;
3351        if (Object.keys(sourceBuffer).length) {
3352            if (this.media.error) {
3353                this.segments = [];
3354                logger_1.logger.error('trying to append although a media error occured, flush segment and abort');
3355                return;
3356            }
3357            if (this.appending) {
3358                // logger.log(`sb appending in progress`);
3359                return;
3360            }
3361            if (segments && segments.length) {
3362                var segment = segments.shift();
3363                try {
3364                    var type = segment.type, sb = sourceBuffer[type];
3365                    if (sb) {
3366                        if (!sb.updating) {
3367                            // reset sourceBuffer ended flag before appending segment
3368                            sb.ended = false;
3369                            // logger.log(`appending ${segment.content} ${type} SB, size:${segment.data.length}, ${segment.parent}`);
3370                            this.parent = segment.parent;
3371                            sb.appendBuffer(segment.data);
3372                            this.appendError = 0;
3373                            this.appended++;
3374                            this.appending = true;
3375                        }
3376                        else {
3377                            segments.unshift(segment);
3378                        }
3379                    }
3380                    else {
3381                        // in case we don't have any source buffer matching with this segment type,
3382                        // it means that Mediasource fails to create sourcebuffer
3383                        // discard this segment, and trigger update end
3384                        this.onSBUpdateEnd();
3385                    }
3386                }
3387                catch (err) {
3388                    // in case any error occured while appending, put back segment in segments table
3389                    logger_1.logger.error("error while trying to append buffer:" + err.message);
3390                    segments.unshift(segment);
3391                    var event_1 = { type: errors_1.ErrorTypes.MEDIA_ERROR, parent: segment.parent };
3392                    if (err.code !== 22) {
3393                        if (this.appendError) {
3394                            this.appendError++;
3395                        }
3396                        else {
3397                            this.appendError = 1;
3398                        }
3399                        event_1.details = errors_1.ErrorDetails.BUFFER_APPEND_ERROR;
3400                        /* with UHD content, we could get loop of quota exceeded error until
3401                          browser is able to evict some data from sourcebuffer. retrying help recovering this
3402                        */
3403                        if (this.appendError > hls.config.appendErrorMaxRetry) {
3404                            logger_1.logger.log("fail " + hls.config.appendErrorMaxRetry + " times to append segment in sourceBuffer");
3405                            this.segments = [];
3406                            event_1.fatal = true;
3407                            hls.trigger(events_1.default.ERROR, event_1);
3408                        }
3409                        else {
3410                            event_1.fatal = false;
3411                            hls.trigger(events_1.default.ERROR, event_1);
3412                        }
3413                    }
3414                    else {
3415                        // QuotaExceededError: http://www.w3.org/TR/html5/infrastructure.html#quotaexceedederror
3416                        // let's stop appending any segments, and report BUFFER_FULL_ERROR error
3417                        this.segments = [];
3418                        event_1.details = errors_1.ErrorDetails.BUFFER_FULL_ERROR;
3419                        event_1.fatal = false;
3420                        hls.trigger(events_1.default.ERROR, event_1);
3421                    }
3422                }
3423            }
3424        }
3425    };
3426    /*
3427      flush specified buffered range,
3428      return true once range has been flushed.
3429      as sourceBuffer.remove() is asynchronous, flushBuffer will be retriggered on sourceBuffer update end
3430    */
3431    BufferController.prototype.flushBuffer = function (startOffset, endOffset, typeIn) {
3432        var sb;
3433        var sourceBuffer = this.sourceBuffer;
3434        if (Object.keys(sourceBuffer).length) {
3435            logger_1.logger.log("flushBuffer,pos/start/end: " + this.media.currentTime.toFixed(3) + "/" + startOffset + "/" + endOffset);
3436            // safeguard to avoid infinite looping : don't try to flush more than the nb of appended segments
3437            if (this.flushBufferCounter < this.appended) {
3438                for (var type in sourceBuffer) {
3439                    // check if sourcebuffer type is defined (typeIn): if yes, let's only flush this one
3440                    // if no, let's flush all sourcebuffers
3441                    if (typeIn && type !== typeIn) {
3442                        continue;
3443                    }
3444                    sb = sourceBuffer[type];
3445                    // we are going to flush buffer, mark source buffer as 'not ended'
3446                    sb.ended = false;
3447                    if (!sb.updating) {
3448                        if (this.removeBufferRange(type, sb, startOffset, endOffset)) {
3449                            this.flushBufferCounter++;
3450                            return false;
3451                        }
3452                    }
3453                    else {
3454                        logger_1.logger.warn('cannot flush, sb updating in progress');
3455                        return false;
3456                    }
3457                }
3458            }
3459            else {
3460                logger_1.logger.warn('abort flushing too many retries');
3461            }
3462            logger_1.logger.log('buffer flushed');
3463        }
3464        // everything flushed !
3465        return true;
3466    };
3467    /**
3468     * Removes first buffered range from provided source buffer that lies within given start and end offsets.
3469     *
3470     * @param type Type of the source buffer, logging purposes only.
3471     * @param sb Target SourceBuffer instance.
3472     * @param startOffset
3473     * @param endOffset
3474     *
3475     * @returns {boolean} True when source buffer remove requested.
3476     */
3477    BufferController.prototype.removeBufferRange = function (type, sb, startOffset, endOffset) {
3478        try {
3479            for (var i = 0; i < sb.buffered.length; i++) {
3480                var bufStart = sb.buffered.start(i);
3481                var bufEnd = sb.buffered.end(i);
3482                var removeStart = Math.max(bufStart, startOffset);
3483                var removeEnd = Math.min(bufEnd, endOffset);
3484                /* sometimes sourcebuffer.remove() does not flush
3485                  the exact expected time range.
3486                  to avoid rounding issues/infinite loop,
3487                  only flush buffer range of length greater than 500ms.
3488                */
3489                if (Math.min(removeEnd, bufEnd) - removeStart > 0.5) {
3490                    logger_1.logger.log("sb remove " + type + " [" + removeStart + "," + removeEnd + "], of [" + bufStart + "," + bufEnd + "], pos:" + this.media.currentTime);
3491                    sb.remove(removeStart, removeEnd);
3492                    return true;
3493                }
3494            }
3495        }
3496        catch (error) {
3497            logger_1.logger.warn('removeBufferRange failed', error);
3498        }
3499        return false;
3500    };
3501    return BufferController;
3502}(event_handler_1.default));
3503exports.default = BufferController;
3504
3505/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.js")["Number"]))
3506
3507/***/ }),
3508
3509/***/ "./src/controller/cap-level-controller.js":
3510/*!************************************************!*\
3511  !*** ./src/controller/cap-level-controller.js ***!
3512  \************************************************/
3513/*! no static exports found */
3514/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
3515/***/ (function(module, exports, __webpack_require__) {
3516
3517"use strict";
3518/* WEBPACK VAR INJECTION */(function(Number) {
3519/*
3520 * cap stream level to media size dimension controller
3521*/
3522var __extends = (this && this.__extends) || (function () {
3523    var extendStatics = Object.setPrototypeOf ||
3524        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
3525        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
3526    return function (d, b) {
3527        extendStatics(d, b);
3528        function __() { this.constructor = d; }
3529        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
3530    };
3531})();
3532Object.defineProperty(exports, "__esModule", { value: true });
3533var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
3534var event_handler_1 = __webpack_require__(/*! ../event-handler */ "./src/event-handler.js");
3535var CapLevelController = /** @class */ (function (_super) {
3536    __extends(CapLevelController, _super);
3537    function CapLevelController(hls) {
3538        var _this = _super.call(this, hls, events_1.default.FPS_DROP_LEVEL_CAPPING, events_1.default.MEDIA_ATTA
vendor: 4,301 bytes, lines 3538-3634
3538CHING, events_1.default.MANIFEST_PARSED, events_1.default.BUFFER_CODECS, events_1.default.MEDIA_DETACHING) || this;
3539        _this.autoLevelCapping = Number.POSITIVE_INFINITY;
3540        _this.firstLevel = null;
3541        _this.levels = [];
3542        _this.media = null;
3543        _this.restrictedLevels = [];
3544        _this.timer = null;
3545        return _this;
3546    }
3547    CapLevelController.prototype.destroy = function () {
3548        if (this.hls.config.capLevelToPlayerSize) {
3549            this.media = null;
3550            this._stopCapping();
3551        }
3552    };
3553    CapLevelController.prototype.onFpsDropLevelCapping = function (data) {
3554        // Don't add a restricted level more than once
3555        if (CapLevelController.isLevelAllowed(data.droppedLevel, this.restrictedLevels)) {
3556            this.restrictedLevels.push(data.droppedLevel);
3557        }
3558    };
3559    CapLevelController.prototype.onMediaAttaching = function (data) {
3560        this.media = data.media instanceof window.HTMLVideoElement ? data.media : null;
3561    };
3562    CapLevelController.prototype.onManifestParsed = function (data) {
3563        var hls = this.hls;
3564        this.restrictedLevels = [];
3565        this.levels = data.levels;
3566        this.firstLevel = data.firstLevel;
3567        if (hls.config.capLevelToPlayerSize && data.video) {
3568            // Start capping immediately if the manifest has signaled video codecs
3569            this._startCapping();
3570        }
3571    };
3572    // Only activate capping when playing a video stream; otherwise, multi-bitrate audio-only streams will be restricted
3573    // to the first level
3574    CapLevelController.prototype.onBufferCodecs = function (data) {
3575        var hls = this.hls;
3576        if (hls.config.capLevelToPlayerSize && data.video) {
3577            // If the manifest did not signal a video codec capping has been deferred until we're certain video is present
3578            this._startCapping();
3579        }
3580    };
3581    CapLevelController.prototype.onLevelsUpdated = function (data) {
3582        this.levels = data.levels;
3583    };
3584    CapLevelController.prototype.onMediaDetaching = function () {
3585        this._stopCapping();
3586    };
3587    CapLevelController.prototype.detectPlayerSize = function () {
3588        if (this.media) {
3589            var levelsLength = this.levels ? this.levels.length : 0;
3590            if (levelsLength) {
3591                var hls_1 = this.hls;
3592                hls_1.autoLevelCapping = this.getMaxLevel(levelsLength - 1);
3593                if (hls_1.autoLevelCapping > this.autoLevelCapping) {
3594                    // if auto level capping has a higher value for the previous one, flush the buffer using nextLevelSwitch
3595                    // usually happen when the user go to the fullscreen mode.
3596                    hls_1.streamController.nextLevelSwitch();
3597                }
3598                this.autoLevelCapping = hls_1.autoLevelCapping;
3599            }
3600        }
3601    };
3602    /*
3603    * returns level should be the one with the dimensions equal or greater than the media (player) dimensions (so the video will be downscaled)
3604    */
3605    CapLevelController.prototype.getMaxLevel = function (capLevelIndex) {
3606        var _this = this;
3607        if (!this.levels) {
3608            return -1;
3609        }
3610        var validLevels = this.levels.filter(function (level, index) {
3611            return CapLevelController.isLevelAllowed(index, _this.restrictedLevels) && index <= capLevelIndex;
3612        });
3613        return CapLevelController.getMaxLevelByMediaSize(validLevels, this.mediaWidth, this.mediaHeight);
3614    };
3615    CapLevelController.prototype._startCapping = function () {
3616        if (this.timer) {
3617            // Don't reset capping if started twice; this can happen if the manifest signals a video codec
3618            return;
3619        }
3620        this.autoLevelCapping = Number.POSITIVE_INFINITY;
3621        this.hls.firstLevel = this.getMaxLevel(this.firstLevel);
3622        clearInterval(this.timer);
3623        this.timer = setInterval(this.detectPlayerSize.bind(this), 1000);
3624        this.detectPlayerSize();
3625    };
3626    CapLevelController.prototype._stopCapping = function () {
3627        this.restrictedLevels = [];
3628        this.firstLevel = null;
3629        this.autoLevelCapping = Number.POSITIVE_INFINITY;
3630        if (this.timer) {
3631            this.timer = clearInterval(this.timer);
3632            this.timer = null;
3633        }
3634    };
3635    Object.defineProperty(CapLevelController.prototype, "mediaWidth", {
3636        get: function () {
3637            var width;
3638            var media = this.media;
3639            if (media) {
3640                width = media.width || media.clientWidth || media.offsetWidth;
3641                width *= CapLevelController.contentScaleFactor;
3642            }
3643            return width;
3644        },
3645        enumerable: true,
3646        configurable: true
3647    });
3648    Object.defineProperty(CapLevelController.prototype, "mediaHeight", {
3649        get: function () {
3650            var height;
3651            var media = this.media;
3652            if (media) {
3653                height = media.height || media.clientHeight || media.offsetHeight;
3654                height *= CapLevelController.contentScaleFactor;
3655            }
3656            return height;
3657        },
3658        enumerable: true,
3659        configurable: true
3660    });
3661    Object.defineProperty(CapLevelController, "contentScaleFactor", {
3662        get: function () {
3663            var pixelRatio = 1;
3664            try {
3665                pixelRatio = window.devicePixelRatio;
3666            }
3667            catch (e) { }
3668            return pixelRatio;
3669        },
3670        enumerable: true,
3671        configurable: true
3672    });
3673    CapLevelController.isLevelAllowed = function (level, restrictedLevels) {
3674        if (restrictedLevels === void 0) { restrictedLevels = []; }
3675        return restrictedLevels.indexOf(level) === -1;
3676    };
3677    CapLevelController.getMaxLevelByMediaSize = function (levels, width, height) {
3678        if (!levels || (levels && !levels.length)) {
3679            return -1;
3680        }
3681        // Levels can have the same dimensions but differing bandwidths - since levels are ordered, we can look to the next
3682        // to determine whether we've chosen the greatest bandwidth for the media's dimensions
3683        var atGreatestBandiwdth = function (curLevel, nextLevel) {
3684            if (!nextLevel) {
3685                return true;
3686            }
3687            return curLevel.width !== nextLevel.width || curLevel.height !== nextLevel.height;
3688        };
3689        // If we run through the loop without breaking, the media's dimensions are greater than every level, so default to
3690        // the max level
3691        var maxLevelIndex = levels.length - 1;
3692        for (var i = 0; i < levels.length; i += 1) {
3693            var level = levels[i];
3694            if ((level.width >= width || level.height >= height) && atGreatestBandiwdth(level, levels[i + 1])) {
3695                maxLevelIndex = i;
3696                break;
3697            }
3698        }
3699        return maxLevelIndex;
3700    };
3701    return CapLevelController;
3702}(event_handler_1.default));
3703exports.default = CapLevelController;
3704
3705/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.js")["Number"]))
3706
3707/***/ }),
3708
3709/***/ "./src/controller/eme-controller.js":
3710/*!******************************************!*\
3711  !*** ./src/controller/eme-controller.js ***!
3712  \******************************************/
3713/*! no static exports found */
3714/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
3715/***/ (function(module, exports, __webpack_require__) {
3716
3717"use strict";
3718
3719/**
3720 * @author Stephan Hesse <[email protected]> | <[email protected]>
3721 *
3722 * DRM support for Hls.js
3723 */
3724var __extends = (this && this.__extends) || (function () {
3725    var extendStatics = Object.setPrototypeOf ||
3726        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
3727        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
3728    return function (d, b) {
3729        extendStatics(d, b);
3730        function __() { this.constructor = d; }
3731        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
3732    };
3733})();
3734Object.defineProperty(exports, "__esModule", { value: true });
3735var event_handler_1 = __webpack_require__(/*! ../event-handler */ "./src/event-handler.js");
3736var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
3737var errors_1 = __webpack_require__(/*! ../errors */ "./src/errors.js");
3738var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
3739var XMLHttpRequest = window.XMLHttpRequest;
3740var MAX_LICENSE_REQUEST_FAILURES = 3;
3741/**
3742 * @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/requestMediaKeySystemAccess
3743 */
3744var KeySystems = {
3745    WIDEVINE: 'com.widevine.alpha',
3746    PLAYREADY: 'com.microsoft.playready'
3747};
3748/**
3749 * @see https://developer.mozilla.org/en-US/docs/Web/API/MediaKeySystemConfiguration
3750 * @param {Array<string>} audioCodecs List of required audio codecs to support
3751 * @param {Array<string>} videoCodecs List of required video codecs to support
3752 * @param {object} drmSystemOptions Optional parameters/requirements for the key-system
3753 * @returns {Array<MediaSystemConfiguration>} An array of supported configurations
3754 */
3755var createWidevineMediaKeySystemConfigurations = function (audioCodecs, videoCodecs, drmSystemOptions) {
3756    var baseConfig = {
3757        // initDataTypes: ['keyids', 'mp4'],
3758        // label: "",
3759        // persistentState: "not-allowed", // or "required" ?
3760        // distinctiveIdentifier: "not-allowed", // or "required" ?
3761        // sessionTypes: ['temporary'],
3762        videoCapabilities: [
3763        // { contentType: 'video/mp4; codecs="avc1.42E01E"' }
3764        ]
3765    };
3766    videoCodecs.forEach(function (codec) {
3767        baseConfig.videoCapabilities.push({
3768            contentType: "video/mp4; codecs=\"" + codec + "\""
3769        });
3770    });
3771    return [
3772        baseConfig
3773    ];
3774};
3775/**
3776 * The idea here is to handle key-system (and their respective platforms) specific configuration differences
3777 * in order to work with the local requestMediaKeySystemAccess method.
3778 *
3779 * We can also rule-out platform-related key-system support at this point b
3779y throwing an error or returning null.
3780 *
3781 * @param {string} keySystem Identifier for the key-system, see `KeySystems` enum
3782 * @param {Array<string>} audioCodecs List of required audio codecs to support
3783 * @param {Array<string>} videoCodecs List of required video codecs to support
3784 * @returns {Array<MediaSystemConfiguration> | null} A non-empty Array of MediaKeySystemConfiguration objects or `null`
3785 */
3786var getSupportedMediaKeySystemConfigurations = function (keySystem, audioCodecs, videoCodecs) {
3787    switch (keySystem) {
3788        case KeySystems.WIDEVINE:
3789            return createWidevineMediaKeySystemConfigurations(audioCodecs, videoCodecs);
3790        default:
3791            throw Error('Unknown key-system: ' + keySystem);
3792    }
3793};
3794/**
3795 * Controller to deal with encrypted media extensions (EME)
3796 * @see https://developer.mozilla.org/en-US/docs/Web/API/Encrypted_Media_Extensions_API
3797 *
3798 * @class
3799 * @constructor
3800 */
3801var EMEController = /** @class */ (function (_super) {
3802    __extends(EMEController, _super);
3803    /**
3804       * @constructs
3805       * @param {Hls} hls Our Hls.js instance
3806       */
3807    function EMEController(hls) {
3808        var _this = _super.call(this, hls, events_1.default.MEDIA_ATTA
3808CHED, events_1.default.MANIFEST_PARSED) || this;
3809        _this._widevineLicenseUrl = hls.config.widevineLicenseUrl;
3810        _this._licenseXhrSetup = hls.config.licenseXhrSetup;
3811        _this._emeEnabled = hls.config.emeEnabled;
3812        _this._requestMediaKeySystemAccess = hls.config.requestMediaKeySystemAccessFunc;
3813        _this._mediaKeysList = [];
3814        _this._media = null;
3815        _this._hasSetMediaKeys = false;
3816        _this._isMediaEncrypted = false;
3817        _this._requestLicenseFailureCount = 0;
3818        return _this;
3819    }
3820    /**
3821       *
3822       * @param {string} keySystem Identifier for the key-system, see `KeySystems` enum
3823       * @returns {string} License server URL for key-system (if any configured, otherwise causes error)
3824       */
3825    EMEController.prototype.getLicenseServerUrl = function (keySystem) {
3826        var url;
3827        switch (keySystem) {
3828            case KeySystems.WIDEVINE:
3829                url = this._widevineLicenseUrl;
3830                break;
3831            default:
3832                url = null;
3833                break;
3834        }
3835        if (!url) {
3836            logger_1.logger.error("No license server URL configured for key-system \"" + keySystem + "\"");
3837            this.hls.trigger(events_1.default.ERROR, {
3838                type: errors_1.ErrorTypes.KEY_SYSTEM_ERROR,
3839                details: errors_1.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED,
3840                fatal: true
3841            });
3842        }
3843        return url;
3844    };
3845    /**
3846       * Requests access object and adds it to our list upon success
3847       * @private
3848       * @param {string} keySystem System ID (see `KeySystems`)
3849       * @param {Array<string>} audioCodecs List of required audio codecs to support
3850       * @param {Array<string>} videoCodecs List of required video codecs to support
3851       */
3852    EMEController.prototype._attemptKeySystemAccess = function (keySystem, audioCodecs, videoCodecs) {
3853        // TODO: add other DRM "options"
3854        var _this = this;
3855        var mediaKeySystemConfigs = getSupportedMediaKeySystemConfigurations(keySystem, audioCodecs, videoCodecs);
3856        if (!mediaKeySystemConfigs) {
3857            logger_1.logger.warn('Can not create config for key-system (maybe because platform is not supported):', keySystem);
3858            return;
3859        }
3860        logger_1.logger.log('Requesting encrypted media key-system access');
3861        // expecting interface like window.navigator.requestMediaKeySystemAccess
3862        this.requestMediaKeySystemAccess(keySystem, mediaKeySystemConfigs)
3863            .then(function (mediaKeySystemAccess) {
3864            _this._onMediaKeySystemAccessObtained(keySystem, mediaKeySystemAccess);
3865        })
3866            .catch(function (err) {
3867            logger_1.logger.error("Failed to obtain key-system \"" + keySystem + "\" access:", err);
3868        });
3869    };
3870    Object.defineProperty(EMEController.prototype, "requestMediaKeySystemAccess", {
3871        get: function () {
3872            if (!this._requestMediaKeySystemAccess) {
3873                throw new Error('No requestMediaKeySystemAccess function configured');
3874            }
3875            return this._requestMediaKeySystemAccess;
3876        },
3877        enumerable: true,
3878        configurable: true
3879    });
3880    /**
3881       * Handles obtaining access to a key-system
3882       *
3883       * @param {string} keySystem
3884       * @param {MediaKeySystemAccess} mediaKeySystemAccess https://developer.mozilla.org/en-US/docs/Web/API/MediaKeySystemAccess
3885       */
3886    EMEController.prototype._onMediaKeySystemAccessObtained = function (keySystem, mediaKeySystemAccess) {
3887        var _this = this;
3888        logger_1.logger.log("Access for key-system \"" + keySystem + "\" obtained");
3889        var mediaKeysListItem = {
3890            mediaKeys: null,
3891            mediaKeysSession: null,
3892            mediaKeysSessionInitialized: false,
3893            mediaKeySystemAccess: mediaKeySystemAccess,
3894            mediaKeySystemDomain: keySystem
3895        };
3896        this._mediaKeysList.push(mediaKeysListItem);
3897        mediaKeySystemAccess.createMediaKeys()
3898            .then(function (mediaKeys) {
3899            mediaKeysListItem.mediaKeys = mediaKeys;
3900            logger_1.logger.log("Media-keys created for key-system \"" + keySystem + "\"");
3901            _this._onMediaKeysCreated();
3902        })
3903            .catch(function (err) {
3904            logger_1.logger.error('Failed to create media-keys:', err);
3905        });
3906    };
3907    /**
3908       * Handles key-creation (represents access to CDM). We are going to create key-sessions upon this
3909       * for all existing keys where no session exists yet.
3910       */
3911    EMEController.prototype._onMediaKeysCreated = function () {
3912        var _this = this;
3913        // check for all key-list items if a session exists, otherwise, create one
3914        this._mediaKeysList.forEach(function (mediaKeysListItem) {
3915            if (!mediaKeysListItem.mediaKeysSession) {
3916                mediaKeysListItem.mediaKeysSession = mediaKeysListItem.mediaKeys.createSession();
3917                _this._onNewMediaKeySession(mediaKeysListItem.mediaKeysSession);
3918            }
3919        });
3920    };
3921    /**
3922       *
3923       * @param {*} keySession
3924       */
3925    EMEController.prototype._onNewMediaKeySession = function (keySession) {
3926        var _this = this;
3927        logger_1.logger.log("New key-system session " + keySession.sessionId);
3928        keySession.addEventListener('message', function (event) {
3929            _this._onKeySessionMessage(keySession, event.message);
3930        }, false);
3931    };
3932    EMEController.prototype._onKeySessionMessage = function (keySession, message) {
3933        logger_1.logger.log('Got EME message event, creating license request');
3934        this._requestLicense(message, function (data) {
3935            logger_1.logger.log('Received license data, updating key-session');
3936            keySession.update(data);
3937        });
3938    };
3939    EMEController.prototype._onMediaEncrypted = function (initDataType, initData) {
3940        logger_1.logger.log("Media is encrypted using \"" + initDataType + "\" init data type");
3941        this._isMediaEncrypted = true;
3942        this._mediaEncryptionInitDataType = initDataType;
3943        this._mediaEncryptionInitData = initData;
3944        this._attemptSetMediaKeys();
3945        this._generateRequestWithPreferredKeySession();
3946    };
3947    EMEController.prototype._attemptSetMediaKeys = function () {
3948        if (!this._hasSetMediaKeys) {
3949            // FIXME: see if we can/want/need-to really to deal with several potential key-sessions?
3950            var keysListItem = this._mediaKeysList[0];
3951            if (!keysListItem || !keysListItem.mediaKeys) {
3952                logger_1.logger.error('Fatal: Media is encrypted but no CDM access or no keys have been obtained yet');
3953                this.hls.trigger(events_1.default.ERROR, {
3954                    type: errors_1.ErrorTypes.KEY_SYSTEM_ERROR,
3955                    details: errors_1.ErrorDetails.KEY_SYSTEM_NO_KEYS,
3956                    fatal: true
3957                });
3958                return;
3959            }
3960            logger_1.logger.log('Setting keys for encrypted media');
3961            this._media.setMediaKeys(keysListItem.mediaKeys);
3962            this._hasSetMediaKeys = true;
3963        }
3964    };
3965    EMEController.prototype._generateRequestWithPreferredKeySession = function () {
3966        var _this = this;
3967        // FIXME: see if we can/want/need-to really to deal with several potential key-sessions?
3968        var keysListItem = this._mediaKeysList[0];
3969        if (!keysListItem) {
3970            logger_1.logger.error('Fatal: Media is encrypted but not any key-system access has been obtained yet');
3971            this.hls.trigger(events_1.default.ERROR, {
3972                type: errors_1.ErrorTypes.KEY_SYSTEM_ERROR,
3973                details: errors_1.ErrorDetails.KEY_SYSTEM_NO_ACCESS,
3974                fatal: true
3975            });
3976            return;
3977        }
3978        if (keysListItem.mediaKeysSessionInitialized) {
3979            logger_1.logger.warn('Key-Session already initialized but requested again');
3980            return;
3981        }
3982        var keySession = keysListItem.mediaKeysSession;
3983        if (!keySession) {
3984            logger_1.logger.error('Fatal: Media is encrypted but no key-session existing');
3985            this.hls.trigger(events_1.default.ERROR, {
3986                type: errors_1.ErrorTypes.KEY_SYSTEM_ERROR,
3987                details: errors_1.ErrorDetails.KEY_SYSTEM_NO_SESSION,
3988                fatal: true
3989            });
3990        }
3991        var initDataType = this._mediaEncryptionInitDataType;
3992        var initData = this._mediaEncryptionInitData;
3993        logger_1.logger.log("Generating key-session request for \"" + initDataType + "\" init data type");
3994        keysListItem.mediaKeysSessionInitialized = true;
3995        keySession.generateRequest(initDataType, initData)
3996            .then(function () {
3997            logger_1.logger.debug('Key-session generation succeeded');
3998        })
3999            .catch(function (err) {
4000            logger_1.logger.error('Error generating key-session request:', err);
4001            _this.hls.trigger(events_1.default.ERROR, {
4002                type: errors_1.ErrorTypes.KEY_SYSTEM_ERROR,
4003                details: errors_1.ErrorDetails.KEY_SYSTEM_NO_SESSION,
4004                fatal: false
4005            });
4006        });
4007    };
4008    /**
4009       * @param {string} url License server URL
4010       * @param {ArrayBuffer} keyMessage Message data issued by key-system
4011       * @param {function} callback Called when XHR has succeeded
4012       * @returns {XMLHttpRequest} Unsent (but opened state) XHR object
4013       */
4014    EMEController.prototype._createLicenseXhr = function (url, keyMessage, callback) {
4015        var xhr = new XMLHttpRequest();
4016        var licenseXhrSetup = this._licenseXhrSetup;
4017        try {
4018            if (licenseXhrSetup) {
4019                try {
4020                    licenseXhrSetup(xhr, url);
4021                }
4022                catch (e) {
4023                    // let's try to open before running setup
4024                    xhr.open('POST', url, true);
4025                    licenseXhrSetup(xhr, url);
4026                }
4027            }
4028            // if licenseXhrSetup did not yet call open, let's do it now
4029            if (!xhr.readyState) {
4030                xhr.open('POST', url, true);
4031            }
4032        }
4033        catch (e) {
4034            // IE11 throws an exception on xhr.open if attempting to access an HTTP resource over HTTPS
4035            logger_1.logger.error('Error setting up key-system license XHR', e);
4036            this.hls.trigger(events_1.default.ERROR, {
4037                type: errors_1.ErrorTypes.KEY_SYSTEM_ERROR,
4038                details: errors_1.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED,
4039                fatal: true
4040            });
4041            return;
4042        }
4043        xhr.responseType = 'arraybuffer';
4044        xhr.onreadystatechange =
4045            this._onLicenseRequestReadyStageChange.bind(this, xhr, url, keyMessage, callback);
4046        return xhr;
4047    };
4048    /**
4049       * @param {XMLHttpRequest} xhr
4050       * @param {string} url License server URL
4051       * @param {ArrayBuffer} keyMessage Message data issued by key-system
4052       * @param {function} callback Called when XHR has succeeded
4053       *
4054       */
4055    EMEController.prototype._onLicenseRequestReadyStageChange = function (xhr, url, keyMessage, callback) {
4056        switch (xhr.readyState) {
4057            case 4:
4058                if (xhr.status === 200) {
4059                    this._requestLicenseFailureCount = 0;
4060                    logger_1.logger.log('License request succeeded');
4061                    callback(xhr.response);
4062                }
4063                else {
4064                    logger_1.logger.error("License Request XHR failed (" + url + "). Status: " + xhr.status + " (" + xhr.statusText + ")");
4065                    this._requestLicenseFailureCount++;
4066                    if (this._requestLicenseFailureCount <= MAX_LICENSE_REQUEST_FAILURES) {
4067                        var attemptsLeft = MAX_LICENSE_REQUEST_FAILURES - this._requestLicenseFailureCount + 1;
4068                        logger_1.logger.warn("Retrying license request, " + attemptsLeft + " attempts left");
4069                        this._requestLicense(keyMessage, callback);
4070                        return;
4071                    }
4072                    this.hls.trigger(events_1.default.ERROR, {
4073                        type: errors_1.ErrorTypes.KEY_SYSTEM_ERROR,
4074                        details: errors_1.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED,
4075                        fatal: true
4076                    });
4077                }
4078                break;
4079        }
4080    };
4081    /**
4082       * @param {object} keysListItem
4083       * @param {ArrayBuffer} keyMessage
4084       * @returns {ArrayBuffer} Challenge data posted to license server
4085       */
4086    EMEController.prototype._generateLicenseRequestChallenge = function (keysListItem, keyMessage) {
4087        var challenge;
4088        if (keysListItem.mediaKeySystemDomain === KeySystems.PLAYREADY) {
4089            logger_1.logger.error('PlayReady is not supported (yet)');
4090            // from https://github.com/MicrosoftEdge/Demos/blob/master/eme/scripts/demo.js
4091            /*
4092              if (this.licenseType !== this.LICENSE_TYPE_WIDEVINE) {
4093                  // For PlayReady CDMs, we need to dig the Challenge out of the XML.
4094                  var keyMessageXml = new DOMParser().parseFromString(String.fromCharCode.apply(null, new Uint16Array(keyMessage)), 'application/xml');
4095                  if (keyMessageXml.getElementsByTagName('Challenge')[0]) {
4096                      challenge = atob(keyMessageXml.getElementsByTagName('Challenge')[0].childNodes[0].nodeValue);
4097                  } else {
4098                      throw 'Cannot find <Challenge> in key message';
4099                  }
4100                  var headerNames = keyMessageXml.getElementsByTagName('name');
4101                  var headerValues = keyMessageXml.getElementsByTagName('value');
4102                  if (headerNames.length !== headerValues.length) {
4103                      throw 'Mismatched header <name>/<value> pair in key message';
4104                  }
4105                  for (var i = 0; i < headerNames.length; i++) {
4106                      xhr.setRequestHeader(headerNames[i].childNodes[0].nodeValue, headerValues[i].childNodes[0].nodeValue);
4107                  }
4108              }
4109              */
4110        }
4111        else if (keysListItem.mediaKeySystemDomain === KeySystems.WIDEVINE) {
4112            // For Widevine CDMs, the challenge is the keyMessage.
4113            challenge = keyMessage;
4114        }
4115        else {
4116            logger_1.logger.error('Unsupported key-system:', keysListItem.mediaKeySystemDomain);
4117        }
4118        return challenge;
4119    };
4120    EMEController.prototype._requestLicense = function (keyMessage, callback) {
4121        logger_1.logger.log('Requesting content license for key-system');
4122        var keysListItem = this._mediaKeysList[0];
4123        if (!keysListItem) {
4124            logger_1.logger.error('Fatal error: Media is encrypted but no key-system access has been obtained yet');
4125            this.hls.trigger(events_1.default.ERROR, {
4126                type: errors_1.ErrorTypes.KEY_SYSTEM_ERROR,
4127                details: errors_1.ErrorDetails.KEY_SYSTEM_NO_ACCESS,
4128                fatal: true
4129            });
4130            return;
4131        }
4132        var url = this.getLicenseServerUrl(keysListItem.mediaKeySystemDomain);
4133        var xhr = this._createLicenseXhr(url, keyMessage, callback);
4134        logger_1.logger.log("Sending license request to URL: " + url);
4135        xhr.send(this._generateLicenseRequestChallenge(keysListItem, keyMessage));
4136    };
4137    EMEController.prototype.onMediaAttached = function (data) {
4138        var _this = this;
4139        if (!this._emeEnabled) {
4140            return;
4141        }
4142        var media = data.media;
4143        // keep reference of media
4144        this._media = media;
4145        // FIXME: also handle detaching media !
4146        media.addEventListener('encrypted', function (e) {
4147            _this._onMediaEncrypted(e.initDataType, e.initData);
4148        });
4149    };
4150    EMEController.prototype.onManifestParsed = function (data) {
4151        if (!this._emeEnabled) {
4152            return;
4153        }
4154        var audioCodecs = data.levels.map(function (level) { return level.audioCodec; });
4155        var videoCodecs = data.levels.map(function (level) { return level.videoCodec; });
4156        this._attemptKeySystemAccess(KeySystems.WIDEVINE, audioCodecs, videoCodecs);
4157    };
4158    return EMEController;
4159}(event_handler_1.default));
4160exports.default = EMEController;
4161
4162
4163/***/ }),
4164
4165/***/ "./src/controller/fps-controller.js":
4166/*!******************************************!*\
4167  !*** ./src/controller/fps-controller.js ***!
4168  \******************************************/
4169/*! no static exports found */
4170/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
4171/***/ (function(module, exports, __webpack_require__) {
4172
4173"use strict";
4174
4175/*
4176 * FPS Controller
4177*/
4178var __extends = (this && this.__extends) || (function () {
4179    var extendStatics = Object.setPrototypeOf ||
4180        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
4181        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
4182    return function (d, b) {
4183        extendStatics(d, b);
4184        function __() { this.constructor = d; }
4185        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
4186    };
4187})();
4188Object.defineProperty(exports, "__esModule", { value: true });
4189var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
4190var event_handler_1 = __webpack_require__(/*! ../event-handler */ "./src/event-handler.js");
4191var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
4192var performance = window.performance;
4193var FPSController = /** @class */ (function (_super) {
4194    __extends(FPSController, _super);
4195    function FPSController(hls) {
4196        return _super.call(this, hls, events_1.default.MEDIA_ATTA
vendor: 3,171 bytes, lines 4196-4258
4196CHING) || this;
4197    }
4198    FPSController.prototype.destroy = function () {
4199        if (this.timer) {
4200            clearInterval(this.timer);
4201        }
4202        this.isVideoPlaybackQualityAvailable = false;
4203    };
4204    FPSController.prototype.onMediaAttaching = function (data) {
4205        var config = this.hls.config;
4206        if (config.capLevelOnFPSDrop) {
4207            var video_1 = this.video = data.media instanceof window.HTMLVideoElement ? data.media : null;
4208            if (typeof video_1.getVideoPlaybackQuality === 'function') {
4209                this.isVideoPlaybackQualityAvailable = true;
4210            }
4211            clearInterval(this.timer);
4212            this.timer = setInterval(this.checkFPSInterval.bind(this), config.fpsDroppedMonitoringPeriod);
4213        }
4214    };
4215    FPSController.prototype.checkFPS = function (video, decodedFrames, droppedFrames) {
4216        var currentTime = performance.now();
4217        if (decodedFrames) {
4218            if (this.lastTime) {
4219                var currentPeriod = currentTime - this.lastTime, currentDropped = droppedFrames - this.lastDroppedFrames, currentDecoded = decodedFrames - this.lastDecodedFrames, droppedFPS = 1000 * currentDropped / currentPeriod, hls_1 = this.hls;
4220                hls_1.trigger(events_1.default.FPS_DROP, { currentDropped: currentDropped, currentDecoded: currentDecoded, totalDroppedFrames: droppedFrames });
4221                if (droppedFPS > 0) {
4222                    // logger.log('checkFPS : droppedFPS/decodedFPS:' + droppedFPS/(1000 * currentDecoded / currentPeriod));
4223                    if (currentDropped > hls_1.config.fpsDroppedMonitoringThreshold * currentDecoded) {
4224                        var currentLevel = hls_1.currentLevel;
4225                        logger_1.logger.warn('drop FPS ratio greater than max allowed value for currentLevel: ' + currentLevel);
4226                        if (currentLevel > 0 && (hls_1.autoLevelCapping === -1 || hls_1.autoLevelCapping >= currentLevel)) {
4227                            currentLevel = currentLevel - 1;
4228                            hls_1.trigger(events_1.default.FPS_DROP_LEVEL_CAPPING, { level: currentLevel, droppedLevel: hls_1.currentLevel });
4229                            hls_1.autoLevelCapping = currentLevel;
4230                            hls_1.streamController.nextLevelSwitch();
4231                        }
4232                    }
4233                }
4234            }
4235            this.lastTime = currentTime;
4236            this.lastDroppedFrames = droppedFrames;
4237            this.lastDecodedFrames = decodedFrames;
4238        }
4239    };
4240    FPSController.prototype.checkFPSInterval = function () {
4241        var video = this.video;
4242        if (video) {
4243            if (this.isVideoPlaybackQualityAvailable) {
4244                var videoPlaybackQuality = video.getVideoPlaybackQuality();
4245                this.checkFPS(video, videoPlaybackQuality.totalVideoFrames, videoPlaybackQuality.droppedVideoFrames);
4246            }
4247            else {
4248                this.checkFPS(video, video.webkitDecodedFrameCount, video.webkitDroppedFrameCount);
4249            }
4250        }
4251    };
4252    return FPSController;
4253}(event_handler_1.default));
4254exports.default = FPSController;
4255
4256
4257/***/ }),
4258
4259/***/ "./src/controller/fragment-finders.js":
4260/*!********************************************!*\
4261  !*** ./src/controller/fragment-finders.js ***!
4262  \********************************************/
4263/*! no static exports found */
4264/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
4265/***/ (function(module, exports, __webpack_require__) {
4266
4267"use strict";
4268/* WEBPACK VAR INJECTION */(function(Number) {
4269Object.defineProperty(exports, "__esModule", { value: true });
4270var binary_search_1 = __webpack_require__(/*! ../utils/binary-search */ "./src/utils/binary-search.js");
4271/**
4272 * Returns first fragment whose endPdt value exceeds the given PDT.
4273 * @param {Array<Fragment>} fragments - The array of candidate fragments
4274 * @param {number|null} [PDTValue = null] - The PDT value which must be exceeded
4275 * @param {number} [maxFragLookUpTolerance = 0] - The amount of time that a fragment's start/end can be within in order to be considered contiguous
4276 * @returns {*|null} fragment - The best matching fragment
4277 */
4278function findFragmentByPDT(fragments, PDTValue, maxFragLookUpTolerance) {
4279    if (!Array.isArray(fragments) || !fragments.length || !Number.isFinite(PDTValue)) {
4280        return null;
4281    }
4282    // if less than start
4283    if (PDTValue < fragments[0].programDateTime) {
4284        return null;
4285    }
4286    if (PDTValue >= fragments[fragments.length - 1].endProgramDateTime) {
4287        return null;
4288    }
4289    maxFragLookUpTolerance = maxFragLookUpTolerance || 0;
4290    for (var seg = 0; seg < fragments.length; ++seg) {
4291        var frag = fragments[seg];
4292        if (pdtWithinToleranceTest(PDTValue, maxFragLookUpTolerance, frag)) {
4293            return frag;
4294        }
4295    }
4296    return null;
4297}
4298exports.findFragmentByPDT = findFragmentByPDT;
4299/**
4300 * Finds a fragment based on the SN of the previous fragment; or based on the needs of the current buffer.
4301 * This method compensates for small buffer gaps by applying a tolerance to the start of any candidate fragment, thus
4302 * breaking any traps which would cause the same fragment to be continuously selected within a small range.
4303 * @param {*} fragPrevious - The last frag successfully appended
4304 * @param {Array<Fragment>} fragments - The array of candidate fragments
4305 * @param {number} [bufferEnd = 0] - The end of the contiguous buffered range the playhead is currently within
4306 * @param {number} maxFragLookUpTolerance - The amount of time that a fragment's start/end can be within in order to be considered contiguous
4307 * @returns {*} foundFrag - The best matching fragment
4308 */
4309function findFragmentByPTS(fragPrevious, fragments, bufferEnd, maxFragLookUpTolerance) {
4310    if (bufferEnd === void 0) { bufferEnd = 0; }
4311    if (maxFragLookUpTolerance === void 0) { maxFragLookUpTolerance = 0; }
4312    var fragNext = fragPrevious ? fragments[fragPrevious.sn - fragments[0].sn + 1] : null;
4313    // Prefer the next fragment if it's within tolerance
4314    if (fragNext && !fragmentWithinToleranceTest(bufferEnd, maxFragLookUpTolerance, fragNext)) {
4315        return fragNext;
4316    }
4317    return binary_search_1.default.search(fragments, fragmentWithinToleranceTest.bind(null, bufferEnd, maxFragLookUpTolerance));
4318}
4319exports.findFragmentByPTS = findFragmentByPTS;
4320/**
4321 * The test function used by the findFragmentBySn's BinarySearch to look for the best match to the current buffer conditions.
4322 * @param {*} candidate - The fragment to test
4323 * @param {number} [bufferEnd = 0] - The end of the current buffered range the playhead is currently within
4324 * @param {number} [maxFragLookUpTolerance = 0] - The amount of time that a fragment's start can be within in order to be considered contiguous
4325 * @returns {number} - 0 if it matches, 1 if too low, -1 if too high
4326 */
4327function fragmentWithinToleranceTest(bufferEnd, maxFragLookUpTolerance, candidate) {
4328    if (bufferEnd === void 0) { bufferEnd = 0; }
4329    if (maxFragLookUpTolerance === void 0) { maxFragLookUpTolerance = 0; }
4330    // offset should be within fragment boundary - config.maxFragLookUpTolerance
4331    // this is to cope with situations like
4332    // bufferEnd = 9.991
4333    // frag[Ø] : [0,10]
4334    // frag[1] : [10,20]
4335    // bufferEnd is within frag[0] range ... although what we are expecting is to return frag[1] here
4336    //              frag start               frag start+duration
4337    //                  |-----------------------------|
4338    //              <--->                         <--->
4339    //  ...--------><-----------------------------><---------....
4340    // previous frag         matching fragment         next frag
4341    //  return -1             return 0                 return 1
4342    // logger.log(`level/sn/start/end/bufEnd:${level}/${candidate.sn}/${candidate.start}/${(candidate.start+candidate.duration)}/${bufferEnd}`);
4343    // Set the lookup tolerance to be small enough to detect the current segment - ensures we don't skip over very small segments
4344    var candidateLookupTolerance = Math.min(maxFragLookUpTolerance, candidate.duration + (candidate.deltaPTS ? candidate.deltaPTS : 0));
4345    if (candidate.start + candidate.duration - candidateLookupTolerance <= bufferEnd) {
4346        return 1;
4347    }
4348    else if (candidate.start - candidateLookupTolerance > bufferEnd && candidate.start) {
4349        // if maxFragLookUpTolerance will have negative value then don't return -1 for first element
4350        return -1;
4351    }
4352    return 0;
4353}
4354exports.fragmentWithinToleranceTest = fragmentWithinToleranceTest;
4355/**
4356 * The test function used by the findFragmentByPdt's BinarySearch to look for the best match to the current buffer conditions.
4357 * This function tests the candidate's program date time values, as represented in Unix time
4358 * @param {*} candidate - The fragment to test
4359 * @param {number} [pdtBufferEnd = 0] - The Unix time representing the end of the current buffered range
4360 * @param {number} [maxFragLookUpTolerance = 0] - The amount of time that a fragment's start can be within in order to be considered contiguous
4361 * @returns {boolean} True if contiguous, false otherwise
4362 */
4363function pdtWithinToleranceTest(pdtBufferEnd, maxFragLookUpTolerance, candidate) {
4364    var candidateLookupTolerance = Math.min(maxFragLookUpTolerance, candidate.duration + (candidate.deltaPTS ? candidate.deltaPTS : 0)) * 1000;
4365    return candidate.endProgramDateTime - candidateLookupTolerance > pdtBufferEnd;
4366}
4367exports.pdtWithinToleranceTest = pdtWithinToleranceTest;
4368
4369/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.js")["Number"]))
4370
4371/***/ }),
4372
vendor: 10,373 bytes, lines 4373-4599
4373/***/ "./src/controller/fragment-tracker.js":
4374/*!********************************************!*\
4375  !*** ./src/controller/fragment-tracker.js ***!
4376  \********************************************/
4377/*! no static exports found */
4378/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
4379/***/ (function(module, exports, __webpack_require__) {
4380
4381"use strict";
4382/* WEBPACK VAR INJECTION */(function(Number) {
4383var __extends = (this && this.__extends) || (function () {
4384    var extendStatics = Object.setPrototypeOf ||
4385        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
4386        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
4387    return function (d, b) {
4388        extendStatics(d, b);
4389        function __() { this.constructor = d; }
4390        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
4391    };
4392})();
4393Object.defineProperty(exports, "__esModule", { value: true });
4394var event_handler_1 = __webpack_require__(/*! ../event-handler */ "./src/event-handler.js");
4395var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
4396exports.FragmentState = {
4397    NOT_LOADED: 'NOT_LOADED',
4398    APPENDING: 'APPENDING',
4399    PARTIAL: 'PARTIAL',
4400    OK: 'OK'
4401};
4402var FragmentTracker = /** @class */ (function (_super) {
4403    __extends(FragmentTracker, _super);
4404    function FragmentTracker(hls) {
4405        var _this = _super.call(this, hls, events_1.default.BUFFER_APPENDED, events_1.default.FRAG_BUFFERED, events_1.default.FRAG_LOADED) || this;
4406        _this.bufferPadding = 0.2;
4407        _this.fragments = Object.create(null);
4408        _this.timeRanges = Object.create(null);
4409        _this.config = hls.config;
4410        return _this;
4411    }
4412    FragmentTracker.prototype.destroy = function () {
4413        this.fragments = Object.create(null);
4414        this.timeRanges = Object.create(null);
4415        this.config = null;
4416        event_handler_1.default.prototype.destroy.call(this);
4417        _super.prototype.destroy.call(this);
4418    };
4419    /**
4420     * Return a Fragment that match the position and levelType.
4421     * If not found any Fragment, return null
4422     * @param {number} position
4423     * @param {LevelType} levelType
4424     * @returns {Fragment|null}
4425     */
4426    FragmentTracker.prototype.getBufferedFrag = function (position, levelType) {
4427        var fragments = this.fragments;
4428        var bufferedFrags = Object.keys(fragments).filter(function (key) {
4429            var fragmentEntity = fragments[key];
4430            if (fragmentEntity.body.type !== levelType) {
4431                return false;
4432            }
4433            if (!fragmentEntity.buffered) {
4434                return false;
4435            }
4436            var frag = fragmentEntity.body;
4437            return frag.startPTS <= position && position <= frag.endPTS;
4438        });
4439        if (bufferedFrags.length === 0) {
4440            return null;
4441        }
4442        else {
4443            // https://github.com/video-dev/hls.js/pull/1545#discussion_r166229566
4444            var bufferedFragKey = bufferedFrags.pop();
4445            return fragments[bufferedFragKey].body;
4446        }
4447    };
4448    /**
4449     * Partial fragments effected by coded frame eviction will be removed
4450     * The browser will unload parts of the buffer to free up memory for new buffer data
4451     * 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)
4452     * @param {String} elementaryStream The elementaryStream of media this is (eg. video/audio)
4453     * @param {TimeRanges} timeRange TimeRange object from a sourceBuffer
4454     */
4455    FragmentTracker.prototype.detectEvictedFragments = function (elementaryStream, timeRange) {
4456        var _this = this;
4457        var fragmentTimes, time;
4458        // Check if any flagged fragments have been unloaded
4459        Object.keys(this.fragments).forEach(function (key) {
4460            var fragmentEntity = _this.fragments[key];
4461            if (fragmentEntity.buffered === true) {
4462                var esData = fragmentEntity.range[elementaryStream];
4463                if (esData) {
4464                    fragmentTimes = esData.time;
4465                    for (var i = 0; i < fragmentTimes.length; i++) {
4466                        time = fragmentTimes[i];
4467                        if (_this.isTimeBuffered(time.startPTS, time.endPTS, timeRange) === false) {
4468                            // Unregister partial fragment as it needs to load again to be reused
4469                            _this.removeFragment(fragmentEntity.body);
4470                            break;
4471                        }
4472                    }
4473                }
4474            }
4475        });
4476    };
4477    /**
4478     * Checks if the fragment passed in is loaded in the buffer properly
4479     * Partially loaded fragments will be registered as a partial fragment
4480     * @param {Object} fragment Check the fragment against all sourceBuffers loaded
4481     */
4482    FragmentTracker.prototype.detectPartialFragments = function (fragment) {
4483        var _this = this;
4484        var fragKey = this.getFragmentKey(fragment);
4485        var fragmentEntity = this.fragments[fragKey];
4486        if (fragmentEntity) {
4487            fragmentEntity.buffered = true;
4488            Object.keys(this.timeRanges).forEach(function (elementaryStream) {
4489                if (fragment.hasElementaryStream(elementaryStream)) {
4490                    var timeRange = _this.timeRanges[elementaryStream];
4491                    // Check for malformed fragments
4492                    // Gaps need to be calculated for each elementaryStream
4493                    fragmentEntity.range[elementaryStream] = _this.getBufferedTimes(fragment.startPTS, fragment.endPTS, timeRange);
4494                }
4495            });
4496        }
4497    };
4498    FragmentTracker.prototype.getBufferedTimes = function (startPTS, endPTS, timeRange) {
4499        var fragmentTimes = [];
4500        var startTime, endTime;
4501        var fragmentPartial = false;
4502        for (var i = 0; i < timeRange.length; i++) {
4503            startTime = timeRange.start(i) - this.bufferPadding;
4504            endTime = timeRange.end(i) + this.bufferPadding;
4505            if (startPTS >= startTime && endPTS <= endTime) {
4506                // Fragment is entirely contained in buffer
4507                // No need to check the other timeRange times since it's completely playable
4508                fragmentTimes.push({
4509                    startPTS: Math.max(startPTS, timeRange.start(i)),
4510                    endPTS: Math.min(endPTS, timeRange.end(i))
4511                });
4512                break;
4513            }
4514            else if (startPTS < endTime && endPTS > startTime) {
4515                // Check for intersection with buffer
4516                // Get playable sections of the fragment
4517                fragmentTimes.push({
4518                    startPTS: Math.max(startPTS, timeRange.start(i)),
4519                    endPTS: Math.min(endPTS, timeRange.end(i))
4520                });
4521                fragmentPartial = true;
4522            }
4523            else if (endPTS <= startTime) {
4524                // No need to check the rest of the timeRange as it is in order
4525                break;
4526            }
4527        }
4528        return {
4529            time: fragmentTimes,
4530            partial: fragmentPartial
4531        };
4532    };
4533    FragmentTracker.prototype.getFragmentKey = function (fragment) {
4534        return fragment.type + "_" + fragment.level + "_" + fragment.urlId + "_" + fragment.sn;
4535    };
4536    /**
4537     * Gets the partial fragment for a certain time
4538     * @param {Number} time
4539     * @returns {Object} fragment Returns a partial fragment at a time or null if there is no partial fragment
4540     */
4541    FragmentTracker.prototype.getPartialFragment = function (time) {
4542        var _this = this;
4543        var timePadding, startTime, endTime;
4544        var bestFragment = null;
4545        var bestOverlap = 0;
4546        Object.keys(this.fragments).forEach(function (key) {
4547            var fragmentEntity = _this.fragments[key];
4548            if (_this.isPartial(fragmentEntity)) {
4549                startTime = fragmentEntity.body.startPTS - _this.bufferPadding;
4550                endTime = fragmentEntity.body.endPTS + _this.bufferPadding;
4551                if (time >= startTime && time <= endTime) {
4552                    // Use the fragment that has the most padding from start and end time
4553                    timePadding = Math.min(time - startTime, endTime - time);
4554                    if (bestOverlap <= timePadding) {
4555                        bestFragment = fragmentEntity.body;
4556                        bestOverlap = timePadding;
4557                    }
4558                }
4559            }
4560        });
4561        return bestFragment;
4562    };
4563    /**
4564     * @param {Object} fragment The fragment to check
4565     * @returns {String} Returns the fragment state when a fragment never loaded or if it partially loaded
4566     */
4567    FragmentTracker.prototype.getState = function (fragment) {
4568        var fragKey = this.getFragmentKey(fragment);
4569        var fragmentEntity = this.fragments[fragKey];
4570        var state = exports.FragmentState.NOT_LOADED;
4571        if (fragmentEntity !== undefined) {
4572            if (!fragmentEntity.buffered) {
4573                state = exports.FragmentState.APPENDING;
4574            }
4575            else if (this.isPartial(fragmentEntity) === true) {
4576                state = exports.FragmentState.PARTIAL;
4577            }
4578            else {
4579                state = exports.FragmentState.OK;
4580            }
4581        }
4582        return state;
4583    };
4584    FragmentTracker.prototype.isPartial = function (fragmentEntity) {
4585        return fragmentEntity.buffered === true &&
4586            ((fragmentEntity.range.video !== undefined && fragmentEntity.range.video.partial === true) ||
4587                (fragmentEntity.range.audio !== undefined && fragmentEntity.range.audio.partial === true));
4588    };
4589    FragmentTracker.prototype.isTimeBuffered = function (startPTS, endPTS, timeRange) {
4590        var startTime, endTime;
4591        for (var i = 0; i < timeRange.length; i++) {
4592            startTime = timeRange.start(i) - this.bufferPadding;
4593            endTime = timeRange.end(i) + this.bufferPadding;
4594            if (startPTS >= startTime && endPTS <= endTime) {
4595                return true;
4596            }
4597            if (endPTS <= startTime) {
4598                // No need to check the rest of the timeRange as it is in order
4599                return false;
4600            }
4601        }
4602        return false;
4603    };
4604    /**
4605     * Fires when a fragment loading is completed
4606     */
4607    FragmentTracker.prototype.onFragLoaded = function (e) {
4608        var fragment = e.frag;
4609        // don't track initsegment (for which sn is not a number)
4610        // don't track frags used for bitrateTest, they're irrelevant.
4611        if (!Number.isFinite(fragment.sn) || fragment.bitrateTest) {
4612            return;
4613        }
4614        this.fragments[this.getFragmentKey(fragment)] = {
4615            body: fragment,
4616            range: Object.create(null),
4617            buffered: false
4618        };
4619    };
4620    /**
4621     * Fires when the buffer is updated
4622     */
4623    FragmentTracker.prototype.onBufferAppended = function (e) {
4624        var _this = this;
4625        // Store the latest timeRanges loaded in the buffer
4626        this.timeRanges = e.timeRanges;
4627        Object.keys(this.timeRanges).forEach(function (elementaryStream) {
4628            var timeRange = _this.timeRanges[elementaryStream];
4629            _this.detectEvictedFragments(elementaryStream, timeRange);
4630        });
4631    };
4632    /**
4633     * Fires after a fragment has been loaded into the source buffer
4634     */
4635    FragmentTracker.prototype.onFragBuffered = function (e) {
4636        this.detectPartialFragments(e.frag);
4637    };
4638    /**
4639     * Return true if fragment tracker has the fragment.
4640     * @param {Object} fragment
4641     * @returns {boolean}
4642     */
4643    FragmentTracker.prototype.hasFragment = function (fragment) {
4644        var fragKey = this.getFragmentKey(fragment);
4645        return this.fragments[fragKey] !== undefined;
4646    };
4647    /**
4648     * Remove a fragment from fragment tracker until it is loaded again
4649     * @param {Object} fragment The fragment to remove
4650     */
4651    FragmentTracker.prototype.removeFragment = function (fragment) {
4652        var fragKey = this.getFragmentKey(fragment);
4653        delete this.fragments[fragKey];
4654    };
4655    /**
4656     * Remove all fragments from fragment tracker.
4657     */
4658    FragmentTracker.prototype.removeAllFragments = function () {
4659        this.fragments = Object.create(null);
4660    };
4661    return FragmentTracker;
4662}(event_handler_1.default));
4663exports.FragmentTracker = FragmentTracker;
4664
4665/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.js")["Number"]))
4666
4667/***/ }),
4668
4669/***/ "./src/controller/gap-controller.js":
4670/*!******************************************!*\
4671  !*** ./src/controller/gap-controller.js ***!
4672  \******************************************/
4673/*! no static exports found */
4674/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
4675/***/ (function(module, exports, __webpack_require__) {
4676
4677"use strict";
4678
4679Object.defineProperty(exports, "__esModule", { value: true });
4680var buffer_helper_1 = __webpack_require__(/*! ../utils/buffer-helper */ "./src/utils/buffer-helper.js");
4681var errors_1 = __webpack_require__(/*! ../errors */ "./src/errors.js");
4682var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
4683var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
4684var stallDebounceInterval = 1000;
4685var jumpThreshold = 0.5; // tolerance needed as some browsers stalls playback before reaching buffered range end
4686var GapController = /** @class */ (function () {
4687    function GapController(config, media, fragmentTracker, hls) {
4688        this.config = config;
4689        this.media = media;
4690        this.fragmentTracker = fragmentTracker;
4691        this.hls = hls;
4692        this.stallReported = false;
4693    }
4694    /**
4695     * Checks if the playhead is stuck within a gap, and if so, attempts to free it.
4696     * A gap is an unbuffered range between two buffered ranges (or the start and the first buffered range).
4697     * @param lastCurrentTime
4698     * @param buffered
4699     */
4700    GapController.prototype.poll = function (lastCurrentTime, buffered) {
4701        var _a = this, config = _a.config, media = _a.media;
4702        var currentTime = media.currentTime;
4703        var tnow = window.performance.now();
4704        if (currentTime !== lastCurrentTime) {
4705            // The playhead is now moving, but was previously stalled
4706            if (this.stallReported) {
4707                logger_1.logger.warn("playback not stuck anymore @" + currentTime + ", after " + Math.round(tnow - this.stalled) + "ms");
4708                this.stallReported = false;
4709            }
4710            this.stalled = null;
4711            this.nudgeRetry = 0;
4712            return;
4713        }
4714        if (media.ended || !media.buffered.length || media.readyState > 2) {
4715            return;
4716        }
4717        if (media.seeking && buffer_helper_1.BufferHelper.isBuffered(media, currentTime)) {
4718            return;
4719        }
4720        // The playhead isn't moving but it should be
4721        // Allow some slack time to for small stalls to resolve themselves
4722        var stalledDuration = tnow - this.stalled;
4723        var bufferInfo = buffer_helper_1.BufferHelper.bufferInfo(media, currentTime, config.maxBufferHole);
4724        if (!this.stalled) {
4725            this.stalled = tnow;
4726            return;
4727        }
4728        else if (stalledDuration >= stallDebounceInterval) {
4729            // Report stalling after trying to fix
4730            this._reportStall(bufferInfo.len);
4731        }
4732        this._tryFixBufferStall(bufferInfo, stalledDuration);
4733    };
4734    /**
4735     * Detects and attempts to fix known buffer stalling issues.
4736     * @param bufferInfo - The properties of the current buffer.
4737     * @param stalledDuration - The amount of time Hls.js has been stalling for.
4738     * @private
4739     */
4740    GapController.prototype._tryFixBufferStall = function (bufferInfo, stalledDuration) {
4741        var _a = this, config = _a.config, fragmentTracker = _a.fragmentTracker, media = _a.media;
4742        var currentTime = media.currentTime;
4743        var partial = fragmentTracker.getPartialFragment(currentTime);
4744        if (partial) {
4745            // Try to skip over the buffer hole caused by a partial fragment
4746            // This method isn't limited by the size of the gap between buffered ranges
4747            this._trySkipBufferHole(partial);
4748        }
4749        if (bufferInfo.len > jumpThreshold && stalledDuration > config.highBufferWatchdogPeriod * 1000) {
4750            // Try to nudge currentTime over a buffer hole if we've been stalling for the configured amount of seconds
4751            // We only try to jump the hole if it's under the configured size
4752            // Reset stalled so to rearm watchdog timer
4753            this.stalled = null;
4754            this._tryNudgeBuffer();
4755        }
4756    };
4757    /**
4758     * Triggers a BUFFER_STALLED_ERROR event, but only once per stall period.
4759     * @param bufferLen - The playhead distance from the end of the current buffer segment.
4760     * @private
4761     */
4762    GapController.prototype._reportStall = function (bufferLen) {
4763        var _a = this, hls = _a.hls, media = _a.media, stallReported = _a.stallReported;
4764        if (!stallReported) {
4765            // Report stalled error once
4766            this.stallReported = true;
4767            logger_1.logger.warn("Playback stalling at @" + media.currentTime + " due to low buffer");
4768            hls.trigger(events_1.default.ERROR, {
4769                type: errors_1.ErrorTypes.MEDIA_ERROR,
4770                details: errors_1.ErrorDetails.BUFFER_STALLED_ERROR,
4771                fatal: false,
4772                buffer: bufferLen
4773            });
4774        }
4775    };
4776    /**
4777     * Attempts to fix buffer stalls by jumping over known gaps caused by partial fragments
4778     * @param partial - The partial fragment found at the current time (where playback is stalling).
4779     * @private
4780     */
4781    GapController.prototype._trySkipBufferHole = function (partial) {
4782        var _a = this, hls = _a.hls, media = _a.media;
4783        var currentTime = media.currentTime;
4784        var lastEndTime = 0;
4785        // Check if currentTime is between unbuffered regions of partial fragments
4786        for (var i = 0; i < media.buffered.length; i++) {
4787            var startTime = media.buffered.start(i);
4788            if (currentTime >= lastEndTime && currentTime < startTime) {
4789                media.currentTime = Math.max(startTime, media.currentTime + 0.1);
4790                logger_1.logger.warn("skipping hole, adjusting currentTime from " + currentTime + " to " + media.currentTime);
4791                this.stalled = null;
4792                hls.trigger(events_1.default.ERROR, {
4793                    type: errors_1.ErrorTypes.MEDIA_ERROR,
4794                    details: errors_1.ErrorDetails.BUFFER_SEEK_OVER_HOLE,
4795                    fatal: false,
4796                    reason: "fragment loaded with buffer holes, seeking from " + currentTime + " to " + media.currentTime,
4797                    frag: partial
4798                });
4799                return;
4800            }
4801            lastEndTime = media.buffered.end(i);
4802        }
4803    };
4804    /**
4805     * Attempts to fix buffer stalls by advancing the mediaElement's current time by a small amount.
4806     * @private
4807     */
4808    GapController.prototype._tryNudgeBuffer = function () {
4809        var _a = this, config = _a.config, hls = _a.hls, media = _a.media;
4810        var currentTime = media.currentTime;
4811        var nudgeRetry = (this.nudgeRetry || 0) + 1;
4812        this.nudgeRetry = nudgeRetry;
4813        if (nudgeRetry < config.nudgeMaxRetry) {
4814            var targetTime = currentTime + nudgeRetry * config.nudgeOffset;
4815            logger_1.logger.log("adjust currentTime from " + currentTime + " to " + targetTime);
4816            // playback stalled in buffered area ... let's nudge currentTime to try to overcome this
4817            media.currentTime = targetTime;
4818            hls.trigger(events_1.default.ERROR, {
4819                type: errors_1.ErrorTypes.MEDIA_ERROR,
4820                details: errors_1.ErrorDetails.BUFFER_NUDGE_ON_STALL,
4821                fatal: false
4822            });
4823        }
4824        else {
4825            logger_1.logger.error("still stuck in high buffer @" + currentTime + " after " + config.nudgeMaxRetry + ", raise fatal error");
4826            hls.trigger(events_1.default.ERROR, {
4827                type: errors_1.ErrorTypes.MEDIA_ERROR,
4828                details: errors_1.ErrorDetails.BUFFER_STALLED_ERROR,
4829                fatal: true
4830            });
4831        }
4832    };
4833    return GapController;
4834}());
4835exports.default = GapController;
4836
4837
4838/***/ }),
4839
4840/***/ "./src/controller/id3-track-controller.js":
4841/*!************************************************!*\
4842  !*** ./src/controller/id3-track-controller.js ***!
4843  \************************************************/
4844/*! no static exports found */
4845/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
4846/***/ (function(module, exports, __webpack_require__) {
4847
4848"use strict";
4849
4850/*
4851 * id3 metadata track controller
4852*/
4853var __extends = (this && this.__extends) || (function () {
4854    var extendStatics = Object.setPrototypeOf ||
4855        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
4856        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
4857    return function (d, b) {
4858        extendStatics(d, b);
4859        function __() { this.constructor = d; }
4860        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
4861    };
4862})();
4863Object.defineProperty(exports, "__esModule", { value: true });
4864var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
4865var event_handler_1 = __webpack_require__(/*! ../event-handler */ "./src/event-handler.js");
4866var id3_1 = __webpack_require__(/*! ../demux/id3 */ "./src/demux/id3.js");
4867var texttrack_utils_1 = __webpack_require__(/*! ../utils/texttrack-utils */ "./src/utils/texttrack-utils.js");
4868var ID3TrackController = /** @class */ (function (_super) {
4869    __extends(ID3TrackController, _super);
4870    function ID3TrackController(hls) {
4871        var _this = _super.call(this, hls, events_1.default.MEDIA_ATTA
4871CHED, events_1.default.MEDIA_DETACHING, events_1.default.FRAG_PARSING_METADATA) || this;
4872        _this.id3Track = undefined;
4873        _this.media = undefined;
4874        return _this;
4875    }
4876    ID3TrackController.prototype.destroy = function () {
4877        event_handler_1.default.prototype.destroy.call(this);
4878    };
4879    // Add ID3 metatadata text track.
4880    ID3TrackController.prototype.onMediaAttached = function (data) {
4881        this.media = data.media;
4882        if (!this.media) {
4883        }
4884    };
4885    ID3TrackController.prototype.onMediaDetaching = function () {
4886        texttrack_utils_1.clearCurrentCues(this.id3Track);
4887        this.id3Track = undefined;
4888        this.media = undefined;
4889    };
4890    ID3TrackController.prototype.getID3Track = function (textTracks) {
4891        for (var i = 0; i < textTracks.length; i++) {
4892            var textTrack = textTracks[i];
4893            if (textTrack.kind === 'metadata' && textTrack.label === 'id3') {
4894                // send 'addtrack' when reusing the textTrack for metadata,
4895                // same as what we do for captions
4896                texttrack_utils_1.sendAddTrackEvent(textTrack, this.media);
4897                return textTrack;
4898            }
4899        }
4900        return this.media.addTextTrack('metadata', 'id3');
4901    };
4902    ID3TrackController.prototype.onFragParsingMetadata = function (data) {
4903        var fragment = data.frag;
4904        var samples = data.samples;
4905        // create track dynamically
4906        if (!this.id3Track) {
4907            this.id3Track = this.getID3Track(this.media.textTracks);
4908            this.id3Track.mode = 'hidden';
4909        }
4910        // Attempt to recreate Safari functionality by creating
4911        // WebKitDataCue objects when available and store the decoded
4912        // ID3 data in the value property of the cue
4913        var Cue = window.WebKitDataCue || window.VTTCue || window.TextTrackCue;
4914        for (var i = 0; i < samples.length; i++) {
4915            var frames_1 = id3_1.default.getID3Frames(samples[i].data);
4916            if (frames_1) {
4917                var startTime = samples[i].pts;
4918                var endTime = i < samples.length - 1 ? samples[i + 1].pts : fragment.endPTS;
4919                // Give a slight bump to the endTime if it's equal to startTime to avoid a SyntaxError in IE
4920                if (startTime === endTime) {
4921                    endTime += 0.0001;
4922                }
4923                for (var j = 0; j < frames_1.length; j++) {
4924                    var frame = frames_1[j];
4925                    // Safari doesn't put the timestamp frame in the TextTrack
4926                    if (!id3_1.default.isTimeStampFrame(frame)) {
4927                        var cue = new Cue(startTime, endTime, '');
4928                        cue.value = frame;
4929                        this.id3Track.addCue(cue);
4930                    }
4931                }
4932            }
4933        }
4934    };
4935    return ID3TrackController;
4936}(event_handler_1.default));
4937exports.default = ID3TrackController;
4938
4939
4940/***/ }),
4941
vendor: 7,571 bytes, lines 4942-5110
4942/***/ "./src/controller/level-controller.js":
4943/*!********************************************!*\
4944  !*** ./src/controller/level-controller.js ***!
4945  \********************************************/
4946/*! no static exports found */
4947/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
4948/***/ (function(module, exports, __webpack_require__) {
4949
4950"use strict";
4951
4952/*
4953 * Level Controller
4954*/
4955var __extends = (this && this.__extends) || (function () {
4956    var extendStatics = Object.setPrototypeOf ||
4957        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
4958        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
4959    return function (d, b) {
4960        extendStatics(d, b);
4961        function __() { this.constructor = d; }
4962        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
4963    };
4964})();
4965Object.defineProperty(exports, "__esModule", { value: true });
4966var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
4967var event_handler_1 = __webpack_require__(/*! ../event-handler */ "./src/event-handler.js");
4968var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
4969var errors_1 = __webpack_require__(/*! ../errors */ "./src/errors.js");
4970var codecs_1 = __webpack_require__(/*! ../utils/codecs */ "./src/utils/codecs.js");
4971var level_helper_1 = __webpack_require__(/*! ./level-helper */ "./src/controller/level-helper.js");
4972var performance = window.performance;
4973var chromeOrFirefox;
4974var LevelController = /** @class */ (function (_super) {
4975    __extends(LevelController, _super);
4976    function LevelController(hls) {
4977        var _this = _super.call(this, hls, events_1.default.MANIFEST_LOADED, events_1.default.LEVEL_LOADED, events_1.default.AUDIO_TRACK_SWITCHED, events_1.default.FRAG_LOADED, events_1.default.ERROR) || this;
4978        _this.canload = false;
4979        _this.currentLevelIndex = null;
4980        _this.manualLevelIndex = -1;
4981        _this.timer = null;
4982        chromeOrFirefox = /chrome|firefox/.test(navigator.userAgent.toLowerCase());
4983        return _this;
4984    }
4985    LevelController.prototype.onHandlerDestroying = function () {
4986        this.clearTimer();
4987        this.manualLevelIndex = -1;
4988    };
4989    LevelController.prototype.clearTimer = function () {
4990        if (this.timer !== null) {
4991            clearTimeout(this.timer);
4992            this.timer = null;
4993        }
4994    };
4995    LevelController.prototype.startLoad = function () {
4996        var levels = this._levels;
4997        this.canload = true;
4998        this.levelRetryCount = 0;
4999        // clean up live level details to force reload them, and reset load errors
5000        if (levels) {
5001            levels.forEach(function (level) {
5002                level.loadError = 0;
5003                var levelDetails = level.details;
5004                if (levelDetails && levelDetails.live) {
5005                    level.details = undefined;
5006                }
5007            });
5008        }
5009        // speed up live playlist refresh if timer exists
5010        if (this.timer !== null) {
5011            this.loadLevel();
5012        }
5013    };
5014    LevelController.prototype.stopLoad = function () {
5015        this.canload = false;
5016    };
5017    LevelController.prototype.onManifestLoaded = function (data) {
5018        var levels = [];
5019        var audioTracks = [];
5020        var bitrateStart;
5021        var levelSet = {};
5022        var levelFromSet = null;
5023        var videoCodecFound = false;
5024        var audioCodecFound = false;
5025        // regroup redundant levels together
5026        data.levels.forEach(function (level) {
5027            var attributes = level.attrs;
5028            level.loadError = 0;
5029            level.fragmentError = false;
5030            videoCodecFound = videoCodecFound || !!level.videoCodec;
5031            audioCodecFound = audioCodecFound || !!level.audioCodec;
5032            // erase audio codec info if browser does not support mp4a.40.34.
5033            // demuxer will autodetect codec and fallback to mpeg/audio
5034            if (chromeOrFirefox && level.audioCodec && level.audioCodec.indexOf('mp4a.40.34') !== -1) {
5035                level.audioCodec = undefined;
5036            }
5037            levelFromSet = levelSet[level.bitrate]; // FIXME: we would also have to match the resolution here
5038            if (!levelFromSet) {
5039                level.url = [level.url];
5040                level.urlId = 0;
5041                levelSet[level.bitrate] = level;
5042                levels.push(level);
5043            }
5044            else {
5045                levelFromSet.url.push(level.url);
5046            }
5047            if (attributes) {
5048                if (attributes.AUDIO) {
5049                    audioCodecFound = true;
5050                    level_helper_1.addGroupId(levelFromSet || level, 'audio', attributes.AUDIO);
5051                }
5052                if (attributes.SUBTITLES) {
5053                    level_helper_1.addGroupId(levelFromSet || level, 'text', attributes.SUBTITLES);
5054                }
5055            }
5056        });
5057        // remove audio-only level if we also have levels with audio+video codecs signalled
5058        if (videoCodecFound && audioCodecFound) {
5059            levels = levels.filter(function (_a) {
5060                var videoCodec = _a.videoCodec;
5061                return !!videoCodec;
5062            });
5063        }
5064        // only keep levels with supported audio/video codecs
5065        levels = levels.filter(function (_a) {
5066            var audioCodec = _a.audioCodec, videoCodec = _a.videoCodec;
5067            return (!audioCodec || codecs_1.isCodecSupportedInMp4(audioCodec, 'audio')) && (!videoCodec || codecs_1.isCodecSupportedInMp4(videoCodec, 'video'));
5068        });
5069        if (data.audioTracks) {
5070            audioTracks = data.audioTracks.filter(function (track) { return !track.audioCodec || codecs_1.isCodecSupportedInMp4(track.audioCodec, 'audio'); });
5071            // Reassign id's after filtering since they're used as array indices
5072            audioTracks.forEach(function (track, index) {
5073                track.id = index;
5074            });
5075        }
5076        if (levels.length > 0) {
5077            // start bitrate is the first bitrate of the manifest
5078            bitrateStart = levels[0].bitrate;
5079            // sort level on bitrate
5080            levels.sort(function (a, b) { return a.bitrate - b.bitrate; });
5081            this._levels = levels;
5082            // find index of first level in sorted levels
5083            for (var i = 0; i < levels.length; i++) {
5084                if (levels[i].bitrate === bitrateStart) {
5085                    this._firstLevel = i;
5086                    logger_1.logger.log("manifest loaded," + levels.length + " level(s) found, first bitrate:" + bitrateStart);
5087                    break;
5088                }
5089            }
5090            // Audio is only alternate if manifest include a URI along with the audio group tag
5091            this.hls.trigger(events_1.default.MANIFEST_PARSED, {
5092                levels: levels,
5093                audioTracks: audioTracks,
5094                firstLevel: this._firstLevel,
5095                stats: data.stats,
5096                audio: audioCodecFound,
5097                video: videoCodecFound,
5098                altAudio: audioTracks.some(function (t) { return !!t.url; })
5099            });
5100        }
5101        else {
5102            this.hls.trigger(events_1.default.ERROR, {
5103                type: errors_1.ErrorTypes.MEDIA_ERROR,
5104                details: errors_1.ErrorDetails.MANIFEST_INCOMPATIBLE_CODECS_ERROR,
5105                fatal: true,
5106                url: this.hls.url,
5107                reason: 'no level with compatible codecs found in manifest'
5108            });
5109        }
5110    };
5111    Object.defineProperty(LevelController.prototype, "levels", {
5112        get: function () {
5113            return this._levels;
5114        },
5115        enumerable: true,
5116        configurable: true
5117    });
5118    Object.defineProperty(LevelController.prototype, "level", {
5119        get: function () {
5120            return this.currentLevelIndex;
5121        },
5122        set: function (newLevel) {
5123            var levels = this._levels;
5124            if (levels) {
5125                newLevel = Math.min(newLevel, levels.length - 1);
5126                if (this.currentLevelIndex !== newLevel || !levels[newLevel].details) {
5127                    this.setLevelInternal(newLevel);
5128                }
5129            }
5130        },
5131        enumerable: true,
5132        configurable: true
5133    });
5134    LevelController.prototype.setLevelInternal = function (newLevel) {
5135        var levels = this._levels;
5136        var hls = this.hls;
5137        // check if level idx is valid
5138        if (newLevel >= 0 && newLevel < levels.length) {
5139            // stopping live reloading timer if any
5140            this.clearTimer();
5141            if (this.currentLevelIndex !== newLevel) {
5142                logger_1.logger.log("switching to level " + newLevel);
5143                this.currentLevelIndex = newLevel;
5144                var levelProperties = levels[newLevel];
5145                levelProperties.level = newLevel;
5146                hls.trigger(events_1.default.LEVEL_SWITCHING, levelProperties);
5147            }
5148            var level = levels[newLevel];
5149            var levelDetails = level.details;
5150            // check if we need to load playlist for this level
5151            if (!levelDetails || levelDetails.live) {
5152                // level not retrieved yet, or live playlist we need to (re)load it
5153                var urlId = level.urlId;
5154                hls.trigger(events_1.default.LEVEL_LOADING, { url: level.url[urlId], level: newLevel, id: urlId });
5155            }
5156        }
5157        else {
5158            // invalid level id given, trigger error
5159            hls.trigger(events_1.default.ERROR, {
5160                type: errors_1.ErrorTypes.OTHER_ERROR,
5161                details: errors_1.ErrorDetails.LEVEL_SWITCH_ERROR,
5162                level: newLevel,
5163                fatal: false,
5164                reason: 'invalid level idx'
5165            });
5166        }
5167    };
5168    Object.defineProperty(LevelController.prototype, "manualLevel", {
5169        get: function () {
5170            return this.manualLevelIndex;
5171        },
5172        set: function (newLevel) {
5173            this.manualLevelIndex = newLevel;
5174            if (this._startLevel === undefined) {
5175                this._startLevel = newLevel;
5176            }
5177            if (newLevel !== -1) {
5178                this.level = newLevel;
5179            }
5180        },
5181        enumerable: true,
5182        configurable: true
5183    });
5184    Object.defineProperty(LevelController.prototype, "firstLevel", {
5185        get: function () {
5186            return this._firstLevel;
5187        },
5188        set: function (newLevel) {
5189            this._firstLevel = newLevel;
5190        },
5191        enumerable: true,
5192        configurable: true
5193    });
5194    Object.defineProperty(LevelController.prototype, "startLevel", {
5195        get: function () {
5196            // hls.startLevel takes precedence over config.startLevel
5197            // if none of these values are defined, fallback on this._firstLevel (first quality level appearing in variant manifest)
5198            if (this._startLevel === undefined) {
5199                var configStartLevel = this.hls.config.startLevel;
5200                if (configStartLevel !== undefined) {
5201                    return configStartLevel;
5202                }
5203                else {
5204                    return this._firstLevel;
5205                }
5206            }
5207            else {
5208                return this._startLevel;
5209            }
5210        },
5211        set: function (newLevel) {
5212            this._startLevel = newLevel;
5213        },
5214        enumerable: true,
5215        configurable: true
5216    });
5217    LevelController.prototype.onError = function (data) {
5218        if (data.fatal) {
5219            if (data.type === errors_1.ErrorTypes.NETWORK_ERROR) {
5220                this.clearTimer();
5221            }
5222            return;
5223        }
5224        var levelError = false, fragmentError = false;
5225        var levelIndex;
5226        // try to recover not fatal errors
5227        switch (data.details) {
5228            case errors_1.ErrorDetails.FRAG_LOAD_ERROR:
5229            case errors_1.ErrorDetails.FRAG_LOAD_TIMEOUT:
5230            case errors_1.ErrorDetails.KEY_LOAD_ERROR:
5231            case errors_1.ErrorDetails.KEY_LOAD_TIMEOUT:
5232                levelIndex = data.frag.level;
5233                fragmentError = true;
5234                break;
5235            case errors_1.ErrorDetails.LEVEL_LOAD_ERROR:
5236            case errors_1.ErrorDetails.LEVEL_LOAD_TIMEOUT:
5237                levelIndex = data.context.level;
5238                levelError = true;
5239                break;
5240            case errors_1.ErrorDetails.REMUX_ALLOC_ERROR:
5241                levelIndex = data.level;
5242                levelError = true;
5243                break;
5244        }
5245        if (levelIndex !== undefined) {
5246            this.recoverLevel(data, levelIndex, levelError, fragmentError);
5247        }
5248    };
5249    /**
5250     * Switch to a redundant stream if any available.
5251     * If redundant stream is not available, emergency switch down if ABR mode is enabled.
5252     *
5253     * @param {Object} errorEvent
5254     * @param {Number} levelIndex current level index
5255     * @param {Boolean} levelError
5256     * @param {Boolean} fragmentError
5257     */
5258    // FIXME Find a better abstraction where fragment/level retry management is well decoupled
5259    LevelController.prototype.recoverLevel = function (errorEvent, levelIndex, levelError, fragmentError) {
5260        var _this = this;
5261        var config = this.hls.config;
5262        var errorDetails = errorEvent.details;
5263        var level = this._levels[levelIndex];
5264        var redundantLevels, delay, nextLevel;
5265        level.loadError++;
5266        level.fragmentError = fragmentError;
5267        if (levelError) {
5268            if ((this.levelRetryCount + 1) <= config.levelLoadingMaxRetry) {
5269                // exponential backoff capped to max retry timeout
5270                delay = Math.min(Math.pow(2, this.levelRetryCount) * config.levelLoadingRetryDelay, config.levelLoadingMaxRetryTimeout);
5271                // Schedule level reload
5272                this.timer = setTimeout(function () { return _this.loadLevel(); }, delay);
5273                // boolean used to inform stream controller not to switch back to IDLE on non fatal error
5274                errorEvent.levelRetry = true;
5275                this.levelRetryCount++;
5276                logger_1.logger.warn("level controller, " + errorDetails + ", retry in " + delay + " ms, current retry count is " + this.levelRetryCount);
5277            }
5278            else {
5279                logger_1.logger.error("level controller, cannot recover from " + errorDetails + " error");
5280                this.currentLevelIndex = null;
5281                // stopping live reloading timer if any
5282                this.clearTimer();
5283                // switch error to fatal
5284                errorEvent.fatal = true;
5285                return;
5286            }
5287        }
5288        // Try any redundant streams if available for both errors: level and fragment
5289        // If level.loadError reaches redundantLevels it means that we tried them all, no hope  => let's switch down
5290        if (levelError || fragmentError) {
5291            redundantLevels = level.url.length;
5292            if (redundantLevels > 1 && level.loadError < redundantLevels) {
5293                level.urlId = (level.urlId + 1) % redundantLevels;
5294                level.details = undefined;
5295                logger_1.logger.warn("level controller, " + errorDetails + " for level " + levelIndex + ": switching to redundant URL-id " + level.urlId);
5296                // console.log('Current audio track group ID:', this.hls.audioTracks[this.hls.audioTrack].groupId);
5297                // console.log('New video quality level audio group id:', level.attrs.AUDIO);
5298            }
5299            else {
5300                // Search for available level
5301                if (this.manualLevelIndex === -1) {
5302                    // When lowest level has been reached, let's start hunt from the top
5303                    nextLevel = (levelIndex === 0) ? this._levels.length - 1 : levelIndex - 1;
5304                    logger_1.logger.warn("level controller, " + errorDetails + ": switch to " + nextLevel);
5305                    this.hls.nextAutoLevel = this.currentLevelIndex = nextLevel;
5306                }
5307                else if (fragmentError) {
5308                    // Allow fragment retry as long as configuration allows.
5309                    // reset this._level so that another call to set level() will trigger again a frag load
5310                    logger_1.logger.warn("level controller, " + errorDetails + ": reload a fragment");
5311                    this.currentLevelIndex = null;
5312                }
5313            }
5314        }
5315    };
5316    // reset errors on the successful load of a fragment
5317    LevelController.prototype.onFragLoaded = function (_a) {
5318        var frag = _a.frag;
5319        if (frag !== undefined && frag.type === 'main') {
5320            var level = this._levels[frag.level];
5321            if (level !== undefined) {
5322                level.fragmentError = false;
5323                level.loadError = 0;
5324                this.levelRetryCount = 0;
5325            }
5326        }
5327    };
5328    LevelController.prototype.onLevelLoaded = function (data) {
5329        var _this = this;
5330        var level = data.level, details = data.details;
5331        // only process level loaded events matching with expected level
5332        if (level !== this.currentLevelIndex) {
5333            return;
5334        }
5335        var curLevel = this._levels[level];
5336        // reset level load error counter on successful level loaded only if there is no issues with fragments
5337        if (!curLevel.fragmentError) {
5338            curLevel.loadError = 0;
5339            this.levelRetryCount = 0;
5340        }
5341        // if current playlist is a live playlist, arm a timer to reload it
5342        if (details.live) {
5343            var reloadInterval = level_helper_1.computeReloadInterval(curLevel.details, details, data.stats.trequest);
5344            logger_1.logger.log("live playlist, reload in " + Math.round(reloadInterval) + " ms");
5345            this.timer = setTimeout(function () { return _this.loadLevel(); }, reloadInterval);
5346        }
5347        else {
5348            this.clearTimer();
5349        }
5350    };
5351    LevelController.prototype.onAudioTrackSwitched = function (data) {
5352        var audioGroupId = this.hls.audioTracks[data.id].groupId;
5353        var currentLevel = this.hls.levels[this.currentLevelIndex];
5354        if (!currentLevel) {
5355            return;
5356        }
5357        if (currentLevel.audioGroupIds) {
5358            var urlId = -1;
5359            for (var i = 0; i < currentLevel.audioGroupIds.length; i++) {
5360                if (currentLevel.audioGroupIds[i] === audioGroupId) {
5361                    urlId = i;
5362                    break;
5363                }
5364            }
5365            if (urlId !== currentLevel.urlId) {
5366                currentLevel.urlId = urlId;
5367                this.startLoad();
5368            }
5369        }
5370    };
5371    LevelController.prototype.loadLevel = function () {
5372        logger_1.logger.debug('call to loadLevel');
5373        if (this.currentLevelIndex !== null && this.canload) {
5374            var levelObject = this._levels[this.currentLevelIndex];
5375            if (typeof levelObject === 'object' &&
5376                levelObject.url.length > 0) {
5377                var level = this.currentLevelIndex;
5378                var id = levelObject.urlId;
5379                var url = levelObject.url[id];
5380                logger_1.logger.log("Attempt loading level index " + level + " with URL-id " + id);
5381                // console.log('Current audio track group ID:', this.hls.audioTracks[this.hls.audioTrack].groupId);
5382                // console.log('New video quality level audio group id:', levelObject.attrs.AUDIO, level);
5383                this.hls.trigger(events_1.default.LEVEL_LOADING, { url: url, level: level, id: id });
5384            }
5385        }
5386    };
5387    Object.defineProperty(LevelController.prototype, "nextLoadLevel", {
5388        get: function () {
5389            if (this.manualLevelIndex !== -1) {
5390                return this.manualLevelIndex;
5391            }
5392            else {
5393                return this.hls.nextAutoLevel;
5394            }
5395        },
5396        set: function (nextLevel) {
5397            this.level = nextLevel;
5398            if (this.manualLevelIndex === -1) {
5399                this.hls.nextAutoLevel = nextLevel;
5400            }
5401        },
5402        enumerable: true,
5403        configurable: true
5404    });
5405    return LevelController;
5406}(event_handler_1.default));
5407exports.default = LevelController;
5408
5409
5410/***/ }),
5411
vendor: 9,495 bytes, lines 5412-5645
5412/***/ "./src/controller/level-helper.js":
5413/*!****************************************!*\
5414  !*** ./src/controller/level-helper.js ***!
5415  \****************************************/
5416/*! no static exports found */
5417/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
5418/***/ (function(module, exports, __webpack_require__) {
5419
5420"use strict";
5421/* WEBPACK VAR INJECTION */(function(Number) {
5422/**
5423 * @module LevelHelper
5424 *
5425 * Providing methods dealing with playlist sliding and drift
5426 *
5427 * TODO: Create an actual `Level` class/model that deals with all this logic in an object-oriented-manner.
5428 *
5429 * */
5430Object.defineProperty(exports, "__esModule", { value: true });
5431var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
5432function addGroupId(level, type, id) {
5433    switch (type) {
5434        case 'audio':
5435            if (!level.audioGroupIds) {
5436                level.audioGroupIds = [];
5437            }
5438            level.audioGroupIds.push(id);
5439            break;
5440        case 'text':
5441            if (!level.textGroupIds) {
5442                level.textGroupIds = [];
5443            }
5444            level.textGroupIds.push(id);
5445            break;
5446    }
5447}
5448exports.addGroupId = addGroupId;
5449function updatePTS(fragments, fromIdx, toIdx) {
5450    var fragFrom = fragments[fromIdx], fragTo = fragments[toIdx], fragToPTS = fragTo.startPTS;
5451    // if we know startPTS[toIdx]
5452    if (Number.isFinite(fragToPTS)) {
5453        // update fragment duration.
5454        // it helps to fix drifts between playlist reported duration and fragment real duration
5455        if (toIdx > fromIdx) {
5456            fragFrom.duration = fragToPTS - fragFrom.start;
5457            if (fragFrom.duration < 0) {
5458                logger_1.logger.warn("negative duration computed for frag " + fragFrom.sn + ",level " + fragFrom.level + ", there should be some duration drift between playlist and fragment!");
5459            }
5460        }
5461        else {
5462            fragTo.duration = fragFrom.start - fragToPTS;
5463            if (fragTo.duration < 0) {
5464                logger_1.logger.warn("negative duration computed for frag " + fragTo.sn + ",level " + fragTo.level + ", there should be some duration drift between playlist and fragment!");
5465            }
5466        }
5467    }
5468    else {
5469        // we dont know startPTS[toIdx]
5470        if (toIdx > fromIdx) {
5471            fragTo.start = fragFrom.start + fragFrom.duration;
5472        }
5473        else {
5474            fragTo.start = Math.max(fragFrom.start - fragTo.duration, 0);
5475        }
5476    }
5477}
5478exports.updatePTS = updatePTS;
5479function updateFragPTSDTS(details, frag, startPTS, endPTS, startDTS, endDTS) {
5480    // update frag PTS/DTS
5481    var maxStartPTS = startPTS;
5482    if (Number.isFinite(frag.startPTS)) {
5483        // delta PTS between audio and video
5484        var deltaPTS = Math.abs(frag.startPTS - startPTS);
5485        if (!Number.isFinite(frag.deltaPTS)) {
5486            frag.deltaPTS = deltaPTS;
5487        }
5488        else {
5489            frag.deltaPTS = Math.max(deltaPTS, frag.deltaPTS);
5490        }
5491        maxStartPTS = Math.max(startPTS, frag.startPTS);
5492        startPTS = Math.min(startPTS, frag.startPTS);
5493        endPTS = Math.max(endPTS, frag.endPTS);
5494        startDTS = Math.min(startDTS, frag.startDTS);
5495        endDTS = Math.max(endDTS, frag.endDTS);
5496    }
5497    var drift = startPTS - frag.start;
5498    frag.start = frag.startPTS = startPTS;
5499    frag.maxStartPTS = maxStartPTS;
5500    frag.endPTS = endPTS;
5501    frag.startDTS = startDTS;
5502    frag.endDTS = endDTS;
5503    frag.duration = endPTS - startPTS;
5504    var sn = frag.sn;
5505    // exit if sn out of range
5506    if (!details || sn < details.startSN || sn > details.endSN) {
5507        return 0;
5508    }
5509    var fragIdx, fragments, i;
5510    fragIdx = sn - details.startSN;
5511    fragments = details.fragments;
5512    // update frag reference in fragments array
5513    // rationale is that fragments array might not contain this frag object.
5514    // this will happen if playlist has been refreshed between frag loading and call to updateFragPTSDTS()
5515    // if we don't update frag, we won't be able to propagate PTS info on the playlist
5516    // resulting in invalid sliding computation
5517    fragments[fragIdx] = frag;
5518    // adjust fragment PTS/duration from seqnum-1 to frag 0
5519    for (i = fragIdx; i > 0; i--) {
5520        updatePTS(fragments, i, i - 1);
5521    }
5522    // adjust fragment PTS/duration from seqnum to last frag
5523    for (i = fragIdx; i < fragments.length - 1; i++) {
5524        updatePTS(fragments, i, i + 1);
5525    }
5526    details.PTSKnown = true;
5527    return drift;
5528}
5529exports.updateFragPTSDTS = updateFragPTSDTS;
5530function mergeDetails(oldDetails, newDetails) {
5531    // potentially retrieve cached initsegment
5532    if (newDetails.initSegment && oldDetails.initSegment) {
5533        newDetails.initSegment = oldDetails.initSegment;
5534    }
5535    // check if old/new playlists have fragments in common
5536    // loop through overlapping SN and update startPTS , cc, and duration if any found
5537    var ccOffset = 0;
5538    var PTSFrag;
5539    mapFragmentIntersection(oldDetails, newDetails, function (oldFrag, newFrag) {
5540        ccOffset = oldFrag.cc - newFrag.cc;
5541        if (Number.isFinite(oldFrag.startPTS)) {
5542            newFrag.start = newFrag.startPTS = oldFrag.startPTS;
5543            newFrag.endPTS = oldFrag.endPTS;
5544            newFrag.duration = oldFrag.duration;
5545            newFrag.backtracked = oldFrag.backtracked;
5546            newFrag.dropped = oldFrag.dropped;
5547            PTSFrag = newFrag;
5548        }
5549        // PTS is known when there are overlapping segments
5550        newDetails.PTSKnown = true;
5551    });
5552    if (!newDetails.PTSKnown) {
5553        return;
5554    }
5555    if (ccOffset) {
5556        logger_1.logger.log('discontinuity sliding from playlist, take drift into account');
5557        var newFragments = newDetails.fragments;
5558        for (var i = 0; i < newFragments.length; i++) {
5559            newFragments[i].cc += ccOffset;
5560        }
5561    }
5562    // if at least one fragment contains PTS info, recompute PTS information for all fragments
5563    if (PTSFrag) {
5564        updateFragPTSDTS(newDetails, PTSFrag, PTSFrag.startPTS, PTSFrag.endPTS, PTSFrag.startDTS, PTSFrag.endDTS);
5565    }
5566    else {
5567        // ensure that delta is within oldFragments range
5568        // also adjust sliding in case delta is 0 (we could have old=[50-60] and new=old=[50-61])
5569        // in that case we also need to adjust start offset of all fragments
5570        adjustSliding(oldDetails, newDetails);
5571    }
5572    // if we are here, it means we have fragments overlapping between
5573    // old and new level. reliable PTS info is thus relying on old level
5574    newDetails.PTSKnown = oldDetails.PTSKnown;
5575}
5576exports.mergeDetails = mergeDetails;
5577function mergeSubtitlePlaylists(oldPlaylist, newPlaylist, referenceStart) {
5578    if (referenceStart === void 0) { referenceStart = 0; }
5579    var lastIndex = -1;
5580    mapFragmentIntersection(oldPlaylist, newPlaylist, function (oldFrag, newFrag, index) {
5581        newFrag.start = oldFrag.start;
5582        lastIndex = index;
5583    });
5584    var frags = newPlaylist.fragments;
5585    if (lastIndex < 0) {
5586        frags.forEach(function (frag) {
5587            frag.start += referenceStart;
5588        });
5589        return;
5590    }
5591    for (var i = lastIndex + 1; i < frags.length; i++) {
5592        frags[i].start = (frags[i - 1].start + frags[i - 1].duration);
5593    }
5594}
5595exports.mergeSubtitlePlaylists = mergeSubtitlePlaylists;
5596function mapFragmentIntersection(oldPlaylist, newPlaylist, intersectionFn) {
5597    if (!oldPlaylist || !newPlaylist) {
5598        return;
5599    }
5600    var start = Math.max(oldPlaylist.startSN, newPlaylist.startSN) - newPlaylist.startSN;
5601    var end = Math.min(oldPlaylist.endSN, newPlaylist.endSN) - newPlaylist.startSN;
5602    var delta = newPlaylist.startSN - oldPlaylist.startSN;
5603    for (var i = start; i <= end; i++) {
5604        var oldFrag = oldPlaylist.fragments[delta + i];
5605        var newFrag = newPlaylist.fragments[i];
5606        if (!oldFrag || !newFrag) {
5607            break;
5608        }
5609        intersectionFn(oldFrag, newFrag, i);
5610    }
5611}
5612exports.mapFragmentIntersection = mapFragmentIntersection;
5613function adjustSliding(oldPlaylist, newPlaylist) {
5614    var delta = newPlaylist.startSN - oldPlaylist.startSN;
5615    var oldFragments = oldPlaylist.fragments;
5616    var newFragments = newPlaylist.fragments;
5617    if (delta < 0 || delta > oldFragments.length) {
5618        return;
5619    }
5620    for (var i = 0; i < newFragments.length; i++) {
5621        newFragments[i].start += oldFragments[delta].start;
5622    }
5623}
5624exports.adjustSliding = adjustSliding;
5625function computeReloadInterval(currentPlaylist, newPlaylist, lastRequestTime) {
5626    var reloadInterval = 1000 * (newPlaylist.averagetargetduration ? newPlaylist.averagetargetduration : newPlaylist.targetduration);
5627    var minReloadInterval = reloadInterval / 2;
5628    if (currentPlaylist && newPlaylist.endSN === currentPlaylist.endSN) {
5629        // follow HLS Spec, If the client reloads a Playlist file and finds that it has not
5630        // changed then it MUST wait for a period of one-half the target
5631        // duration before retrying.
5632        reloadInterval = minReloadInterval;
5633    }
5634    if (lastRequestTime) {
5635        reloadInterval = Math.max(minReloadInterval, reloadInterval - (window.performance.now() - lastRequestTime));
5636    }
5637    // in any case, don't reload more than half of target duration
5638    return Math.round(reloadInterval);
5639}
5640exports.computeReloadInterval = computeReloadInterval;
5641
5642/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.js")["Number"]))
5643
5644/***/ }),
5645
5646/***/ "./src/controller/stream-controller.js":
5647/*!*********************************************!*\
5648  !*** ./src/controller/stream-controller.js ***!
5649  \*********************************************/
5650/*! no static exports found */
5651/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
5652/***/ (function(module, exports, __webpack_require__) {
5653
5654"use strict";
5655/* WEBPACK VAR INJECTION */(function(Number) {
5656/*
5657 * Stream Controller
5658*/
5659var __extends = (this && this.__extends) || (function () {
5660    var extendStatics = Object.setPrototypeOf ||
5661        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5662        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
5663    return function (d, b) {
5664        extendStatics(d, b);
5665        function __() { this.constructor = d; }
5666        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
5667    };
5668})();
5669Object.defineProperty(exports, "__esModule", { value: true });
5670var binary_search_1 = __webpack_require__(/*! ../utils/binary-search */ "./src/utils/binary-search.js");
5671var buffer_helper_1 = __webpack_require__(/*! ../utils/buffer-helper */ "./src/utils/buffer-helper.js");
5672var demuxer_1 = __webpack_require__(/*! ../demux/demuxer */ "./src/demux/demuxer.js");
5673var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
5674var fragment_tracker_1 = __webpack_require__(/*! ./fragment-tracker */ "./src/controller/fragment-tracker.js");
5675var fragment_1 = __webpack_require__(/*! ../loader/fragment */ "./src/loader/fragment.js");
5676var playlist_loader_1 = __webpack_require__(/*! ../loader/playlist-loader */ "./src/loader/playlist-loader.js");
5677var LevelHelper = __webpack_require__(/*! ./level-helper */ "./src/controller/level-helper.js");
5678var time_ranges_1 = __webpack_require__(/*! ../utils/time-ranges */ "./src/utils/time-ranges.js");
5679var errors_1 = __webpack_require__(/*! ../errors */ "./src/errors.js");
5680var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
5681var discontinuities_1 = __webpack_require__(/*! ../utils/discontinuities */ "./src/utils/discontinuities.js");
5682var fragment_finders_1 = __webpack_require__(/*! ./fragment-finders */ "./src/controller/fragment-finders.js");
5683var gap_controller_1 = __webpack_require__(/*! ./gap-controller */ "./src/controller/gap-controller.js");
5684var base_stream_controller_1 = __webpack_require__(/*! ./base-stream-controller */ "./src/controller/base-stream-controller.js");
5685var TICK_INTERVAL = 100; // how often to tick in ms
5686var StreamController = /** @class */ (function (_super) {
5687    __extends(StreamController, _super);
5688    function StreamController(hls, fragmentTracker) {
5689        var _this = _super.call(this, hls, events_1.default.MEDIA_ATTA
5689CHED, events_1.default.MEDIA_DETACHING, events_1.default.MANIFEST_LOADING, events_1.default.MANIFEST_PARSED, events_1.default.LEVEL_LOADED, events_1.default.KEY_LOADED, events_1.default.FRAG_LOADED, events_1.default.FRAG_LOAD_EMERGENCY_ABORTED, events_1.default.FRAG_PARSING_INIT_SEGMENT, events_1.default.FRAG_PARSING_DATA, events_1.default.FRAG_PARSED, events_1.default.ERROR, events_1.default.AUDIO_TRACK_SWITCHING, events_1.default.AUDIO_TRACK_SWITCHED, events_1.default.BUFFER_CREATED, events_1.default.BUFFER_APPENDED, events_1.default.BUFFER_FLUSHED) || this;
5690        _this.fragmentTracker = fragmentTracker;
5691        _this.config = hls.config;
5692        _this.audioCodecSwap = false;
5693        _this._state = base_stream_controller_1.State.STOPPED;
5694        _this.stallReported = false;
5695        _this.gapController = null;
5696        return _this;
5697    }
5698    StreamController.prototype.startLoad = function (startPosition) {
5699        if (this.levels) {
5700            var lastCurrentTime = this.lastCurrentTime, hls_1 = this.hls;
5701            this.stopLoad();
5702            this.setInterval(TICK_INTERVAL);
5703            this.level = -1;
5704            this.fragLoadError = 0;
5705            if (!this.startFragRequested) {
5706                // determine load level
5707                var startLevel = hls_1.startLevel;
5708                if (startLevel === -1) {
5709                    // -1 : guess start Level by doing a bitrate test by loading first fragment of lowest quality level
5710                    startLevel = 0;
5711                    this.bitrateTest = true;
5712                }
5713                // set new level to playlist loader : this will trigger start level load
5714                // hls.nextLoadLevel remains until it is set to a new value or until a new frag is successfully loaded
5715                this.level = hls_1.nextLoadLevel = startLevel;
5716                this.loadedmetadata = false;
5717            }
5718            // if startPosition undefined but lastCurrentTime set, set startPosition to last currentTime
5719            if (lastCurrentTime > 0 && startPosition === -1) {
5720                logger_1.logger.log("override startPosition with lastCurrentTime @" + lastCurrentTime.toFixed(3));
5721                startPosition = lastCurrentTime;
5722            }
5723            this.state = base_stream_controller_1.State.IDLE;
5724            this.nextLoadPosition = this.startPosition = this.lastCurrentTime = startPosition;
5725            this.tick();
5726        }
5727        else {
5728            this.forceStartLoad = true;
5729            this.state = base_stream_controller_1.State.STOPPED;
5730        }
5731    };
5732    StreamController.prototype.stopLoad = function () {
5733        this.forceStartLoad = false;
5734        _super.prototype.stopLoad.call(this);
5735    };
5736    StreamController.prototype.doTick = function () {
5737        switch (this.state) {
5738            case base_stream_controller_1.State.BUFFER_FLUSHING:
5739                // in buffer flushing state, reset fragLoadError counter
5740                this.fragLoadError = 0;
5741                break;
5742            case base_stream_controller_1.State.IDLE:
5743                this._doTickIdle();
5744                break;
5745            case base_stream_controller_1.State.WAITING_LEVEL:
5746                var level = this.levels[this.level];
5747                // check if playlist is already loaded
5748                if (level && level.details) {
5749                    this.state = base_stream_controller_1.State.IDLE;
5750                }
5751                break;
5752            case base_stream_controller_1.State.FRAG_LOADING_WAITING_RETRY:
5753                var now = window.performance.now();
5754                var retryDate = this.retryDate;
5755                // if current time is gt than retryDate, or if media seeking let's switch to IDLE state to retry loading
5756                if (!retryDate || (now >= retryDate) || (this.media && this.media.seeking)) {
5757                    logger_1.logger.log('mediaController: retryDate reached, switch back to IDLE state');
5758                    this.state = base_stream_controller_1.State.IDLE;
5759                }
5760                break;
5761            case base_stream_controller_1.State.ERROR:
5762            case base_stream_controller_1.State.STOPPED:
5763            case base_stream_controller_1.State.FRAG_LOADING:
5764            case base_stream_controller_1.State.PARSING:
5765            case base_stream_controller_1.State.PARSED:
5766            case base_stream_controller_1.State.ENDED:
5767                break;
5768            default:
5769                break;
5770        }
5771        // check buffer
5772        this._checkBuffer();
5773        // check/update current fragment
5774        this._checkFragmentChanged();
5775    };
5776    // Ironically the "idle" state is the on we do the most logic in it seems ....
5777    // NOTE: Maybe we could rather schedule a check for buffer length after half of the currently
5778    //       played segment, or on pause/play/seek instead of naively checking every 100ms?
5779    StreamController.prototype._doTickIdle = function () {
5780        var hls = this.hls, config = hls.config, media = this.media;
5781        // if start level not parsed yet OR
5782        // if video not attached AND start fragment already requested OR start frag prefetch disable
5783        // exit loop, as we either need more info (level not parsed) or we need media to be attached to load new fragment
5784        if (this.levelLastLoaded === undefined || (!media && (this.startFragRequested || !config.startFragPrefetch))) {
5785            return;
5786        }
5787        // if we have not yet loaded any fragment, start loading from start position
5788        var pos;
5789        if (this.loadedmetadata) {
5790            pos = media.currentTime;
5791        }
5792        else {
5793            pos = this.nextLoadPosition;
5794        }
5795        // determine next load level
5796        var level = hls.nextLoadLevel, levelInfo = this.levels[level];
5797        if (!levelInfo) {
5798            return;
5799        }
5800        var levelBitrate = levelInfo.bitrate, maxBufLen;
5801        // 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
5802        if (levelBitrate) {
5803            maxBufLen = Math.max(8 * config.maxBufferSize / levelBitrate, config.maxBufferLength);
5804        }
5805        else {
5806            maxBufLen = config.maxBufferLength;
5807        }
vendor: 9,873 bytes, lines 5808-5967
5808        maxBufLen = Math.min(maxBufLen, config.maxMaxBufferLength);
5809        // determine next candidate fragment to be loaded, based on current position and end of buffer position
5810        // ensure up to `config.maxMaxBufferLength` of buffer upfront
5811        var bufferInfo = buffer_helper_1.BufferHelper.bufferInfo(this.mediaBuffer ? this.mediaBuffer : media, pos, config.maxBufferHole), bufferLen = bufferInfo.len;
5812        // Stay idle if we are still with buffer margins
5813        if (bufferLen >= maxBufLen) {
5814            return;
5815        }
5816        // if buffer length is less than maxBufLen try to load a new fragment ...
5817        logger_1.logger.trace("buffer length of " + bufferLen.toFixed(3) + " is below max of " + maxBufLen.toFixed(3) + ". checking for more payload ...");
5818        // set next load level : this will trigger a playlist load if needed
5819        this.level = hls.nextLoadLevel = level;
5820        var levelDetails = levelInfo.details;
5821        // if level info not retrieved yet, switch state and wait for level retrieval
5822        // if live playlist, ensure that new playlist has been refreshed to avoid loading/try to load
5823        // a useless and outdated fragment (that might even introduce load error if it is already out of the live playlist)
5824        if (!levelDetails || (levelDetails.live && this.levelLastLoaded !== level)) {
5825            this.state = base_stream_controller_1.State.WAITING_LEVEL;
5826            return;
5827        }
5828        if (this._streamEnded(bufferInfo, levelDetails)) {
5829            var data = {};
5830            if (this.altAudio) {
5831                data.type = 'video';
5832            }
5833            this.hls.trigger(events_1.default.BUFFER_EOS, data);
5834            this.state = base_stream_controller_1.State.ENDED;
5835            return;
5836        }
5837        // if we have the levelDetails for the selected variant, lets continue enrichen our stream (load keys/fragments or trigger EOS, etc..)
5838        this._fetchPayloadOrEos(pos, bufferInfo, levelDetails);
5839    };
5840    StreamController.prototype._fetchPayloadOrEos = function (pos, bufferInfo, levelDetails) {
5841        var fragPrevious = this.fragPrevious, level = this.level, fragments = levelDetails.fragments, fragLen = fragments.length;
5842        // empty playlist
5843        if (fragLen === 0) {
5844            return;
5845        }
5846        // find fragment index, contiguous with end of buffer position
5847        var start = fragments[0].start, end = fragments[fragLen - 1].start + fragments[fragLen - 1].duration, bufferEnd = bufferInfo.end, frag;
5848        if (levelDetails.initSegment && !levelDetails.initSegment.data) {
5849            frag = levelDetails.initSegment;
5850        }
5851        else {
5852            // in case of live playlist we need to ensure that requested position is not located before playlist start
5853            if (levelDetails.live) {
5854                var initialLiveManifestSize = this.config.initialLiveManifestSize;
5855                if (fragLen < initialLiveManifestSize) {
5856                    logger_1.logger.warn("Can not start playback of a level, reason: not enough fragments " + fragLen + " < " + initialLiveManifestSize);
5857                    return;
5858                }
5859                frag = this._ensureFragmentAtLivePoint(levelDetails, bufferEnd, start, end, fragPrevious, fragments, fragLen);
5860                // if it explicitely returns null don't load any fragment and exit function now
5861                if (frag === null) {
5862                    return;
5863                }
5864            }
5865            else {
5866                // VoD playlist: if bufferEnd before start of playlist, load first fragment
5867                if (bufferEnd < start) {
5868                    frag = fragments[0];
5869                }
5870            }
5871        }
5872        if (!frag) {
5873            frag = this._findFragment(start, fragPrevious, fragLen, fragments, bufferEnd, end, levelDetails);
5874        }
5875        if (frag) {
5876            if (frag.encrypted) {
5877                logger_1.logger.log("Loading key for " + frag.sn + " of [" + levelDetails.startSN + " ," + levelDetails.endSN + "],level " + level);
5878                this._loadKey(frag);
5879            }
5880            else {
5881                logger_1.logger.log("Loading " + frag.sn + " of [" + levelDetails.startSN + " ," + levelDetails.endSN + "],level " + level + ", currentTime:" + pos.toFixed(3) + ",bufferEnd:" + bufferEnd.toFixed(3));
5882                this._loadFragment(frag);
5883            }
5884        }
5885    };
5886    StreamController.prototype._ensureFragmentAtLivePoint = function (levelDetails, bufferEnd, start, end, fragPrevious, fragments, fragLen) {
5887        var config = this.hls.config, media = this.media;
5888        var frag;
5889        // check if requested position is within seekable boundaries :
5890        // logger.log(`start/pos/bufEnd/seeking:${start.toFixed(3)}/${pos.toFixed(3)}/${bufferEnd.toFixed(3)}/${this.media.seeking}`);
5891        var maxLatency = config.liveMaxLatencyDuration !== undefined ? config.liveMaxLatencyDuration : config.liveMaxLatencyDurationCount * levelDetails.targetduration;
5892        if (bufferEnd < Math.max(start - config.maxFragLookUpTolerance, end - maxLatency)) {
5893            var liveSyncPosition = this.liveSyncPosition = this.computeLivePosition(start, levelDetails);
5894            logger_1.logger.log("buffer end: " + bufferEnd.toFixed(3) + " is located too far from the end of live sliding playlist, reset currentTime to : " + liveSyncPosition.toFixed(3));
5895            bufferEnd = liveSyncPosition;
5896            if (media && media.readyState && media.duration > liveSyncPosition) {
5897                media.currentTime = liveSyncPosition;
5898            }
5899            this.nextLoadPosition = liveSyncPosition;
5900        }
5901        // if end of buffer greater than live edge, don't load any fragment
5902        // this could happen if live playlist intermittently slides in the past.
5903        // level 1 loaded [182580161,182580167]
5904        // level 1 loaded [182580162,182580169]
5905        // Loading 182580168 of [182580162 ,182580169],level 1 ..
5906        // Loading 182580169 of [182580162 ,182580169],level 1 ..
5907        // level 1 loaded [182580162,182580168] <============= here we should have bufferEnd > end. in that case break to avoid reloading 182580168
5908        // level 1 loaded [182580164,182580171]
5909        //
5910        // don't return null in case media not loaded yet (readystate === 0)
5911        if (levelDetails.PTSKnown && bufferEnd > end && media && media.readyState) {
5912            return null;
5913        }
5914        if (this.startFragRequested && !levelDetails.PTSKnown) {
5915            /* we are switching level on live playlist, but we don't have any PTS info for that quality level ...
5916               try to load frag matching with next SN.
5917               even if SN are not synchronized between playlists, loading this frag will help us
5918               compute playlist sliding and find the right one after in case it was not the right consecutive one */
5919            if (fragPrevious) {
5920                if (levelDetails.hasProgramDateTime) {
5921                    // Relies on PDT in order to switch bitrates (Support EXT-X-DISCONTINUITY without EXT-X-DISCONTINUITY-SEQUENCE)
5922                    logger_1.logger.log("live playlist, switching playlist, load frag with same PDT: " + fragPrevious.programDateTime);
5923                    frag = fragment_finders_1.findFragmentByPDT(fragments, fragPrevious.endProgramDateTime, config.maxFragLookUpTolerance);
5924                }
5925                else {
5926                    // Uses buffer and sequence number to calculate switch segment (required if using EXT-X-DISCONTINUITY-SEQUENCE)
5927                    var targetSN = fragPrevious.sn + 1;
5928                    if (targetSN >= levelDetails.startSN && targetSN <= levelDetails.endSN) {
5929                        var fragNext = fragments[targetSN - levelDetails.startSN];
5930                        if (fragPrevious.cc === fragNext.cc) {
5931                            frag = fragNext;
5932                            logger_1.logger.log("live playlist, switching playlist, load frag with next SN: " + frag.sn);
5933                        }
5934                    }
5935                    // next frag SN not available (or not with same continuity counter)
5936                    // look for a frag sharing the same CC
5937                    if (!frag) {
5938                        frag = binary_search_1.default.search(fragments, function (frag) {
5939                            return fragPrevious.cc - frag.cc;
5940                        });
5941                        if (frag) {
5942                            logger_1.logger.log("live playlist, switching playlist, load frag with same CC: " + frag.sn);
5943                        }
5944                    }
5945                }
5946            }
5947            if (!frag) {
5948                /* we have no idea about which fragment should be loaded.
5949                   so let's load mid fragment. it will help computing playlist sliding and find the right one
5950                */
5951                frag = fragments[Math.min(fragLen - 1, Math.round(fragLen / 2))];
5952                logger_1.logger.log("live playlist, switching playlist, unknown, load middle frag : " + frag.sn);
5953            }
5954        }
5955        return frag;
5956    };
5957    StreamController.prototype._findFragment = function (start, fragPrevious, fragLen, fragments, bufferEnd, end, levelDetails) {
5958        var config = this.hls.config;
5959        var frag;
5960        if (bufferEnd < end) {
5961            var lookupTolerance = (bufferEnd > end - config.maxFragLookUpTolerance) ? 0 : config.maxFragLookUpTolerance;
5962            // Remove the tolerance if it would put the bufferEnd past the actual end of stream
5963            // Uses buffer and sequence number to calculate switch segment (required if using EXT-X-DISCONTINUITY-SEQUENCE)
5964            frag = fragment_finders_1.findFragmentByPTS(fragPrevious, fragments, bufferEnd, lookupTolerance);
5965        }
5966        else {
5967            // reach end of playlist
5968            frag = fragments[fragLen - 1];
5969        }
5970        if (frag) {
5971            var curSNIdx = frag.sn - levelDetails.startSN;
5972            var sameLevel = fragPrevious && frag.level === fragPrevious.level;
5973            var prevFrag = fragments[curSNIdx - 1];
5974            var nextFrag = fragments[curSNIdx + 1];
5975            // logger.log('find SN matching with pos:' +  bufferEnd + ':' + frag.sn);
5976            if (fragPrevious && frag.sn === fragPrevious.sn) {
5977                if (sameLevel && !frag.backtracked) {
5978                    if (frag.sn < levelDetails.endSN) {
5979                        var deltaPTS = fragPrevious.deltaPTS;
5980                        // if there is a significant delta between audio and video, larger than max allowed hole,
5981                        // and if previous remuxed fragment did not start with a keyframe. (fragPrevious.dropped)
5982                        // let's try to load previous fragment again to get last keyframe
5983                        // then we will reload again current fragment (that way we should be able to fill the buffer hole ...)
5984                        if (deltaPTS && deltaPTS > config.maxBufferHole && fragPrevious.dropped && curSNIdx) {
5985                            frag = prevFrag;
5986                            logger_1.logger.warn('SN just loaded, with large PTS gap between audio and video, maybe frag is not starting with a keyframe ? load previous one to try to overcome this');
5987                        }
5988                        else {
5989                            frag = nextFrag;
5990                            logger_1.logger.log("SN just loaded, load next one: " + frag.sn, frag);
5991                        }
5992                    }
5993                    else {
5994                        frag = null;
5995                    }
5996                }
5997                else if (frag.backtracked) {
5998                    // Only backtrack a max of 1 consecutive fragment to prevent sliding back too far when little or no frags start with keyframes
5999                    if (nextFrag && nextFrag.backtracked) {
6000                        logger_1.logger.warn("Already backtracked from fragment " + nextFrag.sn + ", will not backtrack to fragment " + frag.sn + ". Loading fragment " + nextFrag.sn);
6001                        frag = nextFrag;
6002                    }
6003                    else {
6004                        // If a fragment has dropped frames and it's in a same level/sequence, load the previous fragment to try and find the keyframe
6005                        // Reset the dropped count now since it won't be reset until we parse the fragment again, which prevents infinite backtracking on the same segment
6006                        logger_1.logger.warn('Loaded fragment with dropped frames, backtracking 1 segment to find a keyframe');
6007                        frag.dropped = 0;
6008                        if (prevFrag) {
6009                            frag = prevFrag;
6010                            frag.backtracked = true;
6011                        }
6012                        else if (curSNIdx) {
6013                            // can't backtrack on very first fragment
6014                            frag = null;
6015                        }
6016                    }
6017                }
6018            }
6019        }
6020        return frag;
6021    };
6022    StreamController.prototype._loadKey = function (frag) {
6023        this.state = base_stream_controller_1.State.KEY_LOADING;
6024        this.hls.trigger(events_1.default.KEY_LOADING, { frag: frag });
6025    };
6026    StreamController.prototype._loadFragment = function (frag) {
6027        // Check if fragment is not loaded
6028        var fragState = this.fragmentTracker.getState(frag);
6029        this.fragCurrent = frag;
6030        this.startFragRequested = true;
6031        // Don't update nextLoadPosition for fragments which are not buffered
6032        if (Number.isFinite(frag.sn) && !frag.bitrateTest) {
6033            this.nextLoadPosition = frag.start + frag.duration;
6034        }
6035        // Allow backtracked fragments to load
6036        if (frag.backtracked || fragState === fragment_tracker_1.FragmentState.NOT_LOADED || fragState === fragment_tracker_1.FragmentState.PARTIAL) {
6037            frag.autoLevel = this.hls.autoLevelEnabled;
6038            frag.bitrateTest = this.bitrateTest;
6039            this.hls.trigger(events_1.default.FRAG_LOADING, { frag: frag });
6040            // lazy demuxer init, as this could take some time ... do it during frag loading
6041            if (!this.demuxer) {
6042                this.demuxer = new demuxer_1.default(this.hls, 'main');
6043            }
6044            this.state = base_stream_controller_1.State.FRAG_LOADING;
6045        }
6046        else if (fragState === fragment_tracker_1.FragmentState.APPENDING) {
6047            // Lower the buffer size and try again
6048            if (this._reduceMaxBufferLength(frag.duration)) {
6049                this.fragmentTracker.removeFragment(frag);
6050            }
6051        }
6052    };
6053    Object.defineProperty(StreamController.prototype, "state", {
6054        get: function () {
6055            return this._state;
6056        },
6057        set: function (nextState) {
6058            if (this.state !== nextState) {
6059                var previousState = this.state;
6060                this._state = nextState;
6061                logger_1.logger.log("main stream:" + previousState + "->" + nextState);
6062                this.hls.trigger(events_1.default.STREAM_STATE_TRANSITION, { previousState: previousState, nextState: nextState });
6063            }
6064        },
6065        enumerable: true,
6066        configurable: true
6067    });
6068    StreamController.prototype.getBufferedFrag = function (position) {
6069        return this.fragmentTracker.getBufferedFrag(position, playlist_loader_1.default.LevelType.MAIN);
6070    };
6071    Object.defineProperty(StreamController.prototype, "currentLevel", {
6072        get: function () {
6073            var media = this.media;
6074            if (media) {
6075                var frag = this.getBufferedFrag(media.currentTime);
6076                if (frag) {
6077                    return frag.level;
6078                }
6079            }
6080            return -1;
6081        },
6082        enumerable: true,
6083        configurable: true
6084    });
6085    Object.defineProperty(StreamController.prototype, "nextBufferedFrag", {
6086        get: function () {
6087            var media = this.media;
6088            if (media) {
6089                // first get end range of current fragment
6090                return this.followingBufferedFrag(this.getBufferedFrag(media.currentTime));
6091            }
6092            else {
6093                return null;
6094            }
6095        },
6096        enumerable: true,
6097        configurable: true
6098    });
6099    StreamController.prototype.followingBufferedFrag = function (frag) {
6100        if (frag) {
6101            // try to get range of next fragment (500ms after this range)
6102            return this.getBufferedFrag(frag.endPTS + 0.5);
6103        }
6104        return null;
6105    };
6106    Object.defineProperty(StreamController.prototype, "nextLevel", {
6107        get: function () {
6108            var frag = this.nextBufferedFrag;
6109            if (frag) {
6110                return frag.level;
6111            }
6112            else {
6113                return -1;
6114            }
6115        },
6116        enumerable: true,
6117        configurable: true
6118    });
6119    StreamController.prototype._checkFragmentChanged = function () {
6120        var fragPlayingCurrent, currentTime, video = this.media;
6121        if (video && video.readyState && video.seeking === false) {
6122            currentTime = video.currentTime;
6123            /* if video element is in seeked state, currentTime can only increase.
6124              (assuming that playback rate is positive ...)
6125              As sometimes currentTime jumps back to zero after a
6126              media decode error, check this, to avoid seeking back to
6127              wrong position after a media decode error
6128            */
6129            if (currentTime > this.lastCurrentTime) {
6130                this.lastCurrentTime = currentTime;
6131            }
6132            if (buffer_helper_1.BufferHelper.isBuffered(video, currentTime)) {
6133                fragPlayingCurrent = this.getBufferedFrag(currentTime);
6134            }
6135            else if (buffer_helper_1.BufferHelper.isBuffered(video, currentTime + 0.1)) {
6136                /* ensure that FRAG_CHANGED event is triggered at startup,
6137                  when first video frame is displayed and playback is paused.
6138                  add a tolerance of 100ms, in case current position is not buffered,
6139                  check if current pos+100ms is buffered and use that buffer range
6140                  for FRAG_CHANGED event reporting */
6141                fragPlayingCurrent = this.getBufferedFrag(currentTime + 0.1);
6142            }
6143            if (fragPlayingCurrent) {
6144                var fragPlaying = fragPlayingCurrent;
6145                if (fragPlaying !== this.fragPlaying) {
6146                    this.hls.trigger(events_1.default.FRAG_CHANGED, { frag: fragPlaying });
6147                    var fragPlayingLevel = fragPlaying.level;
6148                    if (!this.fragPlaying || this.fragPlaying.level !== fragPlayingLevel) {
6149                        this.hls.trigger(events_1.default.LEVEL_SWITCHED, { level: fragPlayingLevel });
6150                    }
6151                    this.fragPlaying = fragPlaying;
6152                }
6153            }
6154        }
6155    };
6156    /*
6157      on immediate level switch :
6158       - pause playback if playing
6159       - cancel any pending load request
6160       - and trigger a buffer flush
6161    */
6162    StreamController.prototype.immediateLevelSwitch = function () {
6163        logger_1.logger.log('immediateLevelSwitch');
6164        if (!this.immediateSwitch) {
6165            this.immediateSwitch = true;
6166            var media = this.media, previouslyPaused = void 0;
6167            if (media) {
6168                previouslyPaused = media.paused;
6169                media.pause();
6170            }
6171            else {
6172                // don't restart playback after instant level switch in case media not attached
6173                previouslyPaused = true;
6174            }
6175            this.previouslyPaused = previouslyPaused;
6176        }
6177        var fragCurrent = this.fragCurrent;
6178        if (fragCurrent && fragCurrent.loader) {
6179            fragCurrent.loader.abort();
6180        }
6181        this.fragCurrent = null;
6182        // flush everything
6183        this.flushMainBuffer(0, Number.POSITIVE_INFINITY);
6184    };
6185    /**
6186     * on immediate level switch end, after new fragment has been buffered:
6187     * - nudge video decoder by slightly adjusting video currentTime (if currentTime buffered)
6188     * - resume the playback if needed
6189     */
6190    StreamController.prototype.immediateLevelSwitchEnd = function () {
6191        var media = this.media;
6192        if (media && media.buffered.length) {
6193            this.immediateSwitch = false;
6194            if (buffer_helper_1.BufferHelper.isBuffered(media, media.currentTime)) {
6195                // only nudge if currentTime is buffered
6196                media.currentTime -= 0.0001;
6197            }
6198            if (!this.previouslyPaused) {
6199                media.play();
6200            }
6201        }
6202    };
6203    /**
6204     * try to switch ASAP without breaking video playback:
6205     * in order to ensure smooth but quick level switching,
6206     * we need to find the next flushable buffer range
6207     * we should take into account new segment fetch time
6208     */
6209    StreamController.prototype.nextLevelSwitch = function () {
6210        var media = this.media;
6211        // ensure that media is defined and that metadata are available (to retrieve currentTime)
6212        if (media && media.readyState) {
6213            var fetchdelay = void 0, fragPlayingCurrent = void 0, nextBufferedFrag = void 0;
6214            fragPlayingCurrent = this.getBufferedFrag(media.currentTime);
6215            if (fragPlayingCurrent && fragPlayingCurrent.startPTS > 1) {
6216                // flush buffer preceding current fragment (flush until current fragment start offset)
6217                // minus 1s to avoid video freezing, that could happen if we flush ke
vendor: 4,255 bytes, lines 6217-6302
6217yframe of current video ...
6218                this.flushMainBuffer(0, fragPlayingCurrent.startPTS - 1);
6219            }
6220            if (!media.paused) {
6221                // add a safety delay of 1s
6222                var nextLevelId = this.hls.nextLoadLevel, nextLevel = this.levels[nextLevelId], fragLastKbps = this.fragLastKbps;
6223                if (fragLastKbps && this.fragCurrent) {
6224                    fetchdelay = this.fragCurrent.duration * nextLevel.bitrate / (1000 * fragLastKbps) + 1;
6225                }
6226                else {
6227                    fetchdelay = 0;
6228                }
6229            }
6230            else {
6231                fetchdelay = 0;
6232            }
6233            // logger.log('fetchdelay:'+fetchdelay);
6234            // find buffer range that will be reached once new fragment will be fetched
6235            nextBufferedFrag = this.getBufferedFrag(media.currentTime + fetchdelay);
6236            if (nextBufferedFrag) {
6237                // we can flush buffer range following this one without stalling playback
6238                nextBufferedFrag = this.followingBufferedFrag(nextBufferedFrag);
6239                if (nextBufferedFrag) {
6240                    // if we are here, we can also cancel any loading/demuxing in progress, as they are useless
6241                    var fragCurrent = this.fragCurrent;
6242                    if (fragCurrent && fragCurrent.loader) {
6243                        fragCurrent.loader.abort();
6244                    }
6245                    this.fragCurrent = null;
6246                    // start flush position is the start PTS of next buffered frag.
6247                    // we use frag.naxStartPTS which is max(audio startPTS, video startPTS).
6248                    // in case there is a small PTS Delta between audio and video, using maxStartPTS avoids flushing last samples from current fragment
6249                    this.flushMainBuffer(nextBufferedFrag.maxStartPTS, Number.POSITIVE_INFINITY);
6250                }
6251            }
6252        }
6253    };
6254    StreamController.prototype.flushMainBuffer = function (startOffset, endOffset) {
6255        this.state = base_stream_controller_1.State.BUFFER_FLUSHING;
6256        var flushScope = { startOffset: startOffset, endOffset: endOffset };
6257        // if alternate audio tracks are used, only flush video, otherwise flush everything
6258        if (this.altAudio) {
6259            flushScope.type = 'video';
6260        }
6261        this.hls.trigger(events_1.default.BUFFER_FLUSHING, flushScope);
6262    };
6263    StreamController.prototype.onMediaAttached = function (data) {
6264        var media = this.media = this.mediaBuffer = data.media;
6265        this.onvseeking = this.onMediaSeeking.bind(this);
6266        this.onvseeked = this.onMediaSeeked.bind(this);
6267        this.onvended = this.onMediaEnded.bind(this);
6268        media.addEventListener('seeking', this.onvseeking);
6269        media.addEventListener('seeked', this.onvseeked);
6270        media.addEventListener('ended', this.onvended);
6271        var config = this.config;
6272        if (this.levels && config.autoStartLoad) {
6273            this.hls.startLoad(config.startPosition);
6274        }
6275        this.gapController = new gap_controller_1.default(config, media, this.fragmentTracker, this.hls);
6276    };
6277    StreamController.prototype.onMediaDetaching = function () {
6278        var media = this.media;
6279        if (media && media.ended) {
6280            logger_1.logger.log('MSE detaching and video ended, reset startPosition');
6281            this.startPosition = this.lastCurrentTime = 0;
6282        }
6283        // reset fragment backtracked flag
6284        var levels = this.levels;
6285        if (levels) {
6286            levels.forEach(function (level) {
6287                if (level.details) {
6288                    level.details.fragments.forEach(function (fragment) {
6289                        fragment.backtracked = undefined;
6290                    });
6291                }
6292            });
6293        }
6294        // remove video listeners
6295        if (media) {
6296            media.removeEventListener('seeking', this.onvseeking);
6297            media.removeEventListener('seeked', this.onvseeked);
6298            media.removeEventListener('ended', this.onvended);
6299            this.onvseeking = this.onvseeked = this.onvended = null;
6300        }
6301        this.media = this.mediaBuffer = null;
6302        this.loadedmetadata = false;
6303        this.stopLoad();
6304    };
6305    StreamController.prototype.onMediaSeeked = function () {
6306        var media = this.media, currentTime = media ? media.currentTime : undefined;
6307        if (Number.isFinite(currentTime)) {
6308            logger_1.logger.log("media seeked to " + currentTime.toFixed(3));
6309        }
6310        // tick to speed up FRAGMENT_PLAYING triggering
6311        this.tick();
6312    };
6313    StreamController.prototype.onManifestLoading = function () {
6314        // reset buffer on manifest loading
6315        logger_1.logger.log('trigger BUFFER_RESET');
6316        this.hls.trigger(events_1.default.BUFFER_RESET);
6317        this.fragmentTracker.removeAllFragments();
6318        this.stalled = false;
6319        this.startPosition = this.lastCurrentTime = 0;
6320    };
6321    StreamController.prototype.onManifestParsed = function (data) {
6322        var aac = false, heaac = false, codec;
6323        data.levels.forEach(function (level) {
6324            // detect if we have different kind of audio codecs used amongst playlists
6325            codec = level.audioCodec;
6326            if (codec) {
6327                if (codec.indexOf('mp4a.40.2') !== -1) {
6328                    aac = true;
6329                }
6330                if (codec.indexOf('mp4a.40.5') !== -1) {
6331                    heaac = true;
6332                }
6333            }
6334        });
6335        this.audioCodecSwitch = (aac && heaac);
6336        if (this.audioCodecSwitch) {
6337            logger_1.logger.log('both AAC/HE-AAC audio found in levels; declaring level codec as HE-AAC');
6338        }
6339        this.levels = data.levels;
6340        this.startFragRequested = false;
6341        var config = this.config;
6342        if (config.autoStartLoad || this.forceStartLoad) {
6343            this.hls.startLoad(config.startPosition);
6344        }
6345    };
6346    StreamController.prototype.onLevelLoaded = function (data) {
6347        var newDetails = data.details;
6348        var newLevelId = data.level;
6349        var lastLevel = this.levels[this.levelLastLoaded];
6350        var curLevel = this.levels[newLevelId];
6351        var duration = newDetails.totalduration;
6352        var sliding = 0;
6353        logger_1.logger.log("level " + newLevelId + " loaded [" + newDetails.startSN + "," + newDetails.endSN + "],duration:" + duration);
6354        if (newDetails.live) {
6355            var curDetails = curLevel.details;
6356            if (curDetails && newDetails.fragments.length > 0) {
6357                // we already have details for that level, merge them
6358                LevelHelper.mergeDetails(curDetails, newDetails);
6359                sliding = newDetails.fragments[0].start;
6360                this.liveSyncPosition = this.computeLivePosition(sliding, curDetails);
6361                if (newDetails.PTSKnown && Number.isFinite(sliding)) {
6362                    logger_1.logger.log("live playlist sliding:" + sliding.toFixed(3));
6363                }
6364                else {
6365                    logger_1.logger.log('live playlist - outdated PTS, unknown sliding');
6366                    discontinuities_1.alignStream(this.fragPrevious, lastLevel, newDetails);
6367                }
6368            }
6369            else {
6370                logger_1.logger.log('live playlist - first load, unknown sliding');
6371                newDetails.PTSKnown = false;
6372                discontinuities_1.alignStream(this.fragPrevious, lastLevel, newDetails);
6373            }
6374        }
6375        else {
6376            newDetails.PTSKnown = false;
6377        }
6378        // override level info
6379        curLevel.details = newDetails;
6380        this.levelLastLoaded = newLevelId;
6381        this.hls.trigger(events_1.default.LEVEL_UPDATED, { details: newDetails, level: newLevelId });
6382        if (this.startFragRequested === false) {
6383            // compute start position if set to -1. use it straight away if value is defined
6384            if (this.startPosition === -1 || this.lastCurrentTime === -1) {
6385                // first, check if start time offset has been set in playlist, if yes, use this value
6386                var startTimeOffset = newDetails.startTimeOffset;
6387                if (Number.isFinite(startTimeOffset)) {
6388                    if (startTimeOffset < 0) {
6389                        logger_1.logger.log("negative start time offset " + startTimeOffset + ", count from end of last fragment");
6390                        startTimeOffset = sliding + duration + startTimeOffset;
6391                    }
6392                    logger_1.logger.log("start time offset found in playlist, adjust startPosition to " + startTimeOffset);
6393                    this.startPosition = startTimeOffset;
6394                }
6395                else {
6396                    // if live playlist, set start position to be fragment N-this.config.liveSyncDurationCount (usually 3)
6397                    if (newDetails.live) {
6398                        this.startPosition = this.computeLivePosition(sliding, newDetails);
6399                        logger_1.logger.log("configure startPosition to " + this.startPosition);
6400                    }
6401                    else {
6402                        this.startPosition = 0;
6403                    }
6404                }
6405                this.lastCurrentTime = this.startPosition;
6406            }
6407            this.nextLoadPosition = this.startPosition;
6408        }
6409        // only switch batck to IDLE state if we were waiting for level to start downloading a new fragment
6410        if (this.state === base_stream_controller_1.State.WAITING_LEVEL) {
6411            this.state = base_stream_controller_1.State.IDLE;
6412        }
6413        // trigger handler right now
6414        this.tick();
6415    };
6416    StreamController.prototype.onKeyLoaded = function () {
6417        if (this.state === base_stream_controller_1.State.KEY_LOADING) {
6418            this.state = base_stream_controller_1.State.IDLE;
6419            this.tick();
6420        }
6421    };
6422    StreamController.prototype.onFragLoaded = function (data) {
6423        var _a = this, fragCurrent = _a.fragCurrent, hls = _a.hls, levels = _a.levels, media = _a.media;
6424        var fragLoaded = data.frag;
6425        if (this.state === base_stream_controller_1.State.FRAG_LOADING &&
6426            fragCurrent &&
6427            fragLoaded.type === 'main' &&
6428            fragLoaded.level === fragCurrent.level &&
6429            fragLoaded.sn === fragCurrent.sn) {
6430            var stats = data.stats;
6431            var currentLevel = levels[fragCurrent.level];
6432            var details = currentLevel.details;
6433            // reset frag bitrate test in any case after frag loaded event
6434            // if this frag was loaded to perform a bitrate test AND if hls.nextLoadLevel is greater than 0
6435            // then this means that we should be able to load a fragment at a higher quality level
6436            this.bitrateTest = false;
vendor: 4,179 bytes, lines 6437-6504
6437            this.stats = stats;
6438            logger_1.logger.log("Loaded " + fragCurrent.sn + " of [" + details.startSN + " ," + details.endSN + "],level " + fragCurrent.level);
6439            if (fragLoaded.bitrateTest && hls.nextLoadLevel) {
6440                // switch back to IDLE state ... we just loaded a fragment to determine adequate start bitrate and initialize autoswitch algo
6441                this.state = base_stream_controller_1.State.IDLE;
6442                this.startFragRequested = false;
6443                stats.tparsed = stats.tbuffered = window.performance.now();
6444                hls.trigger(events_1.default.FRAG_BUFFERED, { stats: stats, frag: fragCurrent, id: 'main' });
6445                this.tick();
6446            }
6447            else if (fragLoaded.sn === 'initSegment') {
6448                this.state = base_stream_controller_1.State.IDLE;
6449                stats.tparsed = stats.tbuffered = window.performance.now();
6450                details.initSegment.data = data.payload;
6451                hls.trigger(events_1.default.FRAG_BUFFERED, { stats: stats, frag: fragCurrent, id: 'main' });
6452                this.tick();
6453            }
6454            else {
6455                logger_1.logger.log("Parsing " + fragCurrent.sn + " of [" + details.startSN + " ," + details.endSN + "],level " + fragCurrent.level + ", cc " + fragCurrent.cc);
6456                this.state = base_stream_controller_1.State.PARSING;
6457                this.pendingBuffering = true;
6458                this.appended = false;
6459                // Bitrate test frags are not usually buffered so the fragment tracker ignores them. If Hls.js decides to buffer
6460                // it (and therefore ends up at this line), then the fragment tracker needs to be manually informed.
6461                if (fragLoaded.bitrateTest) {
6462                    fragLoaded.bitrateTest = false;
6463                    this.fragmentTracker.onFragLoaded({
6464                        frag: fragLoaded
6465                    });
6466                }
6467                // time Offset is accurate if level PTS is known, or if playlist is not sliding (not live) and if media is not seeking (this is to overcome potential timestamp drifts between playlists and fragments)
6468                var accurateTimeOffset = !(media && media.seeking) && (details.PTSKnown || !details.live);
6469                var initSegmentData = details.initSegment ? details.initSegment.data : [];
6470                var audioCodec = this._getAudioCodec(currentLevel);
6471                // transmux the MPEG-TS data to ISO-BMFF segments
6472                var demuxer = this.demuxer = this.demuxer || new demuxer_1.default(this.hls, 'main');
6473                demuxer.push(data.payload, initSegmentData, audioCodec, currentLevel.videoCodec, fragCurrent, details.totalduration, accurateTimeOffset);
6474            }
6475        }
6476        this.fragLoadError = 0;
6477    };
6478    StreamController.prototype.onFragParsingInitSegment = function (data) {
6479        var fragCurrent = this.fragCurrent;
6480        var fragNew = data.frag;
6481        if (fragCurrent &&
6482            data.id === 'main' &&
6483            fragNew.sn === fragCurrent.sn &&
6484            fragNew.level === fragCurrent.level &&
6485            this.state === base_stream_controller_1.State.PARSING) {
6486            var tracks = data.tracks, trackName = void 0, track = void 0;
6487            // if audio track is expected to come from audio stream controller, discard any coming from main
6488            if (tracks.audio && this.altAudio) {
6489                delete tracks.audio;
6490            }
6491            // include levelCodec in audio and video tracks
6492            track = tracks.audio;
6493            if (track) {
6494                var audioCodec = this.levels[this.level].audioCodec, ua = navigator.userAgent.toLowerCase();
6495                if (audioCodec && this.audioCodecSwap) {
6496                    logger_1.logger.log('swapping playlist audio codec');
6497                    if (audioCodec.indexOf('mp4a.40.5') !== -1) {
6498                        audioCodec = 'mp4a.40.2';
6499                    }
6500                    else {
6501                        audioCodec = 'mp4a.40.5';
6502                    }
6503                }
6504                // in case AAC and HE-AAC audio codecs are signalled 
6504in manifest
6505                // force HE-AAC , as it seems that most browsers prefers that way,
6506                // except for mono streams OR on FF
6507                // these conditions might need to be reviewed ...
6508                if (this.audioCodecSwitch) {
6509                    // don't force HE-AAC if mono stream
6510                    if (track.metadata.channelCount !== 1 &&
6511                        // don't force HE-AAC if firefox
6512                        ua.indexOf('firefox') === -1) {
6513                        audioCodec = 'mp4a.40.5';
6514                    }
6515                }
6516                // HE-AAC is broken on Android, always signal audio codec as AAC even if variant manifest states otherwise
6517                if (ua.indexOf('android') !== -1 && track.container !== 'audio/mpeg') { // Exclude mpeg audio
6518                    audioCodec = 'mp4a.40.2';
6519                    logger_1.logger.log("Android: force audio codec to " + audioCodec);
6520                }
6521                track.levelCodec = audioCodec;
6522                track.id = data.id;
6523            }
6524            track = tracks.video;
6525            if (track) {
6526                track.levelCodec = this.levels[this.level].videoCodec;
6527                track.id = data.id;
6528            }
6529            this.hls.trigger(events_1.default.BUFFER_CODECS, tracks);
6530            // loop through tracks that are going to be provided to bufferController
6531            for (trackName in tracks) {
6532                track = tracks[trackName];
6533                logger_1.logger.log("main track:" + trackName + ",container:" + track.container + ",codecs[level/parsed]=[" + track.levelCodec + "/" + track.codec + "]");
6534                var initSegment = track.initSegment;
6535                if (initSegment) {
6536                    this.appended = true;
6537                    // arm pending Buffering flag before appending a segment
6538                    this.pendingBuffering = true;
6539                    this.hls.trigger(events_1.default.BUFFER_APPENDING, { type: trackName, data: initSegment, parent: 'main', content: 'initSegment' });
6540                }
6541            }
6542            // trigger handler right now
6543            this.tick();
6544        }
6545    };
6546    StreamController.prototype.onFragParsingData = function (data) {
6547        var _this = this;
6548        var fragCurrent = this.fragCurrent;
6549        var fragNew = data.frag;
6550        if (fragCurrent &&
6551            data.id === 'main' &&
6552            fragNew.sn === fragCurrent.sn &&
6553            fragNew.level === fragCurrent.level &&
6554            !(data.type === 'audio' && this.altAudio) && // filter out main audio if audio track is loaded through audio stream controller
6555            this.state === base_stream_controller_1.State.PARSING) {
6556            var level = this.levels[this.level], frag = fragCurrent;
6557            if (!Number.isFinite(data.endPTS)) {
6558                data.endPTS = data.startPTS + fragCurrent.duration;
6559                data.endDTS = data.startDTS + fragCurrent.duration;
6560            }
6561            if (data.hasAudio === true) {
6562                frag.addElementaryStream(fragment_1.default.ElementaryStreamTypes.AUDIO);
6563            }
6564            if (data.hasVideo === true) {
6565                frag.addElementaryStream(fragment_1.default.ElementaryStreamTypes.VIDEO);
6566            }
6567            logger_1.logger.log("Parsed " + data.type + ",PTS:[" + data.startPTS.toFixed(3) + "," + data.endPTS.toFixed(3) + "],DTS:[" + data.startDTS.toFixed(3) + "/" + data.endDTS.toFixed(3) + "],nb:" + data.nb + ",dropped:" + (data.dropped || 0));
6568            // Detect gaps in a fragment  and try to fix it by finding a keyframe in the previous fragment (see _findFragments)
6569            if (data.type === 'video') {
6570                frag.dropped = data.dropped;
6571                if (frag.dropped) {
6572                    if (!frag.backtracked) {
6573                        var levelDetails = level.details;
6574                        if (levelDetails && frag.sn === levelDetails.startSN) {
6575                            logger_1.logger.warn('missing video frame(s) on first frag, appending with gap', frag.sn);
6576                        }
6577                        else {
6578                            logger_1.logger.warn('missing video frame(s), backtracking fragment', frag.sn);
6579                            // Return back to the IDLE state without appending to buffer
6580                            // Causes findFragments to backtrack a segment and find the keyframe
6581                            // Audio fragments arriving before video sets the nextLoadPosition, causing _findFragments to skip the backtracked fragment
6582                            this.fragmentTracker.removeFragment(frag);
6583                            frag.backtracked = true;
6584                            this.nextLoadPosition = data.startPTS;
6585                            this.state = base_stream_controller_1.State.IDLE;
6586                            this.fragPrevious = frag;
6587                            this.tick();
6588                            return;
6589                        }
6590                    }
6591                    else {
6592                        logger_1.logger.warn('Already backtracked on this fragment, appending with the gap', frag.sn);
6593                    }
6594                }
6595                else {
6596                    // Only reset the backtracked flag if we've loaded the frag without any dropped frames
6597                    frag.backtracked = false;
6598                }
6599            }
6600            var drift = LevelHelper.updateFragPTSDTS(level.details, frag, data.startPTS, data.endPTS, data.startDTS, data.endDTS), hls_2 = this.hls;
6601            hls_2.trigger(events_1.default.LEVEL_PTS_UPDATED, { details: level.details, level: this.level, drift: drift, type: data.type, start: data.startPTS, end: data.endPTS });
6602            // has remuxer dropped video frames located before first keyframe ?
6603            [data.data1, data.data2].forEach(function (buffer) {
6604                // only append in PARSING state (rationale is that an appending error could happen synchronously on first segment appending)
6605                // in that case it is useless to append following segments
6606                if (buffer && buffer.length && _this.state === base_stream_controller_1.State.PARSING) {
6607                    _this.appended = true;
6608                    // arm pending Buffering flag before appending a segment
6609                    _this.pendingBuffering = true;
6610                    hls_2.trigger(events_1.default.BUFFER_APPENDING, { type: data.type, data: buffer, parent: 'main', content: 'data' });
6611                }
6612            });
6613            // trigger handler right now
6614            this.tick();
6615        }
6616    };
6617    StreamController.prototype.onFragParsed = function (data) {
6618        var fragCurrent = this.fragCurrent;
6619        var fragNew = data.frag;
6620        if (fragCurrent &&
6621            data.id === 'main' &&
6622            fragNew.sn === fragCurrent.sn &&
6623            fragNew.level === fragCurrent.level &&
6624            this.state === base_stream_controller_1.State.PARSING) {
6625            this.stats.tparsed = window.performance.now();
6626            this.state = base_stream_controller_1.State.PARSED;
6627            this._checkAppendedParsed();
6628        }
6629    };
6630    StreamController.prototype.onAudioTrackSwitching = function (data) {
6631        // if any URL found on new audio track, it is an alternate audio track
6632        var altAudio = !!data.url, trackId = data.id;
6633        // if we switch on main audio, ensure that main fragment scheduling is synced with media.buffered
6634        // don't do anything if we switch to alt audio: audio stream controller is handling it.
6635        // we will just have to change buffer scheduling on audioTrackSwitched
6636        if (!altAudio) {
6637            if (this.mediaBuffer !== this.media) {
6638                logger_1.logger.log('switching on main audio, use media.buffered to schedule main fragment loading');
6639                this.mediaBuffer = this.media;
6640                var fragCurrent = this.fragCurrent;
6641                // we need to refill audio buffer from main: cancel any frag loading to speed up audio switch
6642                if (fragCurrent.loader) {
6643                    logger_1.logger.log('switching to main audio track, cancel main fragment load');
6644                    fragCurrent.loader.abort();
6645                }
6646                this.fragCurrent = null;
6647                this.fragPrevious = null;
6648                // destroy demuxer to force init segment generation (following audio switch)
6649                if (this.demuxer) {
6650                    this.demuxer.destroy();
6651                    this.demuxer = null;
6652                }
6653                // switch to IDLE state to load new fragment
6654                this.state = base_stream_controller_1.State.IDLE;
6655            }
6656            var hls_3 = this.hls;
6657            // switching to main audio, flush all audio and trigger track switched
6658            hls_3.trigger(events_1.default.BUFFER_FLUSHING, { startOffset: 0, endOffset: Number.POSITIVE_INFINITY, type: 'audio' });
6659            hls_3.trigger(events_1.default.AUDIO_TRACK_SWITCHED, { id: trackId });
6660            this.altAudio = false;
6661        }
6662    };
6663    StreamController.prototype.onAudioTrackSwitched = function (data) {
6664        var trackId = data.id, altAudio = !!this.hls.audioTracks[trackId].url;
6665        if (altAudio) {
6666            var videoBuffer = this.videoBuffer;
6667            // if we switched on alternate audio, ensure that main fragment scheduling is synced with video sourcebuffer buffered
6668            if (videoBuffer && this.mediaBuffer !== videoBuffer) {
6669                logger_1.logger.log('switching on alternate audio, use video.buffered to schedule main fragment loading');
6670                this.mediaBuffer = videoBuffer;
6671            }
6672        }
6673        this.altAudio = altAudio;
6674        this.tick();
6675    };
6676    StreamController.prototype.onBufferCreated = function (data) {
6677        var tracks = data.tracks, mediaTrack, name, alternate = false;
6678        for (var type in tracks) {
6679            var track = tracks[type];
6680            if (track.id === 'main') {
6681                name = type;
6682                mediaTrack = track;
6683                // keep video source buffer reference
6684                if (type === 'video') {
6685                    this.videoBuffer = tracks[type].buffer;
6686                }
6687            }
6688            else {
6689                alternate = true;
6690            }
6691        }
6692        if (alternate && mediaTrack) {
6693            logger_1.logger.log("alternate track found, use " + name + ".buffered to schedule main fragment loading");
6694            this.mediaBuffer = mediaTrack.buffer;
6695        }
6696        else {
6697            this.mediaBuffer = this.media;
6698        }
6699    };
6700    StreamController.prototype.onBufferAppended = function (data) {
6701        if (data.parent === 'main') {
6702            var state = this.state;
6703            if (state === base_stream_controller_1.State.PARSING || state === base_stream_controller_1.State.PARSED) {
6704                // check if all buffers have been appended
6705                this.pendingBuffering = (data.pending > 0);
6706                this._checkAppendedParsed();
6707            }
6708        }
6709    };
6710    StreamController.prototype._checkAppendedParsed = function () {
6711        // trigger handler right now
6712        if (this.state === base_stream_controller_1.State.PARSED && (!this.appended || !this.pendingBuffering)) {
6713            var frag = this.fragCurrent;
6714            if (frag) {
6715                var media = this.mediaBuffer ? this.mediaBuffer : this.media;
6716                logger_1.logger.log("main buffered : " + time_ranges_1.default.toString(media.buffered));
6717                this.fragPrevious = frag;
6718                var stats = this.stats;
6719                stats.tbuffered = window.performance.now();
6720                // we should get rid of this.fragLastKbps
6721                this.fragLastKbps = Math.round(8 * stats.total / (stats.tbuffered - stats.tfirst));
6722                this.hls.trigger(events_1.default.FRAG_BUFFERED, { stats: stats, frag: frag, id: 'main' });
6723                this.state = base_stream_controller_1.State.IDLE;
6724            }
6725            this.tick();
6726        }
6727    };
6728    StreamController.prototype.onError = function (data) {
6729        var frag = data.frag || this.fragCurrent;
6730        // don't handle frag error not related to main fragment
6731        if (frag && frag.type !== 'main') {
6732            return;
6733        }
6734        // 0.5 : tolerance needed as some browsers stalls playback before reaching buffered end
6735        var mediaBuffered = !!this.media && buffer_helper_1.BufferHelper.isBuffered(this.media, this.media.currentTime) && buffer_helper_1.BufferHelper.isBuffered(this.media, this.media.currentTime + 0.5);
6736        switch (data.details) {
6737            case errors_1.ErrorDetails.FRAG_LOAD_ERROR:
6738            case errors_1.ErrorDetails.FRAG_LOAD_TIMEOUT:
6739            case errors_1.ErrorDetails.KEY_LOAD_ERROR:
6740            case errors_1.ErrorDetails.KEY_LOAD_TIMEOUT:
6741                if (!data.fatal) {
6742                    // keep retrying until the limit will be reached
6743                    if ((this.fragLoadError + 1) <= this.config.fragLoadingMaxRetry) {
6744                        // exponential backoff capped to config.fragLoadingMaxRetryTimeout
6745                        var delay = Math.min(Math.pow(2, this.fragLoadError) * this.config.fragLoadingRetryDelay, this.config.fragLoadingMaxRetryTimeout);
6746                        logger_1.logger.warn("mediaController: frag loading failed, retry in " + delay + " ms");
6747                        this.retryDate = window.performance.now() + delay;
6748                        // retry loading state
6749                        // if loadedmetadata is not set, it means that we are emergency switch down on first frag
6750                        // in that case, reset startFragRequested flag
6751                        if (!this.loadedmetadata) {
6752                            this.startFragRequested = false;
6753                            this.nextLoadPosition = this.startPosition;
6754                        }
6755                        this.fragLoadError++;
6756                        this.state = base_stream_controller_1.State.FRAG_LOADING_WAITING_RETRY;
6757                    }
6758                    else {
6759                        logger_1.logger.error("mediaController: " + data.details + " reaches max retry, redispatch as fatal ...");
6760                        // switch error to fatal
6761                        data.fatal = true;
6762                        this.state = base_stream_controller_1.State.ERROR;
6763                    }
6764                }
6765                break;
6766            case errors_1.ErrorDetails.LEVEL_LOAD_ERROR:
6767            case errors_1.ErrorDetails.LEVEL_LOAD_TIMEOUT:
6768                if (this.state !== base_stream_controller_1.State.ERROR) {
6769                    if (data.fatal) {
6770                        // if fatal error, stop processing
6771                        this.state = base_stream_controller_1.State.ERROR;
6772                        logger_1.logger.warn("streamController: " + data.details + ",switch to " + this.state + " state ...");
6773                    }
6774                    else {
6775                        // in case of non fatal error while loading level, if level controller is not retrying to load level , switch back to IDLE
6776                        if (!data.levelRetry && this.state === base_stream_controller_1.State.WAITING_LEVEL) {
6777                            this.state = base_stream_controller_1.State.IDLE;
6778                        }
6779                    }
6780                }
6781                break;
6782            case errors_1.ErrorDetails.BUFFER_FULL_ERROR:
6783                // if in appending state
6784                if (data.parent === 'main' && (this.state === base_stream_controller_1.State.PARSING || this.state === base_stream_controller_1.State.PARSED)) {
6785                    // reduce max buf len if current position is buffered
6786                    if (mediaBuffered) {
6787                        this._reduceMaxBufferLength(this.config.maxBufferLength);
6788                        this.state = base_stream_controller_1.State.IDLE;
6789                    }
6790                    else {
6791                        // current position is not buffered, but browser is still complaining about buffer full error
6792                        // this happens on IE/Edge, refer to https://github.com/video-dev/hls.js/pull/708
6793                        // in that case flush the whole buffer to recover
6794                        logger_1.logger.warn('buffer full error also media.currentTime is not buffered, flush everything');
6795                        this.fragCurrent = null;
6796                        // flush everything
6797                        this.flushMainBuffer(0, Number.POSITIVE_INFINITY);
6798                    }
6799                }
6800                break;
6801            default:
6802                break;
6803        }
6804    };
6805    StreamController.prototype._reduceMaxBufferLength = function (minLength) {
6806        var config = this.config;
vendor: 4,572 bytes, lines 6807-6900
6807        if (config.maxMaxBufferLength >= minLength) {
6808            // reduce max buffer length as it might be too high. we do this to avoid loop flushing ...
6809            config.maxMaxBufferLength /= 2;
6810            logger_1.logger.warn("main:reduce max buffer length to " + config.maxMaxBufferLength + "s");
6811            return true;
6812        }
6813        return false;
6814    };
6815    /**
6816     * Checks the health of the buffer and attempts to resolve playback stalls.
6817     * @private
6818     */
6819    StreamController.prototype._checkBuffer = function () {
6820        var media = this.media;
6821        if (!media || media.readyState === 0) {
6822            // Exit early if we don't have media or if the media hasn't bufferd anything yet (readyState 0)
6823            return;
6824        }
6825        var mediaBuffer = this.mediaBuffer ? this.mediaBuffer : media;
6826        var buffered = mediaBuffer.buffered;
6827        if (!this.loadedmetadata && buffered.length) {
6828            this.loadedmetadata = true;
6829            this._seekToStartPos();
6830        }
6831        else if (this.immediateSwitch) {
6832            this.immediateLevelSwitchEnd();
6833        }
6834        else {
6835            this.gapController.poll(this.lastCurrentTime, buffered);
6836        }
6837    };
6838    StreamController.prototype.onFragLoadEmergencyAborted = function () {
6839        this.state = base_stream_controller_1.State.IDLE;
6840        // if loadedmetadata is not set, it means that we are emergency switch down on first frag
6841        // in that case, reset startFragRequested flag
6842        if (!this.loadedmetadata) {
6843            this.startFragRequested = false;
6844            this.nextLoadPosition = this.startPosition;
6845        }
6846        this.tick();
6847    };
6848    StreamController.prototype.onBufferFlushed = function () {
6849        /* after successful buffer flushing, filter flushed fragments from bufferedFrags
6850          use mediaBuffered instead of media (so that we will check against video.buffered ranges in case of alt audio track)
6851        */
6852        var media = this.mediaBuffer ? this.mediaBuffer : this.media;
6853        if (media) {
6854            // filter fragments potentially evicted from buffer. this is to avoid memleak on live streams
6855            this.fragmentTracker.detectEvictedFragments(fragment_1.default.ElementaryStreamTypes.VIDEO, media.buffered);
6856        }
6857        // move to IDLE once flush complete. this should trigger new fragment loading
6858        this.state = base_stream_controller_1.State.IDLE;
6859        // reset reference to frag
6860        this.fragPrevious = null;
6861    };
6862    StreamController.prototype.swapAudioCodec = function () {
6863        this.audioCodecSwap = !this.audioCodecSwap;
6864    };
6865    StreamController.prototype.computeLivePosition = function (sliding, levelDetails) {
6866        var targetLatency = this.config.liveSyncDuration !== undefined ? this.config.liveSyncDuration : this.config.liveSyncDurationCount * levelDetails.targetduration;
6867        return sliding + Math.max(0, levelDetails.totalduration - targetLatency);
6868    };
6869    /**
6870     * Seeks to the set startPosition if not equal to the mediaElement's current time.
6871     * @private
6872     */
6873    StreamController.prototype._seekToStartPos = function () {
6874        var media = this.media;
6875        var currentTime = media.currentTime;
6876        // only adjust currentTime if different from startPosition or if startPosition not buffered
6877        // at that stage, there should be only one buffered range, as we reach that code after first fragment has been buffered
6878        var startPosition = media.seeking ? currentTime : this.startPosition;
6879        // if currentTime not matching with expected startPosition or startPosition not buffered but close to first buffered
6880        if (currentTime !== startPosition) {
6881            // if startPosition not buffered, let's seek to buffered.start(0)
6882            logger_1.logger.log("target start position not buffered, seek to buffered.start(0) " + startPosition + " from current time " + currentTime + " ");
6883            media.currentTime = startPosition;
6884        }
6885    };
6886    StreamController.prototype._getAudioCodec = function (currentLevel) {
6887        var audioCodec = this.config.defaultAudioCodec || currentLevel.audioCodec;
6888        if (this.audioCodecSwap) {
6889            logger_1.logger.log('swapping playlist audio codec');
6890            if (audioCodec) {
6891                if (audioCodec.indexOf('mp4a.40.5') !== -1) {
6892                    audioCodec = 'mp4a.40.2';
6893                }
6894                else {
6895                    audioCodec = 'mp4a.40.5';
6896                }
6897            }
6898        }
6899        return audioCodec;
6900    };
6901    Object.defineProperty(StreamController.prototype, "liveSyncPosition", {
6902        get: function () {
6903            return this._liveSyncPosition;
6904        },
6905        set: function (value) {
6906            this._liveSyncPosition = value;
6907        },
6908        enumerable: true,
6909        configurable: true
6910    });
6911    return StreamController;
6912}(base_stream_controller_1.default));
6913exports.default = StreamController;
6914
6915/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.js")["Number"]))
6916
6917/***/ }),
6918
6919/***/ "./src/controller/subtitle-stream-controller.js":
6920/*!******************************************************!*\
6921  !*** ./src/controller/subtitle-stream-controller.js ***!
6922  \******************************************************/
6923/*! no static exports found */
6924/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
6925/***/ (function(module, exports, __webpack_require__) {
6926
6927"use strict";
6928
6929/**
6930 * @class SubtitleStreamController
6931 */
6932var __extends = (this && this.__extends) || (function () {
6933    var extendStatics = Object.setPrototypeOf ||
6934        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6935        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
6936    return function (d, b) {
6937        extendStatics(d, b);
6938        function __() { this.constructor = d; }
6939        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
6940    };
6941})();
6942Object.defineProperty(exports, "__esModule", { value: true });
6943var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
6944var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
6945var decrypter_1 = __webpack_require__(/*! ../crypt/decrypter */ "./src/crypt/decrypter.js");
6946var buffer_helper_1 = __webpack_require__(/*! ../utils/buffer-helper */ "./src/utils/buffer-helper.js");
6947var fragment_finders_1 = __webpack_require__(/*! ./fragment-finders */ "./src/controller/fragment-finders.js");
6948var fragment_tracker_1 = __webpack_require__(/*! ./fragment-tracker */ "./src/controller/fragment-tracker.js");
6949var base_stream_controller_1 = __webpack_require__(/*! ./base-stream-controller */ "./src/controller/base-stream-controller.js");
6950var level_helper_1 = __webpack_require__(/*! ./level-helper */ "./src/controller/level-helper.js");
6951var performance = window.performance;
6952var TICK_INTERVAL = 500; // how often to tick in ms
6953var SubtitleStreamController = /** @class */ (function (_super) {
6954    __extends(SubtitleStreamController, _super);
6955    function SubtitleStreamController(hls, fragmentTracker) {
6956        var _this = _super.call(this, hls, events_1.default.MEDIA_ATTA
6956CHED, events_1.default.MEDIA_DETACHING, events_1.default.ERROR, events_1.default.KEY_LOADED, events_1.default.FRAG_LOADED, events_1.default.SUBTITLE_TRACKS_UPDATED, events_1.default.SUBTITLE_TRACK_SWITCH, events_1.default.SUBTITLE_TRACK_LOADED, events_1.default.SUBTITLE_FRAG_PROCESSED, events_1.default.LEVEL_UPDATED) || this;
6957        _this.fragmentTracker = fragmentTracker;
6958        _this.config = hls.config;
6959        _this.state = base_stream_controller_1.State.STOPPED;
6960        _this.tracks = [];
6961        _this.tracksBuffered = [];
6962        _this.currentTrackId = -1;
6963        _this.decrypter = new decrypter_1.default(hls, hls.config);
6964        // lastAVStart stores the time in seconds for the start time of a level load
6965        _this.lastAVStart = 0;
6966        _this._onMediaSeeking = _this.onMediaSeeking.bind(_this);
6967        return _this;
6968    }
6969    SubtitleStreamController.prototype.onSubtitleFragProcessed = function (data) {
6970        var frag = data.frag, success = data.success;
6971        this.fragPrevious = frag;
6972        this.state = base_stream_controller_1.State.IDLE;
6973        if (!success) {
6974            return;
6975        }
6976        var buffered = this.tracksBuffered[this.currentTrackId];
6977        if (!buffered) {
6978            return;
6979        }
6980        // Create/update a buffered array matching the interface used by BufferHelper.bufferedInfo
6981        // so we can re-use the logic used to detect how much have been buffered
6982        var timeRange;
6983        var fragStart = frag.start;
6984        for (var i = 0; i < buffered.length; i++) {
6985            if (fragStart >= buffered[i].start && fragStart <= buffered[i].end) {
6986                timeRange = buffered[i];
6987                break;
6988            }
6989        }
6990        var fragEnd = frag.start + frag.duration;
6991        if (timeRange) {
6992            timeRange.end = fragEnd;
6993        }
6994        else {
6995            timeRange = {
6996                start: fragStart,
6997                end: fragEnd
6998            };
6999            buffered.push(timeRange);
7000        }
7001    };
7002    SubtitleStreamController.prototype.onMediaAttached = function (_a) {
7003        var media = _a.media;
7004        this.media = media;
7005        media.addEventListener('seeking', this._onMediaSeeking);
7006        this.state = base_stream_controller_1.State.IDLE;
7007    };
7008    SubtitleStreamController.prototype.onMediaDetaching = function () {
7009        this.media.removeEventListener('seeking', this._onMediaSeeking);
7010        this.media = null;
7011        this.state = base_stream_controller_1.State.STOPPED;
7012    };
7013    // If something goes wrong, proceed to next frag, if we were processing one.
7014    SubtitleStreamController.prototype.onError = function (data) {
7015        var frag = data.frag;
7016        // don't handle error not related to subtitle fragment
7017        if (!frag || frag.type !== 'subtitle') {
7018            return;
7019        }
7020        this.state = base_stream_controller_1.State.IDLE;
7021    };
7022    // Got all new subtitle tracks.
7023    SubtitleStreamController.prototype.onSubtitleTracksUpdated = function (data) {
7024        var _this = this;
7025        logger_1.logger.log('subtitle tracks updated');
7026        this.tracksBuffered = [];
7027        this.tracks = data.subtitleTracks;
7028        this.tracks.forEach(function (track) {
7029            _this.tracksBuffered[track.id] = [];
7030        });
7031    };
7032    SubtitleStreamController.prototype.onSubtitleTrackSwitch = function (data) {
7033        this.currentTrackId = data.id;
7034        if (!this.tracks || this.currentTrackId === -1) {
7035            this.clearInterval();
7036            return;
7037        }
7038        // Check if track has the necessary details to load fragments
7039        var currentTrack = this.tracks[this.currentTrackId];
7040        if (currentTrack && currentTrack.details) {
7041            this.setInterval(TICK_INTERVAL);
7042        }
7043    };
7044    // Got a new set of subtitle fragments.
7045    SubtitleStreamController.prototype.onSubtitleTrackLoaded = function (data) {
7046        var id = data.id, details = data.details;
7047        var _a = this, currentTrackId = _a.currentTrackId, tracks = _a.tracks;
7048        var currentTrack = tracks[currentTrackId];
7049        if (id >= tracks.length || id !== currentTrackId || !currentTrack) {
7050            return;
7051        }
7052        if (details.live) {
7053            level_helper_1.mergeSubtitlePlaylists(currentTrack.details, details, this.lastAVStart);
7054        }
7055        currentTrack.details = details;
7056        this.setInterval(TICK_INTERVAL);
7057    };
7058    SubtitleStreamController.prototype.onKeyLoaded = function () {
7059        if (this.state === base_stream_controller_1.State.KEY_LOADING) {
7060            this.state = base_stream_controller_1.State.IDLE;
7061        }
7062    };
7063    SubtitleStreamController.prototype.onFragLoaded = function (data) {
7064        var fragCurrent = this.fragCurrent;
7065        var decryptData = data.frag.decryptdata;
7066        var fragLoaded = data.frag;
7067        var hls = this.hls;
7068        if (this.state === base_stream_controller_1.State.FRAG_LOADING &&
7069            fragCurrent &&
7070            data.frag.type === 'subtitle' &&
7071            fragCurrent.sn === data.frag.sn) {
7072            // check to see if the payload needs to be decrypted
7073            if (data.payload.byteLength > 0 && (decryptData && decryptData.key && decryptData.method === 'AES-128')) {
7074                var startTime_1 = performance.now();
7075                // decrypt the subtitles
7076                this.decrypter.decrypt(data.payload, decryptData.key.buffer, decryptData.iv.buffer, function (decryptedData) {
7077                    var endTime = performance.now();
7078                    hls.trigger(events_1.default.FRAG_DECRYPTED, { frag: fragLoaded, payload: decryptedData, stats: { tstart: startTime_1, tdecrypt: endTime } });
7079                });
7080            }
7081        }
7082    };
7083    SubtitleStreamController.prototype.onLevelUpdated = function (_a) {
7084        var details = _a.details;
7085        var frags = details.fragments;
7086        this.lastAVStart = frags.length ? frags[0].start : 0;
7087    };
7088    SubtitleStreamController.prototype.doTick = function () {
7089        if (!this.media) {
7090            this.state = base_stream_controller_1.State.IDLE;
7091            return;
7092        }
7093        switch (this.state) {
7094            case base_stream_controller_1.State.IDLE: {
7095                var _a = this, config = _a.config, currentTrackId = _a.currentTrackId, fragmentTracker = _a.fragmentTracker, media = _a.media, tracks = _a.tracks;
7096                if (!tracks || !tracks[currentTrackId] || !tracks[currentTrackId].details) {
7097                    break;
7098                }
7099                var maxBufferHole = config.maxBufferHole, maxFragLookUpTolerance = config.maxFragLookUpTolerance;
7100                var maxConfigBuffer = Math.min(config.maxBufferLength, config.maxMaxBufferLength);
7101                var bufferedInfo = buffer_helper_1.BufferHelper.bufferedInfo(this._getBuffered(), media.currentTime, maxBufferHole);
7102                var bufferEnd = bufferedInfo.end, bufferLen = bufferedInfo.len;
7103                var trackDetails = tracks[currentTrackId].details;
7104                var fragments = trackDetails.fragments;
7105                var fragLen = fragments.length;
7106                var end = fragments[fragLen - 1].start + fragments[fragLen - 1].duration;
7107                if (bufferLen > maxConfigBuffer) {
7108                    return;
7109                }
7110                var foundFrag = void 0;
7111                var fragPrevious = this.fragPrevious;
7112                if (bufferEnd < end) {
7113                    if (fragPrevious && trackDetails.hasProgramDateTime) {
7114                        foundFrag = fragment_finders_1.findFragmentByPDT(fragments, fragPrevious.endProgramDateTime, maxFragLookUpTolerance);
7115                    }
7116                    if (!foundFrag) {
7117                        foundFrag = fragment_finders_1.findFragmentByPTS(fragPrevious, fragments, bufferEnd, maxFragLookUpTolerance);
7118                    }
7119                }
7120                else {
7121                    foundFrag = fragments[fragLen - 1];
7122                }
7123                if (foundFrag && foundFrag.encrypted) {
7124                    logger_1.logger.log("Loading key for " + foundFrag.sn);
7125                    this.state = base_stream_controller_1.State.KEY_LOADING;
7126                    this.hls.trigger(events_1.default.KEY_LOADING, { frag: foundFrag });
7127                }
7128                else if (foundFrag && fragmentTracker.getState(foundFrag) === fragment_tracker_1.FragmentState.NOT_LOADED) {
7129                    // only load if fragment is not loaded
7130                    this.fragCurrent = foundFrag;
7131                    this.state = base_stream_controller_1.State.FRAG_LOADING;
7132                    this.hls.trigger(events_1.default.FRAG_LOADING, { frag: foundFrag });
7133                }
7134            }
7135        }
7136    };
7137    SubtitleStreamController.prototype.stopLoad = function () {
7138        this.lastAVStart = 0;
7139        _super.prototype.stopLoad.call(this);
7140    };
7141    SubtitleStreamController.prototype._getBuffered = function () {
7142        return this.tracksBuffered[this.currentTrackId] || [];
7143    };
7144    SubtitleStreamController.prototype.onMediaSeeking = function () {
7145        this.fragPrevious = null;
7146    };
7147    return SubtitleStreamController;
7148}(base_stream_controller_1.default));
7149exports.SubtitleStreamController = SubtitleStreamController;
7150
7151
7152/***/ }),
7153
7154/***/ "./src/controller/subtitle-track-controller.js":
7155/*!*****************************************************!*\
7156  !*** ./src/controller/subtitle-track-controller.js ***!
7157  \*****************************************************/
7158/*! no static exports found */
7159/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
7160/***/ (function(module, exports, __webpack_require__) {
7161
7162"use strict";
7163/* WEBPACK VAR INJECTION */(function(Number) {
7164var __extends = (this && this.__extends) || (function () {
7165    var extendStatics = Object.setPrototypeOf ||
7166        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
7167        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
7168    return function (d, b) {
7169        extendStatics(d, b);
7170        function __() { this.constructor = d; }
7171        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
7172    };
7173})();
7174Object.defineProperty(exports, "__esModule", { value: true });
7175var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
7176var event_handler_1 = __webpack_require__(/*! ../event-handler */ "./src/event-handler.js");
7177var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
7178var level_helper_1 = __webpack_require__(/*! ./level-helper */ "./src/controller/level-helper.js");
7179var SubtitleTrackController = /** @class */ (function (_super) {
7180    __extends(SubtitleTrackController, _super);
7181    function SubtitleTrackController(hls) {
7182        var _this = _super.call(this, hls, events_1.default.MEDIA_ATTA
7182CHED, events_1.default.MEDIA_DETACHING, events_1.default.MANIFEST_LOADED, events_1.default.SUBTITLE_TRACK_LOADED) || this;
7183        _this.tracks = [];
7184        _this.trackId = -1;
7185        _this.media = null;
7186        _this.stopped = true;
7187        /**
7188         * @member {boolean} subtitleDisplay Enable/disable subtitle display rendering
7189         */
7190        _this.subtitleDisplay = true;
7191        return _this;
7192    }
7193    SubtitleTrackController.prototype.destroy = function () {
7194        event_handler_1.default.prototype.destroy.call(this);
7195    };
7196    // Listen for subtitle track change, then extract the current track ID.
7197    SubtitleTrackController.prototype.onMediaAttached = function (data) {
7198        var _this = this;
7199        this.media = data.media;
7200        if (!this.media) {
7201            return;
7202        }
7203        if (this.queuedDefaultTrack) {
7204            this.subtitleTrack = this.queuedDefaultTrack;
7205            delete this.queuedDefaultTrack;
7206        }
7207        this.trackChangeListener = this._onTextTracksChanged.bind(this);
7208        this.useTextTrackPolling = !(this.media.textTracks && 'onchange' in this.media.textTracks);
7209        if (this.useTextTrackPolling) {
7210            this.subtitlePollingInterval = setInterval(function () {
7211                _this.trackChangeListener();
7212            }, 500);
7213        }
7214        else {
7215            this.media.textTracks.addEventListener('change', this.trackChangeListener);
7216        }
7217    };
7218    SubtitleTrackController.prototype.onMediaDetaching = function () {
7219        if (!this.media) {
7220            return;
7221        }
7222        if (this.useTextTrackPolling) {
7223            clearInterval(this.subtitlePollingInterval);
7224        }
7225        else {
7226            this.media.textTracks.removeEventListener('change', this.trackChangeListener);
7227        }
7228        this.media = null;
7229    };
7230    // Fired whenever a new manifest is loaded.
7231    SubtitleTrackController.prototype.onManifestLoaded = function (data) {
7232        var _this = this;
7233        var tracks = data.subtitles || [];
7234        this.tracks = tracks;
7235        this.hls.trigger(events_1.default.SUBTITLE_TRACKS_UPDATED, { subtitleTracks: tracks });
7236        // loop through available subtitle tracks and autoselect default if needed
7237        // TODO: improve selection logic to handle forced, etc
7238        tracks.forEach(function (track) {
7239            if (track.default) {
7240                // setting this.subtitleTrack will trigger internal logic
7241                // if media has not been attached yet, it will fail
7242                // we keep a reference to the default track id
7243                // and we'll set subtitleTrack when onMediaAttached is triggered
7244                if (_this.media) {
7245                    _this.subtitleTrack = track.id;
7246                }
7247                else {
7248                    _this.queuedDefaultTrack = track.id;
7249                }
7250            }
7251        });
7252    };
7253    SubtitleTrackController.prototype.onSubtitleTrackLoaded = function (data) {
7254        var _this = this;
7255        var id = data.id, details = data.details;
7256        var _a = this, trackId = _a.trackId, tracks = _a.tracks;
7257        var currentTrack = tracks[trackId];
7258        if (id >= tracks.length || id !== trackId || !currentTrack || this.stopped) {
7259            this._clearReloadTimer();
7260            return;
7261        }
7262        logger_1.logger.log("subtitle track " + id + " loaded");
7263        if (details.live) {
7264            var reloadInterval = level_helper_1.computeReloadInterval(currentTrack.details, details, data.stats.trequest);
7265            logger_1.logger.log("Reloading live subtitle playlist in " + reloadInterval + "ms");
7266            this.timer = setTimeout(function () {
7267                _this._loadCurrentTrack();
7268            }, reloadInterval);
7269        }
7270        else {
7271            this._clearReloadTimer();
7272        }
7273    };
7274    SubtitleTrackController.prototype.startLoad = function () {
7275        this.stopped = false;
7276        this._loadCurrentTrack();
7277    };
7278    SubtitleTrackController.prototype.stopLoad = function () {
7279        this.stopped = true;
7280        this._clearReloadTimer();
7281    };
7282    Object.defineProperty(SubtitleTrackController.prototype, "subtitleTracks", {
7283        /** get alternate subtitle tracks list from playlist **/
7284        get: function () {
7285            return this.tracks;
7286        },
7287        enumerable: true,
7288        configurable: true
7289    });
7290    Object.defineProperty(SubtitleTrackController.prototype, "subtitleTrack", {
7291        /** get index of the selected subtitle track (index in subtitle track lists) **/
7292        get: function () {
7293            return this.trackId;
7294        },
7295        /** select a subtitle track, based on its index in subtitle track lists**/
7296        set: function (subtitleTrackId) {
7297            if (this.trackId !== subtitleTrackId) {
7298                this._toggleTrackModes(subtitleTrackId);
7299                this._setSubtitleTrackInternal(subtitleTrackId);
7300            }
7301        },
7302        enumerable: true,
7303        configurable: true
7304    });
7305    SubtitleTrackController.prototype._clearReloadTimer = function () {
7306        if (this.timer) {
7307            clearTimeout(this.timer);
7308            this.timer = null;
7309        }
7310    };
7311    SubtitleTrackController.prototype._loadCurrentTrack = function () {
7312        var _a = this, trackId = _a.trackId, tracks = _a.tracks, hls = _a.hls;
7313        var currentTrack = tracks[trackId];
7314        if (trackId < 0 || !currentTrack || (currentTrack.details && !currentTrack.details.live)) {
7315            return;
7316        }
7317        logger_1.logger.log("Loading subtitle track " + trackId);
7318        hls.trigger(events_1.default.SUBTITLE_TRACK_LOADING, { url: currentTrack.url, id: trackId });
7319    };
7320    /**
7321     * Disables the old subtitleTrack and sets current mode on the next subtitleTrack.
7322     * This operates on the DOM textTracks.
7323     * A value of -1 will disable all subtitle tracks.
7324     * @param newId - The id of the next track to enable
7325     * @private
7326     */
7327    SubtitleTrackController.prototype._toggleTrackModes = function (newId) {
7328        var _a = this, media = _a.media, subtitleDisplay = _a.subtitleDisplay, trackId = _a.trackId;
7329        if (!media) {
7330            return;
7331        }
7332        var textTracks = filterSubtitleTracks(media.textTracks);
7333        if (newId === -1) {
vendor: 2,603 bytes, lines 7334-7402
7334            [].slice.call(textTracks).forEach(function (track) {
7335                track.mode = 'disabled';
7336            });
7337        }
7338        else {
7339            var oldTrack = textTracks[trackId];
7340            if (oldTrack) {
7341                oldTrack.mode = 'disabled';
7342            }
7343        }
7344        var nextTrack = textTracks[newId];
7345        if (nextTrack) {
7346            nextTrack.mode = subtitleDisplay ? 'showing' : 'hidden';
7347        }
7348    };
7349    /**
7350       * This method is responsible for validating the subtitle index and periodically reloading if live.
7351       * Dispatches the SUBTITLE_TRACK_SWITCH event, which instructs the subtitle-stream-controller to load the selected track.
7352       * @param newId - The id of the subtitle track to activate.
7353       */
7354    SubtitleTrackController.prototype._setSubtitleTrackInternal = function (newId) {
7355        var _a = this, hls = _a.hls, tracks = _a.tracks;
7356        if (!Number.isFinite(newId) || newId < -1 || newId >= tracks.length) {
7357            return;
7358        }
7359        this.trackId = newId;
7360        logger_1.logger.log("Switching to subtitle track " + newId);
7361        hls.trigger(events_1.default.SUBTITLE_TRACK_SWITCH, { id: newId });
7362        this._loadCurrentTrack();
7363    };
7364    SubtitleTrackController.prototype._onTextTracksChanged = function () {
7365        // Media is undefined when switching streams via loadSource()
7366        if (!this.media) {
7367            return;
7368        }
7369        var trackId = -1;
7370        var tracks = filterSubtitleTracks(this.media.textTracks);
7371        for (var id = 0; id < tracks.length; id++) {
7372            if (tracks[id].mode === 'hidden') {
7373                // Do not break in case there is a following track with showing.
7374                trackId = id;
7375            }
7376            else if (tracks[id].mode === 'showing') {
7377                trackId = id;
7378                break;
7379            }
7380        }
7381        // Setting current subtitleTrack will invoke code.
7382        this.subtitleTrack = trackId;
7383    };
7384    return SubtitleTrackController;
7385}(event_handler_1.default));
7386function filterSubtitleTracks(textTrackList) {
7387    var tracks = [];
7388    for (var i = 0; i < textTrackList.length; i++) {
7389        var track = textTrackList[i];
7390        // Edge adds a track without a label; we don't want to use it
7391        if (track.kind === 'subtitles' && track.label) {
7392            tracks.push(textTrackList[i]);
7393        }
7394    }
7395    return tracks;
7396}
7397exports.default = SubtitleTrackController;
7398
7399/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.js")["Number"]))
7400
7401/***/ }),
7402
7403/***/ "./src/controller/timeline-controller.js":
7404/*!***********************************************!*\
7405  !*** ./src/controller/timeline-controller.js ***!
7406  \***********************************************/
7407/*! no static exports found */
7408/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
7409/***/ (function(module, exports, __webpack_require__) {
7410
7411"use strict";
7412/* WEBPACK VAR INJECTION */(function(Number) {
7413/*
7414 * Timeline Controller
7415*/
7416var __extends = (this && this.__extends) || (function () {
7417    var extendStatics = Object.setPrototypeOf ||
7418        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
7419        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
7420    return function (d, b) {
7421        extendStatics(d, b);
7422        function __() { this.constructor = d; }
7423        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
7424    };
7425})();
7426Object.defineProperty(exports, "__esModule", { value: true });
7427var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
7428var event_handler_1 = __webpack_require__(/*! ../event-handler */ "./src/event-handler.js");
7429var cea_608_parser_1 = __webpack_require__(/*! ../utils/cea-608-parser */ "./src/utils/cea-608-parser.js");
7430var output_filter_1 = __webpack_require__(/*! ../utils/output-filter */ "./src/utils/output-filter.js");
7431var webvtt_parser_1 = __webpack_require__(/*! ../utils/webvtt-parser */ "./src/utils/webvtt-parser.js");
7432var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
7433var texttrack_utils_1 = __webpack_require__(/*! ../utils/texttrack-utils */ "./src/utils/texttrack-utils.js");
7434function canReuseVttTextTrack(inUseTrack, manifestTrack) {
7435    return inUseTrack && inUseTrack.label === manifestTrack.name && !(inUseTrack.textTrack1 || inUseTrack.textTrack2);
7436}
7437function intersection(x1, x2, y1, y2) {
7438    return Math.min(x2, y2) - Math.max(x1, y1);
7439}
7440var TimelineController = /** @class */ (function (_super) {
7441    __extends(TimelineController, _super);
7442    function TimelineController(hls) {
7443        var _this = _super.call(this, hls, events_1.default.MEDIA_ATTA
7443CHING, events_1.default.MEDIA_DETACHING, events_1.default.FRAG_PARSING_USERDATA, events_1.default.FRAG_DECRYPTED, events_1.default.MANIFEST_LOADING, events_1.default.MANIFEST_LOADED, events_1.default.FRAG_LOADED, events_1.default.LEVEL_SWITCHING, events_1.default.INIT_PTS_FOUND) || this;
7444        _this.hls = hls;
7445        _this.config = hls.config;
7446        _this.enabled = true;
7447        _this.Cues = hls.config.cueHandler;
7448        _this.textTracks = [];
7449        _this.tracks = [];
7450        _this.unparsedVttFrags = [];
7451        _this.initPTS = [];
7452        _this.cueRanges = [];
7453        _this.captionsTracks = {};
7454        _this.captionsProperties = {
7455            textTrack1: {
7456                label: _this.config.captionsTextTrack1Label,
7457                languageCode: _this.config.captionsTextTrack1LanguageCode
7458            },
7459            textTrack2: {
7460                label: _this.config.captionsTextTrack2Label,
7461                languageCode: _this.config.captionsTextTrack2LanguageCode
7462            }
7463        };
7464        if (_this.config.enableCEA708Captions) {
7465            var channel1 = new output_filter_1.default(_this, 'textTrack1');
7466            var channel2 = new output_filter_1.default(_this, 'textTrack2');
7467            _this.cea608Parser = new cea_608_parser_1.default(0, channel1, channel2);
7468        }
7469        return _this;
7470    }
7471    TimelineController.prototype.addCues = function (trackName, startTime, endTime, screen) {
7472        // skip cues which overlap more than 50% with previously parsed time ranges
7473        var ranges = this.cueRanges;
7474        var merged = false;
7475        for (var i = ranges.length; i--;) {
7476            var cueRange = ranges[i];
7477            var overlap = intersection(cueRange[0], cueRange[1], startTime, endTime);
7478            if (overlap >= 0) {
7479                cueRange[0] = Math.min(cueRange[0], startTime);
7480                cueRange[1] = Math.max(cueRange[1], endTime);
7481                merged = true;
7482                if ((overlap / (endTime - startTime)) > 0.5) {
7483                    return;
7484                }
7485            }
7486        }
7487        if (!merged) {
7488            ranges.push([startTime, endTime]);
7489        }
7490        this.Cues.newCue(this.captionsTracks[trackName], startTime, endTime, screen);
7491    };
7492    // Triggered when an initial PTS is found; used for synchronisation of WebVTT.
7493    TimelineController.prototype.onInitPtsFound = function (data) {
7494        var _this = this;
7495        if (data.id === 'main') {
7496            this.initPTS[data.frag.cc] = data.initPTS;
7497        }
7498        // Due to asynchronous processing, initial PTS may arrive later than the first VTT fragments are loaded.
7499        // Parse any unparsed fragments upon receiving the initial PTS.
7500        if (this.unparsedVttFrags.length) {
7501            var unparsedVttFrags = this.unparsedVttFrags;
7502            this.unparsedVttFrags = [];
7503            unparsedVttFrags.forEach(function (frag) {
7504                _this.onFragLoaded(frag);
7505            });
7506        }
7507    };
7508    TimelineController.prototype.getExistingTrack = function (trackName) {
7509        var media = this.media;
7510        if (media) {
7511            for (var i = 0; i < media.textTracks.length; i++) {
7512                var textTrack = media.textTracks[i];
7513                if (textTrack[trackName]) {
7514                    return textTrack;
7515                }
7516            }
7517        }
7518        return null;
7519    };
7520    TimelineController.prototype.createCaptionsTrack = function (trackName) {
7521        var _a = this.captionsProperties[trackName], label = _a.label, languageCode = _a.languageCode;
7522        var captionsTracks = this.captionsTracks;
7523        if (!captionsTracks[trackName]) {
7524            // Enable reuse of existing text track.
7525            var existingTrack = this.getExistingTrack(trackName);
7526            if (!existingTrack) {
7527                var textTrack = this.createTextTrack('captions', label, languageCode);
7528                if (textTrack) {
7529                    // Set a special property on the track so we know it's managed by Hls.js
7530                    textTrack[trackName] = true;
7531                    captionsTracks[trackName] = textTrack;
7532                }
7533            }
7534            else {
7535                captionsTracks[trackName] = existingTrack;
7536                texttrack_utils_1.clearCurrentCues(captionsTracks[trackName]);
7537                texttrack_utils_1.sendAddTrackEvent(captionsTracks[trackName], this.media);
7538            }
7539        }
7540    };
7541    TimelineController.prototype.createTextTrack = function (kind, label, lang) {
7542        var media = this.media;
7543        if (media) {
7544            return media.addTextTrack(kind, label, lang);
7545        }
7546    };
7547    TimelineController.prototype.destroy = function () {
7548        event_handler_1.default.prototype.destroy.call(this);
7549    };
7550    TimelineController.prototype.onMediaAttaching = function (data) {
7551        this.media = data.media;
7552        this._cleanTracks();
7553    };
7554    TimelineController.prototype.onMediaDetaching = function () {
7555        var captionsTracks = this.captionsTracks;
7556        Object.keys(captionsTracks).forEach(function (trackName) {
7557            texttrack_utils_1.clearCurrentCues(captionsTracks[trackName]);
7558            delete captionsTracks[trackName];
7559        });
7560    };
7561    TimelineController.prototype.onManifestLoading = function () {
7562        this.lastSn = -1; // Detect discontiguity in fragment parsing
7563        this.prevCC = -1;
7564        this.vttCCs = {
7565            ccOffset: 0,
7566            presentationOffset: 0,
7567            0: {
7568                start: 0, prevCC: -1, new: false
7569            }
7570        };
7571        this._cleanTracks();
7572    };
7573    TimelineController.prototype._cleanTracks = function () {
7574        // clear outdated subtitles
7575        var media = this.media;
7576        if (media) {
7577            var textTracks = media.textTracks;
7578            if (textTracks) {
7579                for (var i = 0; i < textTracks.length; i++) {
7580                    texttrack_utils_1.clearCurrentCues(textTracks[i]);
7581                }
7582            }
7583        }
7584    };
7585    TimelineController.prototype.onManifestLoaded = function (data) {
7586        var _this = this;
7587        this.textTracks = [];
7588        this.unparsedVttFrags = this.unparsedVttFrags || [];
7589        this.initPTS = [];
7590        this.cueRanges = [];
7591        if (this.config.enableWebVTT) {
7592            this.tracks = data.subtitles || [];
7593            var inUseTracks_1 = this.media ? this.media.textTracks : [];
7594            this.tracks.forEach(function (track, index) {
7595                var textTrack;
7596                if (index < inUseTracks_1.length) {
7597                    var inUseTrack = null;
7598                    for (var i = 0; i < inUseTracks_1.length; i++) {
7599                        if (canReuseVttTextTrack(inUseTracks_1[i], track)) {
7600                            inUseTrack = inUseTracks_1[i];
7601                            break;
7602                        }
7603                    }
7604                    // Reuse tracks with the same label, but do not reuse 608/708 tracks
7605                    if (inUseTrack) {
7606                        textTrack = inUseTrack;
7607                    }
7608                }
7609                if (!textTrack) {
7610                    textTrack = _this.createTextTrack('subtitles', track.name, track.lang);
7611                }
7612                if (track.default) {
7613                    textTrack.mode = _this.hls.subtitleDisplay ? 'showing' : 'hidden';
7614                }
7615                else {
7616                    textTrack.mode = 'disabled';
7617                }
7618                _this.textTracks.push(textTrack);
7619            });
7620        }
7621    };
7622    TimelineController.prototype.onLevelSwitching = function () {
7623        this.enabled = this.hls.currentLevel.closedCaptions !== 'NONE';
7624    };
7625    TimelineController.prototype.onFragLoaded = function (data) {
7626        var frag = data.frag, payload = data.payload;
7627        if (frag.type === 'main') {
7628            var sn = frag.sn;
7629            // if this frag isn't contiguous, clear the parser so cues with bad start/end times aren't added to the textTrack
7630            if (sn !== this.lastSn + 1) {
7631                var cea608Parser = this.cea608Parser;
7632                if (cea608Parser) {
7633                    cea608Parser.reset();
7634                }
7635            }
7636            this.lastSn = sn;
7637        } // eslint-disable-line brace-style
7638        // If fragment is subtitle type, parse as WebVTT.
7639        else if (frag.type === 'subtitle') {
7640            if (payload.byteLength) {
7641                // We need an initial synchronisation PTS. Store fragments as long as none has arrived.
7642                if (!Number.isFinite(this.initPTS[frag.cc])) {
7643                    this.unparsedVttFrags.push(data);
7644                    if (this.initPTS.length) {
7645                        // finish unsuccessfully, otherwise the subtitle-stream-controller could be blocked from loading new frags.
7646                        this.hls.trigger(events_1.default.SUBTITLE_FRAG_PROCESSED, { success: false, frag: frag });
7647                    }
7648                    return;
7649                }
7650                var decryptData = frag.decryptdata;
7651                // If the subtitles are not encrypted, parse VTTs now. Otherwise, we need to wait.
7652                if ((decryptData == null) || (decryptData.key == null) || (decryptData.method !== 'AES-128')) {
7653                    this._parseVTTs(frag, payload);
7654                }
7655            }
7656            else {
7657                // In case there is no payload, finish unsuccessfully.
7658                this.hls.trigger(events_1.default.SUBTITLE_FRAG_PROCESSED, { success: false, frag: frag });
7659            }
7660        }
7661    };
7662    TimelineController.prototype._parseVTTs = function (frag, payload) {
7663        var vttCCs = this.vttCCs;
7664        if (!vttCCs[frag.cc]) {
7665            vttCCs[frag.cc] = { start: frag.start, prevCC: this.prevCC, new: true };
7666            this.prevCC = frag.cc;
7667        }
7668        var textTracks = this.textTracks, hls = this.hls;
7669        // Parse the WebVTT file contents.
7670        webvtt_parser_1.default.parse(payload, this.initPTS[frag.cc], vttCCs, frag.cc, function (cues) {
7671            var currentTrack = textTracks[frag.level];
7672            // WebVTTParser.parse is an async method and if the currently selected text track mode is set to "disabled"
7673            // before parsing is done then don't try to access currentTrack.cues.getCueById as cues will be null
7674            // and trying to access getCueById method of cues will throw an exception
7675            if (currentTrack.mode === 'disabled') {
7676                hls.trigger(events_1.default.SUBTITLE_FRAG_PROCESSED, { success: false, frag: frag });
7677                return;
7678            }
7679            // Add cues and trigger event with success true.
7680            cues.forEach(function (cue) {
7681                // Sometimes there are cue overlaps on segmented vtts so the same
7682                // cue can appear more than once in different vtt files.
7683                // This avoid showing duplicated cues with same timecode and text.
7684                if (!currentTrack.cues.getCueById(cue.id)) {
7685                    try {
7686                        currentTrack.addCue(cue);
7687                    }
7688                    catch (err) {
7689                        var textTrackCue = new window.TextTrackCue(cue.startTime, cue.endTime, cue.text);
7690                        textTrackCue.id = cue.id;
7691                        currentTrack.addCue(textTrackCue);
7692                    }
7693                }
7694            });
7695            hls.trigger(events_1.default.SUBTITLE_FRAG_PROCESSED, { success: true, frag: frag });
7696        }, function (e) {
7697            // Something went wrong while parsing. Trigger event with success false.
7698            logger_1.logger.log("Failed to parse VTT cue: " + e);
7699            hls.trigger(events_1.default.SUBTITLE_FRAG_PROCESSED, { success: false, frag: frag });
7700        });
7701    };
7702    TimelineController.prototype.onFragDecrypted = function (data) {
7703        var decryptedData = data.payload, frag = data.frag;
7704        if (frag.type === 'subtitle') {
7705            if (!Number.isFinite(this.initPTS[frag.cc])) {
7706                this.unparsedVttFrags.push(data);
7707                return;
7708            }
7709            this._parseVTTs(frag, decryptedData);
7710        }
7711    };
7712    TimelineController.prototype.onFragParsingUserdata = function (data) {
7713        // push all of the CEA-708 messages into the interpreter
7714        // immediately. It will create the proper timestamps based on our PTS value
7715        if (this.enabled && this.config.enableCEA708Captions) {
7716            for (var i = 0; i < data.samples.length; i++) {
7717                var ccdatas = this.extractCea608Data(data.samples[i].bytes);
7718                this.cea608Parser.addData(data.samples[i].pts, ccdatas);
7719            }
7720        }
7721    };
7722    TimelineController.prototype.extractCea608Data = function (byteArray) {
7723        var count = byteArray[0] & 31;
7724        var position = 2;
7725        var tmpByte, ccbyte1, ccbyte2, ccValid, ccType;
7726        var actualCCBytes = [];
7727        for (var j = 0; j < count; j++) {
7728            tmpByte = byteArray[position++];
7729            ccbyte1 = 0x7F & byteArray[position++];
7730            ccbyte2 = 0x7F & byteArray[position++];
7731            ccValid = (4 & tmpByte) !== 0;
7732            ccType = 3 & tmpByte;
7733            if (ccbyte1 === 0 && ccbyte2 === 0) {
7734                continue;
7735            }
7736            if (ccValid) {
7737                if (ccType === 0) { // || ccType === 1
7738                    actualCCBytes.push(ccbyte1);
7739                    actualCCBytes.push(ccbyte2);
7740                }
7741            }
7742        }
7743        return actualCCBytes;
7744    };
7745    return TimelineController;
7746}(event_handler_1.default));
7747exports.default = TimelineController;
7748
7749/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.js")["Number"]))
7750
7751/***/ }),
7752
7753/***/ "./src/crypt/aes-crypto.js":
7754/*!*********************************!*\
7755  !*** ./src/crypt/aes-crypto.js ***!
7756  \*********************************/
7757/*! no static exports found */
7758/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
7759/***/ (function(module, exports, __webpack_require__) {
7760
7761"use strict";
7762
7763Object.defineProperty(exports, "__esModule", { value: true });
7764var AESCrypto = /** @class */ (function () {
7765    function AESCrypto(subtle, iv) {
7766        this.subtle = subtle;
7767        this.aesIV = iv;
7768    }
7769    AESCrypto.prototype.decrypt = function (data, key) {
7770        return this.subtle.decrypt({ name: 'AES-CBC', iv: this.aesIV }, key, data);
7771    };
7772    return AESCrypto;
7773}());
7774exports.default = AESCrypto;
7775
7776
7777/***/ }),
7778
7779/***/ "./src/crypt/aes-decryptor.js":
7780/*!************************************!*\
7781  !*** ./src/crypt/aes-decryptor.js ***!
7782  \************************************/
7783/*! no static exports found */
7784/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
7785/***/ (function(module, exports, __webpack_require__) {
7786
7787"use strict";
7788
7789Object.defineProperty(exports, "__esModule", { value: true });
7790// PKCS7
7791function removePadding(buffer) {
7792    var outputBytes = buffer.byteLength;
7793    var paddingBytes = outputBytes && (new DataView(buffer)).getUint8(outputBytes - 1);
7794    if (paddingBytes) {
7795        return buffer.slice(0, outputBytes - paddingBytes);
7796    }
7797    else {
7798        return buffer;
7799    }
7800}
7801exports.removePadding = removePadding;
7802var AESDecryptor = /** @class */ (function () {
7803    function AESDecryptor() {
7804        // Static after running initTable
7805        this.rcon = [0x0, 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36];
7806        this.subMix = [new Uint32Array(256), new Uint32Array(256), new Uint32Array(256), new Uint32Array(256)];
7807        this.invSubMix = [new Uint32Array(256), new Uint32Array(256), new Uint32Array(256), new Uint32Array(256)];
7808        this.sBox = new Uint32Array(256);
7809        this.invSBox = new Uint32Array(256);
7810        // Changes during runtime
7811        this.key = new Uint32Array(0);
7812        this.initTable();
7813    }
7814    // Using view.getUint32() also swaps the byte order.
7815    AESDecryptor.prototype.uint8ArrayToUint32Array_ = function (arrayBuffer) {
7816        var view = new DataView(arrayBuffer);
7817        var newArray = new Uint32Array(4);
7818        for (var i = 0; i < 4; i++) {
7819            newArray[i] = view.getUint32(i * 4);
7820        }
7821        return newArray;
7822    };
7823    AESDecryptor.prototype.initTable = function () {
7824        var sBox = this.sBox;
7825        var invSBox = this.invSBox;
7826        var subMix = this.subMix;
7827        var subMix0 = subMix[0];
7828        var subMix1 = subMix[1];
7829        var subMix2 = subMix[2];
7830        var subMix3 = subMix[3];
7831        var invSubMix = this.invSubMix;
7832        var invSubMix0 = invSubMix[0];
7833        var invSubMix1 = invSubMix[1];
7834        var invSubMix2 = invSubMix[2];
7835        var invSubMix3 = invSubMix[3];
7836        var d = new Uint32Array(256);
7837        var x = 0;
7838        var xi = 0;
7839        var i = 0;
7840        for (i = 0; i < 256; i++) {
7841            if (i < 128) {
7842                d[i] = i << 1;
7843            }
7844            else {
7845                d[i] = (i << 1) ^ 0x11b;
7846            }
7847        }
7848        for (i = 0; i < 256; i++) {
7849            var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4);
7850            sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63;
7851            sBox[x] = sx;
7852            invSBox[sx] = x;
7853            // Compute multiplication
7854            var x2 = d[x];
7855            var x4 = d[x2];
7856            var x8 = d[x4];
7857            // Compute sub/invSub bytes, mix columns tables
7858            var t = (d[sx] * 0x101) ^ (sx * 0x1010100);
7859            subMix0[x] = (t << 24) | (t >>> 8);
7860            subMix1[x] = (t << 16) | (t >>> 16);
7861            subMix2[x] = (t << 8) | (t >>> 24);
7862            subMix3[x] = t;
7863            // Compute inv sub bytes, inv mix columns tables
7864            t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100);
7865            invSubMix0[sx] = (t << 24) | (t >>> 8);
7866            invSubMix1[sx] = (t << 16) | (t >>> 16);
7867            invSubMix2[sx] = (t << 8) | (t >>> 24);
7868            invSubMix3[sx] = t;
7869            // Compute next counter
7870            if (!x) {
7871                x = xi = 1;
7872            }
7873            else {
7874                x = x2 ^ d[d[d[x8 ^ x2]]];
7875                xi ^= d[d[xi]];
7876            }
7877        }
7878    };
7879    AESDecryptor.prototype.expandKey = function (keyBuffer) {
7880        // convert keyBuffer to Uint32Array
7881        var key = this.uint8ArrayToUint32Array_(keyBuffer);
7882        var sameKey = true;
7883        var offset = 0;
7884        while (offset < key.length && sameKey) {
7885            sameKey = (key[offset] === this.key[offset]);
7886            offset++;
7887        }
7888        if (sameKey) {
7889            return;
7890        }
7891        this.key = key;
7892        var keySize = this.keySize = key.length;
7893        if (keySize !== 4 && keySize !== 6 && keySize !== 8) {
7894            throw new Error('Invalid aes key size=' + keySize);
7895        }
7896        var ksRows = this.ksRows = (keySize + 6 + 1) * 4;
7897        var ksRow;
7898        var invKsRow;
7899        var keySchedule = this.keySchedule = new Uint32Array(ksRows);
7900        var invKeySchedule = this.invKeySchedule = new Uint32Array(ksRows);
7901        var sbox = this.sBox;
7902        var rcon = this.rcon;
7903        var invSubMix = this.invSubMix;
7904        var invSubMix0 = invSubMix[0];
7905        var invSubMix1 = invSubMix[1];
7906        var invSubMix2 = invSubMix[2];
7907        var invSubMix3 = invSubMix[3];
7908        var prev;
7909        var t;
7910        for (ksRow = 0; ksRow < ksRows; ksRow++) {
7911            if (ksRow < keySize) {
7912                prev = keySchedule[ksRow] = key[ksRow];
7913                continue;
7914            }
7915            t = prev;
7916            if (ksRow % keySize === 0) {
7917                // Rot word
7918                t = (t << 8) | (t >>> 24);
7919                // Sub word
7920                t = (sbox[t >>> 24] << 24) | (sbox[(t >>> 16) & 0xff] << 16) | (sbox[(t >>> 8) & 0xff] << 8) | sbox[t & 0xff];
7921                // Mix Rcon
7922                t ^= rcon[(ksRow / keySize) | 0] << 24;
7923            }
7924            else if (keySize > 6 && ksRow % keySize === 4) {
7925                // Sub word
7926                t = (sbox[t >>> 24] << 24) | (sbox[(t >>> 16) & 0xff] << 16) | (sbox[(t >>> 8) & 0xff] << 8) | sbox[t & 0xff];
7927            }
7928            keySchedule[ksRow] = prev = (keySchedule[ksRow - keySize] ^ t) >>> 0;
7929        }
7930        for (invKsRow = 0; invKsRow < ksRows; invKsRow++) {
7931            ksRow = ksRows - invKsRow;
7932            if (invKsRow & 3) {
7933                t = keySchedule[ksRow];
7934            }
7935            else {
7936                t = keySchedule[ksRow - 4];
7937            }
7938            if (invKsRow < 4 || ksRow <= 4) {
7939                invKeySchedule[invKsRow] = t;
7940            }
7941            else {
7942                invKeySchedule[invKsRow] = invSubMix0[sbox[t >>> 24]] ^ invSubMix1[sbox[(t >>> 16) & 0xff]] ^ invSubMix2[sbox[(t >>> 8) & 0xff]] ^ invSubMix3[sbox[t & 0xff]];
7943            }
7944            invKeySchedule[invKsRow] = invKeySchedule[invKsRow] >>> 0;
7945        }
7946    };
7947    // Adding this as a method greatly improves performance.
7948    AESDecryptor.prototype.networkToHostOrderSwap = function (word) {
7949        return (word << 24) | ((word & 0xff00) << 8) | ((word & 0xff0000) >> 8) | (word >>> 24);
7950    };
7951    AESDecryptor.prototype.decrypt = function (inputArrayBuffer, offset, aesIV, removePKCS7Padding) {
7952        var nRounds = this.keySize + 6;
7953        var invKeySchedule = this.invKeySchedule;
7954        var invSBOX = this.invSBox;
7955        var invSubMix = this.invSubMix;
7956        var invSubMix0 = invSubMix[0];
7957        var invSubMix1 = invSubMix[1];
7958        var invSubMix2 = invSubMix[2];
7959        var invSubMix3 = invSubMix[3];
7960        var initVector = this.uint8ArrayToUint32Array_(aesIV);
7961        var initVector0 = initVector[0];
7962        var initVector1 = initVector[1];
7963        var initVector2 = initVector[2];
7964        var initVector3 = initVector[3];
7965        var inputInt32 = new Int32Array(inputArrayBuffer);
7966        var outputInt32 = new Int32Array(inputInt32.length);
7967        var t0, t1, t2, t3;
7968        var s0, s1, s2, s3;
7969        var inputWords0, inputWords1, inputWords2, inputWords3;
7970        var ksRow, i;
7971        var swapWord = this.networkToHostOrderSwap;
7972        while (offset < inputInt32.length) {
7973            inputWords0 = swapWord(inputInt32[offset]);
7974            inputWords1 = swapWord(inputInt32[offset + 1]);
7975            inputWords2 = swapWord(inputInt32[offset + 2]);
7976            inputWords3 = swapWord(inputInt32[offset + 3]);
7977            s0 = inputWords0 ^ invKeySchedule[0];
7978            s1 = inputWords3 ^ invKeySchedule[1];
7979            s2 = inputWords2 ^ invKeySchedule[2];
7980            s3 = inputWords1 ^ invKeySchedule[3];
7981            ksRow = 4;
7982            // Iterate through the rounds of decryption
7983            for (i = 1; i < nRounds; i++) {
7984                t0 = invSubMix0[s0 >>> 24] ^ invSubMix1[(s1 >> 16) & 0xff] ^ invSubMix2[(s2 >> 8) & 0xff] ^ invSubMix3[s3 & 0xff] ^ invKeySchedule[ksRow];
7985                t1 = invSubMix0[s1 >>> 24] ^ invSubMix1[(s2 >> 16) & 0xff] ^ invSubMix2[(s3 >> 8) & 0xff] ^ invSubMix3[s0 & 0xff] ^ invKeySchedule[ksRow + 1];
7986                t2 = invSubMix0[s2 >>> 24] ^ invSubMix1[(s3 >> 16) & 0xff] ^ invSubMix2[(s0 >> 8) & 0xff] ^ invSubMix3[s1 & 0xff] ^ invKeySchedule[ksRow + 2];
7987                t3 = invSubMix0[s3 >>> 24] ^ invSubMix1[(s0 >> 16) & 0xff] ^ invSubMix2[(s1 >> 8) & 0xff] ^ invSubMix3[s2 & 0xff] ^ invKeySchedule[ksRow + 3];
7988                // Update state
7989                s0 = t0;
7990                s1 = t1;
7991                s2 = t2;
7992                s3 = t3;
7993                ksRow = ksRow + 4;
7994            }
7995            // Shift rows, sub bytes, add round key
7996            t0 = ((invSBOX[s0 >>> 24] << 24) ^ (invSBOX[(s1 >> 16) & 0xff] << 16) ^ (invSBOX[(s2 >> 8) & 0xff] << 8) ^ invSBOX[s3 & 0xff]) ^ invKeySchedule[ksRow];
7997            t1 = ((invSBOX[s1 >>> 24] << 24) ^ (invSBOX[(s2 >> 16) & 0xff] << 16) ^ (invSBOX[(s3 >> 8) & 0xff] << 8) ^ invSBOX[s0 & 0xff]) ^ invKeySchedule[ksRow + 1];
7998            t2 = ((invSBOX[s2 >>> 24] << 24) ^ (invSBOX[(s3 >> 16) & 0xff] << 16) ^ (invSBOX[(s0 >> 8) & 0xff] << 8) ^ invSBOX[s1 & 0xff]) ^ invKeySchedule[ksRow + 2];
7999            t3 = ((invSBOX[s3 >>> 24] << 24) ^ (invSBOX[(s0 >> 16) & 0xff] << 16) ^ (invSBOX[(s1 >> 8) & 0xff] << 8) ^ invSBOX[s2 & 0xff]) ^ invKeySchedule[ksRow + 3];
8000            ksRow = ksRow + 3;
8001            // Write
8002            outputInt32[offset] = swapWord(t0 ^ initVector0);
8003            outputInt32[offset + 1] = swapWord(t3 ^ initVector1);
8004            outputInt32[offset + 2] = swapWord(t2 ^ initVector2);
8005            outputInt32[offset + 3] = swapWord(t1 ^ initVector3);
8006            // reset initVector to last 4 unsigned int
8007            initVector0 = inputWords0;
8008            initVector1 = inputWords1;
8009            initVector2 = inputWords2;
8010            initVector3 = inputWords3;
8011            offset = offset + 4;
8012        }
8013        return removePKCS7Padding ? removePadding(outputInt32.buffer) : outputInt32.buffer;
8014    };
8015    AESDecryptor.prototype.destroy = function () {
8016        this.key = undefined;
8017        this.keySize = undefined;
8018        this.ksRows = undefined;
8019        this.sBox = undefined;
8020        this.invSBox = undefined;
8021        this.subMix = undefined;
8022        this.invSubMix = undefined;
8023        this.keySchedule = undefined;
8024        this.invKeySchedule = undefined;
8025        this.rcon = undefined;
8026    };
8027    return AESDecryptor;
8028}());
8029exports.default = AESDecryptor;
8030
8031
8032/***/ }),
8033
8034/***/ "./src/crypt/decrypter.js":
8035/*!********************************!*\
8036  !*** ./src/crypt/decrypter.js ***!
8037  \********************************/
8038/*! no static exports found */
8039/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
8040/***/ (function(module, exports, __webpack_require__) {
8041
8042"use strict";
8043
8044Object.defineProperty(exports, "__esModule", { value: true });
8045var aes_crypto_1 = __webpack_require__(/*! ./aes-crypto */ "./src/crypt/aes-crypto.js");
8046var fast_aes_key_1 = __webpack_require__(/*! ./fast-aes-key */ "./src/crypt/fast-aes-key.js");
8047var aes_decryptor_1 = __webpack_require__(/*! ./aes-decryptor */ "./src/crypt/aes-decryptor.js");
8048var errors_1 = __webpack_require__(/*! ../errors */ "./src/errors.js");
8049var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
8050var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
8051var get_self_scope_1 = __webpack_require__(/*! ../utils/get-self-scope */ "./src/utils/get-self-scope.js");
8052// see https://stackoverflow.com/a/11237259/589493
8053var global = get_self_scope_1.getSelfScope(); // safeguard for code that might run both on worker and main thread
8054var Decrypter = /** @class */ (function () {
8055    function Decrypter(observer, config, _a) {
8056        var _b = (_a === void 0 ? {} : _a).removePKCS7Padding, removePKCS7Padding = _b === void 0 ? true : _b;
8057        this.logEnabled = true;
8058        this.observer = observer;
8059        this.config = config;
8060        this.removePKCS7Padding = removePKCS7Padding;
8061        // built in decryptor expects PKCS7 padding
8062        if (removePKCS7Padding) {
8063            try {
8064                var browserCrypto = global.crypto;
8065                if (browserCrypto) {
8066                    this.subtle = browserCrypto.subtle || browserCrypto.webkitSubtle;
8067                }
8068            }
8069            catch (e) { }
8070        }
8071        this.disableWebCrypto = !this.subtle;
8072    }
8073    Decrypter.prototype.isSync = function () {
8074        return (this.disableWebCrypto && this.config.enableSoftwareAES);
8075    };
8076    Decrypter.prototype.decrypt = function (data, key, iv, callback) {
8077        var _this = this;
8078        if (this.disableWebCrypto && this.config.enableSoftwareAES) {
8079            if (this.logEnabled) {
8080                logger_1.logger.log('JS AES decrypt');
8081                this.logEnabled = false;
8082            }
8083            var decryptor = this.decryptor;
8084            if (!decryptor) {
8085                this.decryptor = decryptor = new aes_decryptor_1.default();
8086            }
8087            decryptor.expandKey(key);
8088            callback(decryptor.decrypt(data, 0, iv, this.removePKCS7Padding));
8089        }
8090        else {
8091            if (this.logEnabled) {
8092                logger_1.logger.log('WebCrypto AES decrypt');
8093                this.logEnabled = false;
8094            }
8095            var subtle_1 = this.subtle;
8096            if (this.key !== key) {
8097                this.key = key;
8098                this.fastAesKey = new fast_aes_key_1.default(subtle_1, key);
8099            }
8100            this.fastAesKey.expandKey()
8101                .then(function (aesKey) {
8102                // decrypt using web crypto
8103                var crypto = new aes_crypto_1.default(subtle_1, iv);
8104                crypto.decrypt(data, aesKey)
8105                    .catch(function (err) {
8106                    _this.onWebCryptoError(err, data, key, iv, callback);
8107                })
8108                    .then(function (result) {
8109                    callback(result);
8110                });
8111            })
8112                .catch(function (err) {
8113                _this.onWebCryptoError(err, data, key, iv, callback);
8114            });
8115        }
8116    };
8117    Decrypter.prototype.onWebCryptoError = function (err, data, key, iv, callback) {
8118        if (this.config.enableSoftwareAES) {
8119            logger_1.logger.log('WebCrypto Error, disable WebCrypto API');
8120            this.disableWebCrypto = true;
8121            this.logEnabled = true;
8122            this.decrypt(data, key, iv, callback);
8123        }
8124        else {
8125            logger_1.logger.error("decrypting error : " + err.message);
8126            this.observer.trigger(events_1.default.ERROR, { type: errors_1.ErrorTypes.MEDIA_ERROR, details: errors_1.ErrorDetails.FRAG_DECRYPT_ERROR, fatal: true, reason: err.message });
8127        }
8128    };
8129    Decrypter.prototype.destroy = function () {
8130        var decryptor = this.decryptor;
8131        if (decryptor) {
8132            decryptor.destroy();
8133            this.decryptor = undefined;
8134        }
8135    };
8136    return Decrypter;
8137}());
8138exports.default = Decrypter;
8139
8140
8141/***/ }),
8142
8143/***/ "./src/crypt/fast-aes-key.js":
8144/*!***********************************!*\
8145  !*** ./src/crypt/fast-aes-key.js ***!
8146  \***********************************/
8147/*! no static exports found */
8148/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
8149/***/ (function(module, exports, __webpack_require__) {
8150
8151"use strict";
8152
8153Object.defineProperty(exports, "__esModule", { value: true });
8154var FastAESKey = /** @class */ (function () {
8155    function FastAESKey(subtle, key) {
8156        this.subtle = subtle;
8157        this.key = key;
8158    }
8159    FastAESKey.prototype.expandKey = function () {
8160        return this.subtle.importKey('raw', this.key, { name: 'AES-CBC' }, false, ['encrypt', 'decrypt']);
8161    };
8162    return FastAESKey;
8163}());
8164exports.default = FastAESKey;
8165
8166
8167/***/ }),
8168
8169/***/ "./src/demux/aacdemuxer.js":
8170/*!*********************************!*\
8171  !*** ./src/demux/aacdemuxer.js ***!
8172  \*********************************/
8173/*! no static exports found */
8174/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
8175/***/ (function(module, exports, __webpack_require__) {
8176
8177"use strict";
8178/* WEBPACK VAR INJECTION */(function(Number) {
8179Object.defineProperty(exports, "__esModule", { value: true });
8180/**
8181 * AAC demuxer
8182 */
8183var ADTS = __webpack_require__(/*! ./adts */ "./src/demux/adts.js");
8184var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
8185var id3_1 = __webpack_require__(/*! ../demux/id3 */ "./src/demux/id3.js");
8186var AACDemuxer = /** @class */ (function () {
8187    function AACDemuxer(observer, remuxer, config) {
8188        this.observer = observer;
8189        this.config = config;
8190        this.remuxer = remuxer;
8191    }
8192    AACDemuxer.prototype.resetInitSegment = function (initSegment, audioCodec, videoCodec, duration) {
8193        this._audioTrack = { container: 'audio/adts', type: 'audio', id: 0, sequenceNumber: 0, isAAC: true, samples: [], len: 0, manifestCodec: audioCodec, duration: duration, inputTimeScale: 90000 };
8194    };
8195    AACDemuxer.prototype.resetTimeStamp = function () {
8196    };
8197    AACDemuxer.probe = function (data) {
8198        if (!data) {
8199            return false;
8200        }
8201        // Check for the ADTS sync word
8202        // Look for ADTS header | 1111 1111 | 1111 X00X | where X can be either 0 or 1
8203        // Layer bits (position 14 and 15) in header should be always 0 for ADTS
8204        // More info https://wiki.multimedia.cx/index.php?title=ADTS
8205        var id3Data = id3_1.default.getID3Data(data, 0) || [];
8206        var offset = id3Data.length;
8207        for (var length_1 = data.length; offset < length_1; offset++) {
8208            if (ADTS.probe(data, offset)) {
8209                logger_1.logger.log('ADTS sync word found !');
8210                return true;
8211            }
8212        }
8213        return false;
8214    };
8215    // feed incoming data to the front of the parsing pipeline
8216    AACDemuxer.prototype.append = function (data, timeOffset, contiguous, accurateTimeOffset) {
8217        var track = this._audioTrack;
8218        var id3Data = id3_1.default.getID3Data(data, 0) || [];
8219        var timestamp = id3_1.default.getTimeStamp(id3Data);
8220        var pts = Number.isFinite(timestamp) ? timestamp * 90 : timeOffset * 90000;
8221        var frameIndex = 0;
8222        var stamp = pts;
8223        var length = data.length;
8224        var offset = id3Data.length;
8225        var id3Samples = [{ pts: stamp, dts: stamp, data: id3Data }];
8226        while (offset < length - 1) {
8227            if (ADTS.isHeader(data, offset) && (offset + 5) < length) {
8228                ADTS.initTrackConfig(track, this.observer, data, offset, track.manifestCodec);
8229                var frame = ADTS.appendFrame(track, data, offset, pts, frameIndex);
8230                if (frame) {
8231                    offset += frame.length;
8232                    stamp = frame.sample.pts;
8233                    frameIndex++;
8234                }
8235                else {
8236                    logger_1.logger.log('Unable to parse AAC frame');
8237                    break;
8238                }
8239            }
8240            else if (id3_1.default.isHeader(data, offset)) {
8241                id3Data = id3_1.default.getID3Data(data, offset);
8242                id3Samples.push({ pts: stamp, dts: stamp, data: id3Data });
8243                offset += id3Data.length;
8244            }
8245            else {
8246                // nothing found, keep looking
8247                offset++;
8248            }
8249        }
8250        this.remuxer.remux(track, { samples: [] }, { samples: id3Samples, inputTimeScale: 90000 }, { samples: [] }, timeOffset, contiguous, accurateTimeOffset);
8251    };
8252    AACDemuxer.prototype.destroy = function () {
8253    };
8254    return AACDemuxer;
8255}());
8256exports.default = AACDemuxer;
8257
8258/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.js")["Number"]))
8259
8260/***/ }),
8261
8262/***/ "./src/demux/adts.js":
8263/*!***************************!*\
8264  !*** ./src/demux/adts.js ***!
8265  \***************************/
8266/*! no static exports found */
8267/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
8268/***/ (function(module, exports, __webpack_require__) {
8269
8270"use strict";
8271
8272Object.defineProperty(exports, "__esModule", { value: true });
8273/**
8274 *  ADTS parser helper
8275 */
8276var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
8277var errors_1 = __webpack_require__(/*! ../errors */ "./src/errors.js");
8278var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
8279function getAudioConfig(observer, data, offset, audioCodec) {
8280    var adtsObjectType, // :int
8281    adtsSampleingIndex, // :int
8282    adtsExtensionSampleingIndex, // :int
8283    adtsChanelConfig, // :int
8284    config, userAgent = navigator.userAgent.toLowerCase(), manifestCodec = audioCodec, adtsSampleingRates = [
8285        96000, 88200,
8286        64000, 48000,
8287        44100, 32000,
8288        24000, 22050,
8289        16000, 12000,
8290        11025, 8000,
8291        7350
8292    ];
8293    // byte 2
8294    adtsObjectType = ((data[offset + 2] & 0xC0) >>> 6) + 1;
8295    adtsSampleingIndex = ((data[offset + 2] & 0x3C) >>> 2);
8296    if (adtsSampleingIndex > adtsSampleingRates.length - 1) {
8297        observer.trigger(events_1.default.ERROR, { type: errors_1.ErrorTypes.MEDIA_ERROR, details: errors_1.ErrorDetails.FRAG_PARSING_ERROR, fatal: true, reason: "invalid ADTS sampling index:" + adtsSampleingIndex });
8298        return;
8299    }
8300    adtsChanelConfig = ((data[offset + 2] & 0x01) << 2);
8301    // byte 3
8302    adtsChanelConfig |= ((data[offset + 3] & 0xC0) >>> 6);
8303    logger_1.logger.log("manifest codec:" + audioCodec + ",ADTS data:type:" + adtsObjectType + ",sampleingIndex:" + adtsSampleingIndex + "[" + adtsSampleingRates[adtsSampleingIndex] + "Hz],channelConfig:" + adtsChanelConfig);
8304    // firefox: freq less than 24kHz = AAC SBR (HE-AAC)
8305    if (/firefox/i.test(userAgent)) {
8306        if (adtsSampleingIndex >= 6) {
8307            adtsObjectType = 5;
8308            config = new Array(4);
8309            // HE-AAC uses SBR (Spectral Band Replication) , high frequencies are constructed from low frequencies
8310            // there is a factor 2 between frame sample rate and output sample rate
8311            // multiply frequency by 2 (see table below, equivalent to substract 3)
8312            adtsExtensionSampleingIndex = adtsSampleingIndex - 3;
8313        }
8314        else {
8315            adtsObjectType = 2;
8316            config = new Array(2);
8317            adtsExtensionSampleingIndex = adtsSampleingIndex;
8318        }
8319        // Android : always use AAC
8320    }
8321    else if (userAgent.indexOf('android') !== -1) {
8322        adtsObjectType = 2;
8323        config = new Array(2);
8324        adtsExtensionSampleingIndex = adtsSampleingIndex;
8325    }
8326    else {
8327        /*  for other browsers (Chrome/Vivaldi/Opera ...)
8328            always force audio type to be HE-AAC SBR, as some browsers do not support audio codec switch properly (like Chrome ...)
8329        */
8330        adtsObjectType = 5;
8331        config = new Array(4);
8332        // if (manifest codec is HE-AAC or HE-AACv2) OR (manifest codec not specified AND frequency less than 24kHz)
8333        if ((audioCodec && ((audioCodec.indexOf('mp4a.40.29') !== -1) ||
8334            (audioCodec.indexOf('mp4a.40.5') !== -1))) ||
8335            (!audioCodec && adtsSampleingIndex >= 6)) {
8336            // HE-AAC uses SBR (Spectral Band Replication) , high frequencies are constructed from low frequencies
8337            // there is a factor 2 between frame sample rate and output sample rate
8338            // multiply frequency by 2 (see table below, equivalent to substract 3)
8339            adtsExtensionSampleingIndex = adtsSampleingIndex - 3;
8340        }
8341        else {
8342            // if (manifest codec is AAC) AND (frequency less than 24kHz AND nb channel is 1) OR (manifest codec not specified and mono audio)
8343            // Chrome fails to play back with low frequency AAC LC mono when initialized with HE-AAC.  This is not a problem with stereo.
8344            if (audioCodec && audioCodec.indexOf('mp4a.40.2') !== -1 && ((adtsSampleingIndex >= 6 && adtsChanelConfig === 1) ||
8345                /vivaldi/i.test(userAgent)) ||
8346                (!audioCodec && adtsChanelConfig === 1)) {
8347                adtsObjectType = 2;
8348                config = new Array(2);
8349            }
8350            adtsExtensionSampleingIndex = adtsSampleingIndex;
8351        }
8352    }
8353    /* refer to http://wiki.multimedia.cx/index.php?title=MPEG-4_Audio#Audio_Specific_Config
8354        ISO 14496-3 (AAC).pdf - Table 1.13 — Syntax of AudioSpecificConfig()
8355      Audio Profile / Audio Object Type
8356      0: Null
8357      1: AAC Main
8358      2: AAC LC (Low Complexity)
8359      3: AAC SSR (Scalable Sample Rate)
8360      4: AAC LTP (Long Term Prediction)
8361      5: SBR (Spectral Band Replication)
8362      6: AAC Scalable
8363     sampling freq
8364      0: 96000 Hz
8365      1: 88200 Hz
8366      2: 64000 Hz
8367      3: 48000 Hz
8368      4: 44100 Hz
8369      5: 32000 Hz
8370      6: 24000 Hz
8371      7: 22050 Hz
8372      8: 16000 Hz
8373      9: 12000 Hz
8374      10: 11025 Hz
8375      11: 8000 Hz
8376      12: 7350 Hz
8377      13: Reserved
8378      14: Reserved
8379      15: frequency is written explictly
8380      Channel Configurations
8381      These are the channel configurations:
8382      0: Defined in AOT Specifc Config
8383      1: 1 channel: front-center
8384      2: 2 channels: front-left, front-right
8385    */
8386    // audioObjectType = profile => profile, the MPEG-4 Audio Object Type minus 1
8387    config[0] = adtsObjectType << 3;
8388    // samplingFrequencyIndex
8389    config[0] |= (adtsSampleingIndex & 0x0E) >> 1;
8390    config[1] |= (adtsSampleingIndex & 0x01) << 7;
8391    // channelConfiguration
8392    config[1] |= adtsChanelConfig << 3;
8393    if (adtsObjectType === 5) {
8394        // adtsExtensionSampleingIndex
8395        config[1] |= (adtsExtensionSampleingIndex & 0x0E) >> 1;
8396        config[2] = (adtsExtensionSampleingIndex & 0x01) << 7;
8397        // adtsObjectType (force to 2, chrome is checking that object type is less than 5 ???
8398        //    https://chromium.googlesource.com/chromium/src.git/+/master/media/formats/mp4/aac.cc
8399        config[2] |= 2 << 2;
8400        config[3] = 0;
8401    }
8402    return { config: config, samplerate: adtsSampleingRates[adtsSampleingIndex], channelCount: adtsChanelConfig, codec: ('mp4a.40.' + adtsObjectType), manifestCodec: manifestCodec };
8403}
8404exports.getAudioConfig = getAudioConfig;
8405function isHeaderPattern(data, offset) {
8406    return data[offset] === 0xff && (data[offset + 1] & 0xf6) === 0xf0;
8407}
8408exports.isHeaderPattern = isHeaderPattern;
8409function getHeaderLength(data, offset) {
8410    return (data[offset + 1] & 0x01 ? 7 : 9);
8411}
8412exports.getHeaderLength = getHeaderLength;
8413function getFullFrameLength(data, offset) {
8414    return ((data[offset + 3] & 0x03) << 11) |
8415        (data[offset + 4] << 3) |
8416        ((data[offset + 5] & 0xE0) >>> 5);
8417}
8418exports.getFullFrameLength = getFullFrameLength;
8419function isHeader(data, offset) {
8420    // Look for ADTS header | 1111 1111 | 1111 X00X | where X can be either 0 or 1
8421    // Layer bits (position 14 and 15) in header should be always 0 for ADTS
8422    // More info https://wiki.multimedia.cx/index.php?title=ADTS
8423    if (offset + 1 < data.length && isHeaderPattern(data, offset)) {
8424        return true;
8425    }
8426    return false;
8427}
8428exports.isHeader = isHeader;
8429function probe(data, offset) {
8430    // same as isHeader but we also check that ADTS frame follows last ADTS frame
8431    // or end of data is reached
8432    if (offset + 1 < data.length && isHeaderPattern(data, offset)) {
8433        // ADTS header Length
8434        var headerLength = getHeaderLength(data, offset);
8435        // ADTS frame Length
8436        var frameLength = headerLength;
8437        if (offset + 5 < data.length) {
8438            frameLength = getFullFrameLength(data, offset);
8439        }
8440        var newOffset = offset + frameLength;
8441        if (newOffset === data.length || (newOffset + 1 < data.length && isHeaderPattern(data, newOffset))) {
8442            return true;
8443        }
8444    }
8445    return false;
8446}
8447exports.probe = probe;
8448function initTrackConfig(track, observer, data, offset, audioCodec) {
8449    if (!track.samplerate) {
8450        var config = getAudioConfig(observer, data, offset, audioCodec);
8451        track.config = config.config;
8452        track.samplerate = config.samplerate;
8453        track.channelCount = config.channelCount;
8454        track.codec = config.codec;
8455        track.manifestCodec = config.manifestCodec;
8456        logger_1.logger.log("parsed codec:" + track.codec + ",rate:" + config.samplerate + ",nb channel:" + config.channelCount);
8457    }
8458}
8459exports.initTrackConfig = initTrackConfig;
8460function getFrameDuration(samplerate) {
8461    return 1024 * 90000 / samplerate;
8462}
8463exports.getFrameDuration = getFrameDuration;
8464function parseFrameHeader(data, offset, pts, frameIndex, frameDuration) {
8465    var headerLength, frameLength, stamp;
8466    var length = data.length;
8467    // The protection skip bit tells us if we have 2 bytes of CRC data at the end of the ADTS header
8468    headerLength = getHeaderLength(data, offset);
8469    // retrieve frame size
8470    frameLength = getFullFrameLength(data, offset);
8471    frameLength -= headerLength;
8472    if ((frameLength > 0) && ((offset + headerLength + frameLength) <= length)) {
8473        stamp = pts + frameIndex * frameDuration;
8474        // logger.log(`AAC frame, offset/length/total/pts:${offset+headerLength}/${frameLength}/${data.byteLength}/${(stamp/90).toFixed(0)}`);
8475        return { headerLength: headerLength, frameLength: frameLength, stamp: stamp };
8476    }
8477    return undefined;
8478}
8479exports.parseFrameHeader = parseFrameHeader;
8480function appendFrame(track, data, offset, pts, frameIndex) {
8481    var frameDuration = getFrameDuration(track.samplerate);
8482    var header = parseFrameHeader(data, offset, pts, frameIndex, frameDuration);
8483    if (header) {
8484        var stamp = header.stamp;
8485        var headerLength = header.headerLength;
8486        var frameLength = header.frameLength;
8487        // logger.log(`AAC frame, offset/length/total/pts:${offset+headerLength}/${frameLength}/${data.byteLength}/${(stamp/90).toFixed(0)}`);
8488        var aacSample = {
8489            unit: data.subarray(offset + headerLength, offset + headerLength + frameLength),
8490            pts: stamp,
8491            dts: stamp
8492        };
8493        track.samples.push(aacSample);
8494        track.len += frameLength;
8495        return { sample: aacSample, length: frameLength + headerLength };
8496    }
8497    return undefined;
8498}
8499exports.appendFrame = appendFrame;
8500
8501
8502/***/ }),
8503
8504/***/ "./src/demux/demuxer-inline.js":
8505/*!*************************************!*\
8506  !*** ./src/demux/demuxer-inline.js ***!
8507  \*************************************/
8508/*! no static exports found */
8509/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
8510/***/ (function(module, exports, __webpack_require__) {
8511
8512"use strict";
8513
8514/**
8515 *
8516 * inline demuxer: probe fragments and instantiate
8517 * appropriate demuxer depending on content type (TSDemuxer, AACDemuxer, ...)
8518 *
8519 */
8520Object.defineProperty(exports, "__esModule", { value: true });
8521var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
8522var errors_1 = __webpack_require__(/*! ../errors */ "./src/errors.js");
8523var decrypter_1 = __webpack_require__(/*! ../crypt/decrypter */ "./src/crypt/decrypter.js");
8524var aacdemuxer_1 = __webpack_require__(/*! ../demux/aacdemuxer */ "./src/demux/aacdemuxer.js");
8525var mp4demuxer_1 = __webpack_require__(/*! ../demux/mp4demuxer */ "./src/demux/mp4demuxer.js");
8526var tsdemuxer_1 = __webpack_require__(/*! ../demux/tsdemuxer */ "./src/demux/tsdemuxer.js");
8527var mp3demuxer_1 = __webpack_require__(/*! ../demux/mp3demuxer */ "./src/demux/mp3demuxer.js");
8528var mp4_remuxer_1 = __webpack_require__(/*! ../remux/mp4-remuxer */ "./src/remux/mp4-remuxer.js");
8529var passthrough_remuxer_1 = __webpack_require__(/*! ../remux/passthrough-remuxer */ "./src/remux/passthrough-remuxer.js");
8530var get_self_scope_1 = __webpack_require__(/*! ../utils/get-self-scope */ "./src/utils/get-self-scope.js");
8531var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
8532// see https://stackoverflow.com/a/11237259/589493
8533var global = get_self_scope_1.getSelfScope(); // safeguard for code that might run both on worker and main thread
8534var now;
8535// performance.now() not available on WebWorker, at least on Safari Desktop
8536try {
8537    now = global.performance.now.bind(global.performance);
8538}
8539catch (err) {
8540    logger_1.logger.debug('Unable to use Performance API on this environment');
8541    now = global.Date.now;
8542}
8543var DemuxerInline = /** @class */ (function () {
8544    function DemuxerInline(observer, typeSupported, config, vendor) {
8545        this.observer = observer;
8546        this.typeSupported = typeSupported;
8547        this.config = config;
8548        this.vendor = vendor;
8549    }
8550    DemuxerInline.prototype.destroy = function () {
8551        var demuxer = this.demuxer;
8552        if (demuxer) {
8553            demuxer.destroy();
8554        }
8555    };
8556    DemuxerInline.prototype.push = function (data, decryptdata, initSegment, audioCodec, videoCodec, timeOffset, discontinuity, trackSwitch, contiguous, duration, accurateTimeOffset, defaultInitPTS) {
8557        var _this = this;
8558        if ((data.byteLength > 0) && (decryptdata != null) && (decryptdata.key != null) && (decryptdata.method === 'AES-128')) {
8559            var decrypter = this.decrypter;
8560            if (decrypter == null) {
8561                decrypter = this.decrypter = new decrypter_1.default(this.observer, this.config);
8562            }
8563            var startTime_1 = now();
8564            decrypter.decrypt(data, decryptdata.key.buffer, decryptdata.iv.buffer, function (decryptedData) {
8565                var endTime = now();
8566                _this.observer.trigger(events_1.default.FRAG_DECRYPTED, { stats: { tstart: startTime_1, tdecrypt: endTime } });
8567                _this.pushDecrypted(new Uint8Array(decryptedData), decryptdata, new Uint8Array(initSegment), audioCodec, videoCodec, timeOffset, discontinuity, trackSwitch, contiguous, duration, accurateTimeOffset, defaultInitPTS);
8568            });
8569        }
8570        else {
8571            this.pushDecrypted(new Uint8Array(data), decryptdata, new Uint8Array(initSegment), audioCodec, videoCodec, timeOffset, discontinuity, trackSwitch, contiguous, duration, accurateTimeOffset, defaultInitPTS);
8572        }
8573    };
8574    DemuxerInline.prototype.pushDecrypted = function (data, decryptdata, initSegment, audioCodec, videoCodec, timeOffset, discontinuity, trackSwitch, contiguous, duration, accurateTimeOffset, defaultInitPTS) {
8575        var demuxer = this.demuxer;
8576        if (!demuxer ||
8577            // in case of continuity change, or track switch
8578            // we might switch from content type (AAC container to TS container, or TS to fmp4 for example)
8579            // so let's check that current demuxer is still valid
8580            ((discontinuity || trackSwitch) && !this.probe(data))) {
8581            var observer = this.observer;
8582            var typeSupported = this.typeSupported;
8583            var config = this.config;
8584            // probing order is TS/AAC/MP3/MP4
8585            var muxConfig = [
8586                { demux: tsdemuxer_1.default, remux: mp4_remuxer_1.default },
8587                { demux: mp4demuxer_1.default, remux: passthrough_remuxer_1.default },
8588                { demux: aacdemuxer_1.default, remux: mp4_remuxer_1.default },
8589                { demux: mp3demuxer_1.default, remux: mp4_remuxer_1.default }
8590            ];
8591            // probe for content type
8592            for (var i = 0, len = muxConfig.length; i < len; i++) {
8593                var mux = muxConfig[i];
8594                var probe = mux.demux.probe;
8595                if (probe(data)) {
8596                    var remuxer_1 = this.remuxer = new mux.remux(observer, config, typeSupported, this.vendor);
8597                    demuxer = new mux.demux(observer, remuxer_1, config, typeSupported);
8598                    this.probe = probe;
8599                    break;
8600                }
8601            }
8602            if (!demuxer) {
8603                observer.trigger(events_1.default.ERROR, { type: errors_1.ErrorTypes.MEDIA_ERROR, details: errors_1.ErrorDetails.FRAG_PARSING_ERROR, fatal: true, reason: 'no demux matching with content found' });
8604                return;
8605            }
8606            this.demuxer = demuxer;
8607        }
8608        var remuxer = this.remuxer;
8609        if (discontinuity || trackSwitch) {
8610            demuxer.resetInitSegment(initSegment, audioCodec, videoCodec, duration);
8611            remuxer.resetInitSegment();
8612        }
8613        if (discontinuity) {
8614            demuxer.resetTimeStamp(defaultInitPTS);
8615            remuxer.resetTimeStamp(defaultInitPTS);
8616        }
8617        if (typeof demuxer.setDecryptData === 'function') {
8618            demuxer.setDecryptData(decryptdata);
8619        }
8620        demuxer.append(data, timeOffset, contiguous, accurateTimeOffset);
8621    };
8622    return DemuxerInline;
8623}());
8624exports.default = DemuxerInline;
8625
8626
8627/***/ }),
8628
vendor: 3,895 bytes, lines 8629-8715
8629/***/ "./src/demux/demuxer-worker.js":
8630/*!*************************************!*\
8631  !*** ./src/demux/demuxer-worker.js ***!
8632  \*************************************/
8633/*! no static exports found */
8634/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
8635/***/ (function(module, exports, __webpack_require__) {
8636
8637"use strict";
8638
8639/* demuxer web worker.
8640 *  - listen to worker message, and trigger DemuxerInline upon reception of Fragments.
8641 *  - provides MP4 Boxes back to main thread using [transferable objects](https://developers.google.com/web/updates/2011/12/Transferable-Objects-Lightning-Fast) in order to minimize message passing overhead.
8642 */
8643Object.defineProperty(exports, "__esModule", { value: true });
8644var demuxer_inline_1 = __webpack_require__(/*! ../demux/demuxer-inline */ "./src/demux/demuxer-inline.js");
8645var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
8646var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
8647var events_2 = __webpack_require__(/*! events */ "./node_modules/node-libs-browser/node_modules/events/events.js");
8648var DemuxerWorker = function (self) {
8649    // observer setup
8650    var observer = new events_2.EventEmitter();
8651    observer.trigger = function trigger(event) {
8652        var data = [];
8653        for (var _i = 1; _i < arguments.length; _i++) {
8654            data[_i - 1] = arguments[_i];
8655        }
8656        observer.emit.apply(observer, [event, event].concat(data));
8657    };
8658    observer.off = function off(event) {
8659        var data = [];
8660        for (var _i = 1; _i < arguments.length; _i++) {
8661            data[_i - 1] = arguments[_i];
8662        }
8663        observer.removeListener.apply(observer, [event].concat(data));
8664    };
8665    var forwardMessage = function (ev, data) {
8666        self.postMessage({ event: ev, data: data });
8667    };
8668    self.addEventListener('message', function (ev) {
8669        var data = ev.data;
8670        // console.log('demuxer cmd:' + data.cmd);
8671        switch (data.cmd) {
8672            case 'init':
8673                var config = JSON.parse(data.config);
8674                self.demuxer = new demuxer_inline_1.default(observer, data.typeSupported, config, data.vendor);
8675                logger_1.enableLogs(config.debug);
8676                // signal end of worker init
8677                forwardMessage('init', null);
8678                break;
8679            case 'demux':
8680                self.demuxer.push(data.data, data.decryptdata, data.initSegment, data.audioCodec, data.videoCodec, data.timeOffset, data.discontinuity, data.trackSwitch, data.contiguous, data.duration, data.accurateTimeOffset, data.defaultInitPTS);
8681                break;
8682            default:
8683                break;
8684        }
8685    });
8686    // forward events to main thread
8687    observer.on(events_1.default.FRAG_DECRYPTED, forwardMessage);
8688    observer.on(events_1.default.FRAG_PARSING_INIT_SEGMENT, forwardMessage);
8689    observer.on(events_1.default.FRAG_PARSED, forwardMessage);
8690    observer.on(events_1.default.ERROR, forwardMessage);
8691    observer.on(events_1.default.FRAG_PARSING_METADATA, forwardMessage);
8692    observer.on(events_1.default.FRAG_PARSING_USERDATA, forwardMessage);
8693    observer.on(events_1.default.INIT_PTS_FOUND, forwardMessage);
8694    // special case for FRAG_PARSING_DATA: pass data1/data2 as transferable object (no copy)
8695    observer.on(events_1.default.FRAG_PARSING_DATA, function (ev, data) {
8696        var transferable = [];
8697        var message = { event: ev, data: data };
8698        if (data.data1) {
8699            message.data1 = data.data1.buffer;
8700            transferable.push(data.data1.buffer);
8701            delete data.data1;
8702        }
8703        if (data.data2) {
8704            message.data2 = data.data2.buffer;
8705            transferable.push(data.data2.buffer);
8706            delete data.data2;
8707        }
8708        self.postMessage(message, transferable);
8709    });
8710};
8711exports.default = DemuxerWorker;
8712
8713
8714/***/ }),
8715
8716/***/ "./src/demux/demuxer.js":
8717/*!******************************!*\
8718  !*** ./src/demux/demuxer.js ***!
8719  \******************************/
8720/*! no static exports found */
8721/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
8722/***/ (function(module, exports, __webpack_require__) {
8723
8724"use strict";
8725/* WEBPACK VAR INJECTION */(function(Number) {
8726Object.defineProperty(exports, "__esModule", { value: true });
8727var work = __webpack_require__(/*! webworkify-webpack */ "./node_modules/webworkify-webpack/index.js");
8728var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
8729var demuxer_inline_1 = __webpack_require__(/*! ../demux/demuxer-inline */ "./src/demux/demuxer-inline.js");
8730var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
8731var errors_1 = __webpack_require__(/*! ../errors */ "./src/errors.js");
8732var mediasource_helper_1 = __webpack_require__(/*! ../utils/mediasource-helper */ "./src/utils/mediasource-helper.js");
8733var get_self_scope_1 = __webpack_require__(/*! ../utils/get-self-scope */ "./src/utils/get-self-scope.js");
8734var observer_1 = __webpack_require__(/*! ../observer */ "./src/observer.js");
8735// see https://stackoverflow.com/a/11237259/589493
8736var global = get_self_scope_1.getSelfScope(); // safeguard for code that might run both on worker and main thread
8737var MediaSource = mediasource_helper_1.getMediaSource();
8738var Demuxer = /** @class */ (function () {
8739    function Demuxer(hls, id) {
8740        var _this = this;
8741        this.hls = hls;
8742        this.id = id;
8743        var observer = this.observer = new observer_1.Observer();
8744        var config = hls.config;
8745        var forwardMessage = function (ev, data) {
8746            data = data || {};
8747            data.frag = _this.frag;
8748            data.id = _this.id;
8749            hls.trigger(ev, data);
8750        };
8751        // forward events to main thread
8752        observer.on(events_1.default.FRAG_DECRYPTED, forwardMessage);
8753        observer.on(events_1.default.FRAG_PARSING_INIT_SEGMENT, forwardMessage);
8754        observer.on(events_1.default.FRAG_PARSING_DATA, forwardMessage);
8755        observer.on(events_1.default.FRAG_PARSED, forwardMessage);
8756        observer.on(events_1.default.ERROR, forwardMessage);
8757        observer.on(events_1.default.FRAG_PARSING_METADATA, forwardMessage);
8758        observer.on(events_1.default.FRAG_PARSING_USERDATA, forwardMessage);
8759        observer.on(events_1.default.INIT_PTS_FOUND, forwardMessage);
8760        var typeSupported = {
8761            mp4: MediaSource.isTypeSupported('video/mp4'),
8762            mpeg: MediaSource.isTypeSupported('audio/mpeg'),
8763            mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"')
8764        };
8765        // navigator.vendor is not always available in Web Worker
8766        // refer to https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/navigator
8767        var vendor = navigator.vendor;
8768        if (config.enableWorker && (typeof (Worker) !== 'undefined')) {
8769            logger_1.logger.log('demuxing in webworker');
8770            var w = void 0;
8771            try {
8772                w = this.w = work(/*require.resolve*/(/*! ../demux/demuxer-worker.js */ "./src/demux/demuxer-worker.js"));
8773                this.onwmsg = this.onWorkerMessage.bind(this);
8774                w.addEventListener('message', this.onwmsg);
8775                w.onerror = function (event) {
8776                    hls.trigger(events_1.default.ERROR, { type: errors_1.ErrorTypes.OTHER_ERROR, details: errors_1.ErrorDetails.INTERNAL_EXCEPTION, fatal: true, event: 'demuxerWorker', err: { message: event.message + ' (' + event.filename + ':' + event.lineno + ')' } });
8777                };
8778                w.postMessage({ cmd: 'init', typeSupported: typeSupported, vendor: vendor, id: id, config: JSON.stringify(config) });
8779            }
8780            catch (err) {
8781                logger_1.logger.warn('Error in worker:', err);
8782                logger_1.logger.error('Error while initializing DemuxerWorker, fallback on DemuxerInline');
8783                if (w) {
8784                    // revoke the Object URL that was used to create demuxer worker, so as not to leak it
8785                    global.URL.revokeObjectURL(w.objectURL);
8786                }
8787                this.demuxer = new demuxer_inline_1.default(observer, typeSupp
8787orted, config, vendor);
8788                this.w = undefined;
8789            }
8790        }
8791        else {
8792            this.demuxer = new demuxer_inline_1.default(observer, typeSupported, config, vendor);
8793        }
8794    }
8795    Demuxer.prototype.destroy = function () {
8796        var w = this.w;
8797        if (w) {
8798            w.removeEventListener('message', this.onwmsg);
8799            w.terminate();
8800            this.w = null;
8801        }
8802        else {
8803            var demuxer = this.demuxer;
8804            if (demuxer) {
8805                demuxer.destroy();
8806                this.demuxer = null;
8807            }
8808        }
8809        var observer = this.observer;
8810        if (observer) {
8811            observer.removeAllListeners();
8812            this.observer = null;
8813        }
8814    };
8815    Demuxer.prototype.push = function (data, initSegment, audioCodec, videoCodec, frag, duration, accurateTimeOffset, defaultInitPTS) {
8816        var w = this.w;
8817        var timeOffset = Number.isFinite(frag.startPTS) ? frag.startPTS : frag.start;
8818        var decryptdata = frag.decryptdata;
8819        var lastFrag = this.frag;
8820        var discontinuity = !(lastFrag && (frag.cc === lastFrag.cc));
8821        var trackSwitch = !(lastFrag && (frag.level === lastFrag.level));
8822        var nextSN = lastFrag && (frag.sn === (lastFrag.sn + 1));
8823        var contiguous = !trackSwitch && nextSN;
8824        if (discontinuity) {
8825            logger_1.logger.log(this.id + ":discontinuity detected");
8826        }
8827        if (trackSwitch) {
8828            logger_1.logger.log(this.id + ":switch detected");
8829        }
8830        this.frag = frag;
8831        if (w) {
8832            // post fragment payload as transferable objects for ArrayBuffer (no copy)
8833            w.postMessage({ cmd: 'demux', data: data, decryptdata: decryptdata, initSegment: initSegment, audioCodec: audioCodec, videoCodec: videoCodec, timeOffset: timeOffset, discontinuity: discontinuity, trackSwitch: trackSwitch, contiguous: contiguous, duration: duration, accurateTimeOffset: accurateTimeOffset, defaultInitPTS: defaultInitPTS }, data instanceof ArrayBuffer ? [data] : []);
8834        }
8835        else {
8836            var demuxer = this.demuxer;
8837            if (demuxer) {
8838                demuxer.push(data, decryptdata, initSegment, audioCodec, videoCodec, timeOffset, discontinuity, trackSwitch, contiguous, duration, accurateTimeOffset, defaultInitPTS);
8839            }
8840        }
8841    };
8842    Demuxer.prototype.onWorkerMessage = function (ev) {
8843        var data = ev.data, hls = this.hls;
8844        switch (data.event) {
8845            case 'init':
8846                // revoke the Object URL that was used to create demuxer worker, so as not to leak it
8847                global.URL.revokeObjectURL(this.w.objectURL);
8848                break;
8849            // special case for FRAG_PARSING_DATA: data1 and data2 are transferable objects
8850            case events_1.default.FRAG_PARSING_DATA:
8851                data.data.data1 = new Uint8Array(data.data1);
8852                if (data.data2) {
8853                    data.data.data2 = new Uint8Array(data.data2);
8854                }
8855            /* falls through */
8856            default:
8857                data.data = data.data || {};
8858                data.data.frag = this.frag;
8859                data.data.id = this.id;
8860                hls.trigger(data.event, data.data);
8861                break;
8862        }
8863    };
8864    return Demuxer;
8865}());
8866exports.default = Demuxer;
8867
8868/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.js")["Number"]))
8869
8870/***/ }),
8871
vendor: 19,749 bytes, lines 8872-9385
8872/***/ "./src/demux/exp-golomb.js":
8873/*!*********************************!*\
8874  !*** ./src/demux/exp-golomb.js ***!
8875  \*********************************/
8876/*! no static exports found */
8877/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
8878/***/ (function(module, exports, __webpack_require__) {
8879
8880"use strict";
8881
8882/**
8883 * Parser for exponential Golomb codes, a variable-bitwidth number encoding scheme used by h264.
8884*/
8885Object.defineProperty(exports, "__esModule", { value: true });
8886var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
8887var ExpGolomb = /** @class */ (function () {
8888    function ExpGolomb(data) {
8889        this.data = data;
8890        // the number of bytes left to examine in this.data
8891        this.bytesAvailable = data.byteLength;
8892        // the current word being examined
8893        this.word = 0; // :uint
8894        // the number of bits left to examine in the current word
8895        this.bitsAvailable = 0; // :uint
8896    }
8897    // ():void
8898    ExpGolomb.prototype.loadWord = function () {
8899        var data = this.data, bytesAvailable = this.bytesAvailable, position = data.byteLength - bytesAvailable, workingBytes = new Uint8Array(4), availableBytes = Math.min(4, bytesAvailable);
8900        if (availableBytes === 0) {
8901            throw new Error('no bytes available');
8902        }
8903        workingBytes.set(data.subarray(position, position + availableBytes));
8904        this.word = new DataView(workingBytes.buffer).getUint32(0);
8905        // track the amount of this.data that has been processed
8906        this.bitsAvailable = availableBytes * 8;
8907        this.bytesAvailable -= availableBytes;
8908    };
8909    // (count:int):void
8910    ExpGolomb.prototype.skipBits = function (count) {
8911        var skipBytes; // :int
8912        if (this.bitsAvailable > count) {
8913            this.word <<= count;
8914            this.bitsAvailable -= count;
8915        }
8916        else {
8917            count -= this.bitsAvailable;
8918            skipBytes = count >> 3;
8919            count -= (skipBytes >> 3);
8920            this.bytesAvailable -= skipBytes;
8921            this.loadWord();
8922            this.word <<= count;
8923            this.bitsAvailable -= count;
8924        }
8925    };
8926    // (size:int):uint
8927    ExpGolomb.prototype.readBits = function (size) {
8928        var bits = Math.min(this.bitsAvailable, size), // :uint
8929        valu = this.word >>> (32 - bits); // :uint
8930        if (size > 32) {
8931            logger_1.logger.error('Cannot read more than 32 bits at a time');
8932        }
8933        this.bitsAvailable -= bits;
8934        if (this.bitsAvailable > 0) {
8935            this.word <<= bits;
8936        }
8937        else if (this.bytesAvailable > 0) {
8938            this.loadWord();
8939        }
8940        bits = size - bits;
8941        if (bits > 0 && this.bitsAvailable) {
8942            return valu << bits | this.readBits(bits);
8943        }
8944        else {
8945            return valu;
8946        }
8947    };
8948    // ():uint
8949    ExpGolomb.prototype.skipLZ = function () {
8950        var leadingZeroCount; // :uint
8951        for (leadingZeroCount = 0; leadingZeroCount < this.bitsAvailable; ++leadingZeroCount) {
8952            if ((this.word & (0x80000000 >>> leadingZeroCount)) !== 0) {
8953                // the first bit of working word is 1
8954                this.word <<= leadingZeroCount;
8955                this.bitsAvailable -= leadingZeroCount;
8956                return leadingZeroCount;
8957            }
8958        }
8959        // we exhausted word and still have not found a 1
8960        this.loadWord();
8961        return leadingZeroCount + this.skipLZ();
8962    };
8963    // ():void
8964    ExpGolomb.prototype.skipUEG = function () {
8965        this.skipBits(1 + this.skipLZ());
8966    };
8967    // ():void
8968    ExpGolomb.prototype.skipEG = function () {
8969        this.skipBits(1 + this.skipLZ());
8970    };
8971    // ():uint
8972    ExpGolomb.prototype.readUEG = function () {
8973        var clz = this.skipLZ(); // :uint
8974        return this.readBits(clz + 1) - 1;
8975    };
8976    // ():int
8977    ExpGolomb.prototype.readEG = function () {
8978        var valu = this.readUEG(); // :int
8979        if (0x01 & valu) {
8980            // the number is odd if the low order bit is set
8981            return (1 + valu) >>> 1; // add 1 to make it even, and divide by 2
8982        }
8983        else {
8984            return -1 * (valu >>> 1); // divide by two then make it negative
8985        }
8986    };
8987    // Some convenience functions
8988    // :Boolean
8989    ExpGolomb.prototype.readBoolean = function () {
8990        return this.readBits(1) === 1;
8991    };
8992    // ():int
8993    ExpGolomb.prototype.readUByte = function () {
8994        return this.readBits(8);
8995    };
8996    // ():int
8997    ExpGolomb.prototype.readUShort = function () {
8998        return this.readBits(16);
8999    };
9000    // ():int
9001    ExpGolomb.prototype.readUInt = function () {
9002        return this.readBits(32);
9003    };
9004    /**
9005     * Advance the ExpGolomb decoder past a scaling list. The scaling
9006     * list is optionally transmitted as part of a sequence parameter
9007     * set and is not relevant to transmuxing.
9008     * @param count {number} the number of entries in this scaling list
9009     * @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1
9010     */
9011    ExpGolomb.prototype.skipScalingList = function (count) {
9012        var lastScale = 8, nextScale = 8, j, deltaScale;
9013        for (j = 0; j < count; j++) {
9014            if (nextScale !== 0) {
9015                deltaScale = this.readEG();
9016                nextScale = (lastScale + deltaScale + 256) % 256;
9017            }
9018            lastScale = (nextScale === 0) ? lastScale : nextScale;
9019        }
9020    };
9021    /**
9022     * Read a sequence parameter set and return some interesting video
9023     * properties. A sequence parameter set is the H264 metadata that
9024     * describes the properties of upcoming video frames.
9025     * @param data {Uint8Array} the bytes of a sequence parameter set
9026     * @return {object} an object with configuration parsed from the
9027     * sequence parameter set, including the dimensions of the
9028     * associated video frames.
9029     */
9030    ExpGolomb.prototype.readSPS = function () {
9031        var frameCropLeftOffset = 0, frameCropRightOffset = 0, frameCropTopOffset = 0, frameCropBottomOffset = 0, profileIdc, profileCompat, levelIdc, numRefFramesInPicOrderCntCycle, picWidthInMbsMinus1, picHeightInMapUnitsMinus1, frameMbsOnlyFlag, scalingListCount, i, readUByte = this.readUByte.bind(this), readBits = this.readBits.bind(this), readUEG = this.readUEG.bind(this), readBoolean = this.readBoolean.bind(this), skipBits = this.skipBits.bind(this), skipEG = this.skipEG.bind(this), skipUEG = this.skipUEG.bind(this), skipScalingList = this.skipScalingList.bind(this);
9032        readUByte();
9033        profileIdc = readUByte(); // profile_idc
9034        profileCompat = readBits(5); // constraint_set[0-4]_flag, u(5)
9035        skipBits(3); // reserved_zero_3bits u(3),
9036        levelIdc = readUByte(); // level_idc u(8)
9037        skipUEG(); // seq_parameter_set_id
9038        // some profiles have more optional data we don't need
9039        if (profileIdc === 100 ||
9040            profileIdc === 110 ||
9041            profileIdc === 122 ||
9042            profileIdc === 244 ||
9043            profileIdc === 44 ||
9044            profileIdc === 83 ||
9045            profileIdc === 86 ||
9046            profileIdc === 118 ||
9047            profileIdc === 128) {
9048            var chromaFormatIdc = readUEG();
9049            if (chromaFormatIdc === 3) {
9050                skipBits(1);
9051            } // separate_colour_plane_flag
9052            skipUEG(); // bit_depth_luma_minus8
9053            skipUEG(); // bit_depth_chroma_minus8
9054            skipBits(1); // qpprime_y_zero_transform_bypass_flag
9055            if (readBoolean()) { // seq_scaling_matrix_present_flag
9056                scalingListCount = (chromaFormatIdc !== 3) ? 8 : 12;
9057                for (i = 0; i < scalingListCount; i++) {
9058                    if (readBoolean()) { // seq_scaling_list_present_flag[ i ]
9059                        if (i < 6) {
9060                            skipScalingList(16);
9061                        }
9062                        else {
9063                            skipScalingList(64);
9064                        }
9065                    }
9066                }
9067            }
9068        }
9069        skipUEG(); // log2_max_frame_num_minus4
9070        var picOrderCntType = readUEG();
9071        if (picOrderCntType === 0) {
9072            readUEG(); // log2_max_pic_order_cnt_lsb_minus4
9073        }
9074        else if (picOrderCntType === 1) {
9075            skipBits(1); // delta_pic_order_always_zero_flag
9076            skipEG(); // offset_for_non_ref_pic
9077            skipEG(); // offset_for_top_to_bottom_field
9078            numRefFramesInPicOrderCntCycle = readUEG();
9079            for (i = 0; i < numRefFramesInPicOrderCntCycle; i++) {
9080                skipEG();
9081            } // offset_for_ref_frame[ i ]
9082        }
9083        skipUEG(); // max_num_ref_frames
9084        skipBits(1); // gaps_in_frame_num_value_allowed_flag
9085        picWidthInMbsMinus1 = readUEG();
9086        picHeightInMapUnitsMinus1 = readUEG();
9087        frameMbsOnlyFlag = readBits(1);
9088        if (frameMbsOnlyFlag === 0) {
9089            skipBits(1);
9090        } // mb_adaptive_frame_field_flag
9091        skipBits(1); // direct_8x8_inference_flag
9092        if (readBoolean()) { // frame_cropping_flag
9093            frameCropLeftOffset = readUEG();
9094            frameCropRightOffset = readUEG();
9095            frameCropTopOffset = readUEG();
9096            frameCropBottomOffset = readUEG();
9097        }
9098        var pixelRatio = [1, 1];
9099        if (readBoolean()) {
9100            // vui_parameters_present_flag
9101            if (readBoolean()) {
9102                // aspect_ratio_info_present_flag
9103                var aspectRatioIdc = readUByte();
9104                switch (aspectRatioIdc) {
9105                    case 1:
9106                        pixelRatio = [1, 1];
9107                        break;
9108                    case 2:
9109                        pixelRatio = [12, 11];
9110                        break;
9111                    case 3:
9112                        pixelRatio = [10, 11];
9113                        break;
9114                    case 4:
9115                        pixelRatio = [16, 11];
9116                        break;
9117                    case 5:
9118                        pixelRatio = [40, 33];
9119                        break;
9120                    case 6:
9121                        pixelRatio = [24, 11];
9122                        break;
9123                    case 7:
9124                        pixelRatio = [20, 11];
9125                        break;
9126                    case 8:
9127                        pixelRatio = [32, 11];
9128                        break;
9129                    case 9:
9130                        pixelRatio = [80, 33];
9131                        break;
9132                    case 10:
9133                        pixelRatio = [18, 11];
9134                        break;
9135                    case 11:
9136                        pixelRatio = [15, 11];
9137                        break;
9138                    case 12:
9139                        pixelRatio = [64, 33];
9140                        break;
9141                    case 13:
9142                        pixelRatio = [160, 99];
9143                        break;
9144                    case 14:
9145                        pixelRatio = [4, 3];
9146                        break;
9147                    case 15:
9148                        pixelRatio = [3, 2];
9149                        break;
9150                    case 16:
9151                        pixelRatio = [2, 1];
9152                        break;
9153                    case 255: {
9154                        pixelRatio = [readUByte() << 8 | readUByte(), readUByte() << 8 | readUByte()];
9155                        break;
9156                    }
9157                }
9158            }
9159        }
9160        return {
9161            width: Math.ceil((((picWidthInMbsMinus1 + 1) * 16) - frameCropLeftOffset * 2 - frameCropRightOffset * 2)),
9162            height: ((2 - frameMbsOnlyFlag) * (picHeightInMapUnitsMinus1 + 1) * 16) - ((frameMbsOnlyFlag ? 2 : 4) * (frameCropTopOffset + frameCropBottomOffset)),
9163            pixelRatio: pixelRatio
9164        };
9165    };
9166    ExpGolomb.prototype.readSliceType = function () {
9167        // skip NALu type
9168        this.readUByte();
9169        // discard first_mb_in_slice
9170        this.readUEG();
9171        // return slice_type
9172        return this.readUEG();
9173    };
9174    return ExpGolomb;
9175}());
9176exports.default = ExpGolomb;
9177
9178
9179/***/ }),
9180
9181/***/ "./src/demux/id3.js":
9182/*!**************************!*\
9183  !*** ./src/demux/id3.js ***!
9184  \**************************/
9185/*! no static exports found */
9186/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
9187/***/ (function(module, exports, __webpack_require__) {
9188
9189"use strict";
9190
9191Object.defineProperty(exports, "__esModule", { value: true });
9192/**
9193 * ID3 parser
9194 */
9195var ID3 = /** @class */ (function () {
9196    function ID3() {
9197    }
9198    /**
9199     * Returns true if an ID3 header can be found at offset in data
9200     * @param {Uint8Array} data - The data to search in
9201     * @param {number} offset - The offset at which to start searching
9202     * @return {boolean} - True if an ID3 header is found
9203     */
9204    ID3.isHeader = function (data, offset) {
9205        /*
9206        * http://id3.org/id3v2.3.0
9207        * [0]     = 'I'
9208        * [1]     = 'D'
9209        * [2]     = '3'
9210        * [3,4]   = {Version}
9211        * [5]     = {Flags}
9212        * [6-9]   = {ID3 Size}
9213        *
9214        * An ID3v2 tag can be detected with the following pattern:
9215        *  $49 44 33 yy yy xx zz zz zz zz
9216        * Where yy is less than $FF, xx is the 'flags' byte and zz is less than $80
9217        */
9218        if (offset + 10 <= data.length) {
9219            // look for 'ID3' identifier
9220            if (data[offset] === 0x49 && data[offset + 1] === 0x44 && data[offset + 2] === 0x33) {
9221                // check version is within range
9222                if (data[offset + 3] < 0xFF && data[offset + 4] < 0xFF) {
9223                    // check size is within range
9224                    if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) {
9225                        return true;
9226                    }
9227                }
9228            }
9229        }
9230        return false;
9231    };
9232    /**
9233     * Returns true if an ID3 footer can be found at offset in data
9234     * @param {Uint8Array} data - The data to search in
9235     * @param {number} offset - The offset at which to start searching
9236     * @return {boolean} - True if an ID3 footer is found
9237     */
9238    ID3.isFooter = function (data, offset) {
9239        /*
9240        * The footer is a copy of the header, but with a different identifier
9241        */
9242        if (offset + 10 <= data.length) {
9243            // look for '3DI' identifier
9244            if (data[offset] === 0x33 && data[offset + 1] === 0x44 && data[offset + 2] === 0x49) {
9245                // check version is within range
9246                if (data[offset + 3] < 0xFF && data[offset + 4] < 0xFF) {
9247                    // check size is within range
9248                    if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) {
9249                        return true;
9250                    }
9251                }
9252            }
9253        }
9254        return false;
9255    };
9256    /**
9257     * Returns any adjacent ID3 tags found in data starting at offset, as one block of data
9258     * @param {Uint8Array} data - The data to search in
9259     * @param {number} offset - The offset at which to start searching
9260     * @return {Uint8Array} - The block of data containing any ID3 tags found
9261     */
9262    ID3.getID3Data = function (data, offset) {
9263        var front = offset;
9264        var length = 0;
9265        while (ID3.isHeader(data, offset)) {
9266            // ID3 header is 10 bytes
9267            length += 10;
9268            var size = ID3._readSize(data, offset + 6);
9269            length += size;
9270            if (ID3.isFooter(data, offset + 10)) {
9271                // ID3 footer is 10 bytes
9272                length += 10;
9273            }
9274            offset += length;
9275        }
9276        if (length > 0) {
9277            return data.subarray(front, front + length);
9278        }
9279        return undefined;
9280    };
9281    ID3._readSize = function (data, offset) {
9282        var size = 0;
9283        size = ((data[offset] & 0x7f) << 21);
9284        size |= ((data[offset + 1] & 0x7f) << 14);
9285        size |= ((data[offset + 2] & 0x7f) << 7);
9286        size |= (data[offset + 3] & 0x7f);
9287        return size;
9288    };
9289    /**
9290     * Searches for the Elementary Stream timestamp found in the ID3 data chunk
9291     * @param {Uint8Array} data - Block of data containing one or more ID3 tags
9292     * @return {number} - The timestamp
9293     */
9294    ID3.getTimeStamp = function (data) {
9295        var frames = ID3.getID3Frames(data);
9296        for (var i = 0; i < frames.length; i++) {
9297            var frame = frames[i];
9298            if (ID3.isTimeStampFrame(frame)) {
9299                return ID3._readTimeStamp(frame);
9300            }
9301        }
9302        return undefined;
9303    };
9304    /**
9305     * Returns true if the ID3 frame is an Elementary Stream timestamp frame
9306     * @param {ID3 frame} frame
9307     */
9308    ID3.isTimeStampFrame = function (frame) {
9309        return (frame && frame.key === 'PRIV' && frame.info === 'com.apple.streaming.transportStreamTimestamp');
9310    };
9311    ID3._getFrameData = function (data) {
9312        /*
9313        Frame ID       $xx xx xx xx (four characters)
9314        Size           $xx xx xx xx
9315        Flags          $xx xx
9316        */
9317        var type = String.fromCharCode(data[0], data[1], data[2], data[3]);
9318        var size = ID3._readSize(data, 4);
9319        // skip frame id, size, and flags
9320        var offset = 10;
9321        return { type: type, size: size, data: data.subarray(offset, offset + size) };
9322    };
9323    /**
9324     * Returns an array of ID3 frames found in all the ID3 tags in the id3Data
9325     * @param {Uint8Array} id3Data - The ID3 data containing one or more ID3 tags
9326     * @return {ID3 frame[]} - Array of ID3 frame objects
9327     */
9328    ID3.getID3Frames = function (id3Data) {
9329        var offset = 0;
9330        var frames = [];
9331        while (ID3.isHeader(id3Data, offset)) {
9332            var size = ID3._readSize(id3Data, offset + 6);
9333            // skip past ID3 header
9334            offset += 10;
9335            var end = offset + size;
9336            // loop through frames in the ID3 tag
9337            while (offset + 8 < end) {
9338                var frameData = ID3._getFrameData(id3Data.subarray(offset));
9339                var frame = ID3._decodeFrame(frameData);
9340                if (frame) {
9341                    frames.push(frame);
9342                }
9343                // skip frame header and frame data
9344                offset += frameData.size + 10;
9345            }
9346            if (ID3.isFooter(id3Data, offset)) {
9347                offset += 10;
9348            }
9349        }
9350        return frames;
9351    };
9352    ID3._decodeFrame = function (frame) {
9353        if (frame.type === 'PRIV') {
9354            return ID3._decodePrivFrame(frame);
9355        }
9356        else if (frame.type[0] === 'T') {
9357            return ID3._decodeTextFrame(frame);
9358        }
9359        else if (frame.type[0] === 'W') {
9360            return ID3._decodeURLFrame(frame);
9361        }
9362        return undefined;
9363    };
9364    ID3._readTimeStamp = function (timeStampFrame) {
9365        if (timeStampFrame.data.byteLength === 8) {
9366            var data = new Uint8Array(timeStampFrame.data);
9367            // timestamp is 33 bit expressed as a big-endian eight-octet number,
9368            // with the upper 31 bits set to zero.
9369            var pts33Bit = data[3] & 0x1;
9370            var timestamp = (data[4] << 23) +
9371                (data[5] << 15) +
9372                (data[6] << 7) +
9373                data[7];
9374            timestamp /= 45;
9375            if (pts33Bit) {
9376                timestamp += 47721858.84;
9377            } // 2^32 / 90
9378            return Math.round(timestamp);
9379        }
9380        return undefined;
9381    };
9382    ID3._decodePrivFrame = function (frame) {
9383        /*
9384        Format: <text string>\0<binary data>
9385        */
9386        if (frame.size < 2) {
9387            return undefined;
9388        }
9389        var owner = ID3._utf8ArrayToStr(frame.data, true);
9390        var privateData = new Uint8Array(frame.data.subarray(owner.length + 1));
9391        return { key: frame.type, info: owner, data: privateData.buffer };
9392    };
9393    ID3._decodeTextFrame = function (frame) {
9394        if (frame.size < 2) {
9395            return undefined;
9396        }
9397        if (frame.type === 'TXXX') {
9398            /*
9399            Format:
9400            [0]   = {Text Encoding}
9401            [1-?] = {Description}\0{Value}
9402            */
9403            var index = 1;
9404            var description = ID3._utf8ArrayToStr(frame.data.subarray(index));
9405            index += description.length + 1;
9406            var value = ID3._utf8ArrayToStr(frame.data.subarray(index));
9407            return { key: frame.type, info: description, data: value };
9408        }
9409        else {
9410            /*
9411            Format:
9412            [0]   = {Text Encoding}
9413            [1-?] = {Value}
9414            */
9415            var text = ID3._utf8ArrayToStr(frame.data.subarray(1));
9416            return { key: frame.type, data: text };
9417        }
9418    };
9419    ID3._decodeURLFrame = function (frame) {
9420        if (frame.type === 'WXXX') {
9421            /*
9422            Format:
9423            [0]   = {Text Encoding}
9424            [1-?] = {Description}\0{URL}
9425            */
9426            if (frame.size < 2) {
9427                return undefined;
9428            }
9429            var index = 1;
9430            var description = ID3._utf8ArrayToStr(frame.data.subarray(index));
9431            index += description.length + 1;
9432            var value = ID3._utf8ArrayToStr(frame.data.subarray(index));
9433            return { key: frame.type, info: description, data: value };
9434        }
9435        else {
9436            /*
9437            Format:
9438            [0-?] = {URL}
9439            */
9440            var url = ID3._utf8ArrayToStr(frame.data);
9441            return { key: frame.type, data: url };
9442        }
9443    };
9444    // http://stackoverflow.com/questions/8936984/uint8array-to-string-in-javascript/22373197
9445    // http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt
9446    /* utf.js - UTF-8 <=> UTF-16 convertion
9447     *
9448     * Copyright (C) 1999 Masanao Izumo <[email protected]>
9449     * Version: 1.0
9450     * LastModified: Dec 25 1999
9451     * This library is free.  You can redistribute it and/or modify it.
9452     */
9453    ID3._utf8ArrayToStr = function (array, exitOnNull) {
9454        if (exitOnNull === void 0) { exitOnNull = false; }
9455        var len = array.length;
9456        var c;
9457        var char2;
9458        var char3;
9459        var out = '';
9460        var i = 0;
9461        while (i < len) {
9462            c = array[i++];
9463            if (c === 0x00 && exitOnNull) {
9464                return out;
9465            }
9466            else if (c === 0x00 || c === 0x03) {
9467                // If the character is 3 (END_OF_TEXT) or 0 (NULL) then skip it
9468                continue;
9469            }
9470            switch (c >> 4) {
9471                case 0:
9472                case 1:
9473                case 2:
9474                case 3:
9475                case 4:
9476                case 5:
9477                case 6:
9478                case 7:
9479                    // 0xxxxxxx
9480                    out += String.fromCharCode(c);
9481                    break;
9482                case 12:
9483                case 13:
9484                    // 110x xxxx   10xx xxxx
9485                    char2 = array[i++];
9486                    out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
9487                    break;
9488                case 14:
9489                    // 1110 xxxx  10xx xxxx  10xx xxxx
9490                    char2 = array[i++];
9491                    char3 = array[i++];
9492                    out += String.fromCharCode(((c & 0x0F) << 12) |
9493                        ((char2 & 0x3F) << 6) |
9494                        ((char3 & 0x3F) << 0));
9495                    break;
9496                default:
9497            }
9498        }
9499        return out;
9500    };
9501    return ID3;
9502}());
9503var utf8ArrayToStr = ID3._utf8ArrayToStr;
9504exports.utf8ArrayToStr = utf8ArrayToStr;
9505exports.default = ID3;
9506
9507
9508/***/ }),
9509
9510/***/ "./src/demux/mp3demuxer.js":
9511/*!*********************************!*\
9512  !*** ./src/demux/mp3demuxer.js ***!
9513  \*********************************/
9514/*! no static exports found */
9515/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
9516/***/ (function(module, exports, __webpack_require__) {
9517
9518"use strict";
9519
9520Object.defineProperty(exports, "__esModule", { value: true });
9521/**
9522 * MP3 demuxer
9523 */
9524var id3_1 = __webpack_require__(/*! ../demux/id3 */ "./src/demux/id3.js");
9525var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
9526var mpegaudio_1 = __webpack_require__(/*! ./mpegaudio */ "./src/demux/mpegaudio.js");
9527var MP3Demuxer = /** @class */ (function () {
9528    function MP3Demuxer(observer, remuxer, config) {
9529        this.observer = observer;
9530        this.config = config;
9531        this.remuxer = remuxer;
9532    }
9533    MP3Demuxer.prototype.resetInitSegment = function (initSegment, audioCodec, videoCodec, duration) {
9534        this._audioTrack = { container: 'audio/mpeg', type: 'audio', id: -1, sequenceNumber: 0, isAAC: false, samples: [], len: 0, manifestCodec: audioCodec, duration: duration, inputTimeScale: 90000 };
9535    };
9536    MP3Demuxer.prototype.resetTimeStamp = function () {
9537    };
9538    MP3Demuxer.probe = function (data) {
9539        // check if data contains ID3 timestamp and MPEG sync word
9540        var offset, length;
9541        var id3Data = id3_1.default.getID3Data(data, 0);
9542        if (id3Data && id3_1.default.getTimeStamp(id3Data) !== undefined) {
9543            // Look for MPEG header | 1111 1111 | 111X XYZX | where X can be either 0 or 1 and Y or Z should be 1
9544            // Layer bits (position 14 and 15) in header should be always different from 0 (Layer I or Layer II or Layer III)
9545            // More info http://www.mp3-tech.org/programmer/frame_header.html
9546            for (offset = id3Data.length, length = Math.min(data.length - 1, offset + 100); offset < length; offset++) {
9547                if (mpegaudio_1.default.probe(data, offset)) {
9548                    logger_1.logger.log('MPEG Audio sync word found !');
9549                    return true;
9550                }
9551            }
9552        }
9553        return false;
9554    };
9555    // feed incoming data to the front of the parsing pipeline
9556    MP3Demuxer.prototype.append = function (data, timeOffset, contiguous, accurateTimeOffset) {
9557        var id3Data = id3_1.default.getID3Data(data, 0);
9558        var timestamp = id3_1.default.getTimeStamp(id3Data);
9559        var pts = timestamp ? 90 * timestamp : timeOffset * 90000;
9560        var offset = id3Data.length;
9561        var length = data.length;
9562        var frameIndex = 0, stamp = 0;
9563        var track = this._audioTrack;
9564        var id3Samples = [{ pts: pts, dts: pts, data: id3Data }];
9565        while (offset < length) {
9566            if (mpegaudio_1.default.isHeader(data, offset)) {
9567                var frame = mpegaudio_1.default.appendFrame(track, data, offset, pts, frameIndex);
9568                if (frame) {
9569                    offset += frame.length;
9570                    stamp = frame.sample.pts;
9571                    frameIndex++;
9572                }
9573                else {
9574                    // logger.log('Unable to parse Mpeg audio frame');
9575                    break;
9576                }
9577            }
9578            else if (id3_1.default.isHeader(data, offset)) {
9579                id3Data = id3_1.default.getID3Data(data, offset);
9580                id3Samples.push({ pts: stamp, dts: stamp, data: id3Data });
9581                offset += id3Data.length;
9582            }
9583            else {
9584                // nothing found, keep looking
9585                offset++;
9586            }
9587        }
9588        this.remuxer.remux(track, { samples: [] }, { samples: id3Samples, inputTimeScale: 90000 }, { samples: [] }, timeOffset, contiguous, accurateTimeOffset);
9589    };
9590    MP3Demuxer.prototype.destroy = function () {
9591    };
9592    return MP3Demuxer;
9593}());
9594exports.default = MP3Demuxer;
9595
9596
9597/***/ }),
9598
vendor: 19,843 bytes, lines 9599-10065
9599/***/ "./src/demux/mp4demuxer.js":
9600/*!*********************************!*\
9601  !*** ./src/demux/mp4demuxer.js ***!
9602  \*********************************/
9603/*! no static exports found */
9604/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
9605/***/ (function(module, exports, __webpack_require__) {
9606
9607"use strict";
9608
9609Object.defineProperty(exports, "__esModule", { value: true });
9610/**
9611 * MP4 demuxer
9612 */
9613var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
9614var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
9615var UINT32_MAX = Math.pow(2, 32) - 1;
9616var MP4Demuxer = /** @class */ (function () {
9617    function MP4Demuxer(observer, remuxer) {
9618        this.observer = observer;
9619        this.remuxer = remuxer;
9620    }
9621    MP4Demuxer.prototype.resetTimeStamp = function (initPTS) {
9622        this.initPTS = initPTS;
9623    };
9624    MP4Demuxer.prototype.resetInitSegment = function (initSegment, audioCodec, videoCodec, duration) {
9625        // jshint unused:false
9626        if (initSegment && initSegment.byteLength) {
9627            var initData = this.initData = MP4Demuxer.parseInitSegment(initSegment);
9628            // default audio codec if nothing specified
9629            // TODO : extract that from initsegment
9630            if (audioCodec == null) {
9631                audioCodec = 'mp4a.40.5';
9632            }
9633            if (videoCodec == null) {
9634                videoCodec = 'avc1.42e01e';
9635            }
9636            var tracks = {};
9637            if (initData.audio && initData.video) {
9638                tracks.audiovideo = { container: 'video/mp4', codec: audioCodec + ',' + videoCodec, initSegment: duration ? initSegment : null };
9639            }
9640            else {
9641                if (initData.audio) {
9642                    tracks.audio = { container: 'audio/mp4', codec: audioCodec, initSegment: duration ? initSegment : null };
9643                }
9644                if (initData.video) {
9645                    tracks.video = { container: 'video/mp4', codec: videoCodec, initSegment: duration ? initSegment : null };
9646                }
9647            }
9648            this.observer.trigger(events_1.default.FRAG_PARSING_INIT_SEGMENT, { tracks: tracks });
9649        }
9650        else {
9651            if (audioCodec) {
9652                this.audioCodec = audioCodec;
9653            }
9654            if (videoCodec) {
9655                this.videoCodec = videoCodec;
9656            }
9657        }
9658    };
9659    MP4Demuxer.probe = function (data) {
9660        // ensure we find a moof box in the first 16 kB
9661        return MP4Demuxer.findBox({ data: data, start: 0, end: Math.min(data.length, 16384) }, ['moof']).length > 0;
9662    };
9663    MP4Demuxer.bin2str = function (buffer) {
9664        return String.fromCharCode.apply(null, buffer);
9665    };
9666    MP4Demuxer.readUint16 = function (buffer, offset) {
9667        if (buffer.data) {
9668            offset += buffer.start;
9669            buffer = buffer.data;
9670        }
9671        var val = buffer[offset] << 8 |
9672            buffer[offset + 1];
9673        return val < 0 ? 65536 + val : val;
9674    };
9675    MP4Demuxer.readUint32 = function (buffer, offset) {
9676        if (buffer.data) {
9677            offset += buffer.start;
9678            buffer = buffer.data;
9679        }
9680        var val = buffer[offset] << 24 |
9681            buffer[offset + 1] << 16 |
9682            buffer[offset + 2] << 8 |
9683            buffer[offset + 3];
9684        return val < 0 ? 4294967296 + val : val;
9685    };
9686    MP4Demuxer.writeUint32 = function (buffer, offset, value) {
9687        if (buffer.data) {
9688            offset += buffer.start;
9689            buffer = buffer.data;
9690        }
9691        buffer[offset] = value >> 24;
9692        buffer[offset + 1] = (value >> 16) & 0xff;
9693        buffer[offset + 2] = (value >> 8) & 0xff;
9694        buffer[offset + 3] = value & 0xff;
9695    };
9696    // Find the data for a box specified by its path
9697    MP4Demuxer.findBox = function (data, path) {
9698        var results = [], i, size, type, end, subresults, start, endbox;
9699        if (data.data) {
9700            start = data.start;
9701            end = data.end;
9702            data = data.data;
9703        }
9704        else {
9705            start = 0;
9706            end = data.byteLength;
9707        }
9708        if (!path.length) {
9709            // short-circuit the search for empty paths
9710            return null;
9711        }
9712        for (i = start; i < end;) {
9713            size = MP4Demuxer.readUint32(data, i);
9714            type = MP4Demuxer.bin2str(data.subarray(i + 4, i + 8));
9715            endbox = size > 1 ? i + size : end;
9716            if (type === path[0]) {
9717                if (path.length === 1) {
9718                    // this is the end of the path and we've found the box we were
9719                    // looking for
9720                    results.push({ data: data, start: i + 8, end: endbox });
9721                }
9722                else {
9723                    // recursively search for the next box along the path
9724                    subresults = MP4Demuxer.findBox({ data: data, start: i + 8, end: endbox }, path.slice(1));
9725                    if (subresults.length) {
9726                        results = results.concat(subresults);
9727                    }
9728                }
9729            }
9730            i = endbox;
9731        }
9732        // we've finished searching all of data
9733        return results;
9734    };
9735    MP4Demuxer.parseSegmentIndex = function (initSegment) {
9736        var moov = MP4Demuxer.findBox(initSegment, ['moov'])[0];
9737        var moovEndOffset = moov ? moov.end : null; // we need this in case we need to chop of garbage of the end of current data
9738        var index = 0;
9739        var sidx = MP4Demuxer.findBox(initSegment, ['sidx']);
9740        var references;
9741        if (!sidx || !sidx[0]) {
9742            return null;
9743        }
9744        references = [];
9745        sidx = sidx[0];
9746        var version = sidx.data[0];
9747        // set initial offset, we skip the reference ID (not needed)
9748        index = version === 0 ? 8 : 16;
9749        var timescale = MP4Demuxer.readUint32(sidx, index);
9750        index += 4;
9751        // TODO: parse earliestPresentationTime and firstOffset
9752        // usually zero in our case
9753        var earliestPresentationTime = 0;
9754        var firstOffset = 0;
9755        if (version === 0) {
9756            index += 8;
9757        }
9758        else {
9759            index += 16;
9760        }
9761        // skip reserved
9762        index += 2;
9763        var startByte = sidx.end + firstOffset;
9764        var referencesCount = MP4Demuxer.readUint16(sidx, index);
9765        index += 2;
9766        for (var i = 0; i < referencesCount; i++) {
9767            var referenceIndex = index;
9768            var referenceInfo = MP4Demuxer.readUint32(sidx, referenceIndex);
9769            referenceIndex += 4;
9770            var referenceSize = referenceInfo & 0x7FFFFFFF;
9771            var referenceType = (referenceInfo & 0x80000000) >>> 31;
9772            if (referenceType === 1) {
9773                console.warn('SIDX has hierarchical references (not supported)');
9774                return;
9775            }
9776            var subsegmentDuration = MP4Demuxer.readUint32(sidx, referenceIndex);
9777            referenceIndex += 4;
9778            references.push({
9779                referenceSize: referenceSize,
9780                subsegmentDuration: subsegmentDuration,
9781                info: {
9782                    duration: subsegmentDuration / timescale,
9783                    start: startByte,
9784                    end: startByte + referenceSize - 1
9785                }
9786            });
9787            startByte += referenceSize;
9788            // Skipping 1 bit for |startsWithSap|, 3 bits for |sapType|, and 28 bits
9789            // for |sapDelta|.
9790            referenceIndex += 4;
9791            // skip to next ref
9792            index = referenceIndex;
9793        }
9794        return {
9795            earliestPresentationTime: earliestPresentationTime,
9796            timescale: timescale,
9797            version: version,
9798            referencesCount: referencesCount,
9799            references: references,
9800            moovEndOffset: moovEndOffset
9801        };
9802    };
9803    /**
9804     * Parses an MP4 initialization segment and extracts stream type and
9805     * timescale values for any declared tracks. Timescale values indicate the
9806     * number of clock ticks per second to assume for time-based values
9807     * elsewhere in the MP4.
9808     *
9809     * To determine the start time of an MP4, you need two pieces of
9810     * information: the timescale unit and the earliest base media decode
9811     * time. Multiple timescales can be specified within an MP4 but the
9812     * base media decode time is always expressed in the timescale from
9813     * the media header box for the track:
9814     * ```
9815     * moov > trak > mdia > mdhd.timescale
9816     * moov > trak > mdia > hdlr
9817     * ```
9818     * @param init {Uint8Array} the bytes of the init segment
9819     * @return {object} a hash of track type to timescale values or null if
9820     * the init segment is malformed.
9821     */
9822    MP4Demuxer.parseInitSegment = function (initSegment) {
9823        var result = [];
9824        var traks = MP4Demuxer.findBox(initSegment, ['moov', 'trak']);
9825        traks.forEach(function (trak) {
9826            var tkhd = MP4Demuxer.findBox(trak, ['tkhd'])[0];
9827            if (tkhd) {
9828                var version = tkhd.data[tkhd.start];
9829                var index = version === 0 ? 12 : 20;
9830                var trackId = MP4Demuxer.readUint32(tkhd, index);
9831                var mdhd = MP4Demuxer.findBox(trak, ['mdia', 'mdhd'])[0];
9832                if (mdhd) {
9833                    version = mdhd.data[mdhd.start];
9834                    index = version === 0 ? 12 : 20;
9835                    var timescale = MP4Demuxer.readUint32(mdhd, index);
9836                    var hdlr = MP4Demuxer.findBox(trak, ['mdia', 'hdlr'])[0];
9837                    if (hdlr) {
9838                        var hdlrType = MP4Demuxer.bin2str(hdlr.data.subarray(hdlr.start + 8, hdlr.start + 12));
9839                        var type = { 'soun': 'audio', 'vide': 'video' }[hdlrType];
9840                        if (type) {
9841                            // extract codec info. TODO : parse codec details to be able to build MIME type
9842                            var codecBox = MP4Demuxer.findBox(trak, ['mdia', 'minf', 'stbl', 'stsd']);
9843                            if (codecBox.length) {
9844                                codecBox = codecBox[0];
9845                                var codecType = MP4Demuxer.bin2str(codecBox.data.subarray(codecBox.start + 12, codecBox.start + 16));
9846                                logger_1.logger.log("MP4Demuxer:" + type + ":" + codecType + " found");
9847                            }
9848                            result[trackId] = { timescale: timescale, type: type };
9849                            result[type] = { timescale: timescale, id: trackId };
9850                        }
9851                    }
9852                }
9853            }
9854        });
9855        return result;
9856    };
9857    /**
9858   * Determine the base media decode start time, in seconds, for an MP4
9859   * fragment. If multiple fragments are specified, the earliest time is
9860   * returned.
9861   *
9862   * The base media decode time can be parsed from track fragment
9863   * metadata:
9864   * ```
9865   * moof > traf > tfdt.baseMediaDecodeTime
9866   * ```
9867   * It requires the timescale value from the mdhd to interpret.
9868   *
9869   * @param timescale {object} a hash of track ids to timescale values.
9870   * @return {number} the earliest base media decode start time for the
9871   * fragment, in seconds
9872   */
9873    MP4Demuxer.getStartDTS = function (initData, fragment) {
9874        var trafs, baseTimes, result;
9875        // we need info from two childrend of each track fragment box
9876        trafs = MP4Demuxer.findBox(fragment, ['moof', 'traf']);
9877        // determine the start times for each track
9878        baseTimes = [].concat.apply([], trafs.map(function (traf) {
9879            return MP4Demuxer.findBox(traf, ['tfhd']).map(function (tfhd) {
9880                var id, scale, baseTime;
9881                // get the track id from the tfhd
9882                id = MP4Demuxer.readUint32(tfhd, 4);
9883                // assume a 90kHz clock if no timescale was specified
9884                scale = initData[id].timescale || 90e3;
9885                // get the base media decode time from the tfdt
9886                baseTime = MP4Demuxer.findBox(traf, ['tfdt']).map(function (tfdt) {
9887                    var version, result;
9888                    version = tfdt.data[tfdt.start];
9889                    result = MP4Demuxer.readUint32(tfdt, 4);
9890                    if (version === 1) {
9891                        result *= Math.pow(2, 32);
9892                        result += MP4Demuxer.readUint32(tfdt, 8);
9893                    }
9894                    return result;
9895                })[0];
9896                // convert base time to seconds
9897                return baseTime / scale;
9898            });
9899        }));
9900        // return the minimum
9901        result = Math.min.apply(null, baseTimes);
9902        return isFinite(result) ? result : 0;
9903    };
9904    MP4Demuxer.offsetStartDTS = function (initData, fragment, timeOffset) {
9905        MP4Demuxer.findBox(fragment, ['moof', 'traf']).map(function (traf) {
9906            return MP4Demuxer.findBox(traf, ['tfhd']).map(function (tfhd) {
9907                // get the track id from the tfhd
9908                var id = MP4Demuxer.readUint32(tfhd, 4);
9909                // assume a 90kHz clock if no timescale was specified
9910                var timescale = initData[id].timescale || 90e3;
9911                // get the base media decode time from the tfdt
9912                MP4Demuxer.findBox(traf, ['tfdt']).map(function (tfdt) {
9913                    var version = tfdt.data[tfdt.start];
9914                    var baseMediaDecodeTime = MP4Demuxer.readUint32(tfdt, 4);
9915                    if (version === 0) {
9916                        MP4Demuxer.writeUint32(tfdt, 4, baseMediaDecodeTime - timeOffset * timescale);
9917                    }
9918                    else {
9919                        baseMediaDecodeTime *= Math.pow(2, 32);
9920                        baseMediaDecodeTime += MP4Demuxer.readUint32(tfdt, 8);
9921                        baseMediaDecodeTime -= timeOffset * timescale;
9922                        baseMediaDecodeTime = Math.max(baseMediaDecodeTime, 0);
9923                        var upper = Math.floor(baseMediaDecodeTime / (UINT32_MAX + 1));
9924                        var lower = Math.floor(baseMediaDecodeTime % (UINT32_MAX + 1));
9925                        MP4Demuxer.writeUint32(tfdt, 4, upper);
9926                        MP4Demuxer.writeUint32(tfdt, 8, lower);
9927                    }
9928                });
9929            });
9930        });
9931    };
9932    // feed incoming data to the front of the parsing pipeline
9933    MP4Demuxer.prototype.append = function (data, timeOffset, contiguous, accurateTimeOffset) {
9934        var initData = this.initData;
9935        if (!initData) {
9936            this.resetInitSegment(data, this.audioCodec, this.videoCodec, false);
9937            initData = this.initData;
9938        }
9939        var startDTS, initPTS = this.initPTS;
9940        if (initPTS === undefined) {
9941            var startDTS_1 = MP4Demuxer.getStartDTS(initData, data);
9942            this.initPTS = initPTS = startDTS_1 - timeOffset;
9943            this.observer.trigger(events_1.default.INIT_PTS_FOUND, { initPTS: initPTS });
9944        }
9945        MP4Demuxer.offsetStartDTS(initData, data, initPTS);
9946        startDTS = MP4Demuxer.getStartDTS(initData, data);
9947        this.remuxer.remux(initData.audio, initData.video, null, null, startDTS, contiguous, accurateTimeOffset, data);
9948    };
9949    MP4Demuxer.prototype.destroy = function () { };
9950    return MP4Demuxer;
9951}());
9952exports.default = MP4Demuxer;
9953
9954
9955/***/ }),
9956
9957/***/ "./src/demux/mpegaudio.js":
9958/*!********************************!*\
9959  !*** ./src/demux/mpegaudio.js ***!
9960  \********************************/
9961/*! no static exports found */
9962/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
9963/***/ (function(module, exports, __webpack_require__) {
9964
9965"use strict";
9966
9967/**
9968 *  MPEG parser helper
9969 */
9970Object.defineProperty(exports, "__esModule", { value: true });
9971var MpegAudio = {
9972    BitratesMap: [
9973        32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,
9974        32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384,
9975        32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,
9976        32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,
9977        8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160
9978    ],
9979    SamplingRateMap: [44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000],
9980    SamplesCoefficients: [
9981        // MPEG 2.5
9982        [
9983            0,
9984            72,
9985            144,
9986            12 // Layer1
9987        ],
9988        // Reserved
9989        [
9990            0,
9991            0,
9992            0,
9993            0 // Layer1
9994        ],
9995        // MPEG 2
9996        [
9997            0,
9998            72,
9999            144,
10000            12 // Layer1
10001        ],
10002        // MPEG 1
10003        [
10004            0,
10005            144,
10006            144,
10007            12 // Layer1
10008        ]
10009    ],
10010    BytesInSlot: [
10011        0,
10012        1,
10013        1,
10014        4 // Layer1
10015    ],
10016    appendFrame: function (track, data, offset, pts, frameIndex) {
10017        // Using http://www.datavoyage.com/mpgscript/mpeghdr.htm as a reference
10018        if (offset + 24 > data.length) {
10019            return undefined;
10020        }
10021        var header = this.parseHeader(data, offset);
10022        if (header && offset + header.frameLength <= data.length) {
10023            var frameDuration = header.samplesPerFrame * 90000 / header.sampleRate;
10024            var stamp = pts + frameIndex * frameDuration;
10025            var sample = { unit: data.subarray(offset, offset + header.frameLength), pts: stamp, dts: stamp };
10026            track.config = [];
10027            track.channelCount = header.channelCount;
10028            track.samplerate = header.sampleRate;
10029            track.samples.push(sample);
10030            track.len += header.frameLength;
10031            return { sample: sample, length: header.frameLength };
10032        }
10033        return undefined;
10034    },
10035    parseHeader: function (data, offset) {
10036        var headerB = (data[offset + 1] >> 3) & 3;
10037        var headerC = (data[offset + 1] >> 1) & 3;
10038        var headerE = (data[offset + 2] >> 4) & 15;
10039        var headerF = (data[offset + 2] >> 2) & 3;
10040        var headerG = (data[offset + 2] >> 1) & 1;
10041        if (headerB !== 1 && headerE !== 0 && headerE !== 15 && headerF !== 3) {
10042            var columnInBitrates = headerB === 3 ? (3 - headerC) : (headerC === 3 ? 3 : 4);
10043            var bitRate = MpegAudio.BitratesMap[columnInBitrates * 14 + headerE - 1] * 1000;
10044            var columnInSampleRates = headerB === 3 ? 0 : headerB === 2 ? 1 : 2;
10045            var sampleRate = MpegAudio.SamplingRateMap[columnInSampleRates * 3 + headerF];
10046            var channelCount = data[offset + 3] >> 6 === 3 ? 1 : 2; // If bits of channel mode are `11` then it is a single channel (Mono)
10047            var sampleCoefficient = MpegAudio.SamplesCoefficients[headerB][headerC];
10048            var bytesInSlot = MpegAudio.BytesInSlot[headerC];
10049            var samplesPerFrame = sampleCoefficient * 8 * bytesInSlot;
10050            var frameLength = parseInt(sampleCoefficient * bitRate / sampleRate + headerG, 10) * bytesInSlot;
10051            return { sampleRate: sampleRate, channelCount: channelCount, frameLength: frameLength, samplesPerFrame: samplesPerFrame };
10052        }
10053        return undefined;
10054    },
10055    isHeaderPattern: function (data, offset) {
10056        return data[offset] === 0xff && (data[offset + 1] & 0xe0) === 0xe0 && (data[offset + 1] & 0x06) !== 0x00;
10057    },
10058    isHeader: function (data, offset) {
10059        // Look for MPEG header | 1111 1111 | 111X XYZX | where X can be either 0 or 1 and Y or Z should be 1
10060        // Layer bits (position 14 and 15) in header should be always different from 0 (Layer I or Layer II or Layer III)
10061        // More info http://www.mp3-tech.org/programmer/frame_header.html
10062        if (offset + 1 < data.length && this.isHeaderPattern(data, offset)) {
10063            return true;
10064        }
10065        return false;
10066    },
10067    probe: function (data, offset) {
10068        // same as isHeader but we also check that MPEG frame follows last MPEG frame
10069        // or end of data is reached
10070        if (offset + 1 < data.length && this.isHeaderPattern(data, offset)) {
10071            // MPEG header Length
10072            var headerLength = 4;
10073            // MPEG frame Length
10074            var header = this.parseHeader(data, offset);
10075            var frameLength = headerLength;
10076            if (header && header.frameLength) {
10077                frameLength = header.frameLength;
10078            }
10079            var newOffset = offset + frameLength;
10080            if (newOffset === data.length || (newOffset + 1 < data.length && this.isHeaderPattern(data, newOffset))) {
10081                return true;
10082            }
10083        }
10084        return false;
10085    }
10086};
10087exports.default = MpegAudio;
10088
10089
10090/***/ }),
10091
vendor: 45,603 bytes, lines 10092-11073
10092/***/ "./src/demux/sample-aes.js":
10093/*!*********************************!*\
10094  !*** ./src/demux/sample-aes.js ***!
10095  \*********************************/
10096/*! no static exports found */
10097/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
10098/***/ (function(module, exports, __webpack_require__) {
10099
10100"use strict";
10101
10102/**
10103 * SAMPLE-AES decrypter
10104*/
10105Object.defineProperty(exports, "__esModule", { value: true });
10106var decrypter_1 = __webpack_require__(/*! ../crypt/decrypter */ "./src/crypt/decrypter.js");
10107var SampleAesDecrypter = /** @class */ (function () {
10108    function SampleAesDecrypter(observer, config, decryptdata, discardEPB) {
10109        this.decryptdata = decryptdata;
10110        this.discardEPB = discardEPB;
10111        this.decrypter = new decrypter_1.default(observer, config, { removePKCS7Padding: false });
10112    }
10113    SampleAesDecrypter.prototype.decryptBuffer = function (encryptedData, callback) {
10114        this.decrypter.decrypt(encryptedData, this.decryptdata.key.buffer, this.decryptdata.iv.buffer, callback);
10115    };
10116    // AAC - encrypt all full 16 bytes blocks starting from offset 16
10117    SampleAesDecrypter.prototype.decryptAacSample = function (samples, sampleIndex, callback, sync) {
10118        var curUnit = samples[sampleIndex].unit;
10119        var encryptedData = curUnit.subarray(16, curUnit.length - curUnit.length % 16);
10120        var encryptedBuffer = encryptedData.buffer.slice(encryptedData.byteOffset, encryptedData.byteOffset + encryptedData.length);
10121        var localthis = this;
10122        this.decryptBuffer(encryptedBuffer, function (decryptedData) {
10123            decryptedData = new Uint8Array(decryptedData);
10124            curUnit.set(decryptedData, 16);
10125            if (!sync) {
10126                localthis.decryptAacSamples(samples, sampleIndex + 1, callback);
10127            }
10128        });
10129    };
10130    SampleAesDecrypter.prototype.decryptAacSamples = function (samples, sampleIndex, callback) {
10131        for (;; sampleIndex++) {
10132            if (sampleIndex >= samples.length) {
10133                callback();
10134                return;
10135            }
10136            if (samples[sampleIndex].unit.length < 32) {
10137                continue;
10138            }
10139            var sync = this.decrypter.isSync();
10140            this.decryptAacSample(samples, sampleIndex, callback, sync);
10141            if (!sync) {
10142                return;
10143            }
10144        }
10145    };
10146    // AVC - encrypt one 16 bytes block out of ten, starting from offset 32
10147    SampleAesDecrypter.prototype.getAvcEncryptedData = function (decodedData) {
10148        var encryptedDataLen = Math.floor((decodedData.length - 48) / 160) * 16 + 16;
10149        var encryptedData = new Int8Array(encryptedDataLen);
10150        var outputPos = 0;
10151        for (var inputPos = 32; inputPos <= decodedData.length - 16; inputPos += 160, outputPos += 16) {
10152            encryptedData.set(decodedData.subarray(inputPos, inputPos + 16), outputPos);
10153        }
10154        return encryptedData;
10155    };
10156    SampleAesDecrypter.prototype.getAvcDecryptedUnit = function (decodedData, decryptedData) {
10157        decryptedData = new Uint8Array(decryptedData);
10158        var inputPos = 0;
10159        for (var outputPos = 32; outputPos <= decodedData.length - 16; outputPos += 160, inputPos += 16) {
10160            decodedData.set(decryptedData.subarray(inputPos, inputPos + 16), outputPos);
10161        }
10162        return decodedData;
10163    };
10164    SampleAesDecrypter.prototype.decryptAvcSample = function (samples, sampleIndex, unitIndex, callback, curUnit, sync) {
10165        var decodedData = this.discardEPB(curUnit.data);
10166        var encryptedData = this.getAvcEncryptedData(decodedData);
10167        var localthis = this;
10168        this.decryptBuffer(encryptedData.buffer, function (decryptedData) {
10169            curUnit.data = localthis.getAvcDecryptedUnit(decodedData, decryptedData);
10170            if (!sync) {
10171                localthis.decryptAvcSamples(samples, sampleIndex, unitIndex + 1, callback);
10172            }
10173        });
10174    };
10175    SampleAesDecrypter.prototype.decryptAvcSamples = function (samples, sampleIndex, unitIndex, callback) {
10176        for (;; sampleIndex++, unitIndex = 0) {
10177            if (sampleIndex >= samples.length) {
10178                callback();
10179                return;
10180            }
10181            var curUnits = samples[sampleIndex].units;
10182            for (;; unitIndex++) {
10183                if (unitIndex >= curUnits.length) {
10184                    break;
10185                }
10186                var curUnit = curUnits[unitIndex];
10187                if (curUnit.length <= 48 || (curUnit.type !== 1 && curUnit.type !== 5)) {
10188                    continue;
10189                }
10190                var sync = this.decrypter.isSync();
10191                this.decryptAvcSample(samples, sampleIndex, unitIndex, callback, curUnit, sync);
10192                if (!sync) {
10193                    return;
10194                }
10195            }
10196        }
10197    };
10198    return SampleAesDecrypter;
10199}());
10200exports.default = SampleAesDecrypter;
10201
10202
10203/***/ }),
10204
10205/***/ "./src/demux/tsdemuxer.js":
10206/*!********************************!*\
10207  !*** ./src/demux/tsdemuxer.js ***!
10208  \********************************/
10209/*! no static exports found */
10210/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
10211/***/ (function(module, exports, __webpack_require__) {
10212
10213"use strict";
10214
10215/**
10216 * highly optimized TS demuxer:
10217 * parse PAT, PMT
10218 * extract PES packet from audio and video PIDs
10219 * extract AVC/H264 NAL units and AAC/ADTS samples from PES packet
10220 * trigger the remuxer upon parsing completion
10221 * 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.
10222 * it also controls the remuxing process :
10223 * upon discontinuity or level switch detection, it will also notifies the remuxer so that it can reset its state.
10224*/
10225Object.defineProperty(exports, "__esModule", { value: true });
10226var ADTS = __webpack_require__(/*! ./adts */ "./src/demux/adts.js");
10227var mpegaudio_1 = __webpack_require__(/*! ./mpegaudio */ "./src/demux/mpegaudio.js");
10228var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
10229var exp_golomb_1 = __webpack_require__(/*! ./exp-golomb */ "./src/demux/exp-golomb.js");
10230var sample_aes_1 = __webpack_require__(/*! ./sample-aes */ "./src/demux/sample-aes.js");
10231// import Hex from '../utils/hex';
10232var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
10233var errors_1 = __webpack_require__(/*! ../errors */ "./src/errors.js");
10234// We are using fixed track IDs for driving the MP4 remuxer
10235// instead of following the TS PIDs.
10236// There is no reason not to do this and some browsers/SourceBuffer-demuxers
10237// may not like if there are TrackID "switches"
10238// See https://github.com/video-dev/hls.js/issues/1331
10239// Here we are mapping our internal track types to constant MP4 track IDs
10240// With MSE currently one can only have one track of each, and we are muxing
10241// whatever video/audio rendition in them.
10242var RemuxerTrackIdConfig = {
10243    video: 1,
10244    audio: 2,
10245    id3: 3,
10246    text: 4
10247};
10248var TSDemuxer = /** @class */ (function () {
10249    function TSDemuxer(observer, remuxer, config, typeSupported) {
10250        this.observer = observer;
10251        this.config = config;
10252        this.typeSupported = typeSupported;
10253        this.remuxer = remuxer;
10254        this.sampleAes = null;
10255    }
10256    TSDemuxer.prototype.setDecryptData = function (decryptdata) {
10257        if ((decryptdata != null) && (decryptdata.key != null) && (decryptdata.method === 'SAMPLE-AES')) {
10258            this.sampleAes = new sample_aes_1.default(this.observer, this.config, decryptdata, this.discardEPB);
10259        }
10260        else {
10261            this.sampleAes = null;
10262        }
10263    };
10264    TSDemuxer.probe = function (data) {
10265        var syncOffset = TSDemuxer._syncOffset(data);
10266        if (syncOffset < 0) {
10267            return false;
10268        }
10269        else {
10270            if (syncOffset) {
10271                logger_1.logger.warn("MPEG2-TS detected but first sync word found @ offset " + syncOffset + ", junk ahead ?");
10272            }
10273            return true;
10274        }
10275    };
10276    TSDemuxer._syncOffset = function (data) {
10277        // scan 1000 first bytes
10278        var scanwindow = Math.min(1000, data.length - 3 * 188);
10279        var i = 0;
10280        while (i < scanwindow) {
10281            // a TS fragment should contain at least 3 TS packets, a PAT, a PMT, and one PID, each starting with 0x47
10282            if (data[i] === 0x47 && data[i + 188] === 0x47 && data[i + 2 * 188] === 0x47) {
10283                return i;
10284            }
10285            else {
10286                i++;
10287            }
10288        }
10289        return -1;
10290    };
10291    /**
10292     * Creates a track model internal to demuxer used to drive remuxing input
10293     *
10294     * @param {string} type 'audio' | 'video' | 'id3' | 'text'
10295     * @param {number} duration
10296     * @return {object} TSDemuxer's internal track model
10297     */
10298    TSDemuxer.createTrack = function (type, duration) {
10299        return {
10300            container: type === 'video' || type === 'audio' ? 'video/mp2t' : undefined,
10301            type: type,
10302            id: RemuxerTrackIdConfig[type],
10303            pid: -1,
10304            inputTimeScale: 90000,
10305            sequenceNumber: 0,
10306            samples: [],
10307            len: 0,
10308            dropped: type === 'video' ? 0 : undefined,
10309            isAAC: type === 'audio' ? true : undefined,
10310            duration: type === 'audio' ? duration : undefined
10311        };
10312    };
10313    /**
10314     * Initializes a new init segment on the demuxer/remuxer interface. Needed for discontinuities/track-switches (or at stream start)
10315     * Resets all internal track instances of the demuxer.
10316     *
10317     * @override Implements generic demuxing/remuxing interface (see DemuxerInline)
10318     * @param {object} initSegment
10319     * @param {string} audioCodec
10320     * @param {string} videoCodec
10321     * @param {number} duration (in TS timescale = 90kHz)
10322     */
10323    TSDemuxer.prototype.resetInitSegment = function (initSegment, audioCodec, videoCodec, duration) {
10324        this.pmtParsed = false;
10325        this._pmtId = -1;
10326        this._avcTrack = TSDemuxer.createTrack('video', duration);
10327        this._audioTrack = TSDemuxer.createTrack('audio', duration);
10328        this._id3Track = TSDemuxer.createTrack('id3', duration);
10329        this._txtTrack = TSDemuxer.createTrack('text', duration);
10330        // flush any partial content
10331        this.aacOverFlow = null;
10332        this.aacLastPTS = null;
10333        this.avcSample = null;
10334        this.audioCodec = audioCodec;
10335        this.videoCodec = videoCodec;
10336        this._duration = duration;
10337    };
10338    /**
10339     *
10340     * @override
10341     */
10342    TSDemuxer.prototype.resetTimeStamp = function () { };
10343    // feed incoming data to the front of the parsing pipeline
10344    TSDemuxer.prototype.append = function (data, timeOffset, contiguous, accurateTimeOffset) {
10345        var start, len = data.length, stt, pid, atf, offset, pes, unknownPIDs = false;
10346        this.contiguous = contiguous;
10347        var pmtParsed = this.pmtParsed, avcTrack = this._avcTrack, audioTrack = this._audioTrack, id3Track = this._id3Track, avcId = avcTrack.pid, audioId = audioTrack.pid, id3Id = id3Track.pid, pmtId = this._pmtId, avcData = avcTrack.pesData, audioData = audioTrack.pesData, id3Data = id3Track.pesData, parsePAT = this._parsePAT, parsePMT = this._parsePMT, parsePES = this._parsePES, parseAVCPES = this._parseAVCPES.bind(this), parseAACPES = this._parseAACPES.bind(this), parseMPEGPES = this._parseMPEGPES.bind(this), parseID3PES = this._parseID3PES.bind(this);
10348        var syncOffset = TSDemuxer._syncOffset(data);
10349        // don't parse last TS packet if incomplete
10350        len -= (len + syncOffset) % 188;
10351        // loop through TS packets
10352        for (start = syncOffset; start < len; start += 188) {
10353            if (data[start] === 0x47) {
10354                stt = !!(data[start + 1] & 0x40);
10355                // pid is a 13-bit field starting at the last bit of TS[1]
10356                pid = ((data[start + 1] & 0x1f) << 8) + data[start + 2];
10357                atf = (data[start + 3] & 0x30) >> 4;
10358                // if an adaption field is present, its length is specified by the fifth byte of the TS packet header.
10359                if (atf > 1) {
10360                    offset = start + 5 + data[start + 4];
10361                    // continue if there is only adaptation field
10362                    if (offset === (start + 188)) {
10363                        continue;
10364                    }
10365                }
10366                else {
10367                    offset = start + 4;
10368                }
10369                switch (pid) {
10370                    case avcId:
10371                        if (stt) {
10372                            if (avcData && (pes = parsePES(avcData)) && pes.pts !== undefined) {
10373                                parseAVCPES(pes, false);
10374                            }
10375                            avcData = { data: [], size: 0 };
10376                        }
10377                        if (avcData) {
10378                            avcData.data.push(data.subarray(offset, start + 188));
10379                            avcData.size += start + 188 - offset;
10380                        }
10381                        break;
10382                    case audioId:
10383                        if (stt) {
10384                            if (audioData && (pes = parsePES(audioData)) && pes.pts !== undefined) {
10385                                if (audioTrack.isAAC) {
10386                                    parseAACPES(pes);
10387                                }
10388                                else {
10389                                    parseMPEGPES(pes);
10390                                }
10391                            }
10392                            audioData = { data: [], size: 0 };
10393                        }
10394                        if (audioData) {
10395                            audioData.data.push(data.subarray(offset, start + 188));
10396                            audioData.size += start + 188 - offset;
10397                        }
10398                        break;
10399                    case id3Id:
10400                        if (stt) {
10401                            if (id3Data && (pes = parsePES(id3Data)) && pes.pts !== undefined) {
10402                                parseID3PES(pes);
10403                            }
10404                            id3Data = { data: [], size: 0 };
10405                        }
10406                        if (id3Data) {
10407                            id3Data.data.push(data.subarray(offset, start + 188));
10408                            id3Data.size += start + 188 - offset;
10409                        }
10410                        break;
10411                    case 0:
10412                        if (stt) {
10413                            offset += data[offset] + 1;
10414                        }
10415                        pmtId = this._pmtId = parsePAT(data, offset);
10416                        break;
10417                    case pmtId:
10418                        if (stt) {
10419                            offset += data[offset] + 1;
10420                        }
10421                        var parsedPIDs = parsePMT(data, offset, this.typeSupported.mpeg === true || this.typeSupported.mp3 === true, this.sampleAes != null);
10422                        // only update track id if track PID found while parsing PMT
10423                        // this is to avoid resetting the PID to -1 in case
10424                        // track PID transiently disappears from the stream
10425                        // this could happen in case of transient missing audio samples for example
10426                        // NOTE this is only the PID of the track as found in TS,
10427                        // but we are not using this for MP4 track IDs.
10428                        avcId = parsedPIDs.avc;
10429                        if (avcId > 0) {
10430                            avcTrack.pid = avcId;
10431                        }
10432                        audioId = parsedPIDs.audio;
10433                        if (audioId > 0) {
10434                            audioTrack.pid = audioId;
10435                            audioTrack.isAAC = parsedPIDs.isAAC;
10436                        }
10437                        id3Id = parsedPIDs.id3;
10438                        if (id3Id > 0) {
10439                            id3Track.pid = id3Id;
10440                        }
10441                        if (unknownPIDs && !pmtParsed) {
10442                            logger_1.logger.log('reparse from beginning');
10443                            unknownPIDs = false;
10444                            // we set it to -188, the += 188 in the for loop will reset start to 0
10445                            start = syncOffset - 188;
10446                        }
10447                        pmtParsed = this.pmtParsed = true;
10448                        break;
10449                    case 17:
10450                    case 0x1fff:
10451                        break;
10452                    default:
10453                        unknownPIDs = true;
10454                        break;
10455                }
10456            }
10457            else {
10458                this.observer.trigger(events_1.default.ERROR, { type: errors_1.ErrorTypes.MEDIA_ERROR, details: errors_1.ErrorDetails.FRAG_PARSING_ERROR, fatal: false, reason: 'TS packet did not start with 0x47' });
10459            }
10460        }
10461        // try to parse last PES packets
10462        if (avcData && (pes = parsePES(avcData)) && pes.pts !== undefined) {
10463            parseAVCPES(pes, true);
10464            avcTrack.pesData = null;
10465        }
10466        else {
10467            // either avcData null or PES truncated, keep it for next frag parsing
10468            avcTrack.pesData = avcData;
10469        }
10470        if (audioData && (pes = parsePES(audioData)) && pes.pts !== undefined) {
10471            if (audioTrack.isAAC) {
10472                parseAACPES(pes);
10473            }
10474            else {
10475                parseMPEGPES(pes);
10476            }
10477            audioTrack.pesData = null;
10478        }
10479        else {
10480            if (audioData && audioData.size) {
10481                logger_1.logger.log('last AAC PES packet truncated,might overlap between fragments');
10482            }
10483            // either audioData null or PES truncated, keep it for next frag parsing
10484            audioTrack.pesData = audioData;
10485        }
10486        if (id3Data && (pes = parsePES(id3Data)) && pes.pts !== undefined) {
10487            parseID3PES(pes);
10488            id3Track.pesData = null;
10489        }
10490        else {
10491            // either id3Data null or PES truncated, keep it for next frag parsing
10492            id3Track.pesData = id3Data;
10493        }
10494        if (this.sampleAes == null) {
10495            this.remuxer.remux(audioTrack, avcTrack, id3Track, this._txtTrack, timeOffset, contiguous, accurateTimeOffset);
10496        }
10497        else {
10498            this.decryptAndRemux(audioTrack, avcTrack, id3Track, this._txtTrack, timeOffset, contiguous, accurateTimeOffset);
10499        }
10500    };
10501    TSDemuxer.prototype.decryptAndRemux = function (audioTrack, videoTrack, id3Track, textTrack, timeOffset, contiguous, accurateTimeOffset) {
10502        if (audioTrack.samples && audioTrack.isAAC) {
10503            var localthis_1 = this;
10504            this.sampleAes.decryptAacSamples(audioTrack.samples, 0, function () {
10505                localthis_1.decryptAndRemuxAvc(audioTrack, videoTrack, id3Track, textTrack, timeOffset, contiguous, accurateTimeOffset);
10506            });
10507        }
10508        else {
10509            this.decryptAndRemuxAvc(audioTrack, videoTrack, id3Track, textTrack, timeOffset, contiguous, accurateTimeOffset);
10510        }
10511    };
10512    TSDemuxer.prototype.decryptAndRemuxAvc = function (audioTrack, videoTrack, id3Track, textTrack, timeOffset, contiguous, accurateTimeOffset) {
10513        if (videoTrack.samples) {
10514            var localthis_2 = this;
10515            this.sampleAes.decryptAvcSamples(videoTrack.samples, 0, 0, function () {
10516                localthis_2.remuxer.remux(audioTrack, videoTrack, id3Track, textTrack, timeOffset, contiguous, accurateTimeOffset);
10517            });
10518        }
10519        else {
10520            this.remuxer.remux(audioTrack, videoTrack, id3Track, textTrack, timeOffset, contiguous, accurateTimeOffset);
10521        }
10522    };
10523    TSDemuxer.prototype.destroy = function () {
10524        this._initPTS = this._initDTS = undefined;
10525        this._duration = 0;
10526    };
10527    TSDemuxer.prototype._parsePAT = function (data, offset) {
10528        // skip the PSI header and parse the first PMT entry
10529        return (data[offset + 10] & 0x1F) << 8 | data[offset + 11];
10530        // logger.log('PMT PID:'  + this._pmtId);
10531    };
10532    TSDemuxer.prototype._parsePMT = function (data, offset, mpegSupported, isSampleAes) {
10533        var sectionLength, tableEnd, programInfoLength, pid, result = { audio: -1, avc: -1, id3: -1, isAAC: true };
10534        sectionLength = (data[offset + 1] & 0x0f) << 8 | data[offset + 2];
10535        tableEnd = offset + 3 + sectionLength - 4;
10536        // to determine where the table is, we have to figure out how
10537        // long the program info descriptors are
10538        programInfoLength = (data[offset + 10] & 0x0f) << 8 | data[offset + 11];
10539        // advance the offset to the first entry in the mapping table
10540        offset += 12 + programInfoLength;
10541        while (offset < tableEnd) {
10542            pid = (data[offset + 1] & 0x1F) << 8 | data[offset + 2];
10543            switch (data[offset]) {
10544                case 0xcf: // SAMPLE-AES AAC
10545                    if (!isSampleAes) {
10546                        logger_1.logger.log('unkown stream type:' + data[offset]);
10547                        break;
10548                    }
10549                /* falls through */
10550                // ISO/IEC 13818-7 ADTS AAC (MPEG-2 lower bit-rate audio)
10551                case 0x0f:
10552                    // logger.log('AAC PID:'  + pid);
10553                    if (result.audio === -1) {
10554                        result.audio = pid;
10555                    }
10556                    break;
10557                // Packetized metadata (ID3)
10558                case 0x15:
10559                    // logger.log('ID3 PID:'  + pid);
10560                    if (result.id3 === -1) {
10561                        result.id3 = pid;
10562                    }
10563                    break;
10564                case 0xdb: // SAMPLE-AES AVC
10565                    if (!isSampleAes) {
10566                        logger_1.logger.log('unkown stream type:' + data[offset]);
10567                        break;
10568                    }
10569                /* falls through */
10570                // ITU-T Rec. H.264 and ISO/IEC 14496-10 (lower bit-rate video)
10571                case 0x1b:
10572                    // logger.log('AVC PID:'  + pid);
10573                    if (result.avc === -1) {
10574                        result.avc = pid;
10575                    }
10576                    break;
10577                // ISO/IEC 11172-3 (MPEG-1 audio)
10578                // or ISO/IEC 13818-3 (MPEG-2 halved sample rate audio)
10579                case 0x03:
10580                case 0x04:
10581                    // logger.log('MPEG PID:'  + pid);
10582                    if (!mpegSupported) {
10583                        logger_1.logger.log('MPEG audio found, not supported in this browser for now');
10584                    }
10585                    else if (result.audio === -1) {
10586                        result.audio = pid;
10587                        result.isAAC = false;
10588                    }
10589                    break;
10590                case 0x24:
10591                    logger_1.logger.warn('HEVC stream type found, not supported for now');
10592                    break;
10593                default:
10594                    logger_1.logger.log('unkown stream type:' + data[offset]);
10595                    break;
10596            }
10597            // move to the next table entry
10598            // skip past the elementary stream descriptors, if present
10599            offset += ((data[offset + 3] & 0x0F) << 8 | data[offset + 4]) + 5;
10600        }
10601        return result;
10602    };
10603    TSDemuxer.prototype._parsePES = function (stream) {
10604        var i = 0, frag, pesFlags, pesPrefix, pesLen, pesHdrLen, pesData, pesPts, pesDts, payloadStartOffset, data = stream.data;
10605        // safety check
10606        if (!stream || stream.size === 0) {
10607            return null;
10608        }
10609        // we might need up to 19 bytes to read PES header
10610        // if first chunk of data is less than 19 bytes, let's merge it with following ones until we get 19 bytes
10611        // usually only one merge is needed (and this is rare ...)
10612        while (data[0].length < 19 && data.length > 1) {
10613            var newData = new Uint8Array(data[0].length + data[1].length);
10614            newData.set(data[0]);
10615            newData.set(data[1], data[0].length);
10616            data[0] = newData;
10617            data.splice(1, 1);
10618        }
10619        // retrieve PTS/DTS from first fragment
10620        frag = data[0];
10621        pesPrefix = (frag[0] << 16) + (frag[1] << 8) + frag[2];
10622        if (pesPrefix === 1) {
10623            pesLen = (frag[4] << 8) + frag[5];
10624            // if PES parsed length is not zero and greater than total received length, stop parsing. PES might be truncated
10625            // minus 6 : PES header size
10626            if (pesLen && pesLen > stream.size - 6) {
10627                return null;
10628            }
10629            pesFlags = frag[7];
10630            if (pesFlags & 0xC0) {
10631                /* PES header described here : http://dvd.sourceforge.net/dvdinfo/pes-hdr.html
10632                    as PTS / DTS is 33 bit we cannot use bitwise operator in JS,
10633                    as Bitwise operators treat their operands as a sequence of 32 bits */
10634                pesPts = (frag[9] & 0x0E) * 536870912 + // 1 << 29
10635                    (frag[10] & 0xFF) * 4194304 + // 1 << 22
10636                    (frag[11] & 0xFE) * 16384 + // 1 << 14
10637                    (frag[12] & 0xFF) * 128 + // 1 << 7
10638                    (frag[13] & 0xFE) / 2;
10639                // check if greater than 2^32 -1
10640                if (pesPts > 4294967295) {
10641                    // decrement 2^33
10642                    pesPts -= 8589934592;
10643                }
10644                if (pesFlags & 0x40) {
10645                    pesDts = (frag[14] & 0x0E) * 536870912 + // 1 << 29
10646                        (frag[15] & 0xFF) * 4194304 + // 1 << 22
10647                        (frag[16] & 0xFE) * 16384 + // 1 << 14
10648                        (frag[17] & 0xFF) * 128 + // 1 << 7
10649                        (frag[18] & 0xFE) / 2;
10650                    // check if greater than 2^32 -1
10651                    if (pesDts > 4294967295) {
10652                        // decrement 2^33
10653                        pesDts -= 8589934592;
10654                    }
10655                    if (pesPts - pesDts > 60 * 90000) {
10656                        logger_1.logger.warn(Math.round((pesPts - pesDts) / 90000) + "s delta between PTS and DTS, align them");
10657                        pesPts = pesDts;
10658                    }
10659                }
10660                else {
10661                    pesDts = pesPts;
10662                }
10663            }
10664            pesHdrLen = frag[8];
10665            // 9 bytes : 6 bytes for PES header + 3 bytes for PES extension
10666            payloadStartOffset = pesHdrLen + 9;
10667            stream.size -= payloadStartOffset;
10668            // reassemble PES packet
10669            pesData = new Uint8Array(stream.size);
10670            for (var j = 0, dataLen = data.length; j < dataLen; j++) {
10671                frag = data[j];
10672                var len = frag.byteLength;
10673                if (payloadStartOffset) {
10674                    if (payloadStartOffset > len) {
10675                        // trim full frag if PES header bigger than frag
10676                        payloadStartOffset -= len;
10677                        continue;
10678                    }
10679                    else {
10680                        // trim partial frag if PES header smaller than frag
10681                        frag = frag.subarray(payloadStartOffset);
10682                        len -= payloadStartOffset;
10683                        payloadStartOffset = 0;
10684                    }
10685                }
10686                pesData.set(frag, i);
10687                i += len;
10688            }
10689            if (pesLen) {
10690                // payload size : remove PES header + PES extension
10691                pesLen -= pesHdrLen + 3;
10692            }
10693            return { data: pesData, pts: pesPts, dts: pesDts, len: pesLen };
10694        }
10695        else {
10696            return null;
10697        }
10698    };
10699    TSDemuxer.prototype.pushAccesUnit = function (avcSample, avcTrack) {
10700        if (avcSample.units.length && avcSample.frame) {
10701            var samples = avcTrack.samples;
10702            var nbSamples = samples.length;
10703            // only push AVC sample if starting with a keyframe is not mandatory OR
10704            //    if keyframe already found in this fragment OR
10705            //       keyframe found in last fragment (track.sps) AND
10706            //          samples already appended (we already found a keyframe in this fragment) OR fragment is contiguous
10707            if (!this.config.forceKeyFrameOnDiscontinuity ||
10708                avcSample.key === true ||
10709                (avcTrack.sps && (nbSamples || this.contiguous))) {
10710                avcSample.id = nbSamples;
10711                samples.push(avcSample);
10712            }
10713            else {
10714                // dropped samples, track it
10715                avcTrack.dropped++;
10716            }
10717        }
10718        if (avcSample.debug.length) {
10719            logger_1.logger.log(avcSample.pts + '/' + avcSample.dts + ':' + avcSample.debug);
10720        }
10721    };
10722    TSDemuxer.prototype._parseAVCPES = function (pes, last) {
10723        var _this = this;
10724        // logger.log('parse new PES');
10725        var track = this._avcTrack, units = this._parseAVCNALu(pes.data), debug = false, expGolombDecoder, avcSample = this.avcSample, push, spsfound = false, i, pushAccesUnit = this.pushAccesUnit.bind(this), createAVCSample = function (key, pts, dts, debug) {
10726            return { key: key, pts: pts, dts: dts, units: [], debug: debug };
10727        };
10728        // free pes.data to save up some memory
10729        pes.data = null;
10730        // if new NAL units found and last sample still there, let's push ...
10731        // this helps parsing streams with missing AUD (only do this if AUD never found)
10732        if (avcSample && units.length && !track.audFound) {
10733            pushAccesUnit(avcSample, track);
10734            avcSample = this.avcSample = createAVCSample(false, pes.pts, pes.dts, '');
10735        }
10736        units.forEach(function (unit) {
10737            switch (unit.type) {
10738                // NDR
10739                case 1:
10740                    push = true;
10741                    if (!avcSample) {
10742                        avcSample = _this.avcSample = createAVCSample(true, pes.pts, pes.dts, '');
10743                    }
10744                    if (debug) {
10745                        avcSample.debug += 'NDR ';
10746                    }
10747                    avcSample.frame = true;
10748                    var data = unit.data;
10749                    // only check slice type to detect KF in case SPS found in same packet (any keyframe is preceded by SPS ...)
10750                    if (spsfound && data.length > 4) {
10751                        // retrieve slice type by parsing beginning of NAL unit (follow H264 spec, slice_header definition) to detect keyframe embedded in NDR
10752                        var sliceType = new exp_golomb_1.default(data).readSliceType();
10753                        // 2 : I slice, 4 : SI slice, 7 : I slice, 9: SI slice
10754                        // SI slice : A slice that is coded using intra prediction only and using quantisation of the prediction samples.
10755                        // An SI slice can be coded such that its decoded samples can be constructed identically to an SP slice.
10756                        // I slice: A slice that is not an SI slice that is decoded using intra prediction only.
10757                        // if (sliceType === 2 || sliceType === 7) {
10758                        if (sliceType === 2 || sliceType === 4 || sliceType === 7 || sliceType === 9) {
10759                            avcSample.key = true;
10760                        }
10761                    }
10762                    break;
10763                // IDR
10764                case 5:
10765                    push = true;
10766                    // handle PES not starting with AUD
10767                    if (!avcSample) {
10768                        avcSample = _this.avcSample = createAVCSample(true, pes.pts, pes.dts, '');
10769                    }
10770                    if (debug) {
10771                        avcSample.debug += 'IDR ';
10772                    }
10773                    avcSample.key = true;
10774                    avcSample.frame = true;
10775                    break;
10776                // SEI
10777                case 6:
10778                    push = true;
10779                    if (debug && avcSample) {
10780                        avcSample.debug += 'SEI ';
10781                    }
10782                    expGolombDecoder = new exp_golomb_1.default(_this.discardEPB(unit.data));
10783                    // skip frameType
10784                    expGolombDecoder.readUByte();
10785                    var payloadType = 0;
10786                    var payloadSize = 0;
10787                    var endOfCaptions = false;
10788                    var b = 0;
10789                    while (!endOfCaptions && expGolombDecoder.bytesAvailable > 1) {
10790                        payloadType = 0;
10791                        do {
10792                            b = expGolombDecoder.readUByte();
10793                            payloadType += b;
10794                        } while (b === 0xFF);
10795                        // Parse payload size.
10796                        payloadSize = 0;
10797                        do {
10798                            b = expGolombDecoder.readUByte();
10799                            payloadSize += b;
10800                        } while (b === 0xFF);
10801                        // TODO: there can be more than one payload in an SEI packet...
10802                        // TODO: need to read type and size in a while loop to get them all
10803                        if (payloadType === 4 && expGolombDecoder.bytesAvailable !== 0) {
10804                            endOfCaptions = true;
10805                            var countryCode = expGolombDecoder.readUByte();
10806                            if (countryCode === 181) {
10807                                var providerCode = expGolombDecoder.readUShort();
10808                                if (providerCode === 49) {
10809                                    var userStructure = expGolombDecoder.readUInt();
10810                                    if (userStructure === 0x47413934) {
10811                                        var userDataType = expGolombDecoder.readUByte();
10812                                        // Raw CEA-608 bytes wrapped in CEA-708 packet
10813                                        if (userDataType === 3) {
10814                                            var firstByte = expGolombDecoder.readUByte();
10815                                            var secondByte = expGolombDecoder.readUByte();
10816                                            var totalCCs = 31 & firstByte;
10817                                            var byteArray = [firstByte, secondByte];
10818                                            for (i = 0; i < totalCCs; i++) {
10819                                                // 3 bytes per CC
10820                                                byteArray.push(expGolombDecoder.readUByte());
10821                                                byteArray.push(expGolombDecoder.readUByte());
10822                                                byteArray.push(expGolombDecoder.readUByte());
10823                                            }
10824                                            _this._insertSampleInOrder(_this._txtTrack.samples, { type: 3, pts: pes.pts, bytes: byteArray });
10825                                        }
10826                                    }
10827                                }
10828                            }
10829                        }
10830                        else if (payloadSize < expGolombDecoder.bytesAvailable) {
10831                            for (i = 0; i < payloadSize; i++) {
10832                                expGolombDecoder.readUByte();
10833                            }
10834                        }
10835                    }
10836                    break;
10837                // SPS
10838                case 7:
10839                    push = true;
10840                    spsfound = true;
10841                    if (debug && avcSample) {
10842                        avcSample.debug += 'SPS ';
10843                    }
10844                    if (!track.sps) {
10845                        expGolombDecoder = new exp_golomb_1.default(unit.data);
10846                        var config = expGolombDecoder.readSPS();
10847                        track.width = config.width;
10848                        track.height = config.height;
10849                        track.pixelRatio = config.pixelRatio;
10850                        track.sps = [unit.data];
10851                        track.duration = _this._duration;
10852                        var codecarray = unit.data.subarray(1, 4);
10853                        var codecstring = 'avc1.';
10854                        for (i = 0; i < 3; i++) {
10855                            var h = codecarray[i].toString(16);
10856                            if (h.length < 2) {
10857                                h = '0' + h;
10858                            }
10859                            codecstring += h;
10860                        }
10861                        track.codec = codecstring;
10862                    }
10863                    break;
10864                // PPS
10865                case 8:
10866                    push = true;
10867                    if (debug && avcSample) {
10868                        avcSample.debug += 'PPS ';
10869                    }
10870                    if (!track.pps) {
10871                        track.pps = [unit.data];
10872                    }
10873                    break;
10874                // AUD
10875                case 9:
10876                    push = false;
10877                    track.audFound = true;
10878                    if (avcSample) {
10879                        pushAccesUnit(avcSample, track);
10880                    }
10881                    avcSample = _this.avcSample = createAVCSample(false, pes.pts, pes.dts, debug ? 'AUD ' : '');
10882                    break;
10883                // Filler Data
10884                case 12:
10885                    push = false;
10886                    break;
10887                default:
10888                    push = false;
10889                    if (avcSample) {
10890                        avcSample.debug += 'unknown NAL ' + unit.type + ' ';
10891                    }
10892                    break;
10893            }
10894            if (avcSample && push) {
10895                var units_1 = avcSample.units;
10896                units_1.push(unit);
10897            }
10898        });
10899        // if last PES packet, push samples
10900        if (last && avcSample) {
10901            pushAccesUnit(avcSample, track);
10902            this.avcSample = null;
10903        }
10904    };
10905    TSDemuxer.prototype._insertSampleInOrder = function (arr, data) {
10906        var len = arr.length;
10907        if (len > 0) {
10908            if (data.pts >= arr[len - 1].pts) {
10909                arr.push(data);
10910            }
10911            else {
10912                for (var pos = len - 1; pos >= 0; pos--) {
10913                    if (data.pts < arr[pos].pts) {
10914                        arr.splice(pos, 0, data);
10915                        break;
10916                    }
10917                }
10918            }
10919        }
10920        else {
10921            arr.push(data);
10922        }
10923    };
10924    TSDemuxer.prototype._getLastNalUnit = function () {
10925        var avcSample = this.avcSample, lastUnit;
10926        // try to fallback to previous sample if current one is empty
10927        if (!avcSample || avcSample.units.length === 0) {
10928            var track = this._avcTrack, samples = track.samples;
10929            avcSample = samples[samples.length - 1];
10930        }
10931        if (avcSample) {
10932            var units = avcSample.units;
10933            lastUnit = units[units.length - 1];
10934        }
10935        return lastUnit;
10936    };
10937    TSDemuxer.prototype._parseAVCNALu = function (array) {
10938        var i = 0, len = array.byteLength, value, overflow, track = this._avcTrack, state = track.naluState || 0, lastState = state;
10939        var units = [], unit, unitType, lastUnitStart = -1, lastUnitType;
10940        // logger.log('PES:' + Hex.hexDump(array));
10941        if (state === -1) {
10942            // special use case where we found 3 or 4-byte start codes exactly at the end of previous PES packet
10943            lastUnitStart = 0;
10944            // NALu type is value read from offset 0
10945            lastUnitType = array[0] & 0x1f;
10946            state = 0;
10947            i = 1;
10948        }
10949        while (i < len) {
10950            value = array[i++];
10951            // optimization. state 0 and 1 are the predominant case. let's handle them outside of the switch/case
10952            if (!state) {
10953                state = value ? 0 : 1;
10954                continue;
10955            }
10956            if (state === 1) {
10957                state = value ? 0 : 2;
10958                continue;
10959            }
10960            // here we have state either equal to 2 or 3
10961            if (!value) {
10962                state = 3;
10963            }
10964            else if (value === 1) {
10965                if (lastUnitStart >= 0) {
10966                    unit = { data: array.subarray(lastUnitStart, i - state - 1), type: lastUnitType };
10967                    // logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength);
10968                    units.push(unit);
10969                }
10970                else {
10971                    // lastUnitStart is undefined => this is the first start code found in this PES packet
10972                    // first check if start code delimiter is overlapping between 2 PES packets,
10973                    // ie it started in last packet (lastState not zero)
10974                    // and ended at the beginning of this PES packet (i <= 4 - lastState)
10975                    var lastUnit = this._getLastNalUnit();
10976                    if (lastUnit) {
10977                        if (lastState && (i <= 4 - lastState)) {
10978                            // start delimiter overlapping between PES packets
10979                            // strip start delimiter bytes from the end of last NAL unit
10980                            // check if lastUnit had a state different from zero
10981                            if (lastUnit.state) {
10982                                // strip last bytes
10983                                lastUnit.data = lastUnit.data.subarray(0, lastUnit.data.byteLength - lastState);
10984                            }
10985                        }
10986                        // If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit.
10987                        overflow = i - state - 1;
10988                        if (overflow > 0) {
10989                            // logger.log('first NALU found with overflow:' + overflow);
10990                            var tmp = new Uint8Array(lastUnit.data.byteLength + overflow);
10991                            tmp.set(lastUnit.data, 0);
10992                            tmp.set(array.subarray(0, overflow), lastUnit.data.byteLength);
10993                            lastUnit.data = tmp;
10994                        }
10995                    }
10996                }
10997                // check if we can read unit type
10998                if (i < len) {
10999                    unitType = array[i] & 0x1f;
11000                    // logger.log('find NALU @ offset:' + i + ',type:' + unitType);
11001                    lastUnitStart = i;
11002                    lastUnitType = unitType;
11003                    state = 0;
11004                }
11005                else {
11006                    // not enough byte to read unit type. let's read it on next PES parsing
11007                    state = -1;
11008                }
11009            }
11010            else {
11011                state = 0;
11012            }
11013        }
11014        if (lastUnitStart >= 0 && state >= 0) {
11015            unit = { data: array.subarray(lastUnitStart, len), type: lastUnitType, state: state };
11016            units.push(unit);
11017            // logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);
11018        }
11019        // no NALu found
11020        if (units.length === 0) {
11021            // append pes.data to previous NAL unit
11022            var lastUnit = this._getLastNalUnit();
11023            if (lastUnit) {
11024                var tmp = new Uint8Array(lastUnit.data.byteLength + array.byteLength);
11025                tmp.set(lastUnit.data, 0);
11026                tmp.set(array, lastUnit.data.byteLength);
11027                lastUnit.data = tmp;
11028            }
11029        }
11030        track.naluState = state;
11031        return units;
11032    };
11033    /**
11034     * remove Emulation Prevention bytes from a RBSP
11035     */
11036    TSDemuxer.prototype.discardEPB = function (data) {
11037        var length = data.byteLength, EPBPositions = [], i = 1, newLength, newData;
11038        // Find all `Emulation Prevention Bytes`
11039        while (i < length - 2) {
11040            if (data[i] === 0 &&
11041                data[i + 1] === 0 &&
11042                data[i + 2] === 0x03) {
11043                EPBPositions.push(i + 2);
11044                i += 2;
11045            }
11046            else {
11047                i++;
11048            }
11049        }
11050        // If no Emulation Prevention Bytes were found just return the original
11051        // array
11052        if (EPBPositions.length === 0) {
11053            return data;
11054        }
11055        // Create a new array to hold the NAL unit data
11056        newLength = length - EPBPositions.length;
11057        newData = new Uint8Array(newLength);
11058        var sourceIndex = 0;
11059        for (i = 0; i < newLength; sourceIndex++, i++) {
11060            if (sourceIndex === EPBPositions[0]) {
11061                // Skip this byte
11062                sourceIndex++;
11063                // Remove this position index
11064                EPBPositions.shift();
11065            }
11066            newData[i] = data[sourceIndex];
11067        }
11068        return newData;
11069    };
11070    TSDemuxer.prototype._parseAACPES = function (pes) {
11071        var track = this._audioTrack, data = pes.data, pts = pes.pts, startOffset = 0, aacOverFlow = this.aacOverFlow, aacLastPTS = this.aacLastPTS, frameDuration, frameIndex, offset, stamp, len;
11072        if (aacOverFlow) {
11073            var tmp = new Uint8Array(aacOverFlow.byteLength + data.byteLength);
11074            tmp.set(aacOverFlow, 0);
11075            tmp.set(data, aacOverFlow.byteLength);
11076            // logger.log(`AAC: append overflowing ${aacOverFlow.byteLength} bytes to beginning of new PES`);
11077            data = tmp;
11078        }
11079        // look for ADTS header (0xFFFx)
11080        for (offset = startOffset, len = data.length; offset < len - 1; offset++) {
11081            if (ADTS.isHeader(data, offset)) {
11082                break;
11083            }
11084        }
11085        // if ADTS header does not start straight from the beginning of the PES payload, raise an error
11086        if (offset) {
11087            var reason = void 0, fatal = void 0;
11088            if (offset < len - 1) {
11089                reason = "AAC PES did not start with ADTS header,offset:" + offset;
11090                fatal = false;
11091            }
11092            else {
11093                reason = 'no ADTS header found in AAC PES';
11094                fatal = true;
11095            }
11096            logger_1.logger.warn("parsing error:" + reason);
11097            this.observer.trigger(events_1.default.ERROR, { type: errors_1.ErrorTypes.MEDIA_ERROR, details: errors_1.ErrorDetails.FRAG_PARSING_ERROR, fatal: fatal, reason: reason });
11098            if (fatal) {
11099                return;
11100            }
11101        }
11102        ADTS.initTrackConfig(track, this.observer, data, offset, this.audioCodec);
11103        frameIndex = 0;
11104        frameDuration = ADTS.getFrameDuration(track.samplerate);
11105        // if last AAC frame is overflowing, we should ensure timestamps are contiguous:
11106        // first sample PTS should be equal to last sample PTS + frameDuration
11107        if (aacOverFlow && aacLastPTS) {
11108            var newPTS = aacLastPTS + frameDuration;
11109            if (Math.abs(newPTS - pts) > 1) {
11110                logger_1.logger.log("AAC: align PTS for overlapping frames by " + Math.round((newPTS - pts) / 90));
11111                pts = newPTS;
11112            }
11113        }
11114        // scan for aac samples
11115        while (offset < len) {
11116            if (ADTS.isHeader(data, offset) && (offset + 5) < len) {
11117                var frame = ADTS.appendFrame(track, data, offset, pts, frameIndex);
11118                if (frame) {
11119                    // logger.log(`${Math.round(frame.sample.pts)} : AAC`);
11120                    offset += frame.length;
11121                    stamp = frame.sample.pts;
11122                    frameIndex++;
11123                }
11124                else {
11125                    // logger.log('Unable to parse AAC frame');
11126                    break;
11127                }
11128            }
11129            else {
11130                // nothing found, keep looking
11131                offset++;
11132            }
11133        }
11134        if (offset < len) {
11135            aacOverFlow = data.subarray(offset, len);
11136            // logger.log(`AAC: overflow detected:${len-offset}`);
11137        }
11138        else {
11139            aacOverFlow = null;
11140        }
11141        this.aacOverFlow = aacOverFlow;
11142        this.aacLastPTS = stamp;
11143    };
11144    TSDemuxer.prototype._parseMPEGPES = function (pes) {
11145        var data = pes.data;
11146        var length = data.length;
11147        var frameIndex = 0;
11148        var offset = 0;
11149        var pts = pes.pts;
11150        while (offset < length) {
11151            if (mpegaudio_1.default.isHeader(data, offset)) {
11152                var frame = mpegaudio_1.default.appendFrame(this._audioTrack, data, offset, pts, frameIndex);
11153                if (frame) {
11154                    offset += frame.length;
11155                    frameIndex++;
11156                }
11157                else {
11158                    // logger.log('Unable to parse Mpeg audio frame');
11159                    break;
11160                }
11161            }
11162            else {
11163                // nothing found, keep looking
11164                offset++;
11165            }
11166        }
11167    };
11168    TSDemuxer.prototype._parseID3PES = function (pes) {
11169        this._id3Track.samples.push(pes);
11170    };
11171    return TSDemuxer;
11172}());
11173exports.default = TSDemuxer;
11174
11175
11176/***/ }),
11177
11178/***/ "./src/errors.js":
11179/*!***********************!*\
11180  !*** ./src/errors.js ***!
11181  \***********************/
11182/*! no static exports found */
11183/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
11184/***/ (function(module, exports, __webpack_require__) {
11185
11186"use strict";
11187
11188Object.defineProperty(exports, "__esModule", { value: true });
11189exports.ErrorTypes = {
11190    // Identifier for a network error (loading error / timeout ...)
11191    NETWORK_ERROR: 'networkError',
11192    // Identifier for a media Error (video/parsing/mediasource error)
11193    MEDIA_ERROR: 'mediaError',
11194    // EME (encrypted media extensions) errors
11195    KEY_SYSTEM_ERROR: 'keySystemError',
11196    // Identifier for a mux Error (demuxing/remuxing)
11197    MUX_ERROR: 'muxError',
11198    // Identifier for all other errors
11199    OTHER_ERROR: 'otherError'
11200};
11201/**
11202 * @enum {ErrorDetails}
11203 * @typedef {string} ErrorDetail
11204 */
11205exports.ErrorDetails = {
11206    KEY_SYSTEM_NO_KEYS: 'keySystemNoKeys',
11207    KEY_SYSTEM_NO_ACCESS: 'keySystemNoAccess',
11208    KEY_SYSTEM_NO_SESSION: 'keySystemNoSession',
11209    KEY_SYSTEM_LICENSE_REQUEST_FAILED: 'keySystemLicenseRequestFailed',
11210    // Identifier for a manifest load error - data: { url : faulty URL, response : { code: error code, text: error text }}
11211    MANIFEST_LOAD_ERROR: 'manifestLoadError',
11212    // Identifier for a manifest load timeout - data: { url : faulty URL, response : { code: error code, text: error text }}
11213    MANIFEST_LOAD_TIMEOUT: 'manifestLoadTimeOut',
11214    // Identifier for a manifest parsing error - data: { url : faulty URL, reason : error reason}
11215    MANIFEST_PARSING_ERROR: 'manifestParsingError',
11216    // Identifier for a manifest with only incompatible codecs error - data: { url : faulty URL, reason : error reason}
11217    MANIFEST_INCOMPATIBLE_CODECS_ERROR: 'manifestIncompatibleCodecsError',
11218    // Identifier for a level load error - data: { url : faulty URL, response : { code: error code, text: error text }}
11219    LEVEL_LOAD_ERROR: 'levelLoadError',
11220    // Identifier for a level load timeout - data: { url : faulty URL, response : { code: error code, text: error text }}
11221    LEVEL_LOAD_TIMEOUT: 'levelLoadTimeOut',
11222    // Identifier for a level switch error - data: { level : faulty level Id, event : error description}
11223    LEVEL_SWITCH_ERROR: 'levelSwitchError',
11224    // Identifier for an audio track load error - data: { url : faulty URL, response : { code: error code, text: error text }}
11225    AUDIO_TRACK_LOAD_ERROR: 'audioTrackLoadError',
11226    // Identifier for an audio track load timeout - data: { url : faulty URL, response : { code: error code, text: error text }}
11227    AUDIO_TRACK_LOAD_TIMEOUT: 'audioTrackLoadTimeOut',
11228    // Identifier for fragment load error - data: { frag : fragment object, response : { code: error code, text: error text }}
11229    FRAG_LOAD_ERROR: 'fragLoadError',
11230    // Identifier for fragment load timeout error - data: { frag : fragment object}
11231    FRAG_LOAD_TIMEOUT: 'fragLoadTimeOut',
11232    // Identifier for a fragment decryption error event - data: {id : demuxer Id,frag: fragment object, reason : parsing error description }
11233    FRAG_DECRYPT_ERROR: 'fragDecryptError',
11234    // Identifier for a fragment parsing error event - data: { id : demuxer Id, reason : parsing error description }
11235    // will be renamed DEMUX_PARSING_ERROR and switched to MUX_ERROR in the next major release
11236    FRAG_PARSING_ERROR: 'fragParsingError',
11237    // Identifier for a remux alloc error event - data: { id : demuxer Id, frag : fragment object, bytes : nb of bytes on which allocation failed , reason : error text }
11238    REMUX_ALLOC_ERROR: 'remuxAllocError',
11239    // Identifier for decrypt key load error - data: { frag : fragment object, response : { code: error code, text: error text }}
11240    KEY_LOAD_ERROR: 'keyLoadError',
11241    // Identifier for decrypt key load timeout error - data: { frag : fragment object}
11242    KEY_LOAD_TIMEOUT: 'keyLoadTimeOut',
11243    // Triggered when an exception occurs while adding a sourceBuffer to MediaSource - data : {  err : exception , mimeType : mimeType }
11244    BUFFER_ADD_CODEC_ERROR: 'bufferAddCodecError',
11245    // Identifier for a buffer append error - data: append error description
11246    BUFFER_APPEND_ERROR: 'bufferAppendError',
11247    // Identifier for a buffer appending error event - data: appending error description
11248    BUFFER_APPENDING_ERROR: 'bufferAppendingError',
11249    // Identifier for a buffer stalled error event
11250    BUFFER_STALLED_ERROR: 'bufferStalledError',
11251    // Identifier for a buffer full event
11252    BUFFER_FULL_ERROR: 'bufferFullError',
11253    // Identifier for a buffer seek over hole event
11254    BUFFER_SEEK_OVER_HOLE: 'bufferSeekOverHole',
11255    // Identifier for a buffer nudge on stall (playback is stuck although currentTime is in a buffered area)
11256    BUFFER_NUDGE_ON_STALL: 'bufferNudgeOnStall',
11257    // Identifier for an internal exception happening inside hls.js while handling an event
11258    INTERNAL_EXCEPTION: 'internalException'
11259};
11260
11261
11262/***/ }),
11263
vendor: 3,523 bytes, lines 11264-11355
11264/***/ "./src/event-handler.js":
11265/*!******************************!*\
11266  !*** ./src/event-handler.js ***!
11267  \******************************/
11268/*! no static exports found */
11269/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
11270/***/ (function(module, exports, __webpack_require__) {
11271
11272"use strict";
11273
11274/*
11275*
11276* All objects in the event handling chain should inherit from this class
11277*
11278*/
11279Object.defineProperty(exports, "__esModule", { value: true });
11280var logger_1 = __webpack_require__(/*! ./utils/logger */ "./src/utils/logger.js");
11281var errors_1 = __webpack_require__(/*! ./errors */ "./src/errors.js");
11282var events_1 = __webpack_require__(/*! ./events */ "./src/events.js");
11283var FORBIDDEN_EVENT_NAMES = {
11284    'hlsEventGeneric': true,
11285    'hlsHandlerDestroying': true,
11286    'hlsHandlerDestroyed': true
11287};
11288var EventHandler = /** @class */ (function () {
11289    function EventHandler(hls) {
11290        var events = [];
11291        for (var _i = 1; _i < arguments.length; _i++) {
11292            events[_i - 1] = arguments[_i];
11293        }
11294        this.hls = hls;
11295        this.onEvent = this.onEvent.bind(this);
11296        this.handledEvents = events;
11297        this.useGenericHandler = true;
11298        this.registerListeners();
11299    }
11300    EventHandler.prototype.destroy = function () {
11301        this.onHandlerDestroying();
11302        this.unregisterListeners();
11303        this.onHandlerDestroyed();
11304    };
11305    EventHandler.prototype.onHandlerDestroying = function () { };
11306    EventHandler.prototype.onHandlerDestroyed = function () { };
11307    EventHandler.prototype.isEventHandler = function () {
11308        return typeof this.handledEvents === 'object' && this.handledEvents.length && typeof this.onEvent === 'function';
11309    };
11310    EventHandler.prototype.registerListeners = function () {
11311        if (this.isEventHandler()) {
11312            this.handledEvents.forEach(function (event) {
11313                if (FORBIDDEN_EVENT_NAMES[event]) {
11314                    throw new Error('Forbidden event-name: ' + event);
11315                }
11316                this.hls.on(event, this.onEvent);
11317            }, this);
11318        }
11319    };
11320    EventHandler.prototype.unregisterListeners = function () {
11321        if (this.isEventHandler()) {
11322            this.handledEvents.forEach(function (event) {
11323                this.hls.off(event, this.onEvent);
11324            }, this);
11325        }
11326    };
11327    /**
11328     * arguments: event (string), data (any)
11329     */
11330    EventHandler.prototype.onEvent = function (event, data) {
11331        this.onEventGeneric(event, data);
11332    };
11333    EventHandler.prototype.onEventGeneric = function (event, data) {
11334        var eventToFunction = function (event, data) {
11335            var funcName = 'on' + event.replace('hls', '');
11336            if (typeof this[funcName] !== 'function') {
11337                throw new Error("Event " + event + " has no generic handler in this " + this.constructor.name + " class (tried " + funcName + ")");
11338            }
11339            return this[funcName].bind(this, data);
11340        };
11341        try {
11342            eventToFunction.call(this, event, data).call();
11343        }
11344        catch (err) {
11345            logger_1.logger.error("An internal error happened while handling event " + event + ". Error message: \"" + err.message + "\". Here is a stacktrace:", err);
11346            this.hls.trigger(events_1.default.ERROR, { type: errors_1.ErrorTypes.OTHER_ERROR, details: errors_1.ErrorDetails.INTERNAL_EXCEPTION, fatal: false, event: event, err: err });
11347        }
11348    };
11349    return EventHandler;
11350}());
11351exports.default = EventHandler;
11352
11353
11354/***/ }),
11355
11356/***/ "./src/events.js":
11357/*!***********************!*\
11358  !*** ./src/events.js ***!
11359  \***********************/
11360/*! no static exports found */
11361/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
11362/***/ (function(module, exports, __webpack_require__) {
11363
11364"use strict";
11365
11366Object.defineProperty(exports, "__esModule", { value: true });
11367/**
11368 * @readonly
11369 * @enum {string}
11370 */
11371var HlsEvents = {
11372    // fired before MediaSource is attaching to media element - data: { media }
11373    MEDIA_ATTACHING: 'hlsMediaAttaching',
11374    // fired when MediaSource has been succesfully attached to media element - data: { }
11375    MEDIA_ATTACHED: 'hlsMediaAttached',
11376    // fired before detaching MediaSource from media element - data: { }
11377    MEDIA_DETACHING: 'hlsMediaDetaching',
11378    // fired when MediaSource has been detached from media element - data: { }
11379    MEDIA_DETACHED: 'hlsMediaDetached',
11380    // fired when we buffer is going to be reset - data: { }
11381    BUFFER_RESET: 'hlsBufferReset',
11382    // fired when we know about the codecs that we need buffers for to push into - data: {tracks : { container, codec, levelCodec, initSegment, metadata }}
11383    BUFFER_CODECS: 'hlsBufferCodecs',
11384    // fired when sourcebuffers have been created - data: { tracks : tracks }
11385    BUFFER_CREATED: 'hlsBufferCreated',
11386    // fired when we append a segment to the buffer - data: { segment: segment object }
11387    BUFFER_APPENDING: 'hlsBufferAppending',
11388    // fired when we are done with appending a media segment to the buffer - data : { parent : segment parent that triggered BUFFER_APPENDING, pending : nb of segments waiting for appending for this segment parent}
11389    BUFFER_APPENDED: 'hlsBufferAppended',
11390    // fired when the stream is finished and we want to notify the media buffer that there will be no more data - data: { }
11391    BUFFER_EOS: 'hlsBufferEos',
11392    // fired when the media buffer should be flushed - data { startOffset, endOffset }
11393    BUFFER_FLUSHING: 'hlsBufferFlushing',
11394    // fired when the media buffer has been flushed - data: { }
11395    BUFFER_FLUSHED: 'hlsBufferFlushed',
11396    // fired to signal that a manifest loading starts - data: { url : manifestURL}
11397    MANIFEST_LOADING: 'hlsManifestLoading',
11398    // fired after manifest has been loaded - data: { levels : [available quality levels], audioTracks : [ available audio tracks], url : manifestURL, stats : { trequest, tfirst, tload, mtime}}
11399    MANIFEST_LOADED: 'hlsManifestLoaded',
11400    // fired after manifest has been parsed - data: { levels : [available quality levels], firstLevel : index of first quality level appearing in Manifest}
11401    MANIFEST_PARSED: 'hlsManifestParsed',
11402    // fired when a level switch is requested - data: { level : id of new level }
11403    LEVEL_SWITCHING: 'hlsLevelSwitching',
11404    // fired when a level switch is effective - data: { level : id of new level }
11405    LEVEL_SWITCHED: 'hlsLevelSwitched',
11406    // fired when a level playlist loading starts - data: { url : level URL, level : id of level being loaded}
11407    LEVEL_LOADING: 'hlsLevelLoading',
11408    // fired when a level playlist loading finishes - data: { details : levelDetails object, level : id of loaded level, stats : { trequest, tfirst, tload, mtime} }
11409    LEVEL_LOADED: 'hlsLevelLoaded',
11410    // fired when a level's details have been updated based on previous details, after it has been loaded - data: { details : levelDetails object, level : id of updated level }
11411    LEVEL_UPDATED: 'hlsLevelUpdated',
11412    // fired when a level's PTS information has been updated after parsing a fragment - data: { details : levelDetails object, level : id of updated level, drift: PTS drift observed when parsing last fragment }
11413    LEVEL_PTS_UPDATED: 'hlsLevelPtsUpdated',
11414    // fired to notify that audio track lists has been updated - data: { audioTracks : audioTracks }
11415    AUDIO_TRACKS_UPDATED: 'hlsAudioTracksUpdated',
11416    // fired when an audio track switching is requested - data: { id : audio track id }
11417    AUDIO_TRACK_SWITCHING: 'hlsAudioTrackSwitching',
11418    // fired when an audio track switch actually occurs - data: { id : audio track id }
11419    AUDIO_TRACK_SWITCHED: 'hlsAudioTrackSwitched',
11420    // fired when an audio track loading starts - data: { url : audio track URL, id : audio track id }
11421    AUDIO_TRACK_LOADING: 'hlsAudioTrackLoading',
11422    // fired when an audio track loading finishes - data: { details : levelDetails object, id : audio track id, stats : { trequest, tfirst, tload, mtime } }
11423    AUDIO_TRACK_LOADED: 'hlsAudioTrackLoaded',
11424    // fired to notify that subtitle track lists has been updated - data: { subtitleTracks : subtitleTracks }
11425    SUBTITLE_TRACKS_UPDATED: 'hlsSubtitleTracksUpdated',
11426    // fired when an subtitle track switch occurs - data: { id : subtitle track id }
11427    SUBTITLE_TRACK_SWITCH: 'hlsSubtitleTrackSwitch',
11428    // fired when a subtitle track loading starts - data: { url : subtitle track URL, id : subtitle track id }
11429    SUBTITLE_TRACK_LOADING: 'hlsSubtitleTrackLoading',
11430    // fired when a subtitle track loading finishes - data: { details : levelDetails object, id : subtitle track id, stats : { trequest, tfirst, tload, mtime } }
11431    SUBTITLE_TRACK_LOADED: 'hlsSubtitleTrackLoaded',
11432    // fired when a subtitle fragment has been processed - data: { success : boolean, frag : the processed frag }
11433    SUBTITLE_FRAG_PROCESSED: 'hlsSubtitleFragProcessed',
11434    // fired when the first timestamp is found - data: { id : demuxer id, initPTS: initPTS, frag : fragment object }
11435    INIT_PTS_FOUND: 'hlsInitPtsFound',
11436    // fired when a fragment loading starts - data: { frag : fragment object }
11437    FRAG_LOADING: 'hlsFragLoading',
11438    // fired when a fragment loading is progressing - data: { frag : fragment object, { trequest, tfirst, loaded } }
11439    FRAG_LOAD_PROGRESS: 'hlsFragLoadProgress',
11440    // Identifier for fragment load aborting for emergency switch down - data: { frag : fragment object }
11441    FRAG_LOAD_EMERGENCY_ABORTED: 'hlsFragLoadEmergencyAborted',
11442    // fired when a fragment loading is completed - data: { frag : fragment object, payload : fragment payload, stats : { trequest, tfirst, tload, length } }
11443    FRAG_LOADED: 'hlsFragLoaded',
11444    // fired when a fragment has finished decrypting - data: { id : demuxer id, frag: fragment object, payload : fragment payload, stats : { tstart, tdecrypt } }
11445    FRAG_DECRYPTED: 'hlsFragDecrypted',
11446    // fired when Init Segment has been extracted from fragment - data: { id : demuxer id, frag: fragment object, moov : moov MP4 box, codecs : codecs found while parsing fragment }
11447    FRAG_PARSING_INIT_SEGMENT: 'hlsFragParsingInitSegment',
11448    // fired when parsing sei text is completed - data: { id : demuxer id, frag: fragment object, samples : [ sei samples pes ] }
11449    FRAG_PARSING_USERDATA: 'hlsFragParsingUserdata',
11450    // fired when parsing id3 is completed - data: { id : demuxer id, frag: fragment object, samples : [ id3 samples pes ] }
11451    FRAG_PARSING_METADATA: 'hlsFragParsingMetadata',
11452    // fired when data have been extracted from fragment - data: { id : demuxer id, frag: fragment object, data1 : moof MP4 box or TS fragments, data2 : mdat MP4 box or null}
11453    FRAG_PARSING_DATA: 'hlsFragParsingData',
11454    // fired when fragment parsing is completed - data: { id : demuxer id, frag: fragment object }
11455    FRAG_PARSED: 'hlsFragParsed',
11456    // fired when fragment remuxed MP4 boxes have all been appended into SourceBuffer - data: { id : demuxer id, frag : fragment object, stats : { trequest, tfirst, tload, tparsed, tbuffered, length, bwEstimate } }
11457    FRAG_BUFFERED: 'hlsFragBuffered',
11458    // fired when fragment matching with current media position is changing - data : { id : demuxer id, frag : fragment object }
11459    FRAG_CHANGED: 'hlsFragChanged',
11460    // Identifier for a FPS drop event - data: { curentDropped, currentDecoded, totalDroppedFrames }
11461    FPS_DROP: 'hlsFpsDrop',
11462    // triggered when FPS drop triggers auto level capping - data: { level, droppedlevel }
11463    FPS_DROP_LEVEL_CAPPING: 'hlsFpsDropLevelCapping',
11464    // Identifier for an error event - data: { type : error type, details : error details, fatal : if true, hls.js cannot/will not try to recover, if false, hls.js will try to recover,other error specific data }
11465    ERROR: 'hlsError',
11466    // fired when hls.js instance starts destroying. Different from MEDIA_DETACHED as one could want to detach and reattach a media to the instance of hls.js to handle mid-rolls for example - data: { }
11467    DESTROYING: 'hlsDestroying',
11468    // fired when a decrypt key loading starts - data: { frag : fragment object }
11469    KEY_LOADING: 'hlsKeyLoading',
11470    // fired when a decrypt key loading is completed - data: { frag : fragment object, payload : key payload, stats : { trequest, tfirst, tload, length } }
11471    KEY_LOADED: 'hlsKeyLoaded',
11472    // fired upon stream controller state transitions - data: { previousState, nextState }
11473    STREAM_STATE_TRANSITION: 'hlsStreamStateTransition'
11474};
11475exports.default = HlsEvents;
11476
11477
11478/***/ }),
11479
11480/***/ "./src/hls.js":
11481/*!********************!*\
11482  !*** ./src/hls.js ***!
11483  \********************/
11484/*! no static exports found */
11485/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
11486/***/ (function(module, exports, __webpack_require__) {
11487
11488"use strict";
11489
11490var __extends = (this && this.__extends) || (function () {
11491    var extendStatics = Object.setPrototypeOf ||
11492        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
11493        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
11494    return function (d, b) {
11495        extendStatics(d, b);
11496        function __() { this.constructor = d; }
11497        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
11498    };
11499})();
11500Object.defineProperty(exports, "__esModule", { value: true });
11501var URLToolkit = __webpack_require__(/*! url-toolkit */ "./node_modules/url-toolkit/src/url-toolkit.js");
11502var errors_1 = __webpack_require__(/*! ./errors */ "./src/errors.js");
11503var playlist_loader_1 = __webpack_require__(/*! ./loader/playlist-loader */ "./src/loader/playlist-loader.js");
11504var fragment_loader_1 = __webpack_require__(/*! ./loader/fragment-loader */ "./src/loader/fragment-loader.js");
11505var key_loader_1 = __webpack_require__(/*! ./loader/key-loader */ "./src/loader/key-loader.js");
11506var fragment_tracker_1 = __webpack_require__(/*! ./controller/fragment-tracker */ "./src/controller/fragment-tracker.js");
11507var stream_controller_1 = __webpack_require__(/*! ./controller/stream-controller */ "./src/controller/stream-controller.js");
11508var level_controller_1 = __webpack_require__(/*! ./controller/level-controller */ "./src/controller/level-controller.js");
11509var id3_track_controller_1 = __webpack_require__(/*! ./controller/id3-track-controller */ "./src/controller/id3-track-controller.js");
11510var is_supported_1 = __webpack_require__(/*! ./is-supported */ "./src/is-supported.js");
11511var logger_1 = __webpack_require__(/*! ./utils/logger */ "./src/utils/logger.js");
11512var config_1 = __webpack_require__(/*! ./config */ "./src/config.js");
11513var events_1 = __webpack_require__(/*! ./events */ "./src/events.js");
11514var observer_1 = __webpack_require__(/*! ./observer */ "./src/observer.js");
11515/**
11516 * @module Hls
11517 * @class
11518 * @constructor
11519 */
11520var Hls = /** @class */ (function (_super) {
11521    __extends(Hls, _super);
11522    /**
11523     * Creates an instance of an HLS client that can attach to exactly one `HTMLMediaElement`.
11524     *
11525     * @constructs Hls
11526     * @param {HlsConfig} config
11527     */
11528    function Hls(config) {
11529        if (config === void 0) { config = {}; }
11530        var _this = _super.call(this) || this;
11531        var defaultConfig = Hls.DefaultConfig;
11532        if ((config.liveSyncDurationCount || config.liveMaxLatencyDurationCount) && (config.liveSyncDuration || config.liveMaxLatencyDuration)) {
11533            throw new Error('Illegal hls.js config: don\'t mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration');
11534        }
11535        for (var prop in defaultConfig) {
11536            if (prop in config)
11537                continue;
11538            config[prop] = defaultConfig[prop];
11539        }
11540        if (config.liveMaxLatencyDurationCount !== undefined && config.liveMaxLatencyDurationCount <= config.liveSyncDurationCount) {
11541            throw new Error('Illegal hls.js config: "liveMaxLatencyDurationCount" must be gt "liveSyncDurationCount"');
11542        }
11543        if (config.liveMaxLatencyDuration !== undefined && (config.liveMaxLatencyDuration <= config.liveSyncDuration || config.liveSyncDuration === undefined)) {
11544            throw new Error('Illegal hls.js config: "liveMaxLatencyDuration" must be gt "liveSyncDuration"');
11545        }
11546        logger_1.enableLogs(config.debug);
11547        _this.config = config;
11548        _this._autoLevelCapping = -1;
11549        // core controllers and network loaders
11550        /**
11551         * @member {AbrController} abrController
11552         */
11553        var abrController = _this.abrController = new config.abrController(_this);
11554        var bufferController = new config.bufferController(_this);
11555        var capLevelController = new config.capLevelController(_this);
11556        var fpsController = new config.fpsController(_this);
11557        var playListLoader = new playlist_loader_1.default(_this);
11558        var fragmentLoader = new fragment_loader_1.default(_this);
11559        var keyLoader = new key_loader_1.default(_this);
11560        var id3TrackController = new id3_track_controller_1.default(_this);
11561        // network controllers
11562        /**
11563         * @member {LevelController} levelController
11564         */
11565        var levelController = _this.levelController = new level_controller_1.default(_this);
11566        // FIXME: FragmentTracker must be defined before StreamController because the order of event handling is important
11567        var fragmentTracker = new fragment_tracker_1.FragmentTracker(_this);
11568        /**
11569         * @member {StreamController} streamController
11570         */
11571        var streamController = _this.streamController = new stream_controller_1.default(_this, fragmentTracker);
11572        var networkControllers = [levelController, streamController];
11573        // optional audio stream controller
11574        /**
11575         * @var {ICoreComponent | Controller}
11576         */
11577        var Controller = config.audioStreamController;
11578        if (Controller) {
11579            networkControllers.push(new Controller(_this, fragmentTracker));
11580        }
11581        /**
11582         * @member {INetworkController[]} networkControllers
11583         */
11584        _this.networkControllers = networkControllers;
11585        /**
11586         * @var {ICoreComponent[]}
11587         */
11588        var coreComponents = [
11589            playListLoader,
11590            fragmentLoader,
11591            keyLoader,
11592            abrController,
11593            bufferController,
11594            capLevelController,
11595            fpsController,
11596            id3TrackController,
11597            fragmentTracker
11598        ];
11599        // optional audio track and subtitle controller
11600        Controller = config.audioTrackController;
11601        if (Controller) {
11602            var audioTrackController = new Controller(_this);
11603            /**
11604             * @member {AudioTrackController} audioTrackController
11605             */
11606            _this.audioTrackController = audioTrackController;
11607            coreComponents.push(audioTrackController);
11608        }
11609        Controller = config.subtitleTrackController;
11610        if (Controller) {
11611            var subtitleTrackController = new Controller(_this);
11612            /**
11613             * @member {SubtitleTrackController} subtitleTrackController
11614             */
11615            _this.subtitleTrackController = subtitleTrackController;
11616            networkControllers.push(subtitleTrackController);
11617        }
11618        Controller = config.emeController;
11619        if (Controller) {
11620            var emeController = new Controller(_this);
11621            /**
11622             * @member {EMEController} emeController
11623             */
11624            _this.emeController = emeController;
11625            coreComponents.push(emeController);
11626        }
11627        // optional subtitle controllers
11628        Controller = config.subtitleStreamController;
11629        if (Controller) {
11630            networkControllers.push(new Controller(_this, fragmentTracker));
11631        }
11632        Controller = config.timelineController;
11633        if (Controller) {
11634            coreComponents.push(new Controller(_this));
11635        }
11636        /**
11637         * @member {ICoreComponent[]}
11638         */
11639        _this.coreComponents = coreComponents;
11640        return _this;
11641    }
11642    Object.defineProperty(Hls, "version", {
11643        /**
11644         * @type {string}
11645         */
11646        get: function () {
11647            return "0.12.4";
11648        },
11649        enumerable: true,
11650        configurable: true
11651    });
11652    /**
11653     * @type {boolean}
11654     */
11655    Hls.isSupported = function () {
11656        return is_supported_1.isSupported();
11657    };
11658    Object.defineProperty(Hls, "Events", {
11659        /**
11660         * @type {HlsEvents}
11661         */
11662        get: function () {
11663            return events_1.default;
11664        },
11665        enumerable: true,
11666        configurable: true
11667    });
11668    Object.defineProperty(Hls, "ErrorTypes", {
11669        /**
11670         * @type {HlsErrorTypes}
11671         */
11672        get: function () {
11673            return errors_1.ErrorTypes;
11674        },
11675        enumerable: true,
11676        configurable: true
11677    });
11678    Object.defineProperty(Hls, "ErrorDetails", {
11679        /**
11680         * @type {HlsErrorDetails}
11681         */
11682        get: function () {
11683            return errors_1.ErrorDetails;
11684        },
11685        enumerable: true,
11686        configurable: true
11687    });
11688    Object.defineProperty(Hls, "DefaultConfig", {
11689        /**
11690         * @type {HlsConfig}
11691         */
11692        get: function () {
11693            if (!Hls.defaultConfig) {
11694                return config_1.hlsDefaultConfig;
11695            }
11696            return Hls.defaultConfig;
11697        },
11698        /**
11699         * @type {HlsConfig}
11700         */
11701        set: function (defaultConfig) {
11702            Hls.defaultConfig = defaultConfig;
11703        },
11704        enumerable: true,
11705        configurable: true
11706    });
11707    /**
11708     * Dispose of the instance
11709     */
11710    Hls.prototype.destroy = function () {
11711        logger_1.logger.log('destroy');
11712        this.trigger(events_1.default.DESTROYING);
11713        this.detachMedia();
11714        this.coreComponents.concat(this.networkControllers).forEach(function (component) {
11715            component.destroy();
11716        });
11717        this.url = null;
11718        this.removeAllListeners();
11719        this._autoLevelCapping = -1;
11720    };
11721    /**
11722     * Attach a media element
11723     * @param {HTMLMediaElement} media
11724     */
11725    Hls.prototype.attachMedia = function (media) {
11726        logger_1.logger.log('attachMedia');
11727        this.media = media;
11728        this.trigger(events_1.default.MEDIA_ATTACHING, { media: media });
11729    };
11730    /**
11731     * Detach from the media
11732     */
11733    Hls.prototype.detachMedia = function () {
11734        logger_1.logger.log('detachMedia');
11735        this.trigger(events_1.default.MEDIA_DETACHING);
11736        this.media = null;
11737    };
11738    /**
11739     * Set the source URL. Can be relative or absolute.
11740     * @param {string} url
11741     */
11742    Hls.prototype.loadSource = function (url) {
11743        url = URLToolkit.buildAbsoluteURL(window.location.href, url, { alwaysNormalize: true });
11744        logger_1.logger.log("loadSource:" + url);
11745        this.url = url;
11746        // when attaching to a source URL, trigger a playlist load
11747        this.trigger(events_1.default.MANIFEST_LOADING, { url: url });
11748    };
11749    /**
11750     * Start loading data from the stream source.
11751     * Depending on default config, client starts loading automatically when a source is set.
11752     *
11753     * @param {number} startPosition Set the start position to stream from
11754     * @default -1 None (from earliest point)
11755     */
11756    Hls.prototype.startLoad = function (startPosition) {
11757        if (startPosition === void 0) { startPosition = -1; }
11758        logger_1.logger.log("startLoad(" + startPosition + ")");
11759        this.networkControllers.forEach(function (controller) {
11760            controller.startLoad(startPosition);
11761        });
11762    };
11763    /**
11764     * Stop loading of any stream data.
11765     */
11766    Hls.prototype.stopLoad = function () {
11767        logger_1.logger.log('stopLoad');
11768        this.networkControllers.forEach(function (controller) {
11769            controller.stopLoad();
11770        });
11771    };
11772    /**
11773     * Swap through possible audio codecs in the stream (for example to switch from stereo to 5.1)
11774     */
11775    Hls.prototype.swapAudioCodec = function () {
11776        logger_1.logger.log('swapAudioCodec');
11777        this.streamController.swapAudioCodec();
11778    };
11779    /**
11780     * When the media-element fails, this allows to detach and then re-attach it
11781     * as one call (convenience method).
11782     *
11783     * Automatic recovery of media-errors by this process is configurable.
11784     */
11785    Hls.prototype.recoverMediaError = function () {
11786        logger_1.logger.log('recoverMediaError');
11787        var media = this.media;
11788        this.detachMedia();
11789        this.attachMedia(media);
11790    };
11791    Object.defineProperty(Hls.prototype, "levels", {
11792        /**
11793         * @type {QualityLevel[]}
11794         */
11795        get: function () {
11796            return this.levelController.levels;
11797        },
11798        enumerable: true,
11799        configurable: true
11800    });
11801    Object.defineProperty(Hls.prototype, "currentLevel", {
11802        /**
11803         * Index of quality level currently played
11804         * @type {number}
11805         */
11806        get: function () {
11807            return this.streamController.currentLevel;
11808        },
11809        /**
11810         * Set quality level index immediately .
11811         * This will flush the current buffer to replace the quality asap.
11812         * That means playback will interrupt at least shortly to re-buffer and re-sync eventually.
11813         * @type {number} -1 for automatic level selection
11814         */
11815        set: function (newLevel) {
11816            logger_1.logger.log("set currentLevel:" + newLevel);
11817            this.loadLevel = newLevel;
11818            this.streamController.immediateLevelSwitch();
11819        },
11820        enumerable: true,
11821        configurable: true
11822    });
11823    Object.defineProperty(Hls.prototype, "nextLevel", {
11824        /**
11825         * Index of next quality level loaded as scheduled by stream controller.
11826         * @type {number}
11827         */
11828        get: function () {
11829            return this.streamController.nextLevel;
11830        },
11831        /**
11832         * Set quality level index for next loaded data.
11833         * This will switch the video quality asap, without interrupting playback.
11834         * May abort current loading of data, and flush parts of buffer (outside currently played fragment region).
11835         * @type {number} -1 for automatic level selection
11836         */
11837        set: function (newLevel) {
11838            logger_1.logger.log("set nextLevel:" + newLevel);
11839            this.levelController.manualLevel = newLevel;
11840            this.streamController.nextLevelSwitch();
11841        },
11842        enumerable: true,
11843        configurable: true
11844    });
11845    Object.defineProperty(Hls.prototype, "loadLevel", {
11846        /**
11847         * Return the quality level of the currently or last (of none is loaded currently) segment
11848         * @type {number}
11849         */
11850        get: function () {
11851            return this.levelController.level;
11852        },
11853        /**
11854         * Set quality level index for next loaded data in a conservative way.
11855         * This will switch the quality without flushing, but interrupt current loading.
11856         * Thus the moment when the quality switch will appear in effect will only be after the already existing buffer.
11857         * @type {number} newLevel -1 for automatic level selection
11858         */
11859        set: function (newLevel) {
11860            logger_1.logger.log("set loadLevel:" + newLevel);
11861            this.levelController.manualLevel = newLevel;
11862        },
11863        enumerable: true,
11864        configurable: true
11865    });
11866    Object.defineProperty(Hls.prototype, "nextLoadLevel", {
11867        /**
11868         * get next quality level loaded
11869         * @type {number}
11870         */
11871        get: function () {
11872            return this.levelController.nextLoadLevel;
11873        },
11874        /**
11875         * Set quality level of next loaded segment in a fully "non-destructive" way.
11876         * Same as `loadLevel` but will wait for next switch (until current loading is done).
11877         * @type {number} level
11878         */
11879        set: function (level) {
11880            this.levelController.nextLoadLevel = level;
11881        },
11882        enumerable: true,
11883        configurable: true
11884    });
11885    Object.defineProperty(Hls.prototype, "firstLevel", {
11886        /**
11887         * Return "first level": like a default level, if not set,
11888         * falls back to index of first level referenced in manifest
11889         * @type {number}
11890         */
11891        get: function () {
11892            return Math.max(this.levelController.firstLevel, this.minAutoLevel);
11893        },
11894        /**
11895         * Sets "first-level", see getter.
11896         * @type {number}
11897         */
11898        set: function (newLevel) {
11899            logger_1.logger.log("set firstLevel:" + newLevel);
11900            this.levelController.firstLevel = newLevel;
11901        },
11902        enumerable: true,
11903        configurable: true
11904    });
11905    Object.defineProperty(Hls.prototype, "startLevel", {
11906        /**
11907         * Return start level (level of first fragment that will be played back)
11908         * if not overrided by user, first level appearing in manifest will be used as start level
11909         * if -1 : automatic start level selection, playback will start from level matching download bandwidth
11910         * (determined from download of first segment)
11911         * @type {number}
11912         */
11913        get: function () {
11914            return this.levelController.startLevel;
11915        },
11916        /**
11917         * set  start level (level of first fragment that will be played back)
11918         * if not overrided by user, first level appearing in manifest will be used as start level
11919         * if -1 : automatic start level selection, playback will start from level matching download bandwidth
11920         * (determined from download of first segment)
11921         * @type {number} newLevel
11922         */
11923        set: function (newLevel) {
11924            logger_1.logger.log("set startLevel:" + newLevel);
11925            var hls = this;
11926            // if not in automatic start level detection, ensure startLevel is greater than minAutoLevel
11927            if (newLevel !== -1) {
11928                newLevel = Math.max(newLevel, hls.minAutoLevel);
11929            }
11930            hls.levelController.startLevel = newLevel;
11931        },
11932        enumerable: true,
11933        configurable: true
11934    });
11935    Object.defineProperty(Hls.prototype, "autoLevelCapping", {
11936        /**
11937         * Capping/max level value that should be used by automatic level selection algorithm (`ABRController`)
11938         * @type {number}
11939         */
11940        get: function () {
11941            return this._autoLevelCapping;
11942        },
11943        /**
11944         * Capping/max level value that should be used by automatic level selection algorithm (`ABRController`)
11945         * @type {number}
11946         */
11947        set: function (newLevel) {
11948            logger_1.logger.log("set autoLevelCapping:" + newLevel);
11949            this._autoLevelCapping = newLevel;
11950        },
11951        enumerable: true,
11952        configurable: true
11953    });
11954    Object.defineProperty(Hls.prototype, "autoLevelEnabled", {
11955        /**
11956         * True when automatic level selection enabled
11957         * @type {boolean}
11958         */
11959        get: function () {
11960            return (this.levelController.manualLevel === -1);
11961        },
11962        enumerable: true,
11963        configurable: true
11964    });
11965    Object.defineProperty(Hls.prototype, "manualLevel", {
11966        /**
11967         * Level set manually (if any)
11968         * @type {number}
11969         */
11970        get: function () {
11971            return this.levelController.manualLevel;
11972        },
11973        enumerable: true,
11974        configurable: true
11975    });
11976    Object.defineProperty(Hls.prototype, "minAutoLevel", {
11977        /**
11978         * min level selectable in auto mode according to config.minAutoBitrate
11979         * @type {number}
11980         */
11981        get: function () {
11982            var hls = this, levels = hls.levels, minAutoBitrate = hls.config.minAutoBitrate, len = levels ? levels.length : 0;
11983            for (var i = 0; i < len; i++) {
11984                var levelNextBitrate = levels[i].realBitrate ? Math.max(levels[i].realBitrate, levels[i].bitrate) : levels[i].bitrate;
11985                if (levelNextBitrate > minAutoBitrate) {
11986                    return i;
11987                }
11988            }
11989            return 0;
11990        },
11991        enumerable: true,
11992        configurable: true
11993    });
11994    Object.defineProperty(Hls.prototype, "maxAutoLevel", {
11995        /**
11996         * max level selectable in auto mode according to autoLevelCapping
11997         * @type {number}
11998         */
11999        get: function () {
12000            var hls = this;
12001            var levels = hls.levels;
12002            var autoLevelCapping = hls.autoLevelCapping;
12003            var maxAutoLevel;
12004            if (autoLevelCapping === -1 && levels && levels.length) {
12005                maxAutoLevel = levels.length - 1;
12006            }
12007            else {
12008                maxAutoLevel = autoLevelCapping;
12009            }
12010            return maxAutoLevel;
12011        },
12012        enumerable: true,
12013        configurable: true
12014    });
12015    Object.defineProperty(Hls.prototype, "nextAutoLevel", {
12016        /**
12017         * next automatically selected quality level
12018         * @type {number}
12019         */
12020        get: function () {
12021            var hls = this;
12022            // ensure next auto level is between  min and max auto level
12023            return Math.min(Math.max(hls.abrController.nextAutoLevel, hls.minAutoLevel), hls.maxAutoLevel);
12024        },
12025        /**
12026         * this setter is used to force next auto level.
12027         * this is useful to force a switch down in auto mode:
12028         * in case of load error on level N, hls.js can set nextAutoLevel to N-1 for example)
12029         * forced value is valid for one fragment. upon succesful frag loading at forced level,
12030         * this value will be resetted to -1 by ABR controller.
12031         * @type {number}
12032         */
12033        set: function (nextLevel) {
12034            var hls = this;
12035            hls.abrController.nextAutoLevel = Math.max(hls.minAutoLevel, nextLevel);
12036        },
12037        enumerable: true,
12038        configurable: true
12039    });
12040    Object.defineProperty(Hls.prototype, "audioTracks", {
12041        /**
12042         * @type {AudioTrack[]}
12043         */
12044        get: function () {
12045            var audioTrackController = this.audioTrackController;
12046            return audioTrackController ? audioTrackController.audioTracks : [];
12047        },
12048        enumerable: true,
12049        configurable: true
12050    });
12051    Object.defineProperty(Hls.prototype, "audioTrack", {
12052        /**
12053         * index of the selected audio track (index in audio track lists)
12054         * @type {number}
12055         */
12056        get: function () {
12057            var audioTrackController = this.audioTrackController;
12058            return audioTrackController ? audioTrackController.audioTrack : -1;
12059        },
12060        /**
12061         * selects an audio track, based on its index in audio track lists
12062         * @type {number}
12063         */
12064        set: function (audioTrackId) {
12065            var audioTrackController = this.audioTrackController;
12066            if (audioTrackController) {
12067                audioTrackController.audioTrack = audioTrackId;
12068            }
12069        },
12070        enumerable: true,
12071        configurable: true
12072    });
12073    Object.defineProperty(Hls.prototype, "liveSyncPosition", {
12074        /**
12075         * @type {Seconds}
12076         */
12077        get: function () {
12078            return this.streamController.liveSyncPosition;
12079        },
12080        enumerable: true,
12081        configurable: true
12082    });
12083    Object.defineProperty(Hls.prototype, "subtitleTracks", {
12084        /**
12085         * get alternate subtitle tracks list from playlist
12086         * @type {SubtitleTrack[]}
12087         */
12088        get: function () {
12089            var subtitleTrackController = this.subtitleTrackController;
12090            return subtitleTrackController ? subtitleTrackController.subtitleTracks : [];
12091        },
12092        enumerable: true,
12093        configurable: true
12094    });
12095    Object.defineProperty(Hls.prototype, "subtitleTrack", {
12096        /**
12097         * index of the selected subtitle track (index in subtitle track lists)
12098         * @type {number}
12099         */
12100        get: function () {
12101            var subtitleTrackController = this.subtitleTrackController;
12102            return subtitleTrackController ? subtitleTrackController.subtitleTrack : -1;
12103        },
12104        /**
12105         * select an subtitle track, based on its index in subtitle track lists
12106         * @type{number}
12107         */
12108        set: function (subtitleTrackId) {
12109            var subtitleTrackController = this.subtitleTrackController;
12110            if (subtitleTrackController) {
12111                subtitleTrackController.subtitleTrack = subtitleTrackId;
12112            }
12113        },
12114        enumerable: true,
12115        configurable: true
12116    });
12117    Object.defineProperty(Hls.prototype, "subtitleDisplay", {
12118        /**
12119         * @type {boolean}
12120         */
12121        get: function () {
12122            var subtitleTrackController = this.subtitleTrackController;
12123            return subtitleTrackController ? subtitleTrackController.subtitleDisplay : false;
12124        },
12125        /**
12126         * Enable/disable subtitle display rendering
12127         * @type {boolean}
12128         */
12129        set: function (value) {
12130            var subtitleTrackController = this.subtitleTrackController;
12131            if (subtitleTrackController) {
12132                subtitleTrackController.subtitleDisplay = value;
12133            }
12134        },
12135        enumerable: true,
12136        configurable: true
12137    });
12138    return Hls;
12139}(observer_1.Observer));
12140exports.default = Hls;
12141
12142
12143/***/ }),
12144
12145/***/ "./src/is-supported.js":
12146/*!*****************************!*\
12147  !*** ./src/is-supported.js ***!
12148  \*****************************/
12149/*! no static exports found */
12150/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
12151/***/ (function(module, exports, __webpack_require__) {
12152
12153"use strict";
12154
12155Object.defineProperty(exports, "__esModule", { value: true });
12156var mediasource_helper_1 = __webpack_require__(/*! ./utils/mediasource-helper */ "./src/utils/mediasource-helper.js");
12157function isSupported() {
12158    var mediaSource = mediasource_helper_1.getMediaSource();
12159    var sourceBuffer = window.SourceBuffer || window.WebKitSourceBuffer;
12160    var isTypeSupported = mediaSource &&
12161        typeof mediaSource.isTypeSupported === 'function' &&
12162        mediaSource.isTypeSupported('video/mp4; codecs="avc1.42E01E,mp4a.40.2"');
12163    // if SourceBuffer is exposed ensure its API is valid
12164    // safari and old version of Chrome doe not expose SourceBuffer globally so checking SourceBuffer.prototype is impossible
12165    var sourceBufferValidAPI = !sourceBuffer ||
12166        (sourceBuffer.prototype &&
12167            typeof sourceBuffer.prototype.appendBuffer === 'function' &&
12168            typeof sourceBuffer.prototype.remove === 'function');
12169    return !!isTypeSupported && !!sourceBufferValidAPI;
12170}
12171exports.isSupported = isSupported;
12172
12173
12174/***/ }),
12175
12176/***/ "./src/loader/fragment-loader.js":
12177/*!***************************************!*\
12178  !*** ./src/loader/fragment-loader.js ***!
12179  \***************************************/
12180/*! no static exports found */
12181/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
12182/***/ (function(module, exports, __webpack_require__) {
12183
12184"use strict";
12185/* WEBPACK VAR INJECTION */(function(Number) {
12186/*
12187 * Fragment Loader
12188*/
12189var __extends = (this && this.__extends) || (function () {
12190    var extendStatics = Object.setPrototypeOf ||
12191        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
12192        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
12193    return function (d, b) {
12194        extendStatics(d, b);
12195        function __() { this.constructor = d; }
12196        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
12197    };
12198})();
12199Object.defineProperty(exports, "__esModule", { value: true });
12200var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
12201var event_handler_1 = __webpack_require__(/*! ../event-handler */ "./src/event-handler.js");
12202var errors_1 = __webpack_require__(/*! ../errors */ "./src/errors.js");
12203var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
12204var FragmentLoader = /** @class */ (function (_super) {
12205    __extends(FragmentLoader, _super);
12206    function FragmentLoader(hls) {
12207        var _this = _super.call(this, hls, events_1.default.FRAG_LOADING) || this;
12208        _this.loaders = {};
12209        return _this;
12210    }
12211    FragmentLoader.prototype.destroy = function () {
12212        var loaders = this.loaders;
12213        for (var loaderName in loaders) {
12214            var loader = loaders[loaderName];
12215            if (loader) {
12216                loader.destroy();
12217            }
12218        }
12219        this.loaders = {};
12220        _super.prototype.destroy.call(this);
12221    };
12222    FragmentLoader.prototype.onFragLoading = function (data) {
12223        var frag = data.frag, type = frag.type, loaders = this.loaders, config = this.hls.config, FragmentILoader = config.fLoader, DefaultILoader = config.loader;
12224        // reset fragment state
12225        frag.loaded = 0;
12226        var loader = loaders[type];
12227        if (loader) {
12228            logger_1.logger.warn("abort previous fragment loader for type: " + type);
12229            loader.abort();
12230        }
12231        loader = loaders[type] = frag.loader =
12232            config.fLoader ? new FragmentILoader(config) : new DefaultILoader(config);
12233        var loaderContext, loaderConfig, loaderCallbacks;
12234        loaderContext = { url: frag.url, frag: frag, responseType: 'arraybuffer', progressData: false };
12235        var start = frag.byteRangeStartOffset, end = frag.byteRangeEndOffset;
12236        if (Number.isFinite(start) && Number.isFinite(end)) {
12237            loaderContext.rangeStart = start;
12238            loaderContext.rangeEnd = end;
12239        }
12240        loaderConfig = {
12241            timeout: config.fragLoadingTimeOut,
12242            maxRetry: 0,
12243            retryDelay: 0,
12244            maxRetryDelay: config.fragLoadingMaxRetryTimeout
12245        };
12246        loaderCallbacks = {
12247            onSuccess: this.loadsuccess.bind(this),
12248            onError: this.loaderror.bind(this),
12249            onTimeout: this.loadtimeout.bind(this),
12250            onProgress: this.loadprogress.bind(this)
12251        };
12252        loader.load(loaderContext, loaderConfig, loaderCallbacks);
12253    };
12254    FragmentLoader.prototype.loadsuccess = function (response, stats, context, networkDetails) {
12255        if (networkDetails === void 0) { networkDetails = null; }
12256        var payload = response.data, frag = context.frag;
12257        // detach fragment loader on load success
12258        frag.loader = undefined;
12259        this.loaders[frag.type] = undefined;
12260        this.hls.trigger(events_1.default.FRAG_LOADED, { payload: payload, frag: frag, stats: stats, networkDetails: networkDetails });
12261    };
12262    FragmentLoader.prototype.loaderror = function (response, context, networkDetails) {
12263        if (networkDetails === void 0) { networkDetails = null; }
12264        var frag = context.frag;
12265        var loader = frag.loader;
12266        if (loader) {
12267            loader.abort();
12268        }
12269        this.loaders[frag.type] = undefined;
12270        this.hls.trigger(events_1.default.ERROR, { type: errors_1.ErrorTypes.NETWORK_E
12270RROR, details: errors_1.ErrorDetails.FRAG_LOAD_ERROR, fatal: false, frag: context.frag, response: response, networkDetails: networkDetails });
12271    };
12272    FragmentLoader.prototype.loadtimeout = function (stats, context, networkDetails) {
12273        if (networkDetails === void 0) { networkDetails = null; }
12274        var frag = context.frag;
12275        var loader = frag.loader;
12276        if (loader) {
12277            loader.abort();
12278        }
12279        this.loaders[frag.type] = undefined;
12280        this.hls.trigger(events_1.default.ERROR, { type: errors_1.ErrorTypes.NETWORK_ERROR, details: errors_1.ErrorDetails.FRAG_LOAD_TIMEOUT, fatal: false, frag: context.frag, networkDetails: networkDetails });
12281    };
12282    // data will be used for progressive parsing
12283    FragmentLoader.prototype.loadprogress = function (stats, context, data, networkDetails) {
12284        if (networkDetails === void 0) { networkDetails = null; }
12285        var frag = context.frag;
12286        frag.loaded = stats.loaded;
12287        this.hls.trigger(events_1.default.FRAG_LOAD_PROGRESS, { frag: frag, stats: stats, networkDetails: networkDetails });
12288    };
12289    return FragmentLoader;
12290}(event_handler_1.default));
12291exports.default = FragmentLoader;
12292
12293/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.js")["Number"]))
12294
12295/***/ }),
12296
12297/***/ "./src/loader/fragment.js":
12298/*!********************************!*\
12299  !*** ./src/loader/fragment.js ***!
12300  \********************************/
12301/*! no static exports found */
12302/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
12303/***/ (function(module, exports, __webpack_require__) {
12304
12305"use strict";
12306/* WEBPACK VAR INJECTION */(function(Number) {
12307Object.defineProperty(exports, "__esModule", { value: true });
12308var URLToolkit = __webpack_require__(/*! url-toolkit */ "./node_modules/url-toolkit/src/url-toolkit.js");
12309var level_key_1 = __webpack_require__(/*! ./level-key */ "./src/loader/level-key.js");
12310var Fragment = /** @class */ (function () {
12311    function Fragment() {
12312        var _a;
12313        this._url = null;
12314        this._byteRange = null;
12315        this._decryptdata = null;
12316        this.tagList = [];
12317        this.programDateTime = null;
12318        this.rawProgramDateTime = null;
12319        // Holds the types of data this fragment supports
12320        this._elementaryStreams = (_a = {},
12321            _a[Fragment.ElementaryStreamTypes.AUDIO] = false,
12322            _a[Fragment.ElementaryStreamTypes.VIDEO] = false,
12323            _a);
12324    }
12325    Object.defineProperty(Fragment, "ElementaryStreamTypes", {
12326        /**
12327         * `type` property for this._elementaryStreams
12328         *
12329         * @enum
12330         */
12331        get: function () {
12332            return {
12333                AUDIO: 'audio',
12334                VIDEO: 'video'
12335            };
12336        },
12337        enumerable: true,
12338        configurable: true
12339    });
12340    Object.defineProperty(Fragment.prototype, "url", {
12341        get: function () {
12342            if (!this._url && this.relurl) {
12343                this._url = URLToolkit.buildAbsoluteURL(this.baseurl, this.relurl, { alwaysNormalize: true });
12344            }
12345            return this._url;
12346        },
12347        set: function (value) {
12348            this._url = value;
12349        },
12350        enumerable: true,
12351        configurable: true
12352    });
12353    Object.defineProperty(Fragment.prototype, "byteRange", {
12354        get: function () {
12355            if (!this._byteRange && !this.rawByteRange) {
12356                return [];
12357            }
12358            if (this._byteRange) {
12359                return this._byteRange;
12360            }
12361            var byteRange = [];
12362            if (this.rawByteRange) {
12363                var params = this.rawByteRange.split('@', 2);
12364                if (params.length === 1) {
12365                    var lastByteRangeEndOffset = this.lastByteRangeEndOffset;
12366                    byteRange[0] = lastByteRangeEndOffset || 0;
12367                }
12368                else {
12369                    byteRange[0] = parseInt(params[1]);
12370                }
12371                byteRange[1] = parseInt(params[0]) + byteRange[0];
12372                this._byteRange = byteRange;
12373            }
12374            return byteRange;
12375        },
12376        enumerable: true,
12377        configurable: true
12378    });
12379    Object.defineProperty(Fragment.prototype, "byteRangeStartOffset", {
12380        /**
12381         * @type {number}
12382         */
12383        get: function () {
12384            return this.byteRange[0];
12385        },
12386        enumerable: true,
12387        configurable: true
12388    });
12389    Object.defineProperty(Fragment.prototype, "byteRangeEndOffset", {
12390        get: function () {
12391            return this.byteRange[1];
12392        },
12393        enumerable: true,
12394        configurable: true
12395    });
12396    Object.defineProperty(Fragment.prototype, "decryptdata", {
12397        get: function () {
12398            if (!this._decryptdata) {
12399                this._decryptdata = this.fragmentDecryptdataFromLevelkey(this.levelkey, this.sn);
12400            }
12401            return this._decryptdata;
12402        },
12403        enumerable: true,
12404        configurable: true
12405    });
12406    Object.defineProperty(Fragment.prototype, "endProgramDateTime", {
12407        get: function () {
12408            if (!Number.isFinite(this.programDateTime)) {
12409                return null;
12410            }
12411            var duration = !Number.isFinite(this.duration) ? 0 : this.duration;
12412            return this.programDateTime + (duration * 1000);
12413        },
12414        enumerable: true,
12415        configurable: true
12416    });
12417    Object.defineProperty(Fragment.prototype, "encrypted", {
12418        get: function () {
12419            return !!((this.decryptdata && this.decryptdata.uri !== null) && (this.decryptdata.key === null));
12420        },
12421        enumerable: true,
12422        configurable: true
12423    });
12424    /**
12425     * @param {ElementaryStreamType} type
12426     */
12427    Fragment.prototype.addElementaryStream = function (type) {
12428        this._elementaryStreams[type] = true;
12429    };
12430    /**
12431     * @param {ElementaryStreamType} type
12432     */
12433    Fragment.prototype.hasElementaryStream = function (type) {
12434        return this._elementaryStreams[type] === true;
12435    };
12436    /**
12437     * Utility method for parseLevelPlaylist to create an initialization vector for a given segment
12438     * @returns {Uint8Array}
12439     */
12440    Fragment.prototype.createInitializationVector = function (segmentNumber) {
12441        var uint8View = new Uint8Array(16);
12442        for (var i = 12; i < 16; i++) {
12443            uint8View[i] = (segmentNumber >> 8 * (15 - i)) & 0xff;
12444        }
12445        return uint8View;
12446    };
12447    /**
12448     * Utility method for parseLevelPlaylist to get a fragment's decryption data from the currently parsed encryption key data
12449     * @param levelkey - a playlist's encryption info
12450     * @param segmentNumber - the fragment's segment number
12451     * @returns {*} - an object to be applied as a fragment's decryptdata
12452     */
12453    Fragment.prototype.fragmentDecryptdataFromLevelkey = function (levelkey, segmentNumber) {
12454        var decryptdata = levelkey;
12455        if (levelkey && levelkey.method && levelkey.uri && !levelkey.iv) {
12456            decryptdata = new level_key_1.default();
12457            decryptdata.method = levelkey.method;
12458            decryptdata.baseuri = levelkey.baseuri;
12459            decryptdata.reluri = levelkey.reluri;
12460            decryptdata.iv = this.createInitializationVector(segmentNumber);
12461        }
12462        return decryptdata;
12463    };
12464    return Fragment;
12465}());
12466exports.default = Fragment;
12467
12468/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.js")["Number"]))
12469
12470/***/ }),
12471
12472/***/ "./src/loader/key-loader.js":
12473/*!**********************************!*\
12474  !*** ./src/loader/key-loader.js ***!
12475  \**********************************/
12476/*! no static exports found */
12477/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
12478/***/ (function(module, exports, __webpack_require__) {
12479
12480"use strict";
12481
12482/*
12483 * Decrypt key Loader
12484*/
12485var __extends = (this && this.__extends) || (function () {
12486    var extendStatics = Object.setPrototypeOf ||
12487        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
12488        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
12489    return function (d, b) {
12490        extendStatics(d, b);
12491        function __() { this.constructor = d; }
12492        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
12493    };
12494})();
12495Object.defineProperty(exports, "__esModule", { value: true });
12496var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
12497var event_handler_1 = __webpack_require__(/*! ../event-handler */ "./src/event-handler.js");
12498var errors_1 = __webpack_require__(/*! ../errors */ "./src/errors.js");
12499var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
12500var KeyLoader = /** @class */ (function (_super) {
12501    __extends(KeyLoader, _super);
12502    function KeyLoader(hls) {
12503        var _this = _super.call(this, hls, events_1.default.KEY_LOADING) || this;
12504        _this.loaders = {};
12505        _this.decryptkey = null;
12506        _this.decrypturl = null;
12507        return _this;
12508    }
12509    KeyLoader.prototype.destroy = function () {
12510        for (var loaderName in this.loaders) {
12511            var loader = this.loaders[loaderName];
12512            if (loader) {
12513                loader.destroy();
12514            }
12515        }
12516        this.loaders = {};
12517        event_handler_1.default.prototype.destroy.call(this);
12518    };
12519    KeyLoader.prototype.onKeyLoading = function (data) {
12520        var frag = data.frag, type = frag.type, loader = this.loaders[type], decryptdata = frag.decryptdata, uri = decryptdata.uri;
12521        // if uri is different from previous one or if decrypt key not retrieved yet
12522        if (uri !== this.decrypturl || this.decryptkey === null) {
12523            var config = this.hls.config;
12524            if (loader) {
12525                logger_1.logger.warn("abort previous key loader for type:" + type);
12526                loader.abort();
12527            }
12528            frag.loader = this.loaders[type] = new config.loader(config);
12529            this.decrypturl = uri;
12530            this.decryptkey = null;
12531            var loaderContext = void 0, loaderConfig = void 0, loaderCallbacks = void 0;
12532            loaderContext = { url: uri, frag: frag, responseType: 'arraybuffer' };
12533            // maxRetry is 0 so that instead of retrying the same key on the same variant multiple times,
12534            // key-loader will trigger an error and rely on stream-controller to handle retry logic.
12535            // this will also align retry logic with fragment-loader
12536            loaderConfig = { timeout: config.fragLoadingTimeOut, maxRetry: 0, retryDelay: config.fragLoadingRetryDelay, maxRetryDelay: config.fragLoadingMaxRetryTimeout };
12537            loaderCallbacks = { onSuccess: this.loadsuccess.bind(this), onError: this.loaderror.bind(this), onTimeout: this.loadtimeout.bind(this) };
12538            frag.loader.load(loaderContext, loaderConfig, loaderCallbacks);
12539        }
12540        else if (this.decryptkey) {
12541            // we already loaded this key, return it
12542            decryptdata.key = this.decryptkey;
12543            this.hls.trigger(events_1.default.KEY_LOADED, { frag: frag });
12544        }
12545    };
12546    KeyLoader.prototype.loadsuccess = function (response, stats, context) {
12547        var frag = context.frag;
12548        this.decryptkey = frag.decryptdata.key = new Uint8Array(response.data);
12549        // detach fragment loader on load success
12550        frag.loader = undefined;
12551        this.loaders[frag.type] = undefined;
12552        this.hls.trigger(events_1.default.KEY_LOADED, { frag: frag });
12553    };
12554    KeyLoader.prototype.loaderror = function (response, context) {
12555        var frag = context.frag, loader = frag.loader;
12556        if (loader) {
12557            loader.abort();
12558        }
12559        this.loaders[context.type] = undefined;
12560        this.hls.trigger(events_1.default.ERROR, { type: errors_1.ErrorTypes.NETWORK_E
12560RROR, details: errors_1.ErrorDetails.KEY_LOAD_ERROR, fatal: false, frag: frag, response: response });
12561    };
12562    KeyLoader.prototype.loadtimeout = function (stats, context) {
12563        var frag = context.frag, loader = frag.loader;
12564        if (loader) {
12565            loader.abort();
12566        }
12567        this.loaders[context.type] = undefined;
12568        this.hls.trigger(events_1.default.ERROR, { type: errors_1.ErrorTypes.NETWORK_ERROR, details: errors_1.ErrorDetails.KEY_LOAD_TIMEOUT, fatal: false, frag: frag });
12569    };
12570    return KeyLoader;
12571}(event_handler_1.default));
12572exports.default = KeyLoader;
12573
12574
12575/***/ }),
12576
12577/***/ "./src/loader/level-key.js":
12578/*!*********************************!*\
12579  !*** ./src/loader/level-key.js ***!
12580  \*********************************/
12581/*! no static exports found */
12582/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
12583/***/ (function(module, exports, __webpack_require__) {
12584
12585"use strict";
12586
12587Object.defineProperty(exports, "__esModule", { value: true });
12588var URLToolkit = __webpack_require__(/*! url-toolkit */ "./node_modules/url-toolkit/src/url-toolkit.js");
12589var LevelKey = /** @class */ (function () {
12590    function LevelKey() {
12591        this.method = null;
12592        this.key = null;
12593        this.iv = null;
12594        this._uri = null;
12595    }
12596    Object.defineProperty(LevelKey.prototype, "uri", {
12597        get: function () {
12598            if (!this._uri && this.reluri) {
12599                this._uri = URLToolkit.buildAbsoluteURL(this.baseuri, this.reluri, { alwaysNormalize: true });
12600            }
12601            return this._uri;
12602        },
12603        enumerable: true,
12604        configurable: true
12605    });
12606    return LevelKey;
12607}());
12608exports.default = LevelKey;
12609
12610
12611/***/ }),
12612
12613/***/ "./src/loader/level.js":
12614/*!*****************************!*\
12615  !*** ./src/loader/level.js ***!
12616  \*****************************/
12617/*! no static exports found */
12618/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
12619/***/ (function(module, exports, __webpack_require__) {
12620
12621"use strict";
12622/* WEBPACK VAR INJECTION */(function(Number) {
12623Object.defineProperty(exports, "__esModule", { value: true });
12624var Level = /** @class */ (function () {
12625    function Level(baseUrl) {
12626        // Please keep properties in alphabetical order
12627        this.endCC = 0;
12628        this.endSN = 0;
12629        this.fragments = [];
12630        this.initSegment = null;
12631        this.live = true;
12632        this.needSidxRanges = false;
12633        this.startCC = 0;
12634        this.startSN = 0;
12635        this.startTimeOffset = null;
12636        this.targetduration = 0;
12637        this.totalduration = 0;
12638        this.type = null;
12639        this.url = baseUrl;
12640        this.version = null;
12641    }
12642    Object.defineProperty(Level.prototype, "hasProgramDateTime", {
12643        get: function () {
12644            return !!(this.fragments[0] && Number.isFinite(this.fragments[0].programDateTime));
12645        },
12646        enumerable: true,
12647        configurable: true
12648    });
12649    return Level;
12650}());
12651exports.default = Level;
12652
12653/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.js")["Number"]))
12654
12655/***/ }),
12656
vendor: 10,329 bytes, lines 12657-12878
12657/***/ "./src/loader/m3u8-parser.js":
12658/*!***********************************!*\
12659  !*** ./src/loader/m3u8-parser.js ***!
12660  \***********************************/
12661/*! no static exports found */
12662/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
12663/***/ (function(module, exports, __webpack_require__) {
12664
12665"use strict";
12666/* WEBPACK VAR INJECTION */(function(Number) {
12667Object.defineProperty(exports, "__esModule", { value: true });
12668var URLToolkit = __webpack_require__(/*! url-toolkit */ "./node_modules/url-toolkit/src/url-toolkit.js");
12669var fragment_1 = __webpack_require__(/*! ./fragment */ "./src/loader/fragment.js");
12670var level_1 = __webpack_require__(/*! ./level */ "./src/loader/level.js");
12671var level_key_1 = __webpack_require__(/*! ./level-key */ "./src/loader/level-key.js");
12672var attr_list_1 = __webpack_require__(/*! ../utils/attr-list */ "./src/utils/attr-list.js");
12673var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
12674var codecs_1 = __webpack_require__(/*! ../utils/codecs */ "./src/utils/codecs.js");
12675/**
12676 * M3U8 parser
12677 * @module
12678 */
12679// https://regex101.com is your friend
12680var MASTER_PLAYLIST_REGEX = /#EXT-X-STREAM-INF:([^\n\r]*)[\r\n]+([^\r\n]+)/g;
12681var MASTER_PLAYLIST_MEDIA_REGEX = /#EXT-X-MEDIA:(.*)/g;
12682var LEVEL_PLAYLIST_REGEX_FAST = new RegExp([
12683    /#EXTINF:\s*(\d*(?:\.\d+)?)(?:,(.*)\s+)?/.source,
12684    /|(?!#)([\S+ ?]+)/.source,
12685    /|#EXT-X-BYTERANGE:*(.+)/.source,
12686    /|#EXT-X-PROGRAM-DATE-TIME:(.+)/.source,
12687    /|#.*/.source // All other non-segment oriented tags will match with all groups empty
12688].join(''), 'g');
12689var LEVEL_PLAYLIST_REGEX_SLOW = /(?:(?:#(EXTM3U))|(?:#EXT-X-(PLAYLIST-TYPE):(.+))|(?:#EXT-X-(MEDIA-SEQUENCE): *(\d+))|(?:#EXT-X-(TARGETDURATION): *(\d+))|(?:#EXT-X-(KEY):(.+))|(?:#EXT-X-(START):(.+))|(?:#EXT-X-(ENDLIST))|(?:#EXT-X-(DISCONTINUITY-SEQ)UENCE:(\d+))|(?:#EXT-X-(DIS)CONTINUITY))|(?:#EXT-X-(VERSION):(\d+))|(?:#EXT-X-(MAP):(.+))|(?:(#)([^:]*):(.*))|(?:(#)(.*))(?:.*)\r?\n?/;
12690var MP4_REGEX_SUFFIX = /\.(mp4|m4s|m4v|m4a)$/i;
12691var M3U8Parser = /** @class */ (function () {
12692    function M3U8Parser() {
12693    }
12694    M3U8Parser.findGroup = function (groups, mediaGroupId) {
12695        if (!groups) {
12696            return null;
12697        }
12698        var matchingGroup = null;
12699        for (var i = 0; i < groups.length; i++) {
12700            var group = groups[i];
12701            if (group.id === mediaGroupId) {
12702                matchingGroup = group;
12703            }
12704        }
12705        return matchingGroup;
12706    };
12707    M3U8Parser.convertAVC1ToAVCOTI = function (codec) {
12708        var result, avcdata = codec.split('.');
12709        if (avcdata.length > 2) {
12710            result = avcdata.shift() + '.';
12711            result += parseInt(avcdata.shift()).toString(16);
12712            result += ('000' + parseInt(avcdata.shift()).toString(16)).substr(-4);
12713        }
12714        else {
12715            result = codec;
12716        }
12717        return result;
12718    };
12719    M3U8Parser.resolve = function (url, baseUrl) {
12720        return URLToolkit.buildAbsoluteURL(baseUrl, url, { alwaysNormalize: true });
12721    };
12722    M3U8Parser.parseMasterPlaylist = function (string, baseurl) {
12723        var levels = [], result;
12724        MASTER_PLAYLIST_REGEX.lastIndex = 0;
12725        function setCodecs(codecs, level) {
12726            ['video', 'audio'].forEach(function (type) {
12727                var filtered = codecs.filter(function (codec) { return codecs_1.isCodecType(codec, type); });
12728                if (filtered.length) {
12729                    var preferred = filtered.filter(function (codec) {
12730                        return codec.lastIndexOf('avc1', 0) === 0 || codec.lastIndexOf('mp4a', 0) === 0;
12731                    });
12732                    level[type + "Codec"] = preferred.length > 0 ? preferred[0] : filtered[0];
12733                    // remove from list
12734                    codecs = codecs.filter(function (codec) { return filtered.indexOf(codec) === -1; });
12735                }
12736            });
12737            level.unknownCodecs = codecs;
12738        }
12739        while ((result = MASTER_PLAYLIST_REGEX.exec(string)) != null) {
12740            var level = {};
12741            var attrs = level.attrs = new attr_list_1.default(result[1]);
12742            level.url = M3U8Parser.resolve(result[2], baseurl);
12743            var resolution = attrs.decimalResolution('RESOLUTION');
12744            if (resolution) {
12745                level.width = resolution.width;
12746                level.height = resolution.height;
12747            }
12748            level.bitrate = attrs.decimalInteger('AVERAGE-BANDWIDTH') || attrs.decimalInteger('BANDWIDTH');
12749            level.name = attrs.NAME;
12750            setCodecs([].concat((attrs.CODECS || '').split(/[ ,]+/)), level);
12751            if (level.videoCodec && level.videoCodec.indexOf('avc1') !== -1) {
12752                level.videoCodec = M3U8Parser.convertAVC1ToAVCOTI(level.videoCodec);
12753            }
12754            levels.push(level);
12755        }
12756        return levels;
12757    };
12758    M3U8Parser.parseMasterPlaylistMedia = function (string, baseurl, type, audioGroups) {
12759        if (audioGroups === void 0) { audioGroups = []; }
12760        var result;
12761        var medias = [];
12762        var id = 0;
12763        MASTER_PLAYLIST_MEDIA_REGEX.lastIndex = 0;
12764        while ((result = MASTER_PLAYLIST_MEDIA_REGEX.exec(string)) !== null) {
12765            var media = {};
12766            var attrs = new attr_list_1.default(result[1]);
12767            if (attrs.TYPE === type) {
12768                media.groupId = attrs['GROUP-ID'];
12769                media.name = attrs.NAME;
12770                media.type = type;
12771                media.default = (attrs.DEFAULT === 'YES');
12772                media.autoselect = (attrs.AUTOSELECT === 'YES');
12773                media.forced = (attrs.FORCED === 'YES');
12774                if (attrs.URI) {
12775                    media.url = M3U8Parser.resolve(attrs.URI, baseurl);
12776                }
12777                media.lang = attrs.LANGUAGE;
12778                if (!media.name) {
12779                    media.name = media.lang;
12780                }
12781                if (audioGroups.length) {
12782                    var groupCodec = M3U8Parser.findGroup(audioGroups, media.groupId);
12783                    media.audioCodec = groupCodec ? groupCodec.codec : audioGroups[0].codec;
12784                }
12785                media.id = id++;
12786                medias.push(media);
12787            }
12788        }
12789        return medias;
12790    };
12791    M3U8Parser.parseLevelPlaylist = function (string, baseurl, id, type, levelUrlId) {
12792        var currentSN = 0;
12793        var totalduration = 0;
12794        var level = new level_1.default(baseurl);
12795        var levelkey = new level_key_1.default();
12796        var cc = 0;
12797        var prevFrag = null;
12798        var frag = new fragment_1.default();
12799        var result;
12800        var i;
12801        var firstPdtIndex = null;
12802        LEVEL_PLAYLIST_REGEX_FAST.lastIndex = 0;
12803        while ((result = LEVEL_PLAYLIST_REGEX_FAST.exec(string)) !== null) {
12804            var duration = result[1];
12805            if (duration) { // INF
12806                frag.duration = parseFloat(duration);
12807                // avoid sliced strings    https://github.com/video-dev/hls.js/issues/939
12808                var title = (' ' + result[2]).slice(1);
12809                frag.title = title || null;
12810                frag.tagList.push(title ? ['INF', duration, title] : ['INF', duration]);
12811            }
12812            else if (result[3]) { // url
12813                if (Number.isFinite(frag.duration)) {
12814                    var sn = currentSN++;
12815                    frag.type = type;
12816                    frag.start = totalduration;
12817                    frag.levelkey = levelkey;
12818                    frag.sn = sn;
12819                    frag.level = id;
12820                    frag.cc = cc;
12821                    frag.urlId = levelUrlId;
12822                    frag.baseurl = baseurl;
12823                    // avoid sliced strings    https://github.com/video-dev/hls.js/issues/939
12824                    frag.relurl = (' ' + result[3]).slice(1);
12825                    assignProgramDateTime(frag, prevFrag);
12826                    level.fragments.push(frag);
12827                    prevFrag = frag;
12828                    totalduration += frag.duration;
12829                    frag = new fragment_1.default();
12830                }
12831            }
12832            else if (result[4]) { // X-BYTERANGE
12833                frag.rawByteRange = (' ' + result[4]).slice(1);
12834                if (prevFrag) {
12835                    var lastByteRangeEndOffset = prevFrag.byteRangeEndOffset;
12836                    if (lastByteRangeEndOffset) {
12837                        frag.lastByteRangeEndOffset = lastByteRangeEndOffset;
12838                    }
12839                }
12840            }
12841            else if (result[5]) { // PROGRAM-DATE-TIME
12842                // avoid sliced strings    https://github.com/video-dev/hls.js/issues/939
12843                frag.rawProgramDateTime = (' ' + result[5]).slice(1);
12844                frag.tagList.push(['PROGRAM-DATE-TIME', frag.rawProgramDateTime]);
12845                if (firstPdtIndex === null) {
12846                    firstPdtIndex = level.fragments.length;
12847                }
12848            }
12849            else {
12850                result = result[0].match(LEVEL_PLAYLIST_REGEX_SLOW);
12851                for (i = 1; i < result.length; i++) {
12852                    if (result[i] !== undefined) {
12853                        break;
12854                    }
12855                }
12856                // avoid sliced strings    https://github.com/video-dev/hls.js/issues/939
12857                var value1 = (' ' + result[i + 1]).slice(1);
12858                var value2 = (' ' + result[i + 2]).slice(1);
12859                switch (result[i]) {
12860                    case '#':
12861                        frag.tagList.push(value2 ? [value1, value2] : [value1]);
12862                        break;
12863                    case 'PLAYLIST-TYPE':
12864                        level.type = value1.toUpperCase();
12865                        break;
12866                    case 'MEDIA-SEQUENCE':
12867                        currentSN = level.startSN = parseInt(value1);
12868                        break;
12869                    case 'TARGETDURATION':
12870                        level.targetduration = parseFloat(value1);
12871                        break;
12872                    case 'VERSION':
12873                        level.version = parseInt(value1);
12874                        break;
12875                    case 'EXTM3U':
12876                        break;
12877                    case 'ENDLIST':
12878                        level.live = false;
12879                        break;
12880                    case 'DIS':
12881                        cc++;
12882                        frag.tagList.push(['DIS']);
12883                        break;
12884                    case 'DISCONTINUITY-SEQ':
12885                        cc = parseInt(value1);
12886                        break;
12887                    case 'KEY':
12888                        // https://tools.ietf.org/html/draft-pantos-http-live-streaming-08#section-3.4.4
12889                        var decryptparams = value1;
12890                        var keyAttrs = new attr_list_1.default(decryptparams);
12891                        var decryptmethod = keyAttrs.enumeratedString('METHOD'), decrypturi = keyAttrs.URI, decryptiv = keyAttrs.hexadecimalInteger('IV');
12892                        if (decryptmethod) {
12893                            levelkey = new level_key_1.default();
12894                            if ((decrypturi) && (['AES-128', 'SAMPLE-AES', 'SAMPLE-AES-CENC'].indexOf(decryptmethod) >= 0)) {
12895                                levelkey.method = decryptmethod;
12896                                // URI to get the key
12897                                levelkey.baseuri = baseurl;
12898                                levelkey.reluri = decrypturi;
12899                                levelkey.key = null;
12900                                // Initialization Vector (IV)
12901                                levelkey.iv = decryptiv;
12902                            }
12903                        }
12904                        break;
12905                    case 'START':
12906                        var startParams = value1;
12907                        var startAttrs = new attr_list_1.default(startParams);
12908                        var startTimeOffset = startAttrs.decimalFloatingPoint('TIME-OFFSET');
12909                        // TIME-OFFSET can be 0
12910                        if (Number.isFinite(startTimeOffset)) {
12911                            level.startTimeOffset = startTimeOffset;
12912                        }
12913                        break;
12914                    case 'MAP':
12915                        var mapAttrs = new attr_list_1.default(value1);
12916                        frag.relurl = mapAttrs.URI;
12917                        frag.rawByteRange = mapAttrs.BYTERANGE;
12918                        frag.baseurl = baseurl;
12919                        frag.level = id;
12920                        frag.type = type;
12921                        frag.sn = 'initSegment';
12922                        level.initSegment = frag;
12923                        frag = new fragment_1.default();
12924                        frag.rawProgramDateTime = level.initSegment.rawProgramDateTime;
12925                        break;
12926                    default:
12927                        logger_1.logger.warn("line parsed but not handled: " + result);
12928                        break;
12929                }
12930            }
12931        }
12932        frag = prevFrag;
12933        // logger.log('found ' + level.fragments.length + ' fragments');
12934        if (frag && !frag.relurl) {
12935            level.fragments.pop();
12936            totalduration -= frag.duration;
12937        }
12938        level.totalduration = totalduration;
12939        level.averagetargetduration = totalduration / level.fragments.length;
12940        level.endSN = currentSN - 1;
12941        level.startCC = level.fragments[0] ? level.fragments[0].cc : 0;
12942        level.endCC = cc;
12943        if (!level.initSegment && level.fragments.length) {
12944            // this is a bit lurky but HLS really has no other way to tell us
12945            // if the fragments are TS or MP4, except if we download them :/
12946            // but this is to be able to handle SIDX.
12947            if (level.fragments.every(function (frag) { return MP4_REGEX_SUFFIX.test(frag.relurl); })) {
12948                logger_1.logger.warn('MP4 fragments found but no init segment (probably no MAP, incomplete M3U8), trying to fetch SIDX');
12949                frag = new fragment_1.default();
12950                frag.relurl = level.fragments[0].relurl;
12951                frag.baseurl = baseurl;
12952                frag.level = id;
12953                frag.type = type;
12954                frag.sn = 'initSegment';
12955                level.initSegment = frag;
12956                level.needSidxRanges = true;
12957            }
12958        }
12959        /**
12960         * Backfill any missing PDT values
12961           "If the first EXT-X-PROGRAM-DATE-TIME tag in a Playlist appears after
12962           one or more Media Segment URIs, the client SHOULD extrapolate
12963           backward from that tag (using EXTINF durations and/or media
12964           timestamps) to associate dates with those segments."
12965         * We have already extrapolated forward, but all fragments up to the first instance of PDT do not have their PDTs
12966         * computed.
12967         */
12968        if (firstPdtIndex) {
12969            backfillProgramDateTimes(level.fragments, firstPdtIndex);
12970        }
12971        return level;
12972    };
12973    return M3U8Parser;
12974}());
12975exports.default = M3U8Parser;
12976function backfillProgramDateTimes(fragments, startIndex) {
12977    var fragPrev = fragments[startIndex];
12978    for (var i = startIndex - 1; i >= 0; i--) {
12979        var frag = fragments[i];
12980        frag.programDateTime = fragPrev.programDateTime - (frag.duration * 1000);
12981        fragPrev = frag;
12982    }
12983}
12984function assignProgramDateTime(frag, prevFrag) {
12985    if (frag.rawProgramDateTime) {
12986        frag.programDateTime = Date.parse(frag.rawProgramDateTime);
12987    }
12988    else if (prevFrag && prevFrag.programDateTime) {
12989        frag.programDateTime = prevFrag.endProgramDateTime;
12990    }
12991    if (!Number.isFinite(frag.programDateTime)) {
12992        frag.programDateTime = null;
12993        frag.rawProgramDateTime = null;
12994    }
12995}
12996
12997/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.js")["Number"]))
12998
12999/***/ }),
13000
13001/***/ "./src/loader/playlist-loader.js":
13002/*!***************************************!*\
13003  !*** ./src/loader/playlist-loader.js ***!
13004  \***************************************/
13005/*! no static exports found */
13006/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
13007/***/ (function(module, exports, __webpack_require__) {
13008
13009"use strict";
13010/* WEBPACK VAR INJECTION */(function(Number) {
13011/**
13012 * PlaylistLoader - delegate for media manifest/playlist loading tasks. Takes care of parsing media to internal data-models.
13013 *
13014 * Once loaded, dispatches events with parsed data-models of manifest/levels/audio/subtitle tracks.
13015 *
13016 * Uses loader(s) set in config to do actual internal loading of resource tasks.
13017 *
13018 * @module
13019 *
13020 */
13021var __extends = (this && this.__extends) || (function () {
13022    var extendStatics = Object.setPrototypeOf ||
13023        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
13024        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
13025    return function (d, b) {
13026        extendStatics(d, b);
13027        function __() { this.constructor = d; }
13028        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
13029    };
13030})();
13031Object.defineProperty(exports, "__esModule", { value: true });
13032var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
13033var event_handler_1 = __webpack_require__(/*! ../event-handler */ "./src/event-handler.js");
13034var errors_1 = __webpack_require__(/*! ../errors */ "./src/errors.js");
13035var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
13036var mp4demuxer_1 = __webpack_require__(/*! ../demux/mp4demuxer */ "./src/demux/mp4demuxer.js");
13037var m3u8_parser_1 = __webpack_require__(/*! ./m3u8-parser */ "./src/loader/m3u8-parser.js");
13038var performance = window.performance;
13039/**
13040 * `type` property values for this loaders' context object
13041 * @enum
13042 *
13043 */
13044var ContextType = {
13045    MANIFEST: 'manifest',
13046    LEVEL: 'level',
13047    AUDIO_TRACK: 'audioTrack',
13048    SUBTITLE_TRACK: 'subtitleTrack'
13049};
13050/**
13051 * @enum {string}
13052 */
13053var LevelType = {
13054    MAIN: 'main',
13055    AUDIO: 'audio',
13056    SUBTITLE: 'subtitle'
13057};
13058/**
13059 * @constructor
13060 */
13061var PlaylistLoader = /** @class */ (function (_super) {
13062    __extends(PlaylistLoader, _super);
13063    /**
13064     * @constructs
13065     * @param {Hls} hls
13066     */
13067    function PlaylistLoader(hls) {
13068        var _this = _super.call(this, hls, events_1.default.MANIFEST_LOADING, events_1.default.LEVEL_LOADING, events_1.default.AUDIO_TRACK_LOADING, events_1.default.SUBTITLE_TRACK_LOADING) || this;
13069        _this.loaders = {};
13070        return _this;
13071    }
13072    Object.defineProperty(PlaylistLoader, "ContextType", {
13073        get: function () {
13074            return ContextType;
13075        },
13076        enumerable: true,
13077        configurable: true
13078    });
13079    Object.defineProperty(PlaylistLoader, "LevelType", {
13080        get: function () {
13081            return LevelType;
13082        },
13083        enumerable: true,
13084        configurable: true
13085    });
13086    /**
13087     * @param {ContextType} type
13088     * @returns {boolean}
13089     */
13090    PlaylistLoader.canHaveQualityLevels = function (type) {
13091        return (type !== ContextType.AUDIO_TRACK &&
13092            type !== ContextType.SUBTITLE_TRACK);
13093    };
13094    /**
13095     * Map context.type to LevelType
13096     * @param {{type: ContextType}} context
13097     * @returns {LevelType}
13098     */
13099    PlaylistLoader.mapContextToLevelType = function (context) {
13100        var type = context.type;
13101        switch (type) {
13102            case ContextType.AUDIO_TRACK:
13103                return LevelType.AUDIO;
13104            case ContextType.SUBTITLE_TRACK:
13105                return LevelType.SUBTITLE;
13106            default:
13107                return LevelType.MAIN;
13108        }
13109    };
13110    PlaylistLoader.getResponseUrl = function (response, context) {
13111        var url = response.url;
13112        // responseURL not supported on some browsers (it is used to detect URL redirection)
13113        // data-uri mode also not supported (but no need to detect redirection)
13114        if (url === undefined || url.indexOf('data:') === 0) {
13115            // fallback to initial URL
13116            url = context.url;
13117        }
13118        return url;
13119    };
13120    /**
13121     * Returns defaults or configured loader-type overloads (pLoader and loader config params)
13122     * Default loader is XHRLoader (see utils)
13123     * @param {object} context
13124     * @returns {XHRLoader} or other compatible configured overload
13125     */
13126    PlaylistLoader.prototype.createInternalLoader = function (context) {
13127        var config = this.hls.config;
13128        var PLoader = config.pLoader;
13129        var Loader = config.loader;
13130        var InternalLoader = PLoader || Loader;
13131        var loader = new InternalLoader(config);
13132        context.loader = loader;
13133        this.loaders[context.type] = loader;
13134        return loader;
13135    };
13136    PlaylistLoader.prototype.getInternalLoader = function (context) {
13137        return this.loaders[context.type];
13138    };
13139    PlaylistLoader.prototype.resetInternalLoader = function (contextType) {
13140        if (this.loaders[contextType]) {
13141            delete this.loaders[contextType];
13142        }
13143    };
13144    /**
13145     * Call `destroy` on all internal loader instances mapped (one per context type)
13146     */
13147    PlaylistLoader.prototype.destroyInternalLoaders = function () {
13148        for (var contextType in this.loaders) {
13149            var loader = this.loaders[contextType];
13150            if (loader) {
13151                loader.destroy();
13152            }
13153            this.resetInternalLoader(contextType);
13154        }
13155    };
13156    PlaylistLoader.prototype.destroy = function () {
13157        this.destroyInternalLoaders();
13158        _super.prototype.destroy.call(this);
13159    };
13160    PlaylistLoader.prototype.onManifestLoading = function (data) {
13161        this.load(data.url, { type: ContextType.MANIFEST, level: 0, id: null });
13162    };
13163    PlaylistLoader.prototype.onLevelLoading = function (data) {
13164        this.load(data.url, { type: ContextType.LEVEL, level: data.level, id: data.id });
13165    };
13166    PlaylistLoader.prototype.onAudioTrackLoading = function (data) {
13167        this.load(data.url, { type: ContextType.AUDIO_TRACK, level: null, id: data.id });
13168    };
13169    PlaylistLoader.prototype.onSubtitleTrackLoading = function (data) {
13170        this.load(data.url, { type: ContextType.SUBTITLE_TRACK, level: null, id: data.id });
13171    };
13172    PlaylistLoader.prototype.load = function (url, context) {
13173        var config = this.hls.config;
13174        logger_1.logger.debug("Loading playlist of type " + context.type + ", level: " + context.level + ", id: " + context.
13174id);
13175        // Check if a loader for this context already exists
13176        var loader = this.getInternalLoader(context);
13177        if (loader) {
13178            var loaderContext = loader.context;
13179            if (loaderContext && loaderContext.url === url) { // same URL can't overlap
13180                logger_1.logger.trace('playlist request ongoing');
13181                return false;
13182            }
13183            else {
13184                logger_1.logger.warn("aborting previous loader for type: " + context.type);
13185                loader.abort();
13186            }
13187        }
13188        var maxRetry, timeout, retryDelay, maxRetryDelay;
13189        // apply different configs for retries depending on
13190        // context (manifest, level, audio/subs playlist)
13191        switch (context.type) {
13192            case ContextType.MANIFEST:
13193                maxRetry = config.manifestLoadingMaxRetry;
13194                timeout = config.manifestLoadingTimeOut;
13195                retryDelay = config.manifestLoadingRetryDelay;
13196                maxRetryDelay = config.manifestLoadingMaxRetryTimeout;
13197                break;
13198            case ContextType.LEVEL:
13199                // Disable internal loader retry logic, since we are managing retries in Level Controller
13200                maxRetry = 0;
13201                timeout = config.levelLoadingTimeOut;
13202                // TODO Introduce retry settings for audio-track and subtitle-track, it should not use level retry config
13203                break;
13204            default:
13205                maxRetry = config.levelLoadingMaxRetry;
13206                timeout = config.levelLoadingTimeOut;
13207                retryDelay = config.levelLoadingRetryDelay;
13208                maxRetryDelay = config.levelLoadingMaxRetryTimeout;
13209                break;
13210        }
13211        loader = this.createInternalLoader(context);
13212        context.url = url;
13213        context.responseType = context.responseType || ''; // FIXME: (should not be necessary to do this)
13214        var loaderConfig = {
13215            timeout: timeout,
13216            maxRetry: maxRetry,
13217            retryDelay: retryDelay,
13218            maxRetryDelay: maxRetryDelay
13219        };
13220        var loaderCallbacks = {
13221            onSuccess: this.loadsuccess.bind(this),
13222            onError: this.loaderror.bind(this),
13223            onTimeout: this.loadtimeout.bind(this)
13224        };
13225        logger_1.logger.debug("Calling internal loader delegate for URL: " + url);
13226        loader.load(context, loaderConfig, loaderCallbacks);
13227        return true;
13228    };
13229    PlaylistLoader.prototype.loadsuccess = function (response, stats, context, networkDetails) {
13230        if (networkDetails === void 0) { networkDetails = null; }
13231        if (context.isSidxRequest) {
13232            this._handleSidxRequest(response, context);
13233            this._handlePlaylistLoaded(response, stats, context, networkDetails);
13234            return;
13235        }
13236        this.resetInternalLoader(context.type);
13237        var string = response.data;
13238        stats.tload = performance.now();
13239        // stats.mtime = new Date(target.getResponseHeader('Last-Modified'));
13240        // Validate if it is an M3U8 at all
13241        if (string.indexOf('#EXTM3U') !== 0) {
13242            this._handleManifestParsingError(response, context, 'no EXTM3U delimiter', networkDetails);
13243            return;
13244        }
13245        // Check if chunk-list or master. handle empty chunk list case (first EXTINF not signaled, but TARGETDURATION present)
13246        if (string.indexOf('#EXTINF:') > 0 || string.indexOf('#EXT-X-TARGETDURATION:') > 0) {
13247            this._handleTrackOrLevelPlaylist(response, stats, context, networkDetails);
13248        }
13249        else {
13250            this._handleMasterPlaylist(response, stats, context, networkDetails);
13251        }
13252    };
13253    PlaylistLoader.prototype.loaderror = function (response, context, networkDetails) {
13254        if (networkDetails === void 0) { networkDetails = null; }
13255        this._handleNetworkError(context, networkDetails, false, response);
13256    };
13257    PlaylistLoader.prototype.loadtimeout = function (stats, context, networkDetails) {
13258        if (networkDetails === void 0) { networkDetails = null; }
13259        this._handleNetworkError(context, networkDetails, true);
13260    };
13261    PlaylistLoader.prototype._handleMasterPlaylist = function (response, stats, context, networkDetails) {
13262        var hls = this.hls;
13263        var string = response.data;
13264        var url = PlaylistLoader.getResponseUrl(response, context);
13265        var levels = m3u8_parser_1.default.parseMasterPlaylist(string, url);
13266        if (!levels.length) {
13267            this._handleManifestParsingError(response, context, 'no level found in manifest', networkDetails);
13268            return;
13269        }
13270        // multi level playlist, parse level info
13271        var audioGroups = levels.map(function (level) { return ({
13272            id: level.attrs.AUDIO,
13273            codec: level.audioCodec
13274        }); });
13275        var audioTracks = m3u8_parser_1.default.parseMasterPlaylistMedia(string, url, 'AUDIO', audioGroups);
13276        var subtitles = m3u8_parser_1.default.parseMasterPlaylistMedia(string, url, 'SUBTITLES');
13277        if (audioTracks.length) {
13278            // check if we have found an audio track embedded in main playlist (audio track without URI attribute)
13279            var embeddedAudioFound_1 = false;
13280            audioTracks.forEach(function (audioTrack) {
13281                if (!audioTrack.url) {
13282                    embeddedAudioFound_1 = true;
13283                }
13284            });
13285            // if no embedded audio track defined, but audio codec signaled in quality level,
13286            // we need to signal this main audio track this could happen with playlists with
13287            // alt audio rendition in which quality levels (main)
13288            // contains both audio+video. but with mixed audio track not signaled
13289            if (embeddedAudioFound_1 === false && levels[0].audioCodec && !levels[0].attrs.AUDIO) {
13290                logger_1.logger.log('audio codec signaled in quality level, but no embedded audio track signaled, create one');
13291                audioTracks.unshift({
13292                    type: 'main',
13293                    name: 'main'
13294                });
13295            }
13296        }
13297        hls.trigger(events_1.default.MANIFEST_LOADED, {
13298            levels: levels,
13299            audioTracks: audioTracks,
13300            subtitles: subtitles,
13301            url: url,
13302            stats: stats,
13303            networkDetails: networkDetails
13304        });
13305    };
13306    PlaylistLoader.prototype._handleTrackOrLevelPlaylist = function (response, stats, context, networkDetails) {
13307        var hls = this.hls;
13308        var id = context.id, level = context.level, type = context.type;
13309        var url = PlaylistLoader.getResponseUrl(response, context);
13310        var levelUrlId = Number.isFinite(id) ? id : 0;
13311        var levelId = Number.isFinite(level) ? level : levelUrlId;
13312        var levelType = PlaylistLoader.mapContextToLevelType(context);
13313        var levelDetails = m3u8_parser_1.default.parseLevelPlaylist(response.data, url, levelId, levelType, levelUrlId);
13314        // set stats on level structure
13315        levelDetails.tload = stats.tload;
13316        // We have done our first request (Manifest-type) and receive
13317        // not a master playlist but a chunk-list (track/level)
13318        // We fire the manifest-loaded event anyway with the parsed level-details
13319        // by creating a single-level structure for it.
13320        if (type === ContextType.MANIFEST) {
13321            var singleLevel = {
13322                url: url,
13323                details: levelDetails
13324            };
13325            hls.trigger(events_1.default.MANIFEST_LOADED, {
13326                levels: [singleLevel],
13327                audioTracks: [],
13328                url: url,
13329                stats: stats,
13330                networkDetails: networkDetails
13331            });
13332        }
13333        // save parsing time
13334        stats.tparsed = performance.now();
13335        // in case we need SIDX ranges
13336        // return early after calling load for
13337        // the SIDX box.
13338        if (levelDetails.needSidxRanges) {
13339            var sidxUrl = levelDetails.initSegment.url;
13340            this.load(sidxUrl, {
13341                isSidxRequest: true,
13342                type: type,
13343                level: level,
13344                levelDetails: levelDetails,
13345                id: id,
13346                rangeStart: 0,
13347                rangeEnd: 2048,
13348                responseType: 'arraybuffer'
13349            });
13350            return;
13351        }
13352        // extend the context with the new levelDetails property
13353        context.levelDetails = levelDetails;
13354        this._handlePlaylistLoaded(response, stats, context, networkDetails);
13355    };
13356    PlaylistLoader.prototype._handleSidxRequest = function (response, context) {
13357        var sidxInfo = mp4demuxer_1.default.parseSegmentIndex(new Uint8Array(response.data));
13358        // if provided fragment does not contain sidx, early return
13359        if (!sidxInfo) {
13360            return;
13361        }
13362        var sidxReferences = sidxInfo.references;
13363        var levelDetails = context.levelDetails;
13364        sidxReferences.forEach(function (segmentRef, index) {
13365            var segRefInfo = segmentRef.info;
13366            var frag = levelDetails.fragments[index];
13367            if (frag.byteRange.length === 0) {
13368                frag.rawByteRange = String(1 + segRefInfo.end - segRefInfo.start) + '@' + String(segRefInfo.start);
13369            }
13370        });
13371        levelDetails.initSegment.rawByteRange = String(sidxInfo.moovEndOffset) + '@0';
13372    };
13373    PlaylistLoader.prototype._handleManifestParsingError = function (response, context, reason, networkDetails) {
13374        this.hls.trigger(events_1.default.ERROR, {
13375            type: errors_1.ErrorTypes.NETWORK_ERROR,
13376            details: errors_1.ErrorDetails.MANIFEST_PARSING_ERROR,
13377            fatal: true,
13378            url: response.url,
13379            reason: reason,
13380            networkDetails: networkDetails
13381        });
13382    };
13383    PlaylistLoader.prototype._handleNetworkError = function (context, networkDetails, timeout, response) {
13384        if (timeout === void 0) { timeout = false; }
13385        if (response === void 0) { response = null; }
13386        logger_1.logger.info("A network error occured while loading a " + context.type + "-type playlist");
13387        var details;
13388        var fatal;
13389        var loader = this.getInternalLoader(context);
13390        switch (context.type) {
13391            case ContextType.MANIFEST:
13392                details = (timeout ? errors_1.ErrorDetails.MANIFEST_LOAD_TIMEOUT : errors_1.ErrorDetails.MANIFEST_LOAD_ERROR);
13393                fatal = true;
13394                break;
13395            case ContextType.LEVEL:
13396                details = (timeout ? errors_1.ErrorDetails.LEVEL_LOAD_TIMEOUT : errors_1.ErrorDetails.LEVEL_LOAD_ERROR);
13397                fatal = false;
13398                break;
13399            case ContextType.AUDIO_TRACK:
13400                details = (timeout ? errors_1.ErrorDetails.AUDIO_TRACK_LOAD_TIMEOUT : errors_1.ErrorDetails.AUDIO_TRACK_LOAD_ERROR);
13401                fatal = false;
13402                break;
13403            default:
13404                // details = ...?
13405                fatal = false;
13406        }
13407        if (loader) {
13408            loader.abort();
13409            this.resetInternalLoader(context.type);
13410        }
13411        var errorData = {
13412            type: errors_1.ErrorTypes.NETWORK_ERROR,
13413            details: details,
13414            fatal: fatal,
13415            url: loader.url,
13416            loader: loader,
13417            context: context,
13418            networkDetails: networkDetails
13419        };
13420        if (response) {
13421            errorData.response = response;
13422        }
13423        this.hls.trigger(events_1.default.ERROR, errorData);
13424    };
13425    PlaylistLoader.prototype._handlePlaylistLoaded = function (response, stats, context, networkDetails) {
13426        var type = context.type, level = context.level, id = context.id, levelDetails = context.levelDetails;
13427        if (!levelDetails.targetduration) {
13428            this._handleManifestParsingError(response, context, 'invalid target duration', networkDetails);
13429            return;
13430        }
13431        var canHaveLevels = PlaylistLoader.canHaveQualityLevels(context.type);
13432        if (canHaveLevels) {
13433            this.hls.trigger(events_1.default.LEVEL_LOADED, {
13434                details: levelDetails,
13435                level: level || 0,
13436                id: id || 0,
13437                stats: stats,
13438                networkDetails: networkDetails
13439            });
13440        }
13441        else {
13442            switch (type) {
13443                case ContextType.AUDIO_TRACK:
13444                    this.hls.trigger(events_1.default.AUDIO_TRACK_LOADED, {
13445                        details: levelDetails,
13446                        id: id,
13447                        stats: stats,
13448                        networkDetails: networkDetails
13449                    });
13450                    break;
13451                case ContextType.SUBTITLE_TRACK:
13452                    this.hls.trigger(events_1.default.SUBTITLE_TRACK_LOADED, {
13453                        details: levelDetails,
13454                        id: id,
13455                        stats: stats,
13456                        networkDetails: networkDetails
13457                    });
13458                    break;
13459            }
13460        }
13461    };
13462    return PlaylistLoader;
13463}(event_handler_1.default));
13464exports.default = PlaylistLoader;
13465
13466/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.js")["Number"]))
13467
13468/***/ }),
13469
13470/***/ "./src/observer.js":
13471/*!*************************!*\
13472  !*** ./src/observer.js ***!
13473  \*************************/
13474/*! no static exports found */
13475/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
13476/***/ (function(module, exports, __webpack_require__) {
13477
13478"use strict";
13479
13480var __extends = (this && this.__extends) || (function () {
13481    var extendStatics = Object.setPrototypeOf ||
13482        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
13483        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
13484    return function (d, b) {
13485        extendStatics(d, b);
13486        function __() { this.constructor = d; }
13487        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
13488    };
13489})();
13490Object.defineProperty(exports, "__esModule", { value: true });
13491var eventemitter3_1 = __webpack_require__(/*! eventemitter3 */ "./node_modules/eventemitter3/index.js");
13492/**
13493 * @class
13494 *
13495 * Simple adapter sub-class of Nodejs-like EventEmitter.
13496 *
13497 * We simply want to pass along the event-name itself
13498 * in every call to a handler, which is the purpose of our `trigger` method
13499 * extending the standard API.
13500 *
13501 */
13502var Observer = /** @class */ (function (_super) {
13503    __extends(Observer, _super);
13504    function Observer() {
13505        return _super !== null && _super.apply(this, arguments) || this;
13506    }
13507    /**
13508     *
13509     * @param {string} event
13510     * @param {any} data
13511     */
13512    Observer.prototype.trigger = function (event) {
13513        var data = [];
13514        for (var _i = 1; _i < arguments.length; _i++) {
13515            data[_i - 1] = arguments[_i];
13516        }
13517        this.emit.apply(this, [event, event].concat(data));
13518    };
13519    return Observer;
13520}(eventemitter3_1.EventEmitter));
13521exports.Observer = Observer;
13522
13523
13524/***/ }),
13525
13526/***/ "./src/polyfills/number.js":
13527/*!*********************************!*\
13528  !*** ./src/polyfills/number.js ***!
13529  \*********************************/
13530/*! no static exports found */
13531/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
13532/***/ (function(module, exports, __webpack_require__) {
13533
13534"use strict";
13535
13536Object.defineProperty(exports, "__esModule", { value: true });
13537var get_self_scope_1 = __webpack_require__(/*! ../utils/get-self-scope */ "./src/utils/get-self-scope.js");
13538var self = get_self_scope_1.getSelfScope();
13539var Number = self.Number;
13540exports.Number = Number;
13541// TODO: get rid of global polyfills and replace them with wrappers ("ponyfills")
13542Number.isFinite = Number.isFinite || function (value) {
13543    return typeof value === 'number' && isFinite(value);
13544};
13545
13546
13547/***/ }),
13548
13549/***/ "./src/remux/aac-helper.js":
13550/*!*********************************!*\
13551  !*** ./src/remux/aac-helper.js ***!
13552  \*********************************/
13553/*! no static exports found */
13554/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
13555/***/ (function(module, exports, __webpack_require__) {
13556
13557"use strict";
13558
13559/**
13560 *  AAC helper
13561 */
13562Object.defineProperty(exports, "__esModule", { value: true });
13563var AAC = /** @class */ (function () {
13564    function AAC() {
13565    }
13566    AAC.getSilentFrame = function (codec, channelCount) {
13567        switch (codec) {
13568            case 'mp4a.40.2':
13569                if (channelCount === 1) {
13570                    return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x23, 0x80]);
13571                }
13572                else if (channelCount === 2) {
13573                    return new Uint8Array([0x21, 0x00, 0x49, 0x90, 0x02, 0x19, 0x00, 0x23, 0x80]);
13574                }
13575                else if (channelCount === 3) {
13576                    return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x8e]);
13577                }
13578                else if (channelCount === 4) {
13579                    return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x80, 0x2c, 0x80, 0x08, 0x02, 0x38]);
13580                }
13581                else if (channelCount === 5) {
13582                    return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x82, 0x30, 0x04, 0x99, 0x00, 0x21, 0x90, 0x02, 0x38]);
13583                }
13584                else if (channelCount === 6) {
13585                    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]);
13586                }
13587                break;
13588            // handle HE-AAC below (mp4a.40.5 / mp4a.40.29)
13589            default:
13590                if (channelCount === 1) {
13591                    // 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
13592                    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]);
13593                }
13594                else if (channelCount === 2) {
13595                    // 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
13596                    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]);
13597                }
13598                else if (channelCount === 3) {
13599                    // 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
13600                    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]);
13601                }
13602                break;
13603        }
13604        return null;
13605    };
13606    return AAC;
13607}());
13608exports.default = AAC;
13609
13610
13611/***/ }),
13612
vendor: 4,508 bytes, lines 13613-13762
13613/***/ "./src/remux/mp4-generator.js":
13614/*!************************************!*\
13615  !*** ./src/remux/mp4-generator.js ***!
13616  \************************************/
13617/*! no static exports found */
13618/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
13619/***/ (function(module, exports, __webpack_require__) {
13620
13621"use strict";
13622
13623/**
13624 * Generate MP4 Box
13625*/
13626Object.defineProperty(exports, "__esModule", { value: true });
13627var UINT32_MAX = Math.pow(2, 32) - 1;
13628var MP4 = /** @class */ (function () {
13629    function MP4() {
13630    }
13631    MP4.init = function () {
13632        MP4.types = {
13633            avc1: [],
13634            avcC: [],
13635            btrt: [],
13636            dinf: [],
13637            dref: [],
13638            esds: [],
13639            ftyp: [],
13640            hdlr: [],
13641            mdat: [],
13642            mdhd: [],
13643            mdia: [],
13644            mfhd: [],
13645            minf: [],
13646            moof: [],
13647            moov: [],
13648            mp4a: [],
13649            '.mp3': [],
13650            mvex: [],
13651            mvhd: [],
13652            pasp: [],
13653            sdtp: [],
13654            stbl: [],
13655            stco: [],
13656            stsc: [],
13657            stsd: [],
13658            stsz: [],
13659            stts: [],
13660            tfdt: [],
13661            tfhd: [],
13662            traf: [],
13663            trak: [],
13664            trun: [],
13665            trex: [],
13666            tkhd: [],
13667            vmhd: [],
13668            smhd: []
13669        };
13670        var i;
13671        for (i in MP4.types) {
13672            if (MP4.types.hasOwnProperty(i)) {
13673                MP4.types[i] = [
13674                    i.charCodeAt(0),
13675                    i.charCodeAt(1),
13676                    i.charCodeAt(2),
13677                    i.charCodeAt(3)
13678                ];
13679            }
13680        }
13681        var videoHdlr = new Uint8Array([
13682            0x00,
13683            0x00, 0x00, 0x00,
13684            0x00, 0x00, 0x00, 0x00,
13685            0x76, 0x69, 0x64, 0x65,
13686            0x00, 0x00, 0x00, 0x00,
13687            0x00, 0x00, 0x00, 0x00,
13688            0x00, 0x00, 0x00, 0x00,
13689            0x56, 0x69, 0x64, 0x65,
13690            0x6f, 0x48, 0x61, 0x6e,
13691            0x64, 0x6c, 0x65, 0x72, 0x00 // name: 'VideoHandler'
13692        ]);
13693        var audioHdlr = new Uint8Array([
13694            0x00,
13695            0x00, 0x00, 0x00,
13696            0x00, 0x00, 0x00, 0x00,
13697            0x73, 0x6f, 0x75, 0x6e,
13698            0x00, 0x00, 0x00, 0x00,
13699            0x00, 0x00, 0x00, 0x00,
13700            0x00, 0x00, 0x00, 0x00,
13701            0x53, 0x6f, 0x75, 0x6e,
13702            0x64, 0x48, 0x61, 0x6e,
13703            0x64, 0x6c, 0x65, 0x72, 0x00 // name: 'SoundHandler'
13704        ]);
13705        MP4.HDLR_TYPES = {
13706            'video': videoHdlr,
13707            'audio': audioHdlr
13708        };
13709        var dref = new Uint8Array([
13710            0x00,
13711            0x00, 0x00, 0x00,
13712            0x00, 0x00, 0x00, 0x01,
13713            0x00, 0x00, 0x00, 0x0c,
13714            0x75, 0x72, 0x6c, 0x20,
13715            0x00,
13716            0x00, 0x00, 0x01 // entry_flags
13717        ]);
13718        var stco = new Uint8Array([
13719            0x00,
13720            0x00, 0x00, 0x00,
13721            0x00, 0x00, 0x00, 0x00 // entry_count
13722        ]);
13723        MP4.STTS = MP4.STSC = MP4.STCO = stco;
13724        MP4.STSZ = new Uint8Array([
13725            0x00,
13726            0x00, 0x00, 0x00,
13727            0x00, 0x00, 0x00, 0x00,
13728            0x00, 0x00, 0x00, 0x00 // sample_count
13729        ]);
13730        MP4.VMHD = new Uint8Array([
13731            0x00,
13732            0x00, 0x00, 0x01,
13733            0x00, 0x00,
13734            0x00, 0x00,
13735            0x00, 0x00,
13736            0x00, 0x00 // opcolor
13737        ]);
13738        MP4.SMHD = new Uint8Array([
13739            0x00,
13740            0x00, 0x00, 0x00,
13741            0x00, 0x00,
13742            0x00, 0x00 // reserved
13743        ]);
13744        MP4.STSD = new Uint8Array([
13745            0x00,
13746            0x00, 0x00, 0x00,
13747            0x00, 0x00, 0x00, 0x01
13748        ]); // entry_count
13749        var majorBrand = new Uint8Array([105, 115, 111, 109]); // isom
13750        var avc1Brand = new Uint8Array([97, 118, 99, 49]); // avc1
13751        var minorVersion = new Uint8Array([0, 0, 0, 1]);
13752        MP4.FTYP = MP4.box(MP4.types.ftyp, majorBrand, minorVersion, majorBrand, avc1Brand);
13753        MP4.DINF = MP4.box(MP4.types.dinf, MP4.box(MP4.types.dref, dref));
13754    };
13755    MP4.box = function (type) {
13756        var payload = Array.prototype.slice.call(arguments, 1), size = 8, i = payload.length, len = i, result;
13757        // calculate the total size we need to allocate
13758        while (i--) {
13759            size += payload[i].byteLength;
13760        }
13761        result = new Uint8Array(size);
13762        result[0] = (size >> 24) & 0xff;
13763        result[1] = (size >> 16) & 0xff;
13764        result[2] = (size >> 8) & 0xff;
13765        result[3] = size & 0xff;
13766        result.set(type, 4);
13767        // copy the payload into the result
13768        for (i = 0, size = 8; i < len; i++) {
13769            // copy payload[i] array @ offset size
13770            result.set(payload[i], size);
13771            size += payload[i].byteLength;
13772        }
13773        return result;
13774    };
13775    MP4.hdlr = function (type) {
13776        return MP4.box(MP4.types.hdlr, MP4.HDLR_TYPES[type]);
13777    };
13778    MP4.mdat = function (data) {
13779        return MP4.box(MP4.types.mdat, data);
13780    };
13781    MP4.mdhd = function (timescale, duration) {
13782        duration *= timescale;
13783        var upperWordDuration = Math.floor(duration / (UINT32_MAX + 1));
13784        var lowerWordDuration = Math.floor(duration % (UINT32_MAX + 1));
13785        return MP4.box(MP4.types.mdhd, new Uint8Array([
13786            0x01,
13787            0x00, 0x00, 0x00,
13788            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
13789            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
13790            (timescale >> 24) & 0xFF,
13791            (timescale >> 16) & 0xFF,
13792            (timescale >> 8) & 0xFF,
13793            timescale & 0xFF,
13794            (upperWordDuration >> 24),
13795            (upperWordDuration >> 16) & 0xFF,
13796            (upperWordDuration >> 8) & 0xFF,
13797            upperWordDuration & 0xFF,
13798            (lowerWordDuration >> 24),
13799            (lowerWordDuration >> 16) & 0xFF,
13800            (lowerWordDuration >> 8) & 0xFF,
13801            lowerWordDuration & 0xFF,
13802            0x55, 0xc4,
13803            0x00, 0x00
13804        ]));
13805    };
13806    MP4.mdia = function (track) {
13807        return MP4.box(MP4.types.mdia, MP4.mdhd(track.timescale, track.duration), MP4.hdlr(track.type), MP4.minf(track));
13808    };
13809    MP4.mfhd = function (sequenceNumber) {
13810        return MP4.box(MP4.types.mfhd, new Uint8Array([
13811            0x00,
13812            0x00, 0x00, 0x00,
13813            (sequenceNumber >> 24),
13814            (sequenceNumber >> 16) & 0xFF,
13815            (sequenceNumber >> 8) & 0xFF,
13816            sequenceNumber & 0xFF // sequence_number
13817        ]));
13818    };
13819    MP4.minf = function (track) {
13820        if (track.type === 'audio') {
13821            return MP4.box(MP4.types.minf, MP4.box(MP4.types.smhd, MP4.SMHD), MP4.DINF, MP4.stbl(track));
13822        }
13823        else {
13824            return MP4.box(MP4.types.minf, MP4.box(MP4.types.vmhd, MP4.VMHD), MP4.DINF, MP4.stbl(track));
13825        }
13826    };
13827    MP4.moof = function (sn, baseMediaDecodeTime, track) {
13828        return MP4.box(MP4.types.moof, MP4.mfhd(sn), MP4.traf(track, baseMediaDecodeTime));
13829    };
13830    /**
13831   * @param tracks... (optional) {array} the tracks associated with this movie
13832   */
13833    MP4.moov = function (tracks) {
13834        var i = tracks.length, boxes = [];
13835        while (i--) {
13836            boxes[i] = MP4.trak(tracks[i]);
13837        }
13838        return MP4.box.apply(null, [MP4.types.moov, MP4.mvhd(tracks[0].timescale, tracks[0].duration)].concat(boxes).concat(MP4.mvex(tracks)));
13839    };
13840    MP4.mvex = function (tracks) {
13841        var i = tracks.length, boxes = [];
13842        while (i--) {
13843            boxes[i] = MP4.trex(tracks[i]);
13844        }
13845        return MP4.box.apply(null, [MP4.types.mvex].concat(boxes));
13846    };
13847    MP4.mvhd = function (timescale, duration) {
13848        duration *= timescale;
13849        var upperWordDuration = Math.floor(duration / (UINT32_MAX + 1));
13850        var lowerWordDuration = Math.floor(duration % (UINT32_MAX + 1));
13851        var bytes = new Uint8Array([
13852            0x01,
13853            0x00, 0x00, 0x00,
13854            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
13855            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
13856            (timescale >> 24) & 0xFF,
13857            (timescale >> 16) & 0xFF,
13858            (timescale >> 8) & 0xFF,
13859            timescale & 0xFF,
13860            (upperWordDuration >> 24),
13861            (upperWordDuration >> 16) & 0xFF,
13862            (upperWordDuration >> 8) & 0xFF,
13863            upperWordDuration & 0xFF,
13864            (lowerWordDuration >> 24),
13865            (lowerWordDuration >> 16) & 0xFF,
13866            (lowerWordDuration >> 8) & 0xFF,
13867            lowerWordDuration & 0xFF,
13868            0x00, 0x01, 0x00, 0x00,
13869            0x01, 0x00,
13870            0x00, 0x00,
13871            0x00, 0x00, 0x00, 0x00,
13872            0x00, 0x00, 0x00, 0x00,
13873            0x00, 0x01, 0x00, 0x00,
13874            0x00, 0x00, 0x00, 0x00,
13875            0x00, 0x00, 0x00, 0x00,
13876            0x00, 0x00, 0x00, 0x00,
13877            0x00, 0x01, 0x00, 0x00,
13878            0x00, 0x00, 0x00, 0x00,
13879            0x00, 0x00, 0x00, 0x00,
13880            0x00, 0x00, 0x00, 0x00,
13881            0x40, 0x00, 0x00, 0x00,
13882            0x00, 0x00, 0x00, 0x00,
13883            0x00, 0x00, 0x00, 0x00,
13884            0x00, 0x00, 0x00, 0x00,
13885            0x00, 0x00, 0x00, 0x00,
13886            0x00, 0x00, 0x00, 0x00,
13887            0x00, 0x00, 0x00, 0x00,
13888            0xff, 0xff, 0xff, 0xff // next_track_ID
13889        ]);
13890        return MP4.box(MP4.types.mvhd, bytes);
13891    };
13892    MP4.sdtp = function (track) {
13893        var samples = track.samples || [], bytes = new Uint8Array(4 + samples.length), flags, i;
13894        // leave the full box header (4 bytes) all zero
13895        // write the sample table
13896        for (i = 0; i < samples.length; i++) {
13897            flags = samples[i].flags;
13898            bytes[i + 4] = (flags.dependsOn << 4) |
13899                (flags.isDependedOn << 2) |
13900                (flags.hasRedundancy);
13901        }
13902        return MP4.box(MP4.types.sdtp, bytes);
13903    };
13904    MP4.stbl = function (track) {
13905        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));
13906    };
13907    MP4.avc1 = function (track) {
13908        var sps = [], pps = [], i, data, len;
13909        // assemble the SPSs
13910        for (i = 0; i < track.sps.length; i++) {
13911            data = track.sps[i];
13912            len = data.byteLength;
13913            sps.push((len >>> 8) & 0xFF);
13914            sps.push((len & 0xFF));
13915            // SPS
13916            sps = sps.concat(Array.prototype.slice.call(data));
13917        }
13918        // assemble the PPSs
13919        for (i = 0; i < track.pps.length; i++) {
13920            data = track.pps[i];
13921            len = data.byteLength;
13922            pps.push((len >>> 8) & 0xFF);
13923            pps.push((len & 0xFF));
13924            pps = pps.concat(Array.prototype.slice.call(data));
13925        }
13926        var avcc = MP4.box(MP4.types.avcC, new Uint8Array([
13927            0x01,
13928            sps[3],
13929            sps[4],
13930            sps[5],
13931            0xfc | 3,
13932            0xE0 | track.sps.length // 3bit reserved (111) + numOfSequenceParameterSets
13933        ].concat(sps).concat([
13934            track.pps.length // numOfPictureParameterSets
13935        ]).concat(pps))), // "PPS"
13936        width = track.width, height = track.height, hSpacing = track.pixelRatio[0], vSpacing = track.pixelRatio[1];
13937        return MP4.box(MP4.types.avc1, new Uint8Array([
13938            0x00, 0x00, 0x00,
13939            0x00, 0x00, 0x00,
13940            0x00, 0x01,
13941            0x00, 0x00,
13942            0x00, 0x00,
13943            0x00, 0x00, 0x00, 0x00,
13944            0x00, 0x00, 0x00, 0x00,
13945            0x00, 0x00, 0x00, 0x00,
13946            (width >> 8) & 0xFF,
13947            width & 0xff,
13948            (height >> 8) & 0xFF,
13949            height & 0xff,
13950            0x00, 0x48, 0x00, 0x00,
13951            0x00, 0x48, 0x00, 0x00,
13952            0x00, 0x00, 0x00, 0x00,
13953            0x00, 0x01,
13954            0x12,
13955            0x64, 0x61, 0x69, 0x6C,
13956            0x79, 0x6D, 0x6F, 0x74,
13957            0x69, 0x6F, 0x6E, 0x2F,
13958            0x68, 0x6C, 0x73, 0x2E,
13959            0x6A, 0x73, 0x00, 0x00,
13960            0x00, 0x00, 0x00, 0x00,
13961            0x00, 0x00, 0x00, 0x00,
13962            0x00, 0x00, 0x00,
13963            0x00, 0x18,
13964            0x11, 0x11
13965        ]), // pre_defined = -1
13966        avcc, MP4.box(MP4.types.btrt, new Uint8Array([
13967            0x00, 0x1c, 0x9c, 0x80,
13968            0x00, 0x2d, 0xc6, 0xc0,
13969            0x00, 0x2d, 0xc6, 0xc0
13970        ])), // avgBitrate
13971        MP4.box(MP4.types.pasp, new Uint8Array([
13972            (hSpacing >> 24),
13973            (hSpacing >> 16) & 0xFF,
13974            (hSpacing >> 8) & 0xFF,
13975            hSpacing & 0xFF,
13976            (vSpacing >> 24),
13977            (vSpacing >> 16) & 0xFF,
13978            (vSpacing >> 8) & 0xFF,
13979            vSpacing & 0xFF
13980        ])));
13981    };
13982    MP4.esds = function (track) {
13983        var configlen = track.config.length;
13984        return new Uint8Array([
13985            0x00,
13986            0x00, 0x00, 0x00,
13987            0x03,
13988            0x17 + configlen,
13989            0x00, 0x01,
13990            0x00,
13991            0x04,
13992            0x0f + configlen,
13993            0x40,
13994            0x15,
13995            0x00, 0x00, 0x00,
13996            0x00, 0x00, 0x00, 0x00,
13997            0x00, 0x00, 0x00, 0x00,
13998            0x05 // descriptor_type
13999        ].concat([configlen]).concat(track.config).concat([0x06, 0x01, 0x02])); // GASpecificConfig)); // length + audio config descriptor
14000    };
14001    MP4.mp4a = function (track) {
14002        var samplerate = track.samplerate;
14003        return MP4.box(MP4.types.mp4a, new Uint8Array([
14004            0x00, 0x00, 0x00,
14005            0x00, 0x00, 0x00,
14006            0x00, 0x01,
14007            0x00, 0x00, 0x00, 0x00,
14008            0x00, 0x00, 0x00, 0x00,
14009            0x00, track.channelCount,
14010            0x00, 0x10,
14011            0x00, 0x00, 0x00, 0x00,
14012            (samplerate >> 8) & 0xFF,
14013            samplerate & 0xff,
14014            0x00, 0x00
14015        ]), MP4.box(MP4.types.esds, MP4.esds(track)));
14016    };
14017    MP4.mp3 = function (track) {
14018        var samplerate = track.samplerate;
14019        return MP4.box(MP4.types['.mp3'], new Uint8Array([
14020            0x00, 0x00, 0x00,
14021            0x00, 0x00, 0x00,
14022            0x00, 0x01,
14023            0x00, 0x00, 0x00, 0x00,
14024            0x00, 0x00, 0x00, 0x00,
14025            0x00, track.channelCount,
14026            0x00, 0x10,
14027            0x00, 0x00, 0x00, 0x00,
14028            (samplerate >> 8) & 0xFF,
14029            samplerate & 0xff,
14030            0x00, 0x00
14031        ]));
14032    };
14033    MP4.stsd = function (track) {
14034        if (track.type === 'audio') {
14035            if (!track.isAAC && track.codec === 'mp3') {
14036                return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp3(track));
14037            }
14038            return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp4a(track));
14039        }
14040        else {
14041            return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track));
14042        }
14043    };
14044    MP4.tkhd = function (track) {
14045        var id = track.id, duration = track.duration * track.timescale, width = track.width, height = track.height, upperWordDuration = Math.floor(duration / (UINT32_MAX + 1)), lowerWordDuration = Math.floor(duration % (UINT32_MAX + 1));
14046        return MP4.box(MP4.types.tkhd, new Uint8Array([
14047            0x01,
14048            0x00, 0x00, 0x07,
14049            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
14050            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
14051            (id >> 24) & 0xFF,
14052            (id >> 16) & 0xFF,
14053            (id >> 8) & 0xFF,
14054            id & 0xFF,
14055            0x00, 0x00, 0x00, 0x00,
14056            (upperWordDuration >> 24),
14057            (upperWordDuration >> 16) & 0xFF,
14058            (upperWordDuration >> 8) & 0xFF,
14059            upperWordDuration & 0xFF,
14060            (lowerWordDuration >> 24),
14061            (lowerWordDuration >> 16) & 0xFF,
14062            (lowerWordDuration >> 8) & 0xFF,
14063            lowerWordDuration & 0xFF,
14064            0x00, 0x00, 0x00, 0x00,
14065            0x00, 0x00, 0x00, 0x00,
14066            0x00, 0x00,
14067            0x00, 0x00,
14068            0x00, 0x00,
14069            0x00, 0x00,
14070            0x00, 0x01, 0x00, 0x00,
14071            0x00, 0x00, 0x00, 0x00,
14072            0x00, 0x00, 0x00, 0x00,
14073            0x00, 0x00, 0x00, 0x00,
14074            0x00, 0x01, 0x00, 0x00,
14075            0x00, 0x00, 0x00, 0x00,
14076            0x00, 0x00, 0x00, 0x00,
14077            0x00, 0x00, 0x00, 0x00,
14078            0x40, 0x00, 0x00, 0x00,
14079            (width >> 8) & 0xFF,
14080            width & 0xFF,
14081            0x00, 0x00,
14082            (height >> 8) & 0xFF,
14083            height & 0xFF,
14084            0x00, 0x00 // height
14085        ]));
14086    };
14087    MP4.traf = function (track, baseMediaDecodeTime) {
14088        var sampleDependencyTable = MP4.sdtp(track), id = track.id, upperWordBaseMediaDecodeTime = Math.floor(baseMediaDecodeTime / (UINT32_MAX + 1)), lowerWordBaseMediaDecodeTime = Math.floor(baseMediaDecodeTime % (UINT32_MAX + 1));
14089        return MP4.box(MP4.types.traf, MP4.box(MP4.types.tfhd, new Uint8Array([
14090            0x00,
14091            0x00, 0x00, 0x00,
14092            (id >> 24),
14093            (id >> 16) & 0XFF,
14094            (id >> 8) & 0XFF,
14095            (id & 0xFF) // track_ID
14096        ])), MP4.box(MP4.types.tfdt, new Uint8Array([
14097            0x01,
14098            0x00, 0x00, 0x00,
14099            (upperWordBaseMediaDecodeTime >> 24),
14100            (upperWordBaseMediaDecodeTime >> 16) & 0XFF,
14101            (upperWordBaseMediaDecodeTime >> 8) & 0XFF,
14102            (upperWordBaseMediaDecodeTime & 0xFF),
14103            (lowerWordBaseMediaDecodeTime >> 24),
14104            (lowerWordBaseMediaDecodeTime >> 16) & 0XFF,
14105            (lowerWordBaseMediaDecodeTime >> 8) & 0XFF,
14106            (lowerWordBaseMediaDecodeTime & 0xFF)
14107        ])), MP4.trun(track, sampleDependencyTable.length +
14108            16 + // tfhd
14109            20 + // tfdt
14110            8 + // traf header
14111            16 + // mfhd
14112            8 + // moof header
14113            8), // mdat header
14114        sampleDependencyTable);
14115    };
14116    /**
14117     * Generate a track box.
14118     * @param track {object} a track definition
14119     * @return {Uint8Array} the track box
14120     */
14121    MP4.trak = function (track) {
14122        track.duration = track.duration || 0xffffffff;
14123        return MP4.box(MP4.types.trak, MP4.tkhd(track), MP4.mdia(track));
14124    };
14125    MP4.trex = function (track) {
14126        var id = track.id;
14127        return MP4.box(MP4.types.trex, new Uint8Array([
14128            0x00,
14129            0x00, 0x00, 0x00,
14130            (id >> 24),
14131            (id >> 16) & 0XFF,
14132            (id >> 8) & 0XFF,
14133            (id & 0xFF),
14134            0x00, 0x00, 0x00, 0x01,
14135            0x00, 0x00, 0x00, 0x00,
14136            0x00, 0x00, 0x00, 0x00,
14137            0x00, 0x01, 0x00, 0x01 // default_sample_flags
14138        ]));
14139    };
14140    MP4.trun = function (track, offset) {
14141        var samples = track.samples || [], len = samples.length, arraylen = 12 + (16 * len), array = new Uint8Array(arraylen), i, sample, duration, size, flags, cts;
14142        offset += 8 + arraylen;
14143        array.set([
14144            0x00,
14145            0x00, 0x0f, 0x01,
14146            (len >>> 24) & 0xFF,
14147            (len >>> 16) & 0xFF,
14148            (len >>> 8) & 0xFF,
14149            len & 0xFF,
14150            (offset >>> 24) & 0xFF,
14151            (offset >>> 16) & 0xFF,
14152            (offset >>> 8) & 0xFF,
14153            offset & 0xFF // data_offset
14154        ], 0);
14155        for (i = 0; i < len; i++) {
14156            sample = samples[i];
14157            duration = sample.duration;
14158            size = sample.size;
14159            flags = sample.flags;
14160            cts = sample.cts;
14161            array.set([
14162                (duration >>> 24) & 0xFF,
14163                (duration >>> 16) & 0xFF,
14164                (duration >>> 8) & 0xFF,
14165                duration & 0xFF,
14166                (size >>> 24) & 0xFF,
14167                (size >>> 16) & 0xFF,
14168                (size >>> 8) & 0xFF,
14169                size & 0xFF,
14170                (flags.isLeading << 2) | flags.dependsOn,
14171                (flags.isDependedOn << 6) |
14172                    (flags.hasRedundancy << 4) |
14173                    (flags.paddingValue << 1) |
14174                    flags.isNonSync,
14175                flags.degradPrio & 0xF0 << 8,
14176                flags.degradPrio & 0x0F,
14177                (cts >>> 24) & 0xFF,
14178                (cts >>> 16) & 0xFF,
14179                (cts >>> 8) & 0xFF,
14180                cts & 0xFF // sample_composition_time_offset
14181            ], 12 + 16 * i);
14182        }
14183        return MP4.box(MP4.types.trun, array);
14184    };
14185    MP4.initSegment = function (tracks) {
14186        if (!MP4.types) {
14187            MP4.init();
14188        }
14189        var movie = MP4.moov(tracks), result;
14190        result = new Uint8Array(MP4.FTYP.byteLength + movie.byteLength);
14191        result.set(MP4.FTYP);
14192        result.set(movie, MP4.FTYP.byteLength);
14193        return result;
14194    };
14195    return MP4;
14196}());
14197exports.default = MP4;
14198
14199
14200/***/ }),
14201
vendor: 8,842 bytes, lines 14202-14370
14202/***/ "./src/remux/mp4-remuxer.js":
14203/*!**********************************!*\
14204  !*** ./src/remux/mp4-remuxer.js ***!
14205  \**********************************/
14206/*! no static exports found */
14207/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
14208/***/ (function(module, exports, __webpack_require__) {
14209
14210"use strict";
14211
14212/**
14213 * fMP4 remuxer
14214*/
14215Object.defineProperty(exports, "__esModule", { value: true });
14216var aac_helper_1 = __webpack_require__(/*! ./aac-helper */ "./src/remux/aac-helper.js");
14217var mp4_generator_1 = __webpack_require__(/*! ./mp4-generator */ "./src/remux/mp4-generator.js");
14218var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
14219var errors_1 = __webpack_require__(/*! ../errors */ "./src/errors.js");
14220var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
14221// 10 seconds
14222var MAX_SILENT_FRAME_DURATION = 10 * 1000;
14223var MP4Remuxer = /** @class */ (function () {
14224    function MP4Remuxer(observer, config, typeSupported, vendor) {
14225        this.observer = observer;
14226        this.config = config;
14227        this.typeSupported = typeSupported;
14228        var userAgent = navigator.userAgent;
14229        this.isSafari = vendor && vendor.indexOf('Apple') > -1 && userAgent && !userAgent.match('CriOS');
14230        this.ISGenerated = false;
14231    }
14232    MP4Remuxer.prototype.destroy = function () {
14233    };
14234    MP4Remuxer.prototype.resetTimeStamp = function (defaultTimeStamp) {
14235        this._initPTS = this._initDTS = defaultTimeStamp;
14236    };
14237    MP4Remuxer.prototype.resetInitSegment = function () {
14238        this.ISGenerated = false;
14239    };
14240    MP4Remuxer.prototype.remux = function (audioTrack, videoTrack, id3Track, textTrack, timeOffset, contiguous, accurateTimeOffset) {
14241        // generate Init Segment if needed
14242        if (!this.ISGenerated) {
14243            this.generateIS(audioTrack, videoTrack, timeOffset);
14244        }
14245        if (this.ISGenerated) {
14246            var nbAudioSamples = audioTrack.samples.length;
14247            var nbVideoSamples = videoTrack.samples.length;
14248            var audioTimeOffset = timeOffset;
14249            var videoTimeOffset = timeOffset;
14250            if (nbAudioSamples && nbVideoSamples) {
14251                // timeOffset is expected to be the offset of the first timestamp of this fragment (first DTS)
14252                // if first audio DTS is not aligned with first video DTS then we need to take that into account
14253                // when providing timeOffset to remuxAudio / remuxVideo. if we don't do that, there might be a permanent / small
14254                // drift between audio and video streams
14255                var audiovideoDeltaDts = (audioTrack.samples[0].pts - videoTrack.samples[0].pts) / videoTrack.inputTimeScale;
14256                audioTimeOffset += Math.max(0, audiovideoDeltaDts);
14257                videoTimeOffset += Math.max(0, -audiovideoDeltaDts);
14258            }
14259            // Purposefully remuxing audio before video, so that remuxVideo can use nextAudioPts, which is
14260            // calculated in remuxAudio.
14261            // logger.log('nb AAC samples:' + audioTrack.samples.length);
14262            if (nbAudioSamples) {
14263                // if initSegment was generated without video samples, regenerate it again
14264                if (!audioTrack.timescale) {
14265                    logger_1.logger.warn('regenerate InitSegment as audio detected');
14266                    this.generateIS(audioTrack, videoTrack, timeOffset);
14267                }
14268                var audioData = this.remuxAudio(audioTrack, audioTimeOffset, contiguous, accurateTimeOffset);
14269                // logger.log('nb AVC samples:' + videoTrack.samples.length);
14270                if (nbVideoSamples) {
14271                    var audioTrackLength = void 0;
14272                    if (audioData) {
14273                        audioTrackLength = audioData.endPTS - audioData.startPTS;
14274                    }
14275                    // if initSegment was generated without video samples, regenerate it again
14276                    if (!videoTrack.timescale) {
14277                        logger_1.logger.warn('regenerate InitSegment as video detected');
14278                        this.generateIS(audioTrack, videoTrack, timeOffset);
14279                    }
14280                    this.remuxVideo(videoTrack, videoTimeOffset, contiguous, audioTrackLength, accurateTimeOffset);
14281                }
14282            }
14283            else {
14284                // logger.log('nb AVC samples:' + videoTrack.samples.length);
14285                if (nbVideoSamples) {
14286                    var videoData = this.remuxVideo(videoTrack, videoTimeOffset, contiguous, 0, accurateTimeOffset);
14287                    if (videoData && audioTrack.codec) {
14288                        this.remuxEmptyAudio(audioTrack, audioTimeOffset, contiguous, videoData);
14289                    }
14290                }
14291            }
14292        }
14293        // logger.log('nb ID3 samples:' + audioTrack.samples.length);
14294        if (id3Track.samples.length) {
14295            this.remuxID3(id3Track, timeOffset);
14296        }
14297        // logger.log('nb ID3 samples:' + audioTrack.samples.length);
14298        if (textTrack.samples.length) {
14299            this.remuxText(textTrack, timeOffset);
14300        }
14301        // notify end of parsing
14302        this.observer.trigger(events_1.default.FRAG_PARSED);
14303    };
14304    MP4Remuxer.prototype.generateIS = function (audioTrack, videoTrack, timeOffset) {
14305        var observer = this.observer, audioSamples = audioTrack.samples, videoSamples = videoTrack.samples, typeSupported = this.typeSupported, container = 'audio/mp4', tracks = {}, data = { tracks: tracks }, computePTSDTS = (this._initPTS === undefined), initPTS, initDTS;
14306        if (computePTSDTS) {
14307            initPTS = initDTS = Infinity;
14308        }
14309        if (audioTrack.config && audioSamples.length) {
14310            // let's use audio sampling rate as MP4 time scale.
14311            // rationale is that there is a integer nb of audio frames per audio sample (1024 for AAC)
14312            // using audio sampling rate here helps having an integer MP4 frame duration
14313            // this avoids potential rounding issue and AV sync issue
14314            audioTrack.timescale = audioTrack.samplerate;
14315            logger_1.logger.log("audio sampling rate : " + audioTrack.samplerate);
14316            if (!audioTrack.isAAC) {
14317                if (typeSupported.mpeg) { // Chrome and Safari
14318                    container = 'audio/mpeg';
14319                    audioTrack.codec = '';
14320                }
14321                else if (typeSupported.mp3) { // Firefox
14322                    audioTrack.codec = 'mp3';
14323                }
14324            }
14325            tracks.audio = {
14326                container: container,
14327                codec: audioTrack.codec,
14328                initSegment: !audioTrack.isAAC && typeSupported.mpeg ? new Uint8Array() : mp4_generator_1.default.initSegment([audioTrack]),
14329                metadata: {
14330                    channelCount: audioTrack.channelCount
14331                }
14332            };
14333            if (computePTSDTS) {
14334                // remember first PTS of this demuxing context. for audio, PTS = DTS
14335                initPTS = initDTS = audioSamples[0].pts - audioTrack.inputTimeScale * timeOffset;
14336            }
14337        }
14338        if (videoTrack.sps && videoTrack.pps && videoSamples.length) {
14339            // let's use input time scale as MP4 video timescale
14340            // we use input time scale straight away to avoid rounding issues on frame duration / cts computation
14341            var inputTimeScale = videoTrack.inputTimeScale;
14342            videoTrack.timescale = inputTimeScale;
14343            tracks.video = {
14344                container: 'video/mp4',
14345                codec: videoTrack.codec,
14346                initSegment: mp4_generator_1.default.initSegment([videoTrack]),
14347                metadata: {
14348                    width: videoTrack.width,
14349                    height: videoTrack.height
14350                }
14351            };
14352            if (computePTSDTS) {
14353                initPTS = Math.min(initPTS, videoSamples[0].pts - inputTimeScale * timeOffset);
14354                initDTS = Math.min(initDTS, videoSamples[0].dts - inputTimeScale * timeOffset);
14355                this.observer.trigger(events_1.default.INIT_PTS_FOUND, { initPTS: initPTS });
14356            }
14357        }
14358        if (Object.keys(tracks).length) {
14359            observer.trigger(events_1.default.FRAG_PARSING_INIT_SEGMENT, data);
14360            this.ISGenerated = true;
14361            if (computePTSDTS) {
14362                this._initPTS = initPTS;
14363                this._initDTS = initDTS;
14364            }
14365        }
14366        else {
14367            observer.trigger(events_1.default.ERROR, { type: errors_1.ErrorTypes.MEDIA_ERROR, details: errors_1.ErrorDetails.FRAG_PARSING_ERROR, fatal: false, reason: 'no audio/video samples found' });
14368        }
14369    };
14370    MP4Remuxer.prototype.remuxVideo = function (track, timeOffset, contiguous, audioTrackLength, accurateTimeOff
14370set) {
14371        var offset = 8;
14372        var mp4SampleDuration;
14373        var mdat;
14374        var moof;
14375        var firstPTS;
14376        var firstDTS;
14377        var lastPTS;
14378        var lastDTS;
14379        var timeScale = track.timescale;
14380        var inputSamples = track.samples;
14381        var outputSamples = [];
14382        var nbSamples = inputSamples.length;
14383        var ptsNormalize = this._PTSNormalize;
14384        var initPTS = this._initPTS;
14385        // if parsed fragment is contiguous with last one, let's use last DTS value as reference
14386        var nextAvcDts = this.nextAvcDts;
14387        var isSafari = this.isSafari;
14388        if (nbSamples === 0) {
14389            return;
14390        }
14391        // Safari does not like overlapping DTS on consecutive fragments. let's use nextAvcDts to overcome this if fragments are consecutive
14392        if (isSafari) {
14393            // also consider consecutive fragments as being contiguous (even if a level switch occurs),
14394            // for sake of clarity:
14395            // consecutive fragments are frags with
14396            //  - less than 100ms gaps between new time offset (if accurate) and next expected PTS OR
14397            //  - less than 200 ms PTS gaps (timeScale/5)
14398            contiguous |= (inputSamples.length && nextAvcDts &&
14399                ((accurateTimeOffset && Math.abs(timeOffset - nextAvcDts / timeScale) < 0.1) ||
14400                    Math.abs((inputSamples[0].pts - nextAvcDts - initPTS)) < timeScale / 5));
14401        }
14402        if (!contiguous) {
14403            // if not contiguous, let's use target timeOffset
14404            nextAvcDts = timeOffset * timeScale;
14405        }
14406        // PTS is coded on 33bits, and can loop from -2^32 to 2^32
14407        // ptsNormalize will make PTS/DTS value monotonic, we use last known DTS value as reference value
14408        inputSamples.forEach(function (sample) {
14409            sample.pts = ptsNormalize(sample.pts - initPTS, nextAvcDts);
14410            sample.dts = ptsNormalize(sample.dts - initPTS, nextAvcDts);
14411        });
14412        // sort video samples by DTS then PTS then demux id order
14413        inputSamples.sort(function (a, b) {
14414            var deltadts = a.dts - b.dts;
14415            var deltapts = a.pts - b.pts;
14416            return deltadts || (deltapts || (a.id - b.id));
14417        });
14418        // handle broken streams with PTS < DTS, tolerance up 200ms (18000 in 90kHz timescale)
14419        var PTSDTSshift = inputSamples.reduce(function (prev, curr) { return Math.max(Math.min(prev, curr.pts - curr.dts), -18000); }, 0);
14420        if (PTSDTSshift < 0) {
14421            logger_1.logger.warn("PTS < DTS detected in video samples, shifting DTS by " + Math.round(PTSDTSshift / 90) + " ms to overcome this issue");
14422            for (var i = 0; i < inputSamples.length; i++) {
14423                inputSamples[i].dts += PTSDTSshift;
14424            }
14425        }
14426        // compute first DTS and last DTS, normalize them against reference value
14427        var sample = inputSamples[0];
14428        firstDTS = Math.max(sample.dts, 0);
14429        firstPTS = Math.max(sample.pts, 0);
14430        // check timestamp continuity accross consecutive fragments (this is to remove inter-fragment gap/hole)
14431        var delta = Math.round((firstDTS - nextAvcDts) / 90);
14432        // if fragment are contiguous, detect hole/overlapping between fragments
14433        if (contiguous) {
14434            if (delta) {
14435                if (delta > 1) {
14436                    logger_1.logger.log("AVC:" + delta + " ms hole between fragments detected,filling it");
14437                }
14438                else if (delta < -1) {
14439                    logger_1.logger.log("AVC:" + (-delta) + " ms overlapping between fragments detected");
14440                }
14441                // remove hole/gap : set DTS to next expected DTS
14442                firstDTS = nextAvcDts;
14443                inputSamples[0].dts = firstDTS;
14444                // offset PTS as well, ensure that PTS is smaller or equal than new DTS
14445                firstPTS = Math.max(firstPTS - delta, nextAvcDts);
14446                inputSamples[0].pts = firstPTS;
14447                logger_1.logger.log("Video/PTS/DTS adjusted: " + Math.round(firstPTS / 90) + "/" + Math.round(firstDTS / 90) + ",delta:" + delta + " ms");
14448            }
14449        }
14450        // compute lastPTS/lastDTS
14451        sample = inputSamples[inputSamples.length - 1];
14452        lastDTS = Math.max(sample.dts, 0);
14453        lastPTS = Math.max(sample.pts, 0, lastDTS);
14454        // on Safari let's signal the same sample duration for all samples
14455        // sample duration (as expected by trun MP4 boxes), should be the delta between sample DTS
14456        // set this constant duration as being the avg delta between consecutive DTS.
14457        if (isSafari) {
14458            mp4SampleDuration = Math.round((lastDTS - firstDTS) / (inputSamples.length - 1));
14459        }
14460        var nbNalu = 0, naluLen = 0;
14461        for (var i = 0; i < nbSamples; i++) {
14462            // compute total/avc sample length and nb of NAL units
vendor: 6,912 bytes, lines 14463-14590
14463            var sample_1 = inputSamples[i], units = sample_1.units, nbUnits = units.length, sampleLen = 0;
14464            for (var j = 0; j < nbUnits; j++) {
14465                sampleLen += units[j].data.length;
14466            }
14467            naluLen += sampleLen;
14468            nbNalu += nbUnits;
14469            sample_1.length = sampleLen;
14470            // normalize PTS/DTS
14471            if (isSafari) {
14472                // sample DTS is computed using a constant decoding offset (mp4SampleDuration) between samples
14473                sample_1.dts = firstDTS + i * mp4SampleDuration;
14474            }
14475            else {
14476                // ensure sample monotonic DTS
14477                sample_1.dts = Math.max(sample_1.dts, firstDTS);
14478            }
14479            // ensure that computed value is greater or equal than sample DTS
14480            sample_1.pts = Math.max(sample_1.pts, sample_1.dts);
14481        }
14482        /* concatenate the video data and construct the mdat in place
14483          (need 8 more bytes to fill length and mpdat type) */
14484        var mdatSize = naluLen + (4 * nbNalu) + 8;
14485        try {
14486            mdat = new Uint8Array(mdatSize);
14487        }
14488        catch (err) {
14489            this.observer.trigger(events_1.default.ERROR, { type: errors_1.ErrorTypes.MUX_ERROR, details: errors_1.ErrorDetails.REMUX_ALLOC_ERROR, fatal: false, bytes: mdatSize, reason: "fail allocating video mdat " + mdatSize });
14490            return;
14491        }
14492        var view = new DataView(mdat.buffer);
14493        view.setUint32(0, mdatSize);
14494        mdat.set(mp4_generator_1.default.types.mdat, 4);
14495        for (var i = 0; i < nbSamples; i++) {
14496            var avcSample = inputSamples[i], avcSampleUnits = avcSample.units, mp4SampleLength = 0, compositionTimeOffset = void 0;
14497            // convert NALU bitstream to MP4 format (prepend NALU with size field)
14498            for (var j = 0, nbUnits = avcSampleUnits.length; j < nbUnits; j++) {
14499                var unit = avcSampleUnits[j], unitData = unit.data, unitDataLen = unit.data.byteLength;
14500                view.setUint32(offset, unitDataLen);
14501                offset += 4;
14502                mdat.set(unitData, offset);
14503                offset += unitDataLen;
14504                mp4SampleLength += 4 + unitDataLen;
14505            }
14506            if (!isSafari) {
14507                // expected sample duration is the Decoding Timestamp diff of consecutive samples
14508                if (i < nbSamples - 1) {
14509                    mp4SampleDuration = inputSamples[i + 1].dts - avcSample.dts;
14510                }
14511                else {
14512                    var config = this.config, lastFrameDuration = avcSample.dts - inputSamples[i > 0 ? i - 1 : i].dts;
14513                    if (config.stretchShortVideoTrack) {
14514                        // In some cases, a segment's audio track duration may exceed the video track duration.
14515                        // Since we've already remuxed audio, and we know how long the audio track is, we look to
14516                        // see if the delta to the next segment is longer than maxBufferHole.
14517                        // If so, playback would potentially get stuck, so we artificially inflate
14518                        // the duration of the last frame to minimize any potential gap between segments.
14519                        var maxBufferHole = config.maxBufferHole, gapTolerance = Math.floor(maxBufferHole * timeScale), deltaToFrameEnd = (audioTrackLength ? firstPTS + audioTrackLength * timeScale : this.nextAudioPts) - avcSample.pts;
14520                        if (deltaToFrameEnd > gapTolerance) {
14521                            // We subtract lastFrameDuration from deltaToFrameEnd to try to prevent any video
14522                            // frame overlap. maxBufferHole should be >> lastFrameDuration anyway.
14523                            mp4SampleDuration = deltaToFrameEnd - lastFrameDuration;
14524                            if (mp4SampleDuration < 0) {
14525                                mp4SampleDuration = lastFrameDuration;
14526                            }
14527                            logger_1.logger.log("It is approximately " + deltaToFrameEnd / 90 + " ms to the next segment; using duration " + mp4SampleDuration / 90 + " ms for the last video frame.");
14528                        }
14529                        else {
14530                            mp4SampleDuration = lastFrameDuration;
14531                        }
14532                    }
14533                    else {
14534                        mp4SampleDuration = lastFrameDuration;
14535                    }
14536                }
14537                compositionTimeOffset = Math.round(avcSample.pts - avcSample.dts);
14538            }
14539            else {
14540                compositionTimeOffset = Math.max(0, mp4SampleDuration * Math.round((avcSample.pts - avcSample.dts) / mp4SampleDuration));
14541            }
14542            // console.log('PTS/DTS/initDTS/normPTS/normDTS/relative PTS : ${avcSample.pts}/${avcSample.dts}/${initDTS}/${ptsnorm}/${dtsnorm}/${(avcSample.pts/4294967296).toFixed(3)}');
14543            outputSamples.push({
14544                size: mp4SampleLength,
14545                // constant duration
14546                duration: mp4SampleDuration,
14547                cts: compositionTimeOffset,
14548                flags: {
14549                    isLeading: 0,
14550                    isDependedOn: 0,
14551                    hasRedundancy: 0,
14552                    degradPrio: 0,
14553                    dependsOn: avcSample.key ? 2 : 1,
14554                    isNonSync: avcSample.key ? 0 : 1
14555                }
14556            });
14557        }
14558        // next AVC sample DTS should be equal to last sample DTS + last sample duration (in PES timescale)
14559        this.nextAvcDts = lastDTS + mp4SampleDuration;
14560        var dropped = track.dropped;
14561        track.len = 0;
14562        track.nbNalu = 0;
14563        track.dropped = 0;
14564        if (outputSamples.length && navigator.userAgent.toLowerCase().indexOf('chrome') > -1) {
14565            var flags = outputSamples[0].flags;
14566            // chrome workaround, mark first sample as being a Random Access Point to avoid sourcebuffer append issue
14567            // https://code.google.com/p/chromium/issues/detail?id=229412
14568            flags.dependsOn = 2;
14569            flags.isNonSync = 0;
14570        }
14571        track.samples = outputSamples;
14572        moof = mp4_generator_1.default.moof(track.sequenceNumber++, firstDTS, track);
14573        track.samples = [];
14574        var data = {
14575            data1: moof,
14576            data2: mdat,
14577            startPTS: firstPTS / timeScale,
14578            endPTS: (lastPTS + mp4SampleDuration) / timeScale,
14579            startDTS: firstDTS / timeScale,
14580            endDTS: this.nextAvcDts / timeScale,
14581            type: 'video',
14582            hasAudio: false,
14583            hasVideo: true,
14584            nb: outputSamples.length,
14585            dropped: dropped
14586        };
14587        this.observer.trigger(events_1.default.FRAG_PARSING_DATA, data);
14588        return data;
14589    };
14590    MP4Remuxer.prototype.remuxAudio = function (track, timeOffset, contiguous, accurateTimeOff
14590set) {
14591        var inputTimeScale = track.inputTimeScale;
14592        var mp4timeScale = track.timescale;
14593        var scaleFactor = inputTimeScale / mp4timeScale;
14594        var mp4SampleDuration = track.isAAC ? 1024 : 1152;
14595        var inputSampleDuration = mp4SampleDuration * scaleFactor;
14596        var ptsNormalize = this._PTSNormalize;
14597        var initPTS = this._initPTS;
14598        var rawMPEG = !track.isAAC && this.typeSupported.mpeg;
14599        var offset, mp4Sample, fillFrame, mdat, moof, firstPTS, lastPTS, inputSamples = track.samples, outputSamples = [], nextAudioPts = this.nextAudioPts;
14600        // for audio samples, also consider consecutive fragments as being contiguous (even if a level switch occurs),
14601        // for sake of clarity:
14602        // consecutive fragments are frags with
14603        //  - less than 100ms gaps between new time offset (if accurate) and next expected PTS OR
14604        //  - less than 20 audio frames distance
14605        // contiguous fragments are consecutive fragments from same quality level (same level, new SN = old SN + 1)
14606        // this helps ensuring audio continuity
14607        // and this also avoids audio glitches/cut when switching quality, or reporting wrong duration on first audio frame
14608        contiguous |= (inputSamples.length && nextAudioPts &&
14609            ((accurateTimeOffset && Math.abs(timeOffset - nextAudioPts / inputTimeScale) < 0.1) ||
14610                Math.abs((inputSamples[0].pts - nextAudioPts - initPTS)) < 20 * inputSampleDuration));
14611        // compute normalized PTS
14612        inputSamples.forEach(function (sample) {
14613            sample.pts = sample.dts = ptsNormalize(sample.pts - initPTS, timeOffset * inputTimeScale);
14614        });
14615        // filter out sample with negative PTS that are not playable anyway
14616        // if we don't remove these negative samples, they will shift all audio samples forward.
14617        // leading to audio overlap between current / next fragment
14618        inputSamples = inputSamples.filter(function (sample) {
14619            return sample.pts >= 0;
14620        });
14621        // in case all samples have negative PTS, and have been filtered out, return now
14622        if (inputSamples.length === 0) {
14623            return;
14624        }
14625        if (!contiguous) {
14626            if (!accurateTimeOffset) {
14627                // if frag are mot contiguous and if we cant trust time offset, let's use first sample PTS as next audio PTS
14628                nextAudioPts = inputSamples[0].pts;
14629            }
14630            else {
14631                // if timeOffset is accurate, let's use it as predicted next audio PTS
14632                nextAudioPts = timeOffset * inputTimeScale;
14633            }
14634        }
14635        // If the audio track is missing samples, the frames seem to get "left-shifted" within the
14636        // resulting mp4 segment, causing sync issues and leaving gaps at the end of the audio segment.
14637        // In an effort to prevent this from happening, we inject frames here where there are gaps.
14638        // When possible, we inject a silent frame; when that's not possible, we duplicate the last
14639        // frame.
14640        if (track.isAAC) {
14641            var maxAudioFramesDrift = this.config.maxAudioFramesDrift;
14642            for (var i = 0, nextPts = nextAudioPts; i < inputSamples.length;) {
14643                // First, let's see how far off this frame is from where we expect it to be
14644                var sample = inputSamples[i], delta;
14645                var pts = sample.pts;
14646                delta = pts - nextPts;
14647                var duration = Math.abs(1000 * delta / inputTimeScale);
14648                // If we're overlapping by more than a duration, drop this sample
14649                if (delta <= -maxAudioFramesDrift * inputSampleDuration) {
14650                    logger_1.logger.warn("Dropping 1 audio frame @ " + (nextPts / inputTimeScale).toFixed(3) + "s due to " + Math.round(duration) + " ms overlap.");
14651                    inputSamples.splice(i, 1);
14652                    track.len -= sample.unit.length;
14653                    // Don't touch nextPtsNorm or i
14654                } // eslint-disable-line brace-style
14655                // Insert missing frames if:
14656                // 1: We're more than maxAudioFramesDrift frame away
14657                // 2: Not more than MAX_SILENT_FRAME_DURATION away
14658                // 3: currentTime (aka nextPtsNorm) is not 0
14659                else if (delta >= maxAudioFramesDrift * inputSampleDuration && duration < MAX_SILENT_FRAME_DURATION && nextPts) {
14660                    var missing = Math.round(delta / inputSampleDuration);
14661                    logger_1.logger.warn("Injecting " + missing + " audio frame @ " + (nextPts / inputTimeScale).toFixed(3) + "s due to " + Math.round(1000 * delta / inputTimeScale) + " ms gap.");
14662                    for (var j = 0; j < missing; j++) {
14663                        var newStamp = Math.max(nextPts, 0);
14664                        fillFrame = aac_helper_1.default.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
14665                        if (!fillFrame) {
14666                            logger_1.logger.log('Unable to get silent frame for given audio codec; duplicating last frame instead.');
14667                            fillFrame = sample.unit.subarray();
14668                        }
14669                        inputSamples.splice(i, 0, { unit: fillFrame, pts: newStamp, dts: newStamp });
14670                        track.len += fillFrame.length;
14671                        nextPts += inputSampleDuration;
14672                        i++;
14673                    }
14674                    // Adjust sample to next expected pts
14675                    sample.pts = sample.dts = nextPts;
14676                    nextPts += inputSampleDuration;
14677                    i++;
14678                }
14679                else {
14680                    // Otherwise, just adjust pts
14681                    if (Math.abs(delta) > (0.1 * inputSampleDuration)) {
14682                        // logger.log(`Invalid frame delta ${Math.round(delta + inputSampleDuration)} at PTS ${Math.round(pts / 90)} (should be ${Math.round(inputSampleDuration)}).`);
14683                    }
14684                    sample.pts = sample.dts = nextPts;
14685                    nextPts += inputSampleDuration;
14686                    i++;
14687                }
14688            }
14689        }
14690        for (var j = 0, nbSamples_1 = inputSamples.length; j < nbSamples_1; j++) {
14691            var audioSample = inputSamples[j];
14692            var unit = audioSample.unit;
14693            var pts = audioSample.pts;
14694            // logger.log(`Audio/PTS:${Math.round(pts/90)}`);
14695            // if not first sample
14696            if (lastPTS !== undefined) {
14697                mp4Sample.duration = Math.round((pts - lastPTS) / scaleFactor);
14698            }
14699            else {
14700                var delta_1 = Math.round(1000 * (pts - nextAudioPts) / inputTimeScale), numMissingFrames = 0;
14701                // if fragment are contiguous, detect hole/overlapping between fragments
14702                // contiguous fragments are consecutive fragments from same quality level (same level, new SN = old SN + 1)
14703                if (contiguous && track.isAAC) {
14704                    // log delta
14705                    if (delta_1) {
14706                        if (delta_1 > 0 && delta_1 < MAX_SILENT_FRAME_DURATION) {
14707                            numMissingFrames = Math.round((pts - nextAudioPts) / inputSampleDuration);
14708                            logger_1.logger.log(delta_1 + " ms hole between AAC samples detected,filling it");
14709                            if (numMissingFrames > 0) {
14710                                fillFrame = aac_helper_1.default.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
14711                                if (!fillFrame) {
14712                                    fillFrame = unit.subarray();
14713                                }
14714                                track.len += numMissingFrames * fillFrame.length;
14715                            }
14716                            // if we have frame overlap, overlapping for more than half a frame duraion
14717                        }
14718                        else if (delta_1 < -12) {
14719                            // drop overlapping audio frames... browser will deal with it
14720                            logger_1.logger.log("drop overlapping AAC sample, expected/parsed/delta:" + (nextAudioPts / inputTimeScale).toFixed(3) + "s/" + (pts / inputTimeScale).toFixed(3) + "s/" + (-delta_1) + "ms");
14721                            track.len -= unit.byteLength;
14722                            continue;
14723                        }
14724                        // set PTS/DTS to expected PTS/DTS
14725                        pts = nextAudioPts;
14726                    }
14727                }
14728                // remember first PTS of our audioSamples
14729                firstPTS = pts;
14730                if (track.len > 0) {
14731                    /* concatenate the audio data and construct the mdat in place
14732                      (need 8 more bytes to fill length and mdat type) */
14733                    var mdatSize = rawMPEG ? track.len : track.len + 8;
14734                    offset = rawMPEG ? 0 : 8;
14735                    try {
14736                        mdat = new Uint8Array(mdatSize);
14737                    }
14738                    catch (err) {
14739                        this.observer.trigger(events_1.default.ERROR, { type: errors_1.ErrorTypes.MUX_ERROR, details: errors_1.ErrorDetails.REMUX_ALLOC_ERROR, fatal: false, bytes: mdatSize, reason: "fail allocating audio mdat " + mdatSize });
14740                        return;
14741                    }
14742                    if (!rawMPEG) {
14743                        var view = new DataView(mdat.buffer);
14744                        view.setUint32(0, mdatSize);
14745                        mdat.set(mp4_generator_1.default.types.mdat, 4);
14746                    }
14747                }
14748                else {
14749                    // no audio samples
14750                    return;
14751                }
14752                for (var i = 0; i < numMissingFrames; i++) {
14753                    fillFrame = aac_helper_1.default.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
14754                    if (!fillFrame) {
14755                        logger_1.logger.log('Unable to get silent frame for given audio codec; duplicating this frame instead.');
14756                        fillFrame = unit.subarray();
14757                    }
14758                    mdat.set(fillFrame, offset);
14759                    offset += fillFrame.byteLength;
14760                    mp4Sample = {
14761                        size: fillFrame.byteLength,
14762                        cts: 0,
14763                        duration: 1024,
14764                        flags: {
14765                            isLeading: 0,
14766                            isDependedOn: 0,
14767                            hasRedundancy: 0,
14768                            degradPrio: 0,
14769                            dependsOn: 1
14770                        }
14771                    };
14772                    outputSamples.push(mp4Sample);
14773                }
14774            }
14775            mdat.set(unit, offset);
14776            var unitLen = unit.byteLength;
14777            offset += unitLen;
14778            // console.log('PTS/DTS/initDTS/normPTS/normDTS/relative PTS : ${audioSample.pts}/${audioSample.dts}/${initDTS}/${ptsnorm}/${dtsnorm}/${(audioSample.pts/4294967296).toFixed(3)}');
14779            mp4Sample = {
14780                size: unitLen,
14781                cts: 0,
14782                duration: 0,
14783                flags: {
14784                    isLeading: 0,
14785                    isDependedOn: 0,
14786                    hasRedundancy: 0,
14787                    degradPrio: 0,
14788                    dependsOn: 1
14789                }
14790            };
14791            outputSamples.push(mp4Sample);
14792            lastPTS = pts;
14793        }
14794        var lastSampleDuration = 0;
14795        var nbSamples = outputSamples.length;
14796        // set last sample duration as being identical to previous sample
14797        if (nbSamples >= 2) {
14798            lastSampleDuration = outputSamples[nbSamples - 2].duration;
14799            mp4Sample.duration = lastSampleDuration;
14800        }
14801        if (nbSamples) {
14802            // next audio sample PTS should be equal to last sample PTS + duration
14803            this.nextAudioPts = nextAudioPts = lastPTS + scaleFactor * lastSampleDuration;
14804            // logger.log('Audio/PTS/PTSend:' + audioSample.pts.toFixed(0) + '/' + this.nextAacDts.toFixed(0));
14805            track.len = 0;
14806            track.samples = outputSamples;
14807            if (rawMPEG) {
14808                moof = new Uint8Array();
14809            }
14810            else {
14811                moof = mp4_generator_1.default.moof(track.sequenceNumber++, firstPTS / scaleFactor, track);
14812            }
14813            track.samples = [];
14814            var start = firstPTS / inputTimeScale;
14815            var end = nextAudioPts / inputTimeScale;
14816            var audioData = {
14817                data1: moof,
14818                data2: mdat,
14819                startPTS: start,
14820                endPTS: end,
14821                startDTS: start,
14822                endDTS: end,
14823                type: 'audio',
14824                hasAudio: true,
14825                hasVideo: false,
14826                nb: nbSamples
14827            };
14828            this.observer.trigger(events_1.default.FRAG_PARSING_DATA, audioData);
14829            return audioData;
14830        }
14831        return null;
14832    };
14833    MP4Remuxer.prototype.remuxEmptyAudio = function (track, timeOffset, contiguous, videoData) {
14834        var inputTimeScale = track.inputTimeScale, mp4timeScale = track.samplerate ? track.samplerate : inputTimeScale, scaleFactor = inputTimeScale / mp4timeScale, nextAudioPts = this.nextAudioPts, 
14835        // sync with video's timestamp
14836        startDTS = (nextAudioPts !== undefined ? nextAudioPts : videoData.startDTS * inputTimeScale) + this._initDTS, endDTS = videoData.endDTS * inputTimeScale + this._initDTS, 
14837        // one sample's duration value
14838        sampleDuration = 1024, frameDuration = scaleFactor * sampleDuration, 
14839        // samples count of this segment's duration
14840        nbSamples = Math.ceil((endDTS - startDTS) / frameDuration), 
14841        // silent frame
14842        silentFrame = aac_helper_1.default.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
14843        logger_1.logger.warn('remux empty Audio');
14844        // Can't remux if we can't generate a silent frame...
14845        if (!silentFrame) {
14846            logger_1.logger.trace('Unable to remuxEmptyAudio since we were unable to get a silent frame for given audio codec!');
14847            return;
14848        }
14849        var samples = [];
14850        for (var i = 0; i < nbSamples; i++) {
14851            var stamp = startDTS + i * frameDuration;
14852            samples.push({ unit: silentFrame, pts: stamp, dts: stamp });
14853            track.len += silentFrame.length;
14854        }
14855        track.samples = samples;
14856        this.remuxAudio(track, timeOffset, contiguous);
14857    };
14858    MP4Remuxer.prototype.remuxID3 = function (track) {
14859        var length = track.samples.length, sample;
14860        var inputTimeScale = track.inputTimeScale;
14861        var initPTS = this._initPTS;
14862        var initDTS = this._initDTS;
14863        // consume samples
14864        if (length) {
14865            for (var index = 0; index < length; index++) {
14866                sample = track.samples[index];
14867                // setting id3 pts, dts to relative time
14868                // using this._initPTS and this._initDTS to calculate relative time
14869                sample.pts = ((sample.pts - initPTS) / inputTimeScale);
14870                sample.dts = ((sample.dts - initDTS) / inputTimeScale);
14871            }
14872            this.observer.trigger(events_1.default.FRAG_PARSING_METADATA, {
14873                samples: track.samples
14874            });
14875        }
14876        track.samples = [];
14877    };
14878    MP4Remuxer.prototype.remuxText = function (track) {
14879        track.samples.sort(function (a, b) {
14880            return (a.pts - b.pts);
14881        });
14882        var length = track.samples.length, sample;
14883        var inputTimeScale = track.inputTimeScale;
14884        var initPTS = this._initPTS;
14885        // consume samples
14886        if (length) {
14887            for (var index = 0; index < length; index++) {
14888                sample = track.samples[index];
14889                // setting text pts, dts to relative time
14890                // using this._initPTS and this._initDTS to calculate relative time
14891                sample.pts = ((sample.pts - initPTS) / inputTimeScale);
14892            }
14893            this.observer.trigger(events_1.default.FRAG_PARSING_USERDATA, {
14894                samples: track.samples
14895            });
14896        }
14897        track.samples = [];
14898    };
14899    MP4Remuxer.prototype._PTSNormalize = function (value, reference) {
14900        var offset;
14901        if (reference === undefined) {
14902            return value;
14903        }
14904        if (reference < value) {
14905            // - 2^33
14906            offset = -8589934592;
14907        }
14908        else {
14909            // + 2^33
14910            offset = 8589934592;
14911        }
14912        /* PTS is 33bit (from 0 to 2^33 -1)
14913          if diff between value and reference is bigger than half of the amplitude (2^32) then it means that
14914          PTS looping occured. fill the gap */
14915        while (Math.abs(value - reference) > 4294967296) {
14916            value += offset;
14917        }
14918        return value;
14919    };
14920    return MP4Remuxer;
14921}());
14922exports.default = MP4Remuxer;
14923
14924
14925/***/ }),
14926
14927/***/ "./src/remux/passthrough-remuxer.js":
14928/*!******************************************!*\
14929  !*** ./src/remux/passthrough-remuxer.js ***!
14930  \******************************************/
14931/*! no static exports found */
14932/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
14933/***/ (function(module, exports, __webpack_require__) {
14934
14935"use strict";
14936
14937Object.defineProperty(exports, "__esModule", { value: true });
14938/**
14939 * passthrough remuxer
14940*/
14941var events_1 = __webpack_require__(/*! ../events */ "./src/events.js");
14942var PassThroughRemuxer = /** @class */ (function () {
14943    function PassThroughRemuxer(observer) {
14944        this.observer = observer;
14945    }
14946    PassThroughRemuxer.prototype.destroy = function () {
14947    };
14948    PassThroughRemuxer.prototype.resetTimeStamp = function () {
14949    };
14950    PassThroughRemuxer.prototype.resetInitSegment = function () {
14951    };
14952    PassThroughRemuxer.prototype.remux = function (audioTrack, videoTrack, id3Track, textTrack, timeOffset, contiguous, accurateTimeOffset, rawData) {
14953        var observer = this.observer;
14954        var streamType = '';
14955        if (audioTrack) {
14956            streamType += 'audio';
14957        }
14958        if (videoTrack) {
14959            streamType += 'video';
14960        }
14961        observer.trigger(events_1.default.FRAG_PARSING_DATA, {
14962            data1: rawData,
14963            startPTS: timeOffset,
14964            startDTS: timeOffset,
14965            type: streamType,
14966            hasAudio: !!audioTrack,
14967            hasVideo: !!videoTrack,
14968            nb: 1,
14969            dropped: 0
14970        });
14971        // notify end of parsing
14972        observer.trigger(events_1.default.FRAG_PARSED);
14973    };
14974    return PassThroughRemuxer;
14975}());
14976exports.default = PassThroughRemuxer;
14977
14978
14979/***/ }),
14980
14981/***/ "./src/task-loop.js":
14982/*!**************************!*\
14983  !*** ./src/task-loop.js ***!
14984  \**************************/
14985/*! no static exports found */
14986/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
14987/***/ (function(module, exports, __webpack_require__) {
14988
14989"use strict";
14990
14991var __extends = (this && this.__extends) || (function () {
14992    var extendStatics = Object.setPrototypeOf ||
14993        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
14994        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
14995    return function (d, b) {
14996        extendStatics(d, b);
14997        function __() { this.constructor = d; }
14998        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
14999    };
15000})();
15001Object.defineProperty(exports, "__esModule", { value: true });
15002var event_handler_1 = __webpack_require__(/*! ./event-handler */ "./src/event-handler.js");
15003/**
15004 * Sub-class specialization of EventHandler base class.
15005 *
15006 * TaskLoop allows to schedule a task function being called (optionnaly repeatedly) on the main loop,
15007 * scheduled asynchroneously, avoiding recursive calls in the same tick.
15008 *
15009 * The task itself is implemented in `doTick`. It can be requested and called for single execution
15010 * using the `tick` method.
15011 *
15012 * It will be assured that the task execution method (`tick`) only gets called once per main loop "tick",
15013 * no matter how often it gets requested for execution. Execution in further ticks will be scheduled accordingly.
15014 *
15015 * If further execution requests have already been scheduled on the next tick, it can be checked with `hasNextTick`,
15016 * and cancelled with `clearNextTick`.
15017 *
15018 * The task can be scheduled as an interval repeatedly with a period as parameter (see `setInterval`, `clearInterval`).
15019 *
15020 * Sub-classes need to implement the `doTick` method which will effectively have the task execution routine.
15021 *
15022 * Further explanations:
15023 *
15024 * The baseclass has a `tick` method that will schedule the doTick call. It may be called synchroneously
15025 * only for a stack-depth of one. On re-entrant calls, sub-sequent calls are scheduled for next main loop ticks.
15026 *
15027 * When the task execution (`tick` method) is called in re-entrant way this is detected and
15028 * we are limiting the task execution per call stack to exactly one, but scheduling/post-poning further
15029 * task processing on the next main loop iteration (also known as "next tick" in the Node/JS runtime lingo).
15030 */
15031var TaskLoop = /** @class */ (function (_super) {
15032    __extends(TaskLoop, _super);
15033    function TaskLoop(hls) {
15034        var events = [];
15035        for (var _i = 1; _i < arguments.length; _i++) {
15036            events[_i - 1] = arguments[_i];
15037        }
15038        var _this = _super.apply(this, [hls].concat(events)) || this;
15039        _this._tickInterval = null;
15040        _this._tickTimer = null;
15041        _this._tickCallCount = 0;
15042        _this._boundTick = _this.tick.bind(_this);
15043        return _this;
15044    }
15045    /**
15046     * @override
15047     */
15048    TaskLoop.prototype.onHandlerDestroying = function () {
15049        // clear all timers before unregistering from event bus
15050        this.clearNextTick();
15051        this.clearInterval();
15052    };
15053    /**
15054     * @returns {boolean}
15055     */
15056    TaskLoop.prototype.hasInterval = function () {
15057        return !!this._tickInterval;
15058    };
15059    /**
15060     * @returns {boolean}
15061     */
15062    TaskLoop.prototype.hasNextTick = function () {
15063        return !!this._tickTimer;
15064    };
15065    /**
15066     * @param {number} millis Interval time (ms)
15067     * @returns {boolean} True when interval has been scheduled, false when already scheduled (no effect)
15068     */
15069    TaskLoop.prototype.setInterval = function (millis) {
15070        if (!this._tickInterval) {
15071            this._tickInterval = setInterval(this._boundTick, millis);
15072            return true;
15073        }
15074        return false;
15075    };
15076    /**
15077     * @returns {boolean} True when interval was cleared, false when none was set (no effect)
15078     */
15079    TaskLoop.prototype.clearInterval = function () {
15080        if (this._tickInterval) {
15081            clearInterval(this._tickInterval);
15082            this._tickInterval = null;
15083            return true;
15084        }
15085        return false;
15086    };
15087    /**
15088     * @returns {boolean} True when timeout was cleared, false when none was set (no effect)
15089     */
15090    TaskLoop.prototype.clearNextTick = function () {
15091        if (this._tickTimer) {
15092            clearTimeout(this._tickTimer);
15093            this._tickTimer = null;
15094            return true;
15095        }
15096        return false;
15097    };
15098    /**
15099     * Will call the subclass doTick implementation in this main loop tick
15100     * or in the next one (via setTimeout(,0)) in case it has already been called
15101     * in this tick (in case this is a re-entrant call).
15102     */
15103    TaskLoop.prototype.tick = function () {
15104        this._tickCallCount++;
15105        if (this._tickCallCount === 1) {
15106            this.doTick();
15107            // re-entrant call to tick from previous doTick call stack
15108            // -> schedule a call on the next main loop iteration to process this task processing request
15109            if (this._tickCallCount > 1) {
15110                // make sure only one timer exists at any time at max
15111                this.clearNextTick();
15112                this._tickTimer = setTimeout(this._boundTick, 0);
15113            }
15114            this._tickCallCount = 0;
15115        }
15116    };
15117    /**
15118     * For subclass to implement task logic
15119     * @abstract
15120     */
15121    TaskLoop.prototype.doTick = function () { };
15122    return TaskLoop;
15123}(event_handler_1.default));
15124exports.default = TaskLoop;
15125
15126
15127/***/ }),
15128
vendor: 3,282 bytes, lines 15129-15218
15129/***/ "./src/utils/attr-list.js":
15130/*!********************************!*\
15131  !*** ./src/utils/attr-list.js ***!
15132  \********************************/
15133/*! no static exports found */
15134/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
15135/***/ (function(module, exports, __webpack_require__) {
15136
15137"use strict";
15138/* WEBPACK VAR INJECTION */(function(Number) {
15139Object.defineProperty(exports, "__esModule", { value: true });
15140var DECIMAL_RESOLUTION_REGEX = /^(\d+)x(\d+)$/; // eslint-disable-line no-useless-escape
15141var ATTR_LIST_REGEX = /\s*(.+?)\s*=((?:\".*?\")|.*?)(?:,|$)/g; // eslint-disable-line no-useless-escape
15142// adapted from https://github.com/kanongil/node-m3u8parse/blob/master/attrlist.js
15143var AttrList = /** @class */ (function () {
15144    function AttrList(attrs) {
15145        if (typeof attrs === 'string') {
15146            attrs = AttrList.parseAttrList(attrs);
15147        }
15148        for (var attr in attrs) {
15149            if (attrs.hasOwnProperty(attr)) {
15150                this[attr] = attrs[attr];
15151            }
15152        }
15153    }
15154    AttrList.prototype.decimalInteger = function (attrName) {
15155        var intValue = parseInt(this[attrName], 10);
15156        if (intValue > Number.MAX_SAFE_INTEGER) {
15157            return Infinity;
15158        }
15159        return intValue;
15160    };
15161    AttrList.prototype.hexadecimalInteger = function (attrName) {
15162        if (this[attrName]) {
15163            var stringValue = (this[attrName] || '0x').slice(2);
15164            stringValue = ((stringValue.length & 1) ? '0' : '') + stringValue;
15165            var value = new Uint8Array(stringValue.length / 2);
15166            for (var i = 0; i < stringValue.length / 2; i++) {
15167                value[i] = parseInt(stringValue.slice(i * 2, i * 2 + 2), 16);
15168            }
15169            return value;
15170        }
15171        else {
15172            return null;
15173        }
15174    };
15175    AttrList.prototype.hexadecimalIntegerAsNumber = function (attrName) {
15176        var intValue = parseInt(this[attrName], 16);
15177        if (intValue > Number.MAX_SAFE_INTEGER) {
15178            return Infinity;
15179        }
15180        return intValue;
15181    };
15182    AttrList.prototype.decimalFloatingPoint = function (attrName) {
15183        return parseFloat(this[attrName]);
15184    };
15185    AttrList.prototype.enumeratedString = function (attrName) {
15186        return this[attrName];
15187    };
15188    AttrList.prototype.decimalResolution = function (attrName) {
15189        var res = DECIMAL_RESOLUTION_REGEX.exec(this[attrName]);
15190        if (res === null) {
15191            return undefined;
15192        }
15193        return {
15194            width: parseInt(res[1], 10),
15195            height: parseInt(res[2], 10)
15196        };
15197    };
15198    AttrList.parseAttrList = function (input) {
15199        var match, attrs = {};
15200        ATTR_LIST_REGEX.lastIndex = 0;
15201        while ((match = ATTR_LIST_REGEX.exec(input)) !== null) {
15202            var value = match[2], quote = '"';
15203            if (value.indexOf(quote) === 0 &&
15204                value.lastIndexOf(quote) === (value.length - 1)) {
15205                value = value.slice(1, -1);
15206            }
15207            attrs[match[1]] = value;
15208        }
15209        return attrs;
15210    };
15211    return AttrList;
15212}());
15213exports.default = AttrList;
15214
15215/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.js")["Number"]))
15216
15217/***/ }),
15218
15219/***/ "./src/utils/binary-search.js":
15220/*!************************************!*\
15221  !*** ./src/utils/binary-search.js ***!
15222  \************************************/
15223/*! no static exports found */
15224/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
15225/***/ (function(module, exports, __webpack_require__) {
15226
15227"use strict";
15228
15229Object.defineProperty(exports, "__esModule", { value: true });
15230var BinarySearch = {
15231    /**
15232       * Searches for an item in an array which matches a certain condition.
15233       * This requires the condition to only match one item in the array,
15234       * and for the array to be ordered.
15235       *
15236       * @param {Array} list The array to search.
15237       * @param {Function} comparisonFunction
15238       *      Called and provided a candidate item as the first argument.
15239       *      Should return:
15240       *          > -1 if the item should be located at a lower index than the provided item.
15241       *          > 1 if the item should be located at a higher index than the provided item.
15242       *          > 0 if the item is the item you're looking for.
15243       *
15244       * @return {*} The object if it is found or null otherwise.
15245       */
15246    search: function (list, comparisonFunction) {
15247        var minIndex = 0;
15248        var maxIndex = list.length - 1;
15249        var currentIndex = null;
15250        var currentElement = null;
15251        while (minIndex <= maxIndex) {
15252            currentIndex = (minIndex + maxIndex) / 2 | 0;
15253            currentElement = list[currentIndex];
15254            var comparisonResult = comparisonFunction(currentElement);
15255            if (comparisonResult > 0) {
15256                minIndex = currentIndex + 1;
15257            }
15258            else if (comparisonResult < 0) {
15259                maxIndex = currentIndex - 1;
15260            }
15261            else {
15262                return currentElement;
15263            }
15264        }
15265        return null;
15266    }
15267};
15268exports.default = BinarySearch;
15269
15270
15271/***/ }),
15272
15273/***/ "./src/utils/buffer-helper.js":
15274/*!************************************!*\
15275  !*** ./src/utils/buffer-helper.js ***!
15276  \************************************/
15277/*! no static exports found */
15278/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
15279/***/ (function(module, exports, __webpack_require__) {
15280
15281"use strict";
15282
15283/**
15284 * @module BufferHelper
15285 *
15286 * Providing methods dealing with buffer length retrieval for example.
15287 *
15288 * In general, a helper around HTML5 MediaElement TimeRanges gathered from `buffered` property.
15289 *
15290 * Also @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/buffered
15291*/
15292Object.defineProperty(exports, "__esModule", { value: true });
15293var BufferHelper = /** @class */ (function () {
15294    function BufferHelper() {
15295    }
15296    /**
15297     * Return true if `media`'s buffered include `position`
15298     * @param {HTMLMediaElement|SourceBuffer} media
15299     * @param {number} position
15300     * @returns {boolean}
15301     */
15302    BufferHelper.isBuffered = function (media, position) {
15303        try {
15304            if (media) {
15305                var buffered = media.buffered;
15306                for (var i = 0; i < buffered.length; i++) {
15307                    if (position >= buffered.start(i) && position <= buffered.end(i)) {
15308                        return true;
15309                    }
15310                }
15311            }
15312        }
15313        catch (error) {
15314            // this is to catch
15315            // InvalidStateError: Failed to read the 'buffered' property from 'SourceBuffer':
15316            // This SourceBuffer has been removed from the parent media source
15317        }
15318        return false;
15319    };
15320    BufferHelper.bufferInfo = function (media, pos, maxHoleDuration) {
15321        try {
15322            if (media) {
15323                var vbuffered = media.buffered, buffered = [], i = void 0;
15324                for (i = 0; i < vbuffered.length; i++) {
15325                    buffered.push({ start: vbuffered.start(i), end: vbuffered.end(i) });
15326                }
15327                return this.bufferedInfo(buffered, pos, maxHoleDuration);
15328            }
15329        }
15330        catch (error) {
15331            // this is to catch
15332            // InvalidStateError: Failed to read the 'buffered' property from 'SourceBuffer':
15333            // This SourceBuffer has been removed from the parent media source
15334        }
15335        return { len: 0, start: pos, end: pos, nextStart: undefined };
15336    };
15337    BufferHelper.bufferedInfo = function (buffered, pos, maxHoleDuration) {
15338        var buffered2 = [], 
15339        // bufferStart and bufferEnd are buffer boundaries around current video position
15340        bufferLen, bufferStart, bufferEnd, bufferStartNext, i;
15341        // sort on buffer.start/smaller end (IE does not always return sorted buffered range)
15342        buffered.sort(function (a, b) {
15343            var diff = a.start - b.start;
15344            if (diff) {
15345                return diff;
15346            }
15347            else {
15348                return b.end - a.end;
15349            }
15350        });
15351        // there might be some small holes between buffer time range
15352        // consider that holes smaller than maxHoleDuration are irrelevant and build another
15353        // buffer time range representations that discards those holes
15354        for (i = 0; i < buffered.length; i++) {
15355            var buf2len = buffered2.length;
15356            if (buf2len) {
15357                var buf2end = buffered2[buf2len - 1].end;
15358                // if small hole (value between 0 or maxHoleDuration ) or overlapping (negative)
15359                if ((buffered[i].start - buf2end) < maxHoleDuration) {
15360                    // merge overlapping time ranges
15361                    // update lastRange.end only if smaller than item.end
15362                    // e.g.  [ 1, 15] with  [ 2,8] => [ 1,15] (no need to modify lastRange.end)
15363                    // whereas [ 1, 8] with  [ 2,15] => [ 1,15] ( lastRange should switch from [1,8] to [1,15])
15364                    if (buffered[i].end > buf2end) {
15365                        buffered2[buf2len - 1].end = buffered[i].end;
15366                    }
15367                }
15368                else {
15369                    // big hole
15370                    buffered2.push(buffered[i]);
15371                }
15372            }
15373            else {
15374                // first value
15375                buffered2.push(buffered[i]);
15376            }
15377        }
15378        for (i = 0, bufferLen = 0, bufferStart = bufferEnd = pos; i < buffered2.length; i++) {
15379            var start = buffered2[i].start, end = buffered2[i].end;
15380            // logger.log('buf start/end:' + buffered.start(i) + '/' + buffered.end(i));
15381            if ((pos + maxHoleDuration) >= start && pos < end) {
15382                // play position is inside this buffer TimeRange, retrieve end of buffer position and buffer length
15383                bufferStart = start;
15384                bufferEnd = end;
15385                bufferLen = bufferEnd - pos;
15386            }
15387            else if ((pos + maxHoleDuration) < start) {
15388                bufferStartNext = start;
15389                break;
15390            }
15391        }
15392        return { len: bufferLen, start: bufferStart, end: bufferEnd, nextStart: bufferStartNext };
15393    };
15394    return BufferHelper;
15395}());
15396exports.BufferHelper = BufferHelper;
15397
15398
15399/***/ }),
15400
15401/***/ "./src/utils/cea-608-parser.js":
15402/*!*************************************!*\
15403  !*** ./src/utils/cea-608-parser.js ***!
15404  \*************************************/
15405/*! no static exports found */
15406/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
15407/***/ (function(module, exports, __webpack_require__) {
15408
15409"use strict";
15410
15411/**
15412 *
15413 * This code was ported from the dash.js project at:
15414 *   https://github.com/Dash-Industry-Forum/dash.js/blob/development/externals/cea608-parser.js
15415 *   https://github.com/Dash-Industry-Forum/dash.js/commit/8269b26a761e0853bb21d78780ed945144ecdd4d#diff-71bc295a2d6b6b7093a1d3290d53a4b2
15416 *
15417 * The original copyright appears below:
15418 *
15419 * The copyright in this software is being made available under the BSD License,
15420 * included below. This software may be subject to other third party and contributor
15421 * rights, including patent rights, and no such rights are granted under this license.
15422 *
15423 * Copyright (c) 2015-2016, DASH Industry Forum.
15424 * All rights reserved.
15425 *
15426 * Redistribution and use in source and binary forms, with or without modification,
15427 * are permitted provided that the following conditions are met:
15428 *  1. Redistributions of source code must retain the above copyright notice, this
15429 *  list of conditions and the following disclaimer.
15430 *  * Redistributions in binary form must reproduce the above copyright notice,
15431 *  this list of conditions and the following disclaimer in the documentation and/or
15432 *  other materials provided with the distribution.
15433 *  2. Neither the name of Dash Industry Forum nor the names of its
15434 *  contributors may be used to endorse or promote products derived from this software
15435 *  without specific prior written permission.
15436 *
15437 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
15438 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15439 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
15440 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
15441 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
15442 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
15443 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
15444 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
15445 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
15446 *  POSSIBILITY OF SUCH DAMAGE.
15447 */
15448/**
15449     *  Exceptions from regular ASCII. CodePoints are mapped to UTF-16 codes
15450     */
15451Object.defineProperty(exports, "__esModule", { value: true });
15452var specialCea608CharsCodes = {
15453    0x2a: 0xe1,
15454    0x5c: 0xe9,
15455    0x5e: 0xed,
15456    0x5f: 0xf3,
15457    0x60: 0xfa,
15458    0x7b: 0xe7,
15459    0x7c: 0xf7,
15460    0x7d: 0xd1,
15461    0x7e: 0xf1,
15462    0x7f: 0x2588,
15463    // THIS BLOCK INCLUDES THE 16 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS
15464    // THAT COME FROM HI BYTE=0x11 AND LOW BETWEEN 0x30 AND 0x3F
15465    // THIS MEANS THAT \x50 MUST BE ADDED TO THE VALUES
15466    0x80: 0xae,
15467    0x81: 0xb0,
15468    0x82: 0xbd,
15469    0x83: 0xbf,
15470    0x84: 0x2122,
15471    0x85: 0xa2,
15472    0x86: 0xa3,
15473    0x87: 0x266a,
15474    0x88: 0xe0,
15475    0x89: 0x20,
15476    0x8a: 0xe8,
15477    0x8b: 0xe2,
15478    0x8c: 0xea,
15479    0x8d: 0xee,
15480    0x8e: 0xf4,
15481    0x8f: 0xfb,
15482    // THIS BLOCK INCLUDES THE 32 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS
15483    // THAT COME FROM HI BYTE=0x12 AND LOW BETWEEN 0x20 AND 0x3F
15484    0x90: 0xc1,
15485    0x91: 0xc9,
15486    0x92: 0xd3,
15487    0x93: 0xda,
15488    0x94: 0xdc,
15489    0x95: 0xfc,
15490    0x96: 0x2018,
15491    0x97: 0xa1,
15492    0x98: 0x2a,
15493    0x99: 0x2019,
15494    0x9a: 0x2501,
15495    0x9b: 0xa9,
15496    0x9c: 0x2120,
15497    0x9d: 0x2022,
15498    0x9e: 0x201c,
15499    0x9f: 0x201d,
15500    0xa0: 0xc0,
15501    0xa1: 0xc2,
15502    0xa2: 0xc7,
15503    0xa3: 0xc8,
15504    0xa4: 0xca,
15505    0xa5: 0xcb,
15506    0xa6: 0xeb,
15507    0xa7: 0xce,
15508    0xa8: 0xcf,
15509    0xa9: 0xef,
15510    0xaa: 0xd4,
15511    0xab: 0xd9,
15512    0xac: 0xf9,
15513    0xad: 0xdb,
15514    0xae: 0xab,
15515    0xaf: 0xbb,
15516    // THIS BLOCK INCLUDES THE 32 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS
15517    // THAT COME FROM HI BYTE=0x13 AND LOW BETWEEN 0x20 AND 0x3F
15518    0xb0: 0xc3,
15519    0xb1: 0xe3,
15520    0xb2: 0xcd,
15521    0xb3: 0xcc,
15522    0xb4: 0xec,
15523    0xb5: 0xd2,
15524    0xb6: 0xf2,
15525    0xb7: 0xd5,
15526    0xb8: 0xf5,
15527    0xb9: 0x7b,
15528    0xba: 0x7d,
15529    0xbb: 0x5c,
15530    0xbc: 0x5e,
15531    0xbd: 0x5f,
15532    0xbe: 0x7c,
15533    0xbf: 0x223c,
15534    0xc0: 0xc4,
15535    0xc1: 0xe4,
15536    0xc2: 0xd6,
15537    0xc3: 0xf6,
15538    0xc4: 0xdf,
15539    0xc5: 0xa5,
15540    0xc6: 0xa4,
15541    0xc7: 0x2503,
15542    0xc8: 0xc5,
15543    0xc9: 0xe5,
15544    0xca: 0xd8,
15545    0xcb: 0xf8,
15546    0xcc: 0x250f,
15547    0xcd: 0x2513,
15548    0xce: 0x2517,
15549    0xcf: 0x251b // Box drawings heavy up and left
15550};
15551/**
15552 * Utils
15553 */
15554var getCharForByte = function (byte) {
15555    var charCode = byte;
15556    if (specialCea608CharsCodes.hasOwnProperty(byte)) {
15557        charCode = specialCea608CharsCodes[byte];
15558    }
15559    return String.fromCharCode(charCode);
15560};
15561var NR_ROWS = 15, NR_COLS = 100;
15562// Tables to look up row from PAC data
15563var rowsLowCh1 = { 0x11: 1, 0x12: 3, 0x15: 5, 0x16: 7, 0x17: 9, 0x10: 11, 0x13: 12, 0x14: 14 };
15564var rowsHighCh1 = { 0x11: 2, 0x12: 4, 0x15: 6, 0x16: 8, 0x17: 10, 0x13: 13, 0x14: 15 };
15565var rowsLowCh2 = { 0x19: 1, 0x1A: 3, 0x1D: 5, 0x1E: 7, 0x1F: 9, 0x18: 11, 0x1B: 12, 0x1C: 14 };
15566var rowsHighCh2 = { 0x19: 2, 0x1A: 4, 0x1D: 6, 0x1E: 8, 0x1F: 10, 0x1B: 13, 0x1C: 15 };
15567var backgroundColors = ['white', 'green', 'blue', 'cyan', 'red', 'yellow', 'magenta', 'black', 'transparent'];
15568/**
15569 * Simple logger class to be able to write with time-stamps and filter on level.
15570 */
15571var logger = {
15572    verboseFilter: { 'DATA': 3, 'DEBUG': 3, 'INFO': 2, 'WARNING': 2, 'TEXT': 1, 'ERROR': 0 },
15573    time: null,
15574    verboseLevel: 0,
15575    setTime: function (newTime) {
15576        this.time = newTime;
15577    },
15578    log: function (severity, msg) {
15579        var minLevel = this.verboseFilter[severity];
15580        if (this.verboseLevel >= minLevel) {
15581            // console.log(this.time + ' [' + severity + '] ' + msg);
15582        }
15583    }
15584};
15585var numArrayToHexArray = function (numArray) {
15586    var hexArray = [];
15587    for (var j = 0; j < numArray.length; j++) {
15588        hexArray.push(numArray[j].toString(16));
15589    }
15590    return hexArray;
15591};
15592var PenState = /** @class */ (function () {
15593    function PenState(foreground, underline, italics, background, flash) {
15594        this.foreground = foreground || 'white';
15595        this.underline = underline || false;
15596        this.italics = italics || false;
15597        this.background = background || 'black';
15598        this.flash = flash || false;
15599    }
15600    PenState.prototype.reset = function () {
15601        this.foreground = 'white';
15602        this.underline = false;
15603        this.italics = false;
15604        this.background = 'black';
15605        this.flash = false;
15606    };
15607    PenState.prototype.setStyles = function (styles) {
15608        var attribs = ['foreground', 'underline', 'italics', 'background', 'flash'];
15609        for (var i = 0; i < attribs.length; i++) {
15610            var style = attribs[i];
15611            if (styles.hasOwnProperty(style)) {
15612                this[style] = styles[style];
15613            }
15614        }
15615    };
15616    PenState.prototype.isDefault = function () {
15617        return (this.foreground === 'white' && !this.underline && !this.italics &&
15618            this.background === 'black' && !this.flash);
15619    };
15620    PenState.prototype.equals = function (other) {
15621        return ((this.foreground === other.foreground) &&
15622            (this.underline === other.underline) &&
15623            (this.italics === other.italics) &&
15624            (this.background === other.background) &&
15625            (this.flash === other.flash));
15626    };
15627    PenState.prototype.copy = function (newPenState) {
15628        this.foreground = newPenState.foreground;
15629        this.underline = newPenState.underline;
15630        this.italics = newPenState.italics;
15631        this.background = newPenState.background;
15632        this.flash = newPenState.flash;
15633    };
15634    PenState.prototype.toString = function () {
15635        return ('color=' + this.foreground + ', underline=' + this.underline + ', italics=' + this.italics +
15636            ', background=' + this.background + ', flash=' + this.flash);
15637    };
15638    return PenState;
15639}());
15640/**
15641 * Unicode character with styling and background.
15642 * @constructor
15643 */
15644var StyledUnicodeChar = /** @class */ (function () {
15645    function StyledUnicodeChar(uchar, foreground, underline, italics, background, flash) {
15646        this.uchar = uchar || ' '; // unicode character
15647        this.penState = new PenState(foreground, underline, italics, background, flash);
15648    }
15649    StyledUnicodeChar.prototype.reset = function () {
15650        this.uchar = ' ';
15651        this.penState.reset();
15652    };
15653    StyledUnicodeChar.prototype.setChar = function (uchar, newPenState) {
15654        this.uchar = uchar;
15655        this.penState.copy(newPenState);
15656    };
15657    StyledUnicodeChar.prototype.setPenState = function (newPenState) {
15658        this.penState.copy(newPenState);
15659    };
15660    StyledUnicodeChar.prototype.equals = function (other) {
15661        return this.uchar === other.uchar && this.penState.equals(other.penState);
15662    };
15663    StyledUnicodeChar.prototype.copy = function (newChar) {
15664        this.uchar = newChar.uchar;
15665        this.penState.copy(newChar.penState);
15666    };
15667    StyledUnicodeChar.prototype.isEmpty = function () {
15668        return this.uchar === ' ' && this.penState.isDefault();
15669    };
15670    return StyledUnicodeChar;
15671}());
15672/**
15673 * CEA-608 row consisting of NR_COLS instances of StyledUnicodeChar.
15674 * @constructor
15675 */
15676var Row = /** @class */ (function () {
15677    function Row() {
15678        this.chars = [];
15679        for (var i = 0; i < NR_COLS; i++) {
15680            this.chars.push(new StyledUnicodeChar());
15681        }
15682        this.pos = 0;
15683        this.currPenState = new PenState();
15684    }
15685    Row.prototype.equals = function (other) {
15686        var equal = true;
15687        for (var i = 0; i < NR_COLS; i++) {
15688            if (!this.chars[i].equals(other.chars[i])) {
15689                equal = false;
vendor: 4,350 bytes, lines 15690-15835
15690                break;
15691            }
15692        }
15693        return equal;
15694    };
15695    Row.prototype.copy = function (other) {
15696        for (var i = 0; i < NR_COLS; i++) {
15697            this.chars[i].copy(other.chars[i]);
15698        }
15699    };
15700    Row.prototype.isEmpty = function () {
15701        var empty = true;
15702        for (var i = 0; i < NR_COLS; i++) {
15703            if (!this.chars[i].isEmpty()) {
15704                empty = false;
15705                break;
15706            }
15707        }
15708        return empty;
15709    };
15710    /**
15711       *  Set the cursor to a valid column.
15712       */
15713    Row.prototype.setCursor = function (absPos) {
15714        if (this.pos !== absPos) {
15715            this.pos = absPos;
15716        }
15717        if (this.pos < 0) {
15718            logger.log('ERROR', 'Negative cursor position ' + this.pos);
15719            this.pos = 0;
15720        }
15721        else if (this.pos > NR_COLS) {
15722            logger.log('ERROR', 'Too large cursor position ' + this.pos);
15723            this.pos = NR_COLS;
15724        }
15725    };
15726    /**
15727       * Move the cursor relative to current position.
15728       */
15729    Row.prototype.moveCursor = function (relPos) {
15730        var newPos = this.pos + relPos;
15731        if (relPos > 1) {
15732            for (var i = this.pos + 1; i < newPos + 1; i++) {
15733                this.chars[i].setPenState(this.currPenState);
15734            }
15735        }
15736        this.setCursor(newPos);
15737    };
15738    /**
15739       * Backspace, move one step back and clear character.
15740       */
15741    Row.prototype.backSpace = function () {
15742        this.moveCursor(-1);
15743        this.chars[this.pos].setChar(' ', this.currPenState);
15744    };
15745    Row.prototype.insertChar = function (byte) {
15746        if (byte >= 0x90) { // Extended char
15747            this.backSpace();
15748        }
15749        var char = getCharForByte(byte);
15750        if (this.pos >= NR_COLS) {
15751            logger.log('ERROR', 'Cannot insert ' + byte.toString(16) +
15752                ' (' + char + ') at position ' + this.pos + '. Skipping it!');
15753            return;
15754        }
15755        this.chars[this.pos].setChar(char, this.currPenState);
15756        this.moveCursor(1);
15757    };
15758    Row.prototype.clearFromPos = function (startPos) {
15759        var i;
15760        for (i = startPos; i < NR_COLS; i++) {
15761            this.chars[i].reset();
15762        }
15763    };
15764    Row.prototype.clear = function () {
15765        this.clearFromPos(0);
15766        this.pos = 0;
15767        this.currPenState.reset();
15768    };
15769    Row.prototype.clearToEndOfRow = function () {
15770        this.clearFromPos(this.pos);
15771    };
15772    Row.prototype.getTextString = function () {
15773        var chars = [];
15774        var empty = true;
15775        for (var i = 0; i < NR_COLS; i++) {
15776            var char = this.chars[i].uchar;
15777            if (char !== ' ') {
15778                empty = false;
15779            }
15780            chars.push(char);
15781        }
15782        if (empty) {
15783            return '';
15784        }
15785        else {
15786            return chars.join('');
15787        }
15788    };
15789    Row.prototype.setPenStyles = function (styles) {
15790        this.currPenState.setStyles(styles);
15791        var currChar = this.chars[this.pos];
15792        currChar.setPenState(this.currPenState);
15793    };
15794    return Row;
15795}());
15796/**
15797 * Keep a CEA-608 screen of 32x15 styled characters
15798 * @constructor
15799*/
15800var CaptionScreen = /** @class */ (function () {
15801    function CaptionScreen() {
15802        this.rows = [];
15803        for (var i = 0; i < NR_ROWS; i++) {
15804            this.rows.push(new Row());
15805        } // Note that we use zero-based numbering (0-14)
15806        this.currRow = NR_ROWS - 1;
15807        this.nrRollUpRows = null;
15808        this.reset();
15809    }
15810    CaptionScreen.prototype.reset = function () {
15811        for (var i = 0; i < NR_ROWS; i++) {
15812            this.rows[i].clear();
15813        }
15814        this.currRow = NR_ROWS - 1;
15815    };
15816    CaptionScreen.prototype.equals = function (other) {
15817        var equal = true;
15818        for (var i = 0; i < NR_ROWS; i++) {
15819            if (!this.rows[i].equals(other.rows[i])) {
15820                equal = false;
15821                break;
15822            }
15823        }
15824        return equal;
15825    };
15826    CaptionScreen.prototype.copy = function (other) {
15827        for (var i = 0; i < NR_ROWS; i++) {
15828            this.rows[i].copy(other.rows[i]);
15829        }
15830    };
15831    CaptionScreen.prototype.isEmpty = function () {
15832        var empty = true;
15833        for (var i = 0; i < NR_ROWS; i++) {
15834            if (!this.rows[i].isEmpty()) {
15835                empty = false;
vendor: 18,434 bytes, lines 15836-16328
15836                break;
15837            }
15838        }
15839        return empty;
15840    };
15841    CaptionScreen.prototype.backSpace = function () {
15842        var row = this.rows[this.currRow];
15843        row.backSpace();
15844    };
15845    CaptionScreen.prototype.clearToEndOfRow = function () {
15846        var row = this.rows[this.currRow];
15847        row.clearToEndOfRow();
15848    };
15849    /**
15850       * Insert a character (without styling) in the current row.
15851       */
15852    CaptionScreen.prototype.insertChar = function (char) {
15853        var row = this.rows[this.currRow];
15854        row.insertChar(char);
15855    };
15856    CaptionScreen.prototype.setPen = function (styles) {
15857        var row = this.rows[this.currRow];
15858        row.setPenStyles(styles);
15859    };
15860    CaptionScreen.prototype.moveCursor = function (relPos) {
15861        var row = this.rows[this.currRow];
15862        row.moveCursor(relPos);
15863    };
15864    CaptionScreen.prototype.setCursor = function (absPos) {
15865        logger.log('INFO', 'setCursor: ' + absPos);
15866        var row = this.rows[this.currRow];
15867        row.setCursor(absPos);
15868    };
15869    CaptionScreen.prototype.setPAC = function (pacData) {
15870        logger.log('INFO', 'pacData = ' + JSON.stringify(pacData));
15871        var newRow = pacData.row - 1;
15872        if (this.nrRollUpRows && newRow < this.nrRollUpRows - 1) {
15873            newRow = this.nrRollUpRows - 1;
15874        }
15875        // Make sure this only affects Roll-up Captions by checking this.nrRollUpRows
15876        if (this.nrRollUpRows && this.currRow !== newRow) {
15877            // clear all rows first
15878            for (var i = 0; i < NR_ROWS; i++) {
15879                this.rows[i].clear();
15880            }
15881            // Copy this.nrRollUpRows rows from lastOutputScreen and place it in the newRow location
15882            // topRowIndex - the start of rows to copy (inclusive index)
15883            var topRowIndex = this.currRow + 1 - (this.nrRollUpRows);
15884            // We only copy if the last position was already shown.
15885            // We use the cueStartTime value to check this.
15886            var lastOutputScreen = this.lastOutputScreen;
15887            if (lastOutputScreen) {
15888                var prevLineTime = lastOutputScreen.rows[topRowIndex].cueStartTime;
15889                if (prevLineTime && prevLineTime < logger.time) {
15890                    for (var i = 0; i < this.nrRollUpRows; i++) {
15891                        this.rows[newRow - this.nrRollUpRows + i + 1].copy(lastOutputScreen.rows[topRowIndex + i]);
15892                    }
15893                }
15894            }
15895        }
15896        this.currRow = newRow;
15897        var row = this.rows[this.currRow];
15898        if (pacData.indent !== null) {
15899            var indent = pacData.indent;
15900            var prevPos = Math.max(indent - 1, 0);
15901            row.setCursor(pacData.indent);
15902            pacData.color = row.chars[prevPos].penState.foreground;
15903        }
15904        var styles = { foreground: pacData.color, underline: pacData.underline, italics: pacData.italics, background: 'black', flash: false };
15905        this.setPen(styles);
15906    };
15907    /**
15908       * Set background/extra foreground, but first do back_space, and then insert space (backwards compatibility).
15909       */
15910    CaptionScreen.prototype.setBkgData = function (bkgData) {
15911        logger.log('INFO', 'bkgData = ' + JSON.stringify(bkgData));
15912        this.backSpace();
15913        this.setPen(bkgData);
15914        this.insertChar(0x20); // Space
15915    };
15916    CaptionScreen.prototype.setRollUpRows = function (nrRows) {
15917        this.nrRollUpRows = nrRows;
15918    };
15919    CaptionScreen.prototype.rollUp = function () {
15920        if (this.nrRollUpRows === null) {
15921            logger.log('DEBUG', 'roll_up but nrRollUpRows not set yet');
15922            return; // Not properly setup
15923        }
15924        logger.log('TEXT', this.getDisplayText());
15925        var topRowIndex = this.currRow + 1 - this.nrRollUpRows;
15926        var topRow = this.rows.splice(topRowIndex, 1)[0];
15927        topRow.clear();
15928        this.rows.splice(this.currRow, 0, topRow);
15929        logger.log('INFO', 'Rolling up');
15930        // logger.log('TEXT', this.get_display_text())
15931    };
15932    /**
15933      * Get all non-empty rows with as unicode text.
15934      */
15935    CaptionScreen.prototype.getDisplayText = function (asOneRow) {
15936        asOneRow = asOneRow || false;
15937        var displayText = [];
15938        var text = '';
15939        var rowNr = -1;
15940        for (var i = 0; i < NR_ROWS; i++) {
15941            var rowText = this.rows[i].getTextString();
15942            if (rowText) {
15943                rowNr = i + 1;
15944                if (asOneRow) {
15945                    displayText.push('Row ' + rowNr + ': \'' + rowText + '\'');
15946                }
15947                else {
15948                    displayText.push(rowText.trim());
15949                }
15950            }
15951        }
15952        if (displayText.length > 0) {
15953            if (asOneRow) {
15954                text = '[' + displayText.join(' | ') + ']';
15955            }
15956            else {
15957                text = displayText.join('\n');
15958            }
15959        }
15960        return text;
15961    };
15962    CaptionScreen.prototype.getTextAndFormat = function () {
15963        return this.rows;
15964    };
15965    return CaptionScreen;
15966}());
15967// var modes = ['MODE_ROLL-UP', 'MODE_POP-ON', 'MODE_PAINT-ON', 'MODE_TEXT'];
15968var Cea608Channel = /** @class */ (function () {
15969    function Cea608Channel(channelNumber, outputFilter) {
15970        this.chNr = channelNumber;
15971        this.outputFilter = outputFilter;
15972        this.mode = null;
15973        this.verbose = 0;
15974        this.displayedMemory = new CaptionScreen();
15975        this.nonDisplayedMemory = new CaptionScreen();
15976        this.lastOutputScreen = new CaptionScreen();
15977        this.currRollUpRow = this.displayedMemory.rows[NR_ROWS - 1];
15978        this.writeScreen = this.displayedMemory;
15979        this.mode = null;
15980        this.cueStartTime = null; // Keeps track of where a cue started.
15981    }
15982    Cea608Channel.prototype.reset = function () {
15983        this.mode = null;
15984        this.displayedMemory.reset();
15985        this.nonDisplayedMemory.reset();
15986        this.lastOutputScreen.reset();
15987        this.currRollUpRow = this.displayedMemory.rows[NR_ROWS - 1];
15988        this.writeScreen = this.displayedMemory;
15989        this.mode = null;
15990        this.cueStartTime = null;
15991        this.lastCueEndTime = null;
15992    };
15993    Cea608Channel.prototype.getHandler = function () {
15994        return this.outputFilter;
15995    };
15996    Cea608Channel.prototype.setHandler = function (newHandler) {
15997        this.outputFilter = newHandler;
15998    };
15999    Cea608Channel.prototype.setPAC = function (pacData) {
16000        this.writeScreen.setPAC(pacData);
16001    };
16002    Cea608Channel.prototype.setBkgData = function (bkgData) {
16003        this.writeScreen.setBkgData(bkgData);
16004    };
16005    Cea608Channel.prototype.setMode = function (newMode) {
16006        if (newMode === this.mode) {
16007            return;
16008        }
16009        this.mode = newMode;
16010        logger.log('INFO', 'MODE=' + newMode);
16011        if (this.mode === 'MODE_POP-ON') {
16012            this.writeScreen = this.nonDisplayedMemory;
16013        }
16014        else {
16015            this.writeScreen = this.displayedMemory;
16016            this.writeScreen.reset();
16017        }
16018        if (this.mode !== 'MODE_ROLL-UP') {
16019            this.displayedMemory.nrRollUpRows = null;
16020            this.nonDisplayedMemory.nrRollUpRows = null;
16021        }
16022        this.mode = newMode;
16023    };
16024    Cea608Channel.prototype.insertChars = function (chars) {
16025        for (var i = 0; i < chars.length; i++) {
16026            this.writeScreen.insertChar(chars[i]);
16027        }
16028        var screen = this.writeScreen === this.displayedMemory ? 'DISP' : 'NON_DISP';
16029        logger.log('INFO', screen + ': ' + this.writeScreen.getDisplayText(true));
16030        if (this.mode === 'MODE_PAINT-ON' || this.mode === 'MODE_ROLL-UP') {
16031            logger.log('TEXT', 'DISPLAYED: ' + this.displayedMemory.getDisplayText(true));
16032            this.outputDataUpdate();
16033        }
16034    };
16035    Cea608Channel.prototype.ccRCL = function () {
16036        logger.log('INFO', 'RCL - Resume Caption Loading');
16037        this.setMode('MODE_POP-ON');
16038    };
16039    Cea608Channel.prototype.ccBS = function () {
16040        logger.log('INFO', 'BS - BackSpace');
16041        if (this.mode === 'MODE_TEXT') {
16042            return;
16043        }
16044        this.writeScreen.backSpace();
16045        if (this.writeScreen === this.displayedMemory) {
16046            this.outputDataUpdate();
16047        }
16048    };
16049    Cea608Channel.prototype.ccAOF = function () {
16050    };
16051    Cea608Channel.prototype.ccAON = function () {
16052    };
16053    Cea608Channel.prototype.ccDER = function () {
16054        logger.log('INFO', 'DER- Delete to End of Row');
16055        this.writeScreen.clearToEndOfRow();
16056        this.outputDataUpdate();
16057    };
16058    Cea608Channel.prototype.ccRU = function (nrRows) {
16059        logger.log('INFO', 'RU(' + nrRows + ') - Roll Up');
16060        this.writeScreen = this.displayedMemory;
16061        this.setMode('MODE_ROLL-UP');
16062        this.writeScreen.setRollUpRows(nrRows);
16063    };
16064    Cea608Channel.prototype.ccFON = function () {
16065        logger.log('INFO', 'FON - Flash On');
16066        this.writeScreen.setPen({ flash: true });
16067    };
16068    Cea608Channel.prototype.ccRDC = function () {
16069        logger.log('INFO', 'RDC - Resume Direct Captioning');
16070        this.setMode('MODE_PAINT-ON');
16071    };
16072    Cea608Channel.prototype.ccTR = function () {
16073        logger.log('INFO', 'TR');
16074        this.setMode('MODE_TEXT');
16075    };
16076    Cea608Channel.prototype.ccRTD = function () {
16077        logger.log('INFO', 'RTD');
16078        this.setMode('MODE_TEXT');
16079    };
16080    Cea608Channel.prototype.ccEDM = function () {
16081        logger.log('INFO', 'EDM - Erase Displayed Memory');
16082        this.displayedMemory.reset();
16083        this.outputDataUpdate(true);
16084    };
16085    Cea608Channel.prototype.ccCR = function () {
16086        logger.log('CR - Carriage Return');
16087        this.writeScreen.rollUp();
16088        this.outputDataUpdate(true);
16089    };
16090    Cea608Channel.prototype.ccENM = function () {
16091        logger.log('INFO', 'ENM - Erase Non-displayed Memory');
16092        this.nonDisplayedMemory.reset();
16093    };
16094    Cea608Channel.prototype.ccEOC = function () {
16095        logger.log('INFO', 'EOC - End Of Caption');
16096        if (this.mode === 'MODE_POP-ON') {
16097            var tmp = this.displayedMemory;
16098            this.displayedMemory = this.nonDisplayedMemory;
16099            this.nonDisplayedMemory = tmp;
16100            this.writeScreen = this.nonDisplayedMemory;
16101            logger.log('TEXT', 'DISP: ' + this.displayedMemory.getDisplayText());
16102        }
16103        this.outputDataUpdate(true);
16104    };
16105    Cea608Channel.prototype.ccTO = function (nrCols) {
16106        logger.log('INFO', 'TO(' + nrCols + ') - Tab Offset');
16107        this.writeScreen.moveCursor(nrCols);
16108    };
16109    Cea608Channel.prototype.ccMIDROW = function (secondByte) {
16110        var styles = { flash: false };
16111        styles.underline = secondByte % 2 === 1;
16112        styles.italics = secondByte >= 0x2e;
16113        if (!styles.italics) {
16114            var colorIndex = Math.floor(secondByte / 2) - 0x10;
16115            var colors = ['white', 'green', 'blue', 'cyan', 'red', 'yellow', 'magenta'];
16116            styles.foreground = colors[colorIndex];
16117        }
16118        else {
16119            styles.foreground = 'white';
16120        }
16121        logger.log('INFO', 'MIDROW: ' + JSON.stringify(styles));
16122        this.writeScreen.setPen(styles);
16123    };
16124    Cea608Channel.prototype.outputDataUpdate = function (dispatch) {
16125        if (dispatch === void 0) { dispatch = false; }
16126        var t = logger.time;
16127        if (t === null) {
16128            return;
16129        }
16130        if (this.outputFilter) {
16131            if (this.cueStartTime === null && !this.displayedMemory.isEmpty()) { // Start of a new cue
16132                this.cueStartTime = t;
16133            }
16134            else {
16135                if (!this.displayedMemory.equals(this.lastOutputScreen)) {
16136                    if (this.outputFilter.newCue) {
16137                        this.outputFilter.newCue(this.cueStartTime, t, this.lastOutputScreen);
16138                        if (dispatch === true && this.outputFilter.dispatchCue) {
16139                            this.outputFilter.dispatchCue();
16140                        }
16141                    }
16142                    this.cueStartTime = this.displayedMemory.isEmpty() ? null : t;
16143                }
16144            }
16145            this.lastOutputScreen.copy(this.displayedMemory);
16146        }
16147    };
16148    Cea608Channel.prototype.cueSplitAtTime = function (t) {
16149        if (this.outputFilter) {
16150            if (!this.displayedMemory.isEmpty()) {
16151                if (this.outputFilter.newCue) {
16152                    this.outputFilter.newCue(this.cueStartTime, t, this.displayedMemory);
16153                }
16154                this.cueStartTime = t;
16155            }
16156        }
16157    };
16158    return Cea608Channel;
16159}());
16160var Cea608Parser = /** @class */ (function () {
16161    function Cea608Parser(field, out1, out2) {
16162        this.field = field || 1;
16163        this.outputs = [out1, out2];
16164        this.channels = [new Cea608Channel(1, out1), new Cea608Channel(2, out2)];
16165        this.currChNr = -1; // Will be 1 or 2
16166        this.lastCmdA = null; // First byte of last command
16167        this.lastCmdB = null; // Second byte of last command
16168        this.bufferedData = [];
16169        this.startTime = null;
16170        this.lastTime = null;
16171        this.dataCounters = { 'padding': 0, 'char': 0, 'cmd': 0, 'other': 0 };
16172    }
16173    Cea608Parser.prototype.getHandler = function (index) {
16174        return this.channels[index].getHandler();
16175    };
16176    Cea608Parser.prototype.setHandler = function (index, newHandler) {
16177        this.channels[index].setHandler(newHandler);
16178    };
16179    /**
16180       * Add data for time t in forms of list of bytes (unsigned ints). The bytes are treated as pairs.
16181       */
16182    Cea608Parser.prototype.addData = function (t, byteList) {
16183        var cmdFound, a, b, charsFound = false;
16184        this.lastTime = t;
16185        logger.setTime(t);
16186        for (var i = 0; i < byteList.length; i += 2) {
16187            a = byteList[i] & 0x7f;
16188            b = byteList[i + 1] & 0x7f;
16189            if (a === 0 && b === 0) {
16190                this.dataCounters.padding += 2;
16191                continue;
16192            }
16193            else {
16194                logger.log('DATA', '[' + numArrayToHexArray([byteList[i], byteList[i + 1]]) + '] -> (' + numArrayToHexArray([a, b]) + ')');
16195            }
16196            cmdFound = this.parseCmd(a, b);
16197            if (!cmdFound) {
16198                cmdFound = this.parseMidrow(a, b);
16199            }
16200            if (!cmdFound) {
16201                cmdFound = this.parsePAC(a, b);
16202            }
16203            if (!cmdFound) {
16204                cmdFound = this.parseBackgroundAttributes(a, b);
16205            }
16206            if (!cmdFound) {
16207                charsFound = this.parseChars(a, b);
16208                if (charsFound) {
16209                    if (this.currChNr && this.currChNr >= 0) {
16210                        var channel = this.channels[this.currChNr - 1];
16211                        channel.insertChars(charsFound);
16212                    }
16213                    else {
16214                        logger.log('WARNING', 'No channel found yet. TEXT-MODE?');
16215                    }
16216                }
16217            }
16218            if (cmdFound) {
16219                this.dataCounters.cmd += 2;
16220            }
16221            else if (charsFound) {
16222                this.dataCounters.char += 2;
16223            }
16224            else {
16225                this.dataCounters.other += 2;
16226                logger.log('WARNING', 'Couldn\'t parse cleaned data ' + numArrayToHexArray([a, b]) +
16227                    ' orig: ' + numArrayToHexArray([byteList[i], byteList[i + 1]]));
16228            }
16229        }
16230    };
16231    /**
16232       * Parse Command.
16233       * @returns {Boolean} Tells if a command was found
16234       */
16235    Cea608Parser.prototype.parseCmd = function (a, b) {
16236        var chNr = null;
16237        var cond1 = (a === 0x14 || a === 0x1C) && (b >= 0x20 && b <= 0x2F);
16238        var cond2 = (a === 0x17 || a === 0x1F) && (b >= 0x21 && b <= 0x23);
16239        if (!(cond1 || cond2)) {
16240            return false;
16241        }
16242        if (a === this.lastCmdA && b === this.lastCmdB) {
16243            this.lastCmdA = null;
16244            this.lastCmdB = null; // Repeated commands are dropped (once)
16245            logger.log('DEBUG', 'Repeated command (' + numArrayToHexArray([a, b]) + ') is dropped');
16246            return true;
16247        }
16248        if (a === 0x14 || a === 0x17) {
16249            chNr = 1;
16250        }
16251        else {
16252            chNr = 2;
16253        } // (a === 0x1C || a=== 0x1f)
16254        var channel = this.channels[chNr - 1];
16255        if (a === 0x14 || a === 0x1C) {
16256            if (b === 0x20) {
16257                channel.ccRCL();
16258            }
16259            else if (b === 0x21) {
16260                channel.ccBS();
16261            }
16262            else if (b === 0x22) {
16263                channel.ccAOF();
16264            }
16265            else if (b === 0x23) {
16266                channel.ccAON();
16267            }
16268            else if (b === 0x24) {
16269                channel.ccDER();
16270            }
16271            else if (b === 0x25) {
16272                channel.ccRU(2);
16273            }
16274            else if (b === 0x26) {
16275                channel.ccRU(3);
16276            }
16277            else if (b === 0x27) {
16278                channel.ccRU(4);
16279            }
16280            else if (b === 0x28) {
16281                channel.ccFON();
16282            }
16283            else if (b === 0x29) {
16284                channel.ccRDC();
16285            }
16286            else if (b === 0x2A) {
16287                channel.ccTR();
16288            }
16289            else if (b === 0x2B) {
16290                channel.ccRTD();
16291            }
16292            else if (b === 0x2C) {
16293                channel.ccEDM();
16294            }
16295            else if (b === 0x2D) {
16296                channel.ccCR();
16297            }
16298            else if (b === 0x2E) {
16299                channel.ccENM();
16300            }
16301            else if (b === 0x2F) {
16302                channel.ccEOC();
16303            }
16304        }
16305        else { // a == 0x17 || a == 0x1F
16306            channel.ccTO(b - 0x20);
16307        }
16308        this.lastCmdA = a;
16309        this.lastCmdB = b;
16310        this.currChNr = chNr;
16311        return true;
16312    };
16313    /**
16314       * Parse midrow styling command
16315       * @returns {Boolean}
16316       */
16317    Cea608Parser.prototype.parseMidrow = function (a, b) {
16318        var chNr = null;
16319        if (((a === 0x11) || (a === 0x19)) && b >= 0x20 && b <= 0x2f) {
16320            if (a === 0x11) {
16321                chNr = 1;
16322            }
16323            else {
16324                chNr = 2;
16325            }
16326            if (chNr !== this.currChNr) {
16327                logger.log('ERROR', 'Mismatch channel in midrow parsing');
16328                return false;
16329            }
16330            var channel = this.channels[chNr - 1];
16331            channel.ccMIDROW(b);
16332            logger.log('DEBUG', 'MIDROW (' + numArrayToHexArray([a, b]) + ')');
16333            return true;
16334        }
16335        return false;
16336    };
16337    /**
16338       * Parse Preable Access Codes (Table 53).
16339       * @returns {Boolean} Tells if PAC found
16340       */
16341    Cea608Parser.prototype.parsePAC = function (a, b) {
16342        var chNr = null;
16343        var row = null;
16344        var case1 = ((a >= 0x11 && a <= 0x17) || (a >= 0x19 && a <= 0x1F)) && (b >= 0x40 && b <= 0x7F);
16345        var case2 = (a === 0x10 || a === 0x18) && (b >= 0x40 && b <= 0x5F);
16346        if (!(case1 || case2)) {
16347            return false;
16348        }
16349        if (a === this.lastCmdA && b === this.lastCmdB) {
16350            this.lastCmdA = null;
16351            this.lastCmdB = null;
16352            return true; // Repeated commands are dropped (once)
16353        }
16354        chNr = (a <= 0x17) ? 1 : 2;
16355        if (b >= 0x40 && b <= 0x5F) {
16356            row = (chNr === 1) ? rowsLowCh1[a] : rowsLowCh2[a];
16357        }
16358        else { // 0x60 <= b <= 0x7F
16359            row = (chNr === 1) ? rowsHighCh1[a] : rowsHighCh2[a];
16360        }
16361        var pacData = this.interpretPAC(row, b);
16362        var channel = this.channels[chNr - 1];
16363        channel.setPAC(pacData);
16364        this.lastCmdA = a;
16365        this.lastCmdB = b;
16366        this.currChNr = chNr;
16367        return true;
16368    };
16369    /**
16370       * Interpret the second byte of the pac, and return the information.
16371       * @returns {Object} pacData with style parameters.
16372       */
16373    Cea608Parser.prototype.interpretPAC = function (row, byte) {
16374        var pacIndex = byte;
16375        var pacData = { color: null, italics: false, indent: null, underline: false, row: row };
16376        if (byte > 0x5F) {
16377            pacIndex = byte - 0x60;
16378        }
16379        else {
16380            pacIndex = byte - 0x40;
16381        }
16382        pacData.underline = (pacIndex & 1) === 1;
16383        if (pacIndex <= 0xd) {
16384            pacData.color = ['white', 'green', 'blue', 'cyan', 'red', 'yellow', 'magenta', 'white'][Math.floor(pacIndex / 2)];
16385        }
16386        else if (pacIndex <= 0xf) {
16387            pacData.italics = true;
16388            pacData.color = 'white';
16389        }
16390        else {
16391            pacData.indent = (Math.floor((pacIndex - 0x10) / 2)) * 4;
16392        }
16393        return pacData; // Note that row has zero offset. The spec uses 1.
16394    };
16395    /**
16396       * Parse characters.
16397       * @returns An array with 1 to 2 codes corresponding to chars, if found. null otherwise.
16398       */
16399    Cea608Parser.prototype.parseChars = function (a, b) {
16400        var channelNr = null, charCodes = null, charCode1 = null;
16401        if (a >= 0x19) {
16402            channelNr = 2;
16403            charCode1 = a - 8;
16404        }
16405        else {
16406            channelNr = 1;
16407            charCode1 = a;
16408        }
16409        if (charCode1 >= 0x11 && charCode1 <= 0x13) {
16410            // Special character
16411            var oneCode = b;
16412            if (charCode1 === 0x11) {
16413                oneCode = b + 0x50;
16414            }
16415            else if (charCode1 === 0x12) {
16416                oneCode = b + 0x70;
16417            }
16418            else {
16419                oneCode = b + 0x90;
16420            }
16421            logger.log('INFO', 'Special char \'' + getCharForByte(oneCode) + '\' in channel ' + channelNr);
16422            charCodes = [oneCode];
16423        }
16424        else if (a >= 0x20 && a <= 0x7f) {
16425            charCodes = (b === 0) ? [a] : [a, b];
16426        }
16427        if (charCodes) {
16428            var hexCodes = numArrayToHexArray(charCodes);
16429            logger.log('DEBUG', 'Char codes =  ' + hexCodes.join(','));
16430            this.lastCmdA = null;
16431            this.lastCmdB = null;
16432        }
16433        return charCodes;
16434    };
16435    /**
16436      * Parse extended background attributes as well as new foreground color black.
16437      * @returns{Boolean} Tells if background attributes are found
16438      */
16439    Cea608Parser.prototype.parseBackgroundAttributes = function (a, b) {
16440        var bkgData, index, chNr, channel;
16441        var case1 = (a === 0x10 || a === 0x18) && (b >= 0x20 && b <= 0x2f);
16442        var case2 = (a === 0x17 || a === 0x1f) && (b >= 0x2d && b <= 0x2f);
16443        if (!(case1 || case2)) {
16444            return false;
vendor: 1,518 bytes, lines 16445-16498
16445        }
16446        bkgData = {};
16447        if (a === 0x10 || a === 0x18) {
16448            index = Math.floor((b - 0x20) / 2);
16449            bkgData.background = backgroundColors[index];
16450            if (b % 2 === 1) {
16451                bkgData.background = bkgData.background + '_semi';
16452            }
16453        }
16454        else if (b === 0x2d) {
16455            bkgData.background = 'transparent';
16456        }
16457        else {
16458            bkgData.foreground = 'black';
16459            if (b === 0x2f) {
16460                bkgData.underline = true;
16461            }
16462        }
16463        chNr = (a < 0x18) ? 1 : 2;
16464        channel = this.channels[chNr - 1];
16465        channel.setBkgData(bkgData);
16466        this.lastCmdA = null;
16467        this.lastCmdB = null;
16468        return true;
16469    };
16470    /**
16471       * Reset state of parser and its channels.
16472       */
16473    Cea608Parser.prototype.reset = function () {
16474        for (var i = 0; i < this.channels.length; i++) {
16475            if (this.channels[i]) {
16476                this.channels[i].reset();
16477            }
16478        }
16479        this.lastCmdA = null;
16480        this.lastCmdB = null;
16481    };
16482    /**
16483       * Trigger the generation of a cue, and the start of a new one if displayScreens are not empty.
16484       */
16485    Cea608Parser.prototype.cueSplitAtTime = function (t) {
16486        for (var i = 0; i < this.channels.length; i++) {
16487            if (this.channels[i]) {
16488                this.channels[i].cueSplitAtTime(t);
16489            }
16490        }
16491    };
16492    return Cea608Parser;
16493}());
16494exports.default = Cea608Parser;
16495
16496
16497/***/ }),
16498
16499/***/ "./src/utils/codecs.js":
16500/*!*****************************!*\
16501  !*** ./src/utils/codecs.js ***!
16502  \*****************************/
16503/*! no static exports found */
16504/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
16505/***/ (function(module, exports, __webpack_require__) {
16506
16507"use strict";
16508
16509Object.defineProperty(exports, "__esModule", { value: true });
16510// from http://mp4ra.org/codecs.html
16511var sampleEntryCodesISO = {
16512    audio: {
16513        'a3ds': true,
16514        'ac-3': true,
16515        'ac-4': true,
16516        'alac': true,
16517        'alaw': true,
16518        'dra1': true,
16519        'dts+': true,
16520        'dts-': true,
16521        'dtsc': true,
16522        'dtse': true,
16523        'dtsh': true,
16524        'ec-3': true,
16525        'enca': true,
16526        'g719': true,
16527        'g726': true,
16528        'm4ae': true,
16529        'mha1': true,
16530        'mha2': true,
16531        'mhm1': true,
16532        'mhm2': true,
16533        'mlpa': true,
16534        'mp4a': true,
16535        'raw ': true,
16536        'Opus': true,
16537        'samr': true,
16538        'sawb': true,
16539        'sawp': true,
16540        'sevc': true,
16541        'sqcp': true,
16542        'ssmv': true,
16543        'twos': true,
16544        'ulaw': true
16545    },
16546    video: {
16547        'avc1': true,
16548        'avc2': true,
16549        'avc3': true,
16550        'avc4': true,
16551        'avcp': true,
16552        'drac': true,
16553        'dvav': true,
16554        'dvhe': true,
16555        'encv': true,
16556        'hev1': true,
16557        'hvc1': true,
16558        'mjp2': true,
16559        'mp4v': true,
16560        'mvc1': true,
16561        'mvc2': true,
16562        'mvc3': true,
16563        'mvc4': true,
16564        'resv': true,
16565        'rv60': true,
16566        's263': true,
16567        'svc1': true,
16568        'svc2': true,
16569        'vc-1': true,
16570        'vp08': true,
16571        'vp09': true
16572    }
16573};
16574function isCodecType(codec, type) {
16575    var typeCodes = sampleEntryCodesISO[type];
16576    return !!typeCodes && typeCodes[codec.slice(0, 4)] === true;
16577}
16578exports.isCodecType = isCodecType;
16579function isCodecSupportedInMp4(codec, type) {
16580    return window.MediaSource.isTypeSupported((type || 'video') + "/mp4;codecs=\"" + codec + "\"");
16581}
16582exports.isCodecSupportedInMp4 = isCodecSupportedInMp4;
16583
16584
16585/***/ }),
16586
16587/***/ "./src/utils/cues.js":
16588/*!***************************!*\
16589  !*** ./src/utils/cues.js ***!
16590  \***************************/
16591/*! no static exports found */
16592/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
16593/***/ (function(module, exports, __webpack_require__) {
16594
16595"use strict";
16596
16597Object.defineProperty(exports, "__esModule", { value: true });
16598var vttparser_1 = __webpack_require__(/*! ./vttparser */ "./src/utils/vttparser.js");
16599function newCue(track, startTime, endTime, captionScreen) {
16600    var row;
16601    var cue;
16602    var indenting;
16603    var indent;
16604    var text;
16605    var VTTCue = window.VTTCue || window.TextTrackCue;
16606    for (var r = 0; r < captionScreen.rows.length; r++) {
16607        row = captionScreen.rows[r];
16608        indenting = true;
16609        indent = 0;
16610        text = '';
16611        if (!row.isEmpty()) {
16612            for (var c = 0; c < row.chars.length; c++) {
16613                if (row.chars[c].uchar.match(/\s/) && indenting) {
16614                    indent++;
16615                }
16616                else {
16617                    text += row.chars[c].uchar;
16618                    indenting = false;
16619                }
16620            }
16621            // To be used for cleaning-up orphaned roll-up captions
16622            row.cueStartTime = startTime;
16623            // Give a slight bump to the endTime if it's equal to startTime to avoid a SyntaxError in IE
16624            if (startTime === endTime) {
16625                endTime += 0.0001;
16626            }
16627            cue = new VTTCue(startTime, endTime, vttparser_1.fixLineBreaks(text.trim()));
16628            if (indent >= 16) {
16629                indent--;
16630            }
16631            else {
16632                indent++;
16633            }
16634            // VTTCue.line get's flakey when using controls, so let's now include line 13&14
16635            // also, drop line 1 since it's to close to the top
16636            if (navigator.userAgent.match(/Firefox\//)) {
16637                cue.line = r + 1;
16638            }
16639            else {
16640                cue.line = (r > 7 ? r - 2 : r + 1);
16641            }
16642            cue.align = 'left';
16643            // Clamp the position between 0 and 100 - if out of these bounds, Firefox throws an exception and captions break
16644            cue.position = Math.max(0, Math.min(100, 100 * (indent / 32) + (navigator.userAgent.match(/Firefox\//) ? 50 : 0)));
16645            track.addCue(cue);
16646        }
16647    }
16648}
16649exports.newCue = newCue;
16650
16651
16652/***/ }),
16653
16654/***/ "./src/utils/discontinuities.js":
16655/*!**************************************!*\
16656  !*** ./src/utils/discontinuities.js ***!
16657  \**************************************/
16658/*! no static exports found */
16659/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
16660/***/ (function(module, exports, __webpack_require__) {
16661
16662"use strict";
16663/* WEBPACK VAR INJECTION */(function(Number) {
16664Object.defineProperty(exports, "__esModule", { value: true });
16665var binary_search_1 = __webpack_require__(/*! ./binary-search */ "./src/utils/binary-search.js");
16666var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
16667function findFirstFragWithCC(fragments, cc) {
16668    var firstFrag = null;
16669    for (var i = 0; i < fragments.length; i += 1) {
16670        var currentFrag = fragments[i];
16671        if (currentFrag && currentFrag.cc === cc) {
16672            firstFrag = currentFrag;
16673            break;
16674        }
16675    }
16676    return firstFrag;
16677}
16678exports.findFirstFragWithCC = findFirstFragWithCC;
16679function findFragWithCC(fragments, CC) {
16680    return binary_search_1.default.search(fragments, function (candidate) {
16681        if (candidate.cc < CC) {
16682            return 1;
16683        }
16684        else if (candidate.cc > CC) {
16685            return -1;
16686        }
16687        else {
16688            return 0;
16689        }
16690    });
16691}
16692exports.findFragWithCC = findFragWithCC;
16693function shouldAlignOnDiscontinuities(lastFrag, lastLevel, details) {
16694    var shouldAlign = false;
16695    if (lastLevel && lastLevel.details && details) {
16696        if (details.endCC > details.startCC || (lastFrag && lastFrag.cc < details.startCC)) {
16697            shouldAlign = true;
16698        }
16699    }
16700    return shouldAlign;
16701}
16702exports.shouldAlignOnDiscontinuities = shouldAlignOnDiscontinuities;
16703// Find the first frag in the previous level which matches the CC of the first frag of the new level
16704function findDiscontinuousReferenceFrag(prevDetails, curDetails) {
16705    var prevFrags = prevDetails.fragments;
16706    var curFrags = curDetails.fragments;
16707    if (!curFrags.length || !prevFrags.length) {
16708        logger_1.logger.log('No fragments to align');
16709        return;
16710    }
16711    var prevStartFrag = findFirstFragWithCC(prevFrags, curFrags[0].cc);
16712    if (!prevStartFrag || (prevStartFrag && !prevStartFrag.startPTS)) {
16713        logger_1.logger.log('No frag in previous level to align on');
16714        return;
16715    }
16716    return prevStartFrag;
16717}
16718exports.findDiscontinuousReferenceFrag = findDiscontinuousReferenceFrag;
16719function adjustPts(sliding, details) {
16720    details.fragments.forEach(function (frag) {
16721        if (frag) {
16722            var start = frag.start + sliding;
16723            frag.start = frag.startPTS = start;
16724            frag.endPTS = start + frag.duration;
16725        }
16726    });
16727    details.PTSKnown = true;
16728}
16729exports.adjustPts = adjustPts;
16730/**
16731 * Using the parameters of the last level, this function computes PTS' of the new fragments so that they form a
16732 * contiguous stream with the last fragments.
16733 * The PTS of a fragment lets Hls.js know where it fits into a stream - by knowing every PTS, we know which fragment to
16734 * download at any given time. PTS is normally computed when the fragment is demuxed, so taking this step saves us time
16735 * and an extra download.
16736 * @param lastFrag
16737 * @param lastLevel
16738 * @param details
16739 */
16740function alignStream(lastFrag, lastLevel, details) {
16741    alignDiscontinuities(lastFrag, details, lastLevel);
16742    if (!details.PTSKnown && lastLevel) {
16743        // If the PTS wasn't figured out via discontinuity sequence that means there was no CC increase within the level.
16744        // Aligning via Program Date Time should therefore be reliable, since PDT should be the same within the same
16745        // discontinuity sequence.
16746        alignPDT(details, lastLevel.details);
16747    }
16748}
16749exports.alignStream = alignStream;
16750/**
16751 * Computes the PTS if a new level's fragments using the PTS of a fragment in the last level which shares the same
16752 * discontinuity sequence.
16753 * @param lastLevel - The details of the last loaded level
16754 * @param details - The details of the new level
16755 */
16756function alignDiscontinuities(lastFrag, details, lastLevel) {
16757    if (shouldAlignOnDiscontinuities(lastFrag, lastLevel, details)) {
16758        var referenceFrag = findDiscontinuousReferenceFrag(lastLevel.details, details);
16759        if (referenceFrag) {
16760            logger_1.logger.log('Adjusting PTS using last level due to CC increase within current level');
16761            adjustPts(referenceFrag.start, details);
16762        }
16763    }
16764}
16765exports.alignDiscontinuities = alignDiscontinuities;
16766/**
16767 * Computes the PTS of a new level's fragments using the difference in Program Date Time from the last level.
16768 * @param details - The details of the new level
16769 * @param lastDetails - The details of the last loaded level
16770 */
16771function alignPDT(details, lastDetails) {
16772    if (lastDetails && lastDetails.fragments.length) {
16773        if (!details.hasProgramDateTime || !lastDetails.hasProgramDateTime) {
16774            return;
16775        }
16776        // if last level sliding is 1000 and its first frag PROGRAM-DATE-TIME is 2017-08-20 1:10:00 AM
16777        // and if new details first frag PROGRAM DATE-TIME is 2017-08-20 1:10:08 AM
16778        // then we can deduce that playlist B sliding is 1000+8 = 1008s
16779        var lastPDT = lastDetails.fragments[0].programDateTime;
16780        var newPDT = details.fragments[0].programDateTime;
16781        // date diff is in ms. frag.start is in seconds
16782        var sliding = (newPDT - lastPDT) / 1000 + lastDetails.fragments[0].start;
16783        if (Number.isFinite(sliding)) {
16784            logger_1.logger.log("adjusting PTS using programDateTime delta, sliding:" + sliding.toFixed(3));
16785            adjustPts(sliding, details);
16786        }
16787    }
16788}
16789exports.alignPDT = alignPDT;
16790
16791/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.js")["Number"]))
16792
16793/***/ }),
16794
16795/***/ "./src/utils/ewma-bandwidth-estimator.js":
16796/*!***********************************************!*\
16797  !*** ./src/utils/ewma-bandwidth-estimator.js ***!
16798  \***********************************************/
16799/*! no static exports found */
16800/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
16801/***/ (function(module, exports, __webpack_require__) {
16802
16803"use strict";
16804
16805/*
16806 * EWMA Bandwidth Estimator
16807 *  - heavily inspired from shaka-player
16808 * Tracks bandwidth samples and estimates available bandwidth.
16809 * Based on the minimum of two exponentially-weighted moving averages with
16810 * different half-lives.
16811 */
16812Object.defineProperty(exports, "__esModule", { value: true });
16813var ewma_1 = __webpack_require__(/*! ../utils/ewma */ "./src/utils/ewma.js");
16814var EwmaBandWidthEstimator = /** @class */ (function () {
16815    function EwmaBandWidthEstimator(hls, slow, fast, defaultEstimate) {
16816        this.hls = hls;
16817        this.defaultEstimate_ = defaultEstimate;
16818        this.minWeight_ = 0.001;
16819        this.minDelayMs_ = 50;
16820        this.slow_ = new ewma_1.default(slow);
16821        this.fast_ = new ewma_1.default(fast);
16822    }
16823    EwmaBandWidthEstimator.prototype.sample = function (durationMs, numBytes) {
16824        durationMs = Math.max(durationMs, this.minDelayMs_);
16825        var bandwidth = 8000 * numBytes / durationMs, 
16826        // console.log('instant bw:'+ Math.round(bandwidth));
16827        // we weight sample using loading duration....
16828        weight = durationMs / 1000;
16829        this.fast_.sample(weight, bandwidth);
16830        this.slow_.sample(weight, bandwidth);
16831    };
16832    EwmaBandWidthEstimator.prototype.canEstimate = function () {
16833        var fast = this.fast_;
16834        return (fast && fast.getTotalWeight() >= this.minWeight_);
16835    };
16836    EwmaBandWidthEstimator.prototype.getEstimate = function () {
16837        if (this.canEstimate()) {
16838            // console.log('slow estimate:'+ Math.round(this.slow_.getEstimate()));
16839            // console.log('fast estimate:'+ Math.round(this.fast_.getEstimate()));
16840            // Take the minimum of these two estimates.  This should have the effect of
16841            // adapting down quickly, but up more slowly.
16842            return Math.min(this.fast_.getEstimate(), this.slow_.getEstimate());
16843        }
16844        else {
16845            return this.defaultEstimate_;
16846        }
16847    };
16848    EwmaBandWidthEstimator.prototype.destroy = function () {
16849    };
16850    return EwmaBandWidthEstimator;
16851}());
16852exports.default = EwmaBandWidthEstimator;
16853
16854
16855/***/ }),
16856
vendor: 1,566 bytes, lines 16857-16904
16857/***/ "./src/utils/ewma.js":
16858/*!***************************!*\
16859  !*** ./src/utils/ewma.js ***!
16860  \***************************/
16861/*! no static exports found */
16862/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
16863/***/ (function(module, exports, __webpack_require__) {
16864
16865"use strict";
16866
16867/*
16868 * compute an Exponential Weighted moving average
16869 * - https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
16870 *  - heavily inspired from shaka-player
16871 */
16872Object.defineProperty(exports, "__esModule", { value: true });
16873var EWMA = /** @class */ (function () {
16874    //  About half of the estimated value will be from the last |halfLife| samples by weight.
16875    function EWMA(halfLife) {
16876        // Larger values of alpha expire historical data more slowly.
16877        this.alpha_ = halfLife ? Math.exp(Math.log(0.5) / halfLife) : 0;
16878        this.estimate_ = 0;
16879        this.totalWeight_ = 0;
16880    }
16881    EWMA.prototype.sample = function (weight, value) {
16882        var adjAlpha = Math.pow(this.alpha_, weight);
16883        this.estimate_ = value * (1 - adjAlpha) + adjAlpha * this.estimate_;
16884        this.totalWeight_ += weight;
16885    };
16886    EWMA.prototype.getTotalWeight = function () {
16887        return this.totalWeight_;
16888    };
16889    EWMA.prototype.getEstimate = function () {
16890        if (this.alpha_) {
16891            var zeroFactor = 1 - Math.pow(this.alpha_, this.totalWeight_);
16892            return this.estimate_ / zeroFactor;
16893        }
16894        else {
16895            return this.estimate_;
16896        }
16897    };
16898    return EWMA;
16899}());
16900exports.default = EWMA;
16901
16902
16903/***/ }),
16904
16905/***/ "./src/utils/get-self-scope.js":
16906/*!*************************************!*\
16907  !*** ./src/utils/get-self-scope.js ***!
16908  \*************************************/
16909/*! no static exports found */
16910/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
16911/***/ (function(module, exports, __webpack_require__) {
16912
16913"use strict";
16914
16915Object.defineProperty(exports, "__esModule", { value: true });
16916function getSelfScope() {
16917    // see https://stackoverflow.com/a/11237259/589493
16918    if (typeof window === 'undefined') {
16919        /* eslint-disable-next-line no-undef */
16920        return self;
16921    }
16922    else {
16923        return window;
16924    }
16925}
16926exports.getSelfScope = getSelfScope;
16927
16928
16929/***/ }),
16930
vendor: 2,497 bytes, lines 16931-17014
16931/***/ "./src/utils/logger.js":
16932/*!*****************************!*\
16933  !*** ./src/utils/logger.js ***!
16934  \*****************************/
16935/*! no static exports found */
16936/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
16937/***/ (function(module, exports, __webpack_require__) {
16938
16939"use strict";
16940
16941Object.defineProperty(exports, "__esModule", { value: true });
16942var get_self_scope_1 = __webpack_require__(/*! ./get-self-scope */ "./src/utils/get-self-scope.js");
16943function noop() { }
16944var fakeLogger = {
16945    trace: noop,
16946    debug: noop,
16947    log: noop,
16948    warn: noop,
16949    info: noop,
16950    error: noop
16951};
16952var exportedLogger = fakeLogger;
16953// let lastCallTime;
16954// function formatMsgWithTimeInfo(type, msg) {
16955//   const now = Date.now();
16956//   const diff = lastCallTime ? '+' + (now - lastCallTime) : '0';
16957//   lastCallTime = now;
16958//   msg = (new Date(now)).toISOString() + ' | [' +  type + '] > ' + msg + ' ( ' + diff + ' ms )';
16959//   return msg;
16960// }
16961function formatMsg(type, msg) {
16962    msg = '[' + type + '] > ' + msg;
16963    return msg;
16964}
16965var global = get_self_scope_1.getSelfScope();
16966function consolePrintFn(type) {
16967    var func = global.console[type];
16968    if (func) {
16969        return function () {
16970            var args = [];
16971            for (var _i = 0; _i < arguments.length; _i++) {
16972                args[_i] = arguments[_i];
16973            }
16974            if (args[0]) {
16975                args[0] = formatMsg(type, args[0]);
16976            }
16977            func.apply(global.console, args);
16978        };
16979    }
16980    return noop;
16981}
16982function exportLoggerFunctions(debugConfig) {
16983    var functions = [];
16984    for (var _i = 1; _i < arguments.length; _i++) {
16985        functions[_i - 1] = arguments[_i];
16986    }
16987    functions.forEach(function (type) {
16988        exportedLogger[type] = debugConfig[type] ? debugConfig[type].bind(debugConfig) : consolePrintFn(type);
16989    });
16990}
16991exports.enableLogs = function (debugConfig) {
16992    if (debugConfig === true || typeof debugConfig === 'object') {
16993        exportLoggerFunctions(debugConfig, 
16994        // Remove out from list here to hard-disable a log-level
16995        // 'trace',
16996        'debug', 'log', 'info', 'warn', 'error');
16997        // Some browsers don't allow to use bind on console object anyway
16998        // fallback to default if needed
16999        try {
17000            exportedLogger.log();
17001        }
17002        catch (e) {
17003            exportedLogger = fakeLogger;
17004        }
17005    }
17006    else {
17007        exportedLogger = fakeLogger;
17008    }
17009};
17010exports.logger = exportedLogger;
17011
17012
17013/***/ }),
17014
17015/***/ "./src/utils/mediakeys-helper.js":
17016/*!***************************************!*\
17017  !*** ./src/utils/mediakeys-helper.js ***!
17018  \***************************************/
17019/*! no static exports found */
17020/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
17021/***/ (function(module, exports, __webpack_require__) {
17022
17023"use strict";
17024
17025Object.defineProperty(exports, "__esModule", { value: true });
17026var requestMediaKeySystemAccess = (function () {
17027    if (typeof window !== 'undefined' && window.navigator && window.navigator.requestMediaKeySystemAccess) {
17028        return window.navigator.requestMediaKeySystemAccess.bind(window.navigator);
17029    }
17030    else {
17031        return null;
17032    }
17033})();
17034exports.requestMediaKeySystemAccess = requestMediaKeySystemAccess;
17035
17036
17037/***/ }),
17038
17039/***/ "./src/utils/mediasource-helper.js":
17040/*!*****************************************!*\
17041  !*** ./src/utils/mediasource-helper.js ***!
17042  \*****************************************/
17043/*! no static exports found */
17044/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
17045/***/ (function(module, exports, __webpack_require__) {
17046
17047"use strict";
17048
17049/**
17050 * MediaSource helper
17051 */
17052Object.defineProperty(exports, "__esModule", { value: true });
17053function getMediaSource() {
17054    if (typeof window !== 'undefined') {
17055        return window.MediaSource || window.WebKitMediaSource;
17056    }
17057}
17058exports.getMediaSource = getMediaSource;
17059
17060
17061/***/ }),
17062
17063/***/ "./src/utils/output-filter.js":
17064/*!************************************!*\
17065  !*** ./src/utils/output-filter.js ***!
17066  \************************************/
17067/*! no static exports found */
17068/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
17069/***/ (function(module, exports, __webpack_require__) {
17070
17071"use strict";
17072
17073Object.defineProperty(exports, "__esModule", { value: true });
17074var OutputFilter = /** @class */ (function () {
17075    function OutputFilter(timelineController, trackName) {
17076        this.timelineController = timelineController;
17077        this.trackName = trackName;
17078        this.startTime = null;
17079        this.endTime = null;
17080        this.screen = null;
17081    }
17082    OutputFilter.prototype.dispatchCue = function () {
17083        if (this.startTime === null) {
17084            return;
17085        }
17086        this.timelineController.addCues(this.trackName, this.startTime, this.endTime, this.screen);
17087        this.startTime = null;
17088    };
17089    OutputFilter.prototype.newCue = function (startTime, endTime, screen) {
17090        if (this.startTime === null || this.startTime > startTime) {
17091            this.startTime = startTime;
17092        }
17093        this.endTime = endTime;
17094        this.screen = screen;
17095        this.timelineController.createCaptionsTrack(this.trackName);
17096    };
17097    return OutputFilter;
17098}());
17099exports.default = OutputFilter;
17100
17101
17102/***/ }),
17103
17104/***/ "./src/utils/texttrack-utils.js":
17105/*!**************************************!*\
17106  !*** ./src/utils/texttrack-utils.js ***!
17107  \**************************************/
17108/*! no static exports found */
17109/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
17110/***/ (function(module, exports, __webpack_require__) {
17111
17112"use strict";
17113
17114Object.defineProperty(exports, "__esModule", { value: true });
17115function sendAddTrackEvent(track, videoEl) {
17116    var event = null;
17117    try {
17118        event = new window.Event('addtrack');
17119    }
17120    catch (err) {
17121        // for IE11
17122        event = document.createEvent('Event');
17123        event.initEvent('addtrack', false, false);
17124    }
17125    event.track = track;
17126    videoEl.dispatchEvent(event);
17127}
17128exports.sendAddTrackEvent = sendAddTrackEvent;
17129function clearCurrentCues(track) {
17130    if (track && track.cues) {
17131        while (track.cues.length > 0) {
17132            track.removeCue(track.cues[0]);
17133        }
17134    }
17135}
17136exports.clearCurrentCues = clearCurrentCues;
17137
17138
17139/***/ }),
17140
17141/***/ "./src/utils/time-ranges.js":
17142/*!**********************************!*\
17143  !*** ./src/utils/time-ranges.js ***!
17144  \**********************************/
17145/*! no static exports found */
17146/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
17147/***/ (function(module, exports, __webpack_require__) {
17148
17149"use strict";
17150
17151/**
17152 *  TimeRanges to string helper
17153 */
17154Object.defineProperty(exports, "__esModule", { value: true });
17155var TimeRanges = {
17156    toString: function (r) {
17157        var log = '', len = r.length;
17158        for (var i = 0; i < len; i++) {
17159            log += '[' + r.start(i).toFixed(3) + ',' + r.end(i).toFixed(3) + ']';
17160        }
17161        return log;
17162    }
17163};
17164exports.default = TimeRanges;
17165
17166
17167/***/ }),
17168
vendor: 6,870 bytes, lines 17169-17374
17169/***/ "./src/utils/vttcue.js":
17170/*!*****************************!*\
17171  !*** ./src/utils/vttcue.js ***!
17172  \*****************************/
17173/*! no static exports found */
17174/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
17175/***/ (function(module, exports, __webpack_require__) {
17176
17177"use strict";
17178
17179/**
17180 * Copyright 2013 vtt.js Contributors
17181 *
17182 * Licensed under the Apache License, Version 2.0 (the "License");
17183 * you may not use this file except in compliance with the License.
17184 * You may obtain a copy of the License at
17185 *
17186 *   http://www.apache.org/licenses/LICENSE-2.0
17187 *
17188 * Unless required by applicable law or agreed to in writing, software
17189 * distributed under the License is distributed on an "AS IS" BASIS,
17190 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17191 * See the License for the specific language governing permissions and
17192 * limitations under the License.
17193 */
17194Object.defineProperty(exports, "__esModule", { value: true });
17195exports.default = (function () {
17196    if (typeof window !== 'undefined' && window.VTTCue) {
17197        return window.VTTCue;
17198    }
17199    var autoKeyword = 'auto';
17200    var directionSetting = {
17201        '': true,
17202        lr: true,
17203        rl: true
17204    };
17205    var alignSetting = {
17206        start: true,
17207        middle: true,
17208        end: true,
17209        left: true,
17210        right: true
17211    };
17212    function findDirectionSetting(value) {
17213        if (typeof value !== 'string') {
17214            return false;
17215        }
17216        var dir = directionSetting[value.toLowerCase()];
17217        return dir ? value.toLowerCase() : false;
17218    }
17219    function findAlignSetting(value) {
17220        if (typeof value !== 'string') {
17221            return false;
17222        }
17223        var align = alignSetting[value.toLowerCase()];
17224        return align ? value.toLowerCase() : false;
17225    }
17226    function extend(obj) {
17227        var i = 1;
17228        for (; i < arguments.length; i++) {
17229            var cobj = arguments[i];
17230            for (var p in cobj) {
17231                obj[p] = cobj[p];
17232            }
17233        }
17234        return obj;
17235    }
17236    function VTTCue(startTime, endTime, text) {
17237        var cue = this;
17238        var isIE8 = (function () {
17239            if (typeof navigator === 'undefined') {
17240                return;
17241            }
17242            return (/MSIE\s8\.0/).test(navigator.userAgent);
17243        })();
17244        var baseObj = {};
17245        if (isIE8) {
17246            cue = document.createElement('custom');
17247        }
17248        else {
17249            baseObj.enumerable = true;
17250        }
17251        /**
17252         * Shim implementation specific properties. These properties are not in
17253         * the spec.
17254         */
17255        // Lets us know when the VTTCue's data has changed in such a way that we need
17256        // to recompute its display state. This lets us compute its display state
17257        // lazily.
17258        cue.hasBeenReset = false;
17259        /**
17260         * VTTCue and TextTrackCue properties
17261         * http://dev.w3.org/html5/webvtt/#vttcue-interface
17262         */
17263        var _id = '';
17264        var _pauseOnExit = false;
17265        var _startTime = startTime;
17266        var _endTime = endTime;
17267        var _text = text;
17268        var _region = null;
17269        var _vertical = '';
17270        var _snapToLines = true;
17271        var _line = 'auto';
17272        var _lineAlign = 'start';
17273        var _position = 50;
17274        var _positionAlign = 'middle';
17275        var _size = 50;
17276        var _align = 'middle';
17277        Object.defineProperty(cue, 'id', extend({}, baseObj, {
17278            get: function () {
17279                return _id;
17280            },
17281            set: function (value) {
17282                _id = '' + value;
17283            }
17284        }));
17285        Object.defineProperty(cue, 'pauseOnExit', extend({}, baseObj, {
17286            get: function () {
17287                return _pauseOnExit;
17288            },
17289            set: function (value) {
17290                _pauseOnExit = !!value;
17291            }
17292        }));
17293        Object.defineProperty(cue, 'startTime', extend({}, baseObj, {
17294            get: function () {
17295                return _startTime;
17296            },
17297            set: function (value) {
17298                if (typeof value !== 'number') {
17299                    throw new TypeError('Start time must be set to a number.');
17300                }
17301                _startTime = value;
17302                this.hasBeenReset = true;
17303            }
17304        }));
17305        Object.defineProperty(cue, 'endTime', extend({}, baseObj, {
17306            get: function () {
17307                return _endTime;
17308            },
17309            set: function (value) {
17310                if (typeof value !== 'number') {
17311                    throw new TypeError('End time must be set to a number.');
17312                }
17313                _endTime = value;
17314                this.hasBeenReset = true;
17315            }
17316        }));
17317        Object.defineProperty(cue, 'text', extend({}, baseObj, {
17318            get: function () {
17319                return _text;
17320            },
17321            set: function (value) {
17322                _text = '' + value;
17323                this.hasBeenReset = true;
17324            }
17325        }));
17326        Object.defineProperty(cue, 'region', extend({}, baseObj, {
17327            get: function () {
17328                return _region;
17329            },
17330            set: function (value) {
17331                _region = value;
17332                this.hasBeenReset = true;
17333            }
17334        }));
17335        Object.defineProperty(cue, 'vertical', extend({}, baseObj, {
17336            get: function () {
17337                return _vertical;
17338            },
17339            set: function (value) {
17340                var setting = findDirectionSetting(value);
17341                // Have to check for false because the setting an be an empty string.
17342                if (setting === false) {
17343                    throw new SyntaxError('An invalid or illegal string was specified.');
17344                }
17345                _vertical = setting;
17346                this.hasBeenReset = true;
17347            }
17348        }));
17349        Object.defineProperty(cue, 'snapToLines', extend({}, baseObj, {
17350            get: function () {
17351                return _snapToLines;
17352            },
17353            set: function (value) {
17354                _snapToLines = !!value;
17355                this.hasBeenReset = true;
17356            }
17357        }));
17358        Object.defineProperty(cue, 'line', extend({}, baseObj, {
17359            get: function () {
17360                return _line;
17361            },
17362            set: function (value) {
17363                if (typeof value !== 'number' && value !== autoKeyword) {
17364                    throw new SyntaxError('An invalid number or illegal string was specified.');
17365                }
17366                _line = value;
17367                this.hasBeenReset = true;
17368            }
17369        }));
17370        Object.defineProperty(cue, 'lineAlign', extend({}, baseObj, {
17371            get: function () {
17372                return _lineAlign;
17373            },
17374            set: function (value) {
17375                var setting = findAlignSetting(value);
17376                if (!setting) {
17377                    throw new SyntaxError('An invalid or illegal string was specified.');
17378                }
17379                _lineAlign = setting;
17380                this.hasBeenReset = true;
17381            }
17382        }));
17383        Object.defineProperty(cue, 'position', extend({}, baseObj, {
17384            get: function () {
17385                return _position;
17386            },
17387            set: function (value) {
17388                if (value < 0 || value > 100) {
17389                    throw new Error('Position must be between 0 and 100.');
17390                }
17391                _position = value;
17392                this.hasBeenReset = true;
17393            }
17394        }));
17395        Object.defineProperty(cue, 'positionAlign', extend({}, baseObj, {
17396            get: function () {
17397                return _positionAlign;
17398            },
17399            set: function (value) {
17400                var setting = findAlignSetting(value);
17401                if (!setting) {
17402                    throw new SyntaxError('An invalid or illegal string was specified.');
17403                }
17404                _positionAlign = setting;
17405                this.hasBeenReset = true;
17406            }
17407        }));
17408        Object.defineProperty(cue, 'size', extend({}, baseObj, {
17409            get: function () {
17410                return _size;
17411            },
17412            set: function (value) {
17413                if (value < 0 || value > 100) {
17414                    throw new Error('Size must be between 0 and 100.');
17415                }
17416                _size = value;
17417                this.hasBeenReset = true;
17418            }
17419        }));
17420        Object.defineProperty(cue, 'align', extend({}, baseObj, {
17421            get: function () {
17422                return _align;
17423            },
17424            set: function (value) {
17425                var setting = findAlignSetting(value);
17426                if (!setting) {
17427                    throw new SyntaxError('An invalid or illegal string was specified.');
17428                }
17429                _align = setting;
17430                this.hasBeenReset = true;
17431            }
17432        }));
17433        /**
17434         * Other <track> spec defined properties
17435         */
17436        // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#text-track-cue-display-state
17437        cue.displayState = undefined;
17438        if (isIE8) {
17439            return cue;
17440        }
17441    }
17442    /**
17443     * VTTCue methods
17444     */
17445    VTTCue.prototype.getCueAsHTML = function () {
17446        // Assume WebVTT.convertCueToDOMTree is on the global.
17447        var WebVTT = window.WebVTT;
17448        return WebVTT.convertCueToDOMTree(window, this.text);
17449    };
17450    return VTTCue;
17451})();
17452
17453
17454/***/ }),
17455
vendor: 4,392 bytes, lines 17456-17587
17456/***/ "./src/utils/vttparser.js":
17457/*!********************************!*\
17458  !*** ./src/utils/vttparser.js ***!
17459  \********************************/
17460/*! no static exports found */
17461/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
17462/***/ (function(module, exports, __webpack_require__) {
17463
17464"use strict";
17465
17466/*
17467 * Source: https://github.com/mozilla/vtt.js/blob/master/dist/vtt.js#L1716
17468 */
17469Object.defineProperty(exports, "__esModule", { value: true });
17470var vttcue_1 = __webpack_require__(/*! ./vttcue */ "./src/utils/vttcue.js");
17471var StringDecoder = function StringDecoder() {
17472    return {
17473        decode: function (data) {
17474            if (!data) {
17475                return '';
17476            }
17477            if (typeof data !== 'string') {
17478                throw new Error('Error - expected string data.');
17479            }
17480            return decodeURIComponent(encodeURIComponent(data));
17481        }
17482    };
17483};
17484function VTTParser() {
17485    this.window = window;
17486    this.state = 'INITIAL';
17487    this.buffer = '';
17488    this.decoder = new StringDecoder();
17489    this.regionList = [];
17490}
17491// Try to parse input as a time stamp.
17492function parseTimeStamp(input) {
17493    function computeSeconds(h, m, s, f) {
17494        return (h | 0) * 3600 + (m | 0) * 60 + (s | 0) + (f | 0) / 1000;
17495    }
17496    var m = input.match(/^(\d+):(\d{2})(:\d{2})?\.(\d{3})/);
17497    if (!m) {
17498        return null;
17499    }
17500    if (m[3]) {
17501        // Timestamp takes the form of [hours]:[minutes]:[seconds].[milliseconds]
17502        return computeSeconds(m[1], m[2], m[3].replace(':', ''), m[4]);
17503    }
17504    else if (m[1] > 59) {
17505        // Timestamp takes the form of [hours]:[minutes].[milliseconds]
17506        // First position is hours as it's over 59.
17507        return computeSeconds(m[1], m[2], 0, m[4]);
17508    }
17509    else {
17510        // Timestamp takes the form of [minutes]:[seconds].[milliseconds]
17511        return computeSeconds(0, m[1], m[2], m[4]);
17512    }
17513}
17514// A settings object holds key/value pairs and will ignore anything but the first
17515// assignment to a specific key.
17516function Settings() {
17517    this.values = Object.create(null);
17518}
17519Settings.prototype = {
17520    // Only accept the first assignment to any key.
17521    set: function (k, v) {
17522        if (!this.get(k) && v !== '') {
17523            this.values[k] = v;
17524        }
17525    },
17526    // Return the value for a key, or a default value.
17527    // If 'defaultKey' is passed then 'dflt' is assumed to be an object with
17528    // a number of possible default values as properties where 'defaultKey' is
17529    // the key of the property that will be chosen; otherwise it's assumed to be
17530    // a single value.
17531    get: function (k, dflt, defaultKey) {
17532        if (defaultKey) {
17533            return this.has(k) ? this.values[k] : dflt[defaultKey];
17534        }
17535        return this.has(k) ? this.values[k] : dflt;
17536    },
17537    // Check whether we have a value for a key.
17538    has: function (k) {
17539        return k in this.values;
17540    },
17541    // Accept a setting if its one of the given alternatives.
17542    alt: function (k, v, a) {
17543        for (var n = 0; n < a.length; ++n) {
17544            if (v === a[n]) {
17545                this.set(k, v);
17546                break;
17547            }
17548        }
17549    },
17550    // Accept a setting if its a valid (signed) integer.
17551    integer: function (k, v) {
17552        if (/^-?\d+$/.test(v)) { // integer
17553            this.set(k, parseInt(v, 10));
17554        }
17555    },
17556    // Accept a setting if its a valid percentage.
17557    percent: function (k, v) {
17558        var m;
17559        if ((m = v.match(/^([\d]{1,3})(\.[\d]*)?%$/))) {
17560            v = parseFloat(v);
17561            if (v >= 0 && v <= 100) {
17562                this.set(k, v);
17563                return true;
17564            }
17565        }
17566        return false;
17567    }
17568};
17569// Helper function to parse input into groups separated by 'groupDelim', and
17570// interprete each group as a key/value pair separated by 'keyValueDelim'.
17571function parseOptions(input, callback, keyValueDelim, groupDelim) {
17572    var groups = groupDelim ? input.split(groupDelim) : [input];
17573    for (var i in groups) {
17574        if (typeof groups[i] !== 'string') {
17575            continue;
17576        }
17577        var kv = groups[i].split(keyValueDelim);
17578        if (kv.length !== 2) {
17579            continue;
17580        }
17581        var k = kv[0];
17582        var v = kv[1];
17583        callback(k, v);
17584    }
17585}
17586var defaults = new vttcue_1.default(0, 0, 0);
17587// 'middle' was changed to 'center' in the spec: https://github.com/w3c/webvtt/
vendor: 10,982 bytes, lines 17587-17849
17587pull/244
17588//  Safari doesn't yet support this change, but FF and Chrome do.
17589var center = defaults.align === 'middle' ? 'middle' : 'center';
17590function parseCue(input, cue, regionList) {
17591    // Remember the original input if we need to throw an error.
17592    var oInput = input;
17593    // 4.1 WebVTT timestamp
17594    function consumeTimeStamp() {
17595        var ts = parseTimeStamp(input);
17596        if (ts === null) {
17597            throw new Error('Malformed timestamp: ' + oInput);
17598        }
17599        // Remove time stamp from input.
17600        input = input.replace(/^[^\sa-zA-Z-]+/, '');
17601        return ts;
17602    }
17603    // 4.4.2 WebVTT cue settings
17604    function consumeCueSettings(input, cue) {
17605        var settings = new Settings();
17606        parseOptions(input, function (k, v) {
17607            switch (k) {
17608                case 'region':
17609                    // Find the last region we parsed with the same region id.
17610                    for (var i = regionList.length - 1; i >= 0; i--) {
17611                        if (regionList[i].id === v) {
17612                            settings.set(k, regionList[i].region);
17613                            break;
17614                        }
17615                    }
17616                    break;
17617                case 'vertical':
17618                    settings.alt(k, v, ['rl', 'lr']);
17619                    break;
17620                case 'line':
17621                    var vals = v.split(','), vals0 = vals[0];
17622                    settings.integer(k, vals0);
17623                    if (settings.percent(k, vals0)) {
17624                        settings.set('snapToLines', false);
17625                    }
17626                    settings.alt(k, vals0, ['auto']);
17627                    if (vals.length === 2) {
17628                        settings.alt('lineAlign', vals[1], ['start', center, 'end']);
17629                    }
17630                    break;
17631                case 'position':
17632                    vals = v.split(',');
17633                    settings.percent(k, vals[0]);
17634                    if (vals.length === 2) {
17635                        settings.alt('positionAlign', vals[1], ['start', center, 'end', 'line-left', 'line-right', 'auto']);
17636                    }
17637                    break;
17638                case 'size':
17639                    settings.percent(k, v);
17640                    break;
17641                case 'align':
17642                    settings.alt(k, v, ['start', center, 'end', 'left', 'right']);
17643                    break;
17644            }
17645        }, /:/, /\s/);
17646        // Apply default values for any missing fields.
17647        cue.region = settings.get('region', null);
17648        cue.vertical = settings.get('vertical', '');
17649        var line = settings.get('line', 'auto');
17650        if (line === 'auto' && defaults.line === -1) {
17651            // set numeric line number for Safari
17652            line = -1;
17653        }
17654        cue.line = line;
17655        cue.lineAlign = settings.get('lineAlign', 'start');
17656        cue.snapToLines = settings.get('snapToLines', true);
17657        cue.size = settings.get('size', 100);
17658        cue.align = settings.get('align', center);
17659        var position = settings.get('position', 'auto');
17660        if (position === 'auto' && defaults.position === 50) {
17661            // set numeric position for Safari
17662            position = cue.align === 'start' || cue.align === 'left' ? 0 : cue.align === 'end' || cue.align === 'right' ? 100 : 50;
17663        }
17664        cue.position = position;
17665    }
17666    function skipWhitespace() {
17667        input = input.replace(/^\s+/, '');
17668    }
17669    // 4.1 WebVTT cue timings.
17670    skipWhitespace();
17671    cue.startTime = consumeTimeStamp(); // (1) collect cue start time
17672    skipWhitespace();
17673    if (input.substr(0, 3) !== '-->') { // (3) next characters must match '-->'
17674        throw new Error('Malformed time stamp (time stamps must be separated by \'-->\'): ' +
17675            oInput);
17676    }
17677    input = input.substr(3);
17678    skipWhitespace();
17679    cue.endTime = consumeTimeStamp(); // (5) collect cue end time
17680    // 4.1 WebVTT cue settings list.
17681    skipWhitespace();
17682    consumeCueSettings(input, cue);
17683}
17684function fixLineBreaks(input) {
17685    return input.replace(/<br(?: \/)?>/gi, '\n');
17686}
17687exports.fixLineBreaks = fixLineBreaks;
17688VTTParser.prototype = {
17689    parse: function (data) {
17690        var self = this;
17691        // If there is no data then we won't decode it, but will just try to parse
17692        // whatever is in buffer already. This may occur in circumstances, for
17693        // example when flush() is called.
17694        if (data) {
17695            // Try to decode the data that we received.
17696            self.buffer += self.decoder.decode(data, { stream: true });
17697        }
17698        function collectNextLine() {
17699            var buffer = self.buffer;
17700            var pos = 0;
17701            buffer = fixLineBreaks(buffer);
17702            while (pos < buffer.length && buffer[pos] !== '\r' && buffer[pos] !== '\n') {
17703                ++pos;
17704            }
17705            var line = buffer.substr(0, pos);
17706            // Advance the buffer early in case we fail below.
17707            if (buffer[pos] === '\r') {
17708                ++pos;
17709            }
17710            if (buffer[pos] === '\n') {
17711                ++pos;
17712            }
17713            self.buffer = buffer.substr(pos);
17714            return line;
17715        }
17716        // 3.2 WebVTT metadata header syntax
17717        function parseHeader(input) {
17718            parseOptions(input, function (k, v) {
17719                switch (k) {
17720                    case 'Region':
17721                        // 3.3 WebVTT region metadata header syntax
17722                        // console.log('parse region', v);
17723                        // parseRegion(v);
17724                        break;
17725                }
17726            }, /:/);
17727        }
17728        // 5.1 WebVTT file parsing.
17729        try {
17730            var line = void 0;
17731            if (self.state === 'INITIAL') {
17732                // We can't start parsing until we have the first line.
17733                if (!/\r\n|\n/.test(self.buffer)) {
17734                    return this;
17735                }
17736                line = collectNextLine();
17737                // strip of UTF-8 BOM if any
17738                // https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8
17739                var m = line.match(/^()?WEBVTT([ \t].*)?$/);
17740                if (!m || !m[0]) {
17741                    throw new Error('Malformed WebVTT signature.');
17742                }
17743                self.state = 'HEADER';
17744            }
17745            var alreadyCollectedLine = false;
17746            while (self.buffer) {
17747                // We can't parse a line until we have the full line.
17748                if (!/\r\n|\n/.test(self.buffer)) {
17749                    return this;
17750                }
17751                if (!alreadyCollectedLine) {
17752                    line = collectNextLine();
17753                }
17754                else {
17755                    alreadyCollectedLine = false;
17756                }
17757                switch (self.state) {
17758                    case 'HEADER':
17759                        // 13-18 - Allow a header (metadata) under the WEBVTT line.
17760                        if (/:/.test(line)) {
17761                            parseHeader(line);
17762                        }
17763                        else if (!line) {
17764                            // An empty line terminates the header and starts the body (cues).
17765                            self.state = 'ID';
17766                        }
17767                        continue;
17768                    case 'NOTE':
17769                        // Ignore NOTE blocks.
17770                        if (!line) {
17771                            self.state = 'ID';
17772                        }
17773                        continue;
17774                    case 'ID':
17775                        // Check for the start of NOTE blocks.
17776                        if (/^NOTE($|[ \t])/.test(line)) {
17777                            self.state = 'NOTE';
17778                            break;
17779                        }
17780                        // 19-29 - Allow any number of line terminators, then initialize new cue values.
17781                        if (!line) {
17782                            continue;
17783                        }
17784                        self.cue = new vttcue_1.default(0, 0, '');
17785                        self.state = 'CUE';
17786                        // 30-39 - Check if self line contains an optional identifier or timing data.
17787                        if (line.indexOf('-->') === -1) {
17788                            self.cue.id = line;
17789                            continue;
17790                        }
17791                    // Process line as start of a cue.
17792                    /* falls through */
17793                    case 'CUE':
17794                        // 40 - Collect cue timings and settings.
17795                        try {
17796                            parseCue(line, self.cue, self.regionList);
17797                        }
17798                        catch (e) {
17799                            // In case of an error ignore rest of the cue.
17800                            self.cue = null;
17801                            self.state = 'BADCUE';
17802                            continue;
17803                        }
17804                        self.state = 'CUETEXT';
17805                        continue;
17806                    case 'CUETEXT':
17807                        var hasSubstring = line.indexOf('-->') !== -1;
17808                        // 34 - If we have an empty line then report the cue.
17809                        // 35 - If we have the special substring '-->' then report the cue,
17810                        // but do not collect the line as we need to process the current
17811                        // one as a new cue.
17812                        if (!line || hasSubstring && (alreadyCollectedLine = true)) {
17813                            // We are done parsing self cue.
17814                            if (self.oncue) {
17815                                self.oncue(self.cue);
17816                            }
17817                            self.cue = null;
17818                            self.state = 'ID';
17819                            continue;
17820                        }
17821                        if (self.cue.text) {
17822                            self.cue.text += '\n';
17823                        }
17824                        self.cue.text += line;
17825                        continue;
17826                    case 'BADCUE': // BADCUE
17827                        // 54-62 - Collect and discard the remaining cue.
17828                        if (!line) {
17829                            self.state = 'ID';
17830                        }
17831                        continue;
17832                }
17833            }
17834        }
17835        catch (e) {
17836            // If we are currently parsing a cue, report what we have.
17837            if (self.state === 'CUETEXT' && self.cue && self.oncue) {
17838                self.oncue(self.cue);
17839            }
17840            self.cue = null;
17841            // Enter BADWEBVTT state if header was not parsed correctly otherwise
17842            // another exception occurred so enter BADCUE state.
17843            self.state = self.state === 'INITIAL' ? 'BADWEBVTT' : 'BADCUE';
17844        }
17845        return this;
17846    },
17847    flush: function () {
17848        var self = this;
17849        try {
17850            // Finish decoding the stream.
17851            self.buffer += self.decoder.decode();
17852            // Synthesize the end of the current cue or region.
17853            if (self.cue || self.state === 'HEADER') {
17854                self.buffer += '\n\n';
17855                self.parse();
17856            }
17857            // If we've flushed, parsed, and we're still on the INITIAL state then
17858            // that means we don't have enough of the stream to parse the first
17859            // line.
17860            if (self.state === 'INITIAL') {
17861                throw new Error('Malformed WebVTT signature.');
17862            }
17863        }
17864        catch (e) {
17865            throw e;
17866        }
17867        if (self.onflush) {
17868            self.onflush();
17869        }
17870        return this;
17871    }
17872};
17873exports.default = VTTParser;
17874
17875
17876/***/ }),
17877
vendor: 5,081 bytes, lines 17878-17992
17878/***/ "./src/utils/webvtt-parser.js":
17879/*!************************************!*\
17880  !*** ./src/utils/webvtt-parser.js ***!
17881  \************************************/
17882/*! no static exports found */
17883/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
17884/***/ (function(module, exports, __webpack_require__) {
17885
17886"use strict";
17887/* WEBPACK VAR INJECTION */(function(Number) {
17888Object.defineProperty(exports, "__esModule", { value: true });
17889var vttparser_1 = __webpack_require__(/*! ./vttparser */ "./src/utils/vttparser.js");
17890var id3_1 = __webpack_require__(/*! ../demux/id3 */ "./src/demux/id3.js");
17891// String.prototype.startsWith is not supported in IE11
17892var startsWith = function (inputString, searchString, position) {
17893    return inputString.substr(position || 0, searchString.length) === searchString;
17894};
17895var cueString2millis = function (timeString) {
17896    var ts = parseInt(timeString.substr(-3));
17897    var secs = parseInt(timeString.substr(-6, 2));
17898    var mins = parseInt(timeString.substr(-9, 2));
17899    var hours = timeString.length > 9 ? parseInt(timeString.substr(0, timeString.indexOf(':'))) : 0;
17900    if (!Number.isFinite(ts) || !Number.isFinite(secs) || !Number.isFinite(mins) || !Number.isFinite(hours)) {
17901        return -1;
17902    }
17903    ts += 1000 * secs;
17904    ts += 60 * 1000 * mins;
17905    ts += 60 * 60 * 1000 * hours;
17906    return ts;
17907};
17908// From https://github.com/darkskyapp/string-hash
17909var hash = function (text) {
17910    var hash = 5381;
17911    var i = text.length;
17912    while (i) {
17913        hash = (hash * 33) ^ text.charCodeAt(--i);
17914    }
17915    return (hash >>> 0).toString();
17916};
17917var calculateOffset = function (vttCCs, cc, presentationTime) {
17918    var currCC = vttCCs[cc];
17919    var prevCC = vttCCs[currCC.prevCC];
17920    // This is the first discontinuity or cues have been processed since the last discontinuity
17921    // Offset = current discontinuity time
17922    if (!prevCC || (!prevCC.new && currCC.new)) {
17923        vttCCs.ccOffset = vttCCs.presentationOffset = currCC.start;
17924        currCC.new = false;
17925        return;
17926    }
17927    // There have been discontinuities since cues were last parsed.
17928    // Offset = time elapsed
17929    while (prevCC && prevCC.new) {
17930        vttCCs.ccOffset += currCC.start - prevCC.start;
17931        currCC.new = false;
17932        currCC = prevCC;
17933        prevCC = vttCCs[currCC.prevCC];
17934    }
17935    vttCCs.presentationOffset = presentationTime;
17936};
17937var WebVTTParser = {
17938    parse: function (vttByteArray, syncPTS, vttCCs, cc, callBack, errorCallBack) {
17939        // Convert byteArray into string, replacing any somewhat exotic linefeeds with "\n", then split on that character.
17940        var re = /\r\n|\n\r|\n|\r/g;
17941        // Uint8Array.prototype.reduce is not implemented in IE11
17942        var vttLines = id3_1.utf8ArrayToStr(new Uint8Array(vttByteArray)).trim().replace(re, '\n').split('\n');
17943        var cueTime = '00:00.000';
17944        var mpegTs = 0;
17945        var localTime = 0;
17946        var presentationTime = 0;
17947        var cues = [];
17948        var parsingError;
17949        var inHeader = true;
17950        // let VTTCue = VTTCue || window.TextTrackCue;
17951        // Create parser object using VTTCue with TextTrackCue fallback on certain browsers.
17952        var parser = new vttparser_1.default();
17953        parser.oncue = function (cue) {
17954            // Adjust cue timing; clamp cues to start no earlier than - and drop cues that don't end after - 0 on timeline.
17955            var currCC = vttCCs[cc];
17956            var cueOffset = vttCCs.ccOffset;
17957            // Update offsets for new discontinuities
17958            if (currCC && currCC.new) {
17959                if (localTime !== undefined) {
17960                    // When local time is provided, offset = discontinuity start time - local time
17961                    cueOffset = vttCCs.ccOffset = currCC.start;
17962                }
17963                else {
17964                    calculateOffset(vttCCs, cc, presentationTime);
17965                }
17966            }
17967            if (presentationTime) {
17968                // If we have MPEGTS, offset = presentation time + discontinuity offset
17969                cueOffset = presentationTime - vttCCs.presentationOffset;
17970            }
17971            cue.startTime += cueOffset - localTime;
17972            cue.endTime += cueOffset - localTime;
17973            // Create a unique hash id for a cue based on start/end times and text.
17974            // This helps timeline-controller to avoid showing repeated captions.
17975            cue.id = hash(cue.startTime.toString()) + hash(cue.endTime.toString()) + hash(cue.text);
17976            // Fix encoding of special characters. TODO: Test with all sorts of weird characters.
17977            cue.text = decodeURIComponent(encodeURIComponent(cue.text));
17978            if (cue.endTime > 0) {
17979                cues.push(cue);
17980            }
17981        };
17982        parser.onparsingerror = function (e) {
17983            parsingError = e;
17984        };
17985        parser.onflush = function () {
17986            if (parsingError && errorCallBack) {
17987                errorCallBack(parsingError);
17988                return;
17989            }
17990            callBack(cues);
17991        };
17992        // Go through contents line by line.
17993        vttLines.forEach(function (line) {
17994            if (inHeader) {
17995                // Look for X-TIMESTAMP-MAP in header.
17996                if (startsWith(line, 'X-TIMESTAMP-MAP=')) {
17997                    // Once found, no more are allowed anyway, so stop searching.
17998                    inHeader = false;
17999                    // Extract LOCAL and MPEGTS.
18000                    line.substr(16).split(',').forEach(function (timestamp) {
18001                        if (startsWith(timestamp, 'LOCAL:')) {
18002                            cueTime = timestamp.substr(6);
18003                        }
18004                        else if (startsWith(timestamp, 'MPEGTS:')) {
18005                            mpegTs = parseInt(timestamp.substr(7));
18006                        }
18007                    });
18008                    try {
18009                        // Calculate subtitle offset in milliseconds.
18010                        if (syncPTS + ((vttCCs[cc].start * 90000) || 0) < 0) {
18011                            syncPTS += 8589934592;
18012                        }
18013                        // Adjust MPEGTS by sync PTS.
18014                        mpegTs -= syncPTS;
18015                        // Convert cue time to seconds
18016                        localTime = cueString2millis(cueTime) / 1000;
18017                        // Convert MPEGTS to seconds from 90kHz.
18018                        presentationTime = mpegTs / 90000;
18019                        if (localTime === -1) {
18020                            parsingError = new Error("Malformed X-TIMESTAMP-MAP: " + line);
18021                        }
18022                    }
18023                    catch (e) {
18024                        parsingError = new Error("Malformed X-TIMESTAMP-MAP: " + line);
18025                    }
18026                    // Return without parsing X-TIMESTAMP-MAP line.
18027                    return;
18028                }
18029                else if (line === '') {
18030                    inHeader = false;
18031                }
18032            }
18033            // Parse line by default.
18034            parser.parse(line + '\n');
18035        });
18036        parser.flush();
18037    }
18038};
18039exports.default = WebVTTParser;
18040
18041/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./src/polyfills/number */ "./src/polyfills/number.js")["Number"]))
18042
18043/***/ }),
18044
vendor: 6,843 bytes, lines 18045-18205
18045/***/ "./src/utils/xhr-loader.js":
18046/*!*********************************!*\
18047  !*** ./src/utils/xhr-loader.js ***!
18048  \*********************************/
18049/*! no static exports found */
18050/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
18051/***/ (function(module, exports, __webpack_require__) {
18052
18053"use strict";
18054
18055/**
18056 * XHR based logger
18057*/
18058Object.defineProperty(exports, "__esModule", { value: true });
18059var logger_1 = __webpack_require__(/*! ../utils/logger */ "./src/utils/logger.js");
18060var performance = window.performance, XMLHttpRequest = window.XMLHttpRequest;
18061var XhrLoader = /** @class */ (function () {
18062    function XhrLoader(config) {
18063        if (config && config.xhrSetup) {
18064            this.xhrSetup = config.xhrSetup;
18065        }
18066    }
18067    XhrLoader.prototype.destroy = function () {
18068        this.abort();
18069        this.loader = null;
18070    };
18071    XhrLoader.prototype.abort = function () {
18072        var loader = this.loader;
18073        if (loader && loader.readyState !== 4) {
18074            this.stats.aborted = true;
18075            loader.abort();
18076        }
18077        window.clearTimeout(this.requestTimeout);
18078        this.requestTimeout = null;
18079        window.clearTimeout(this.retryTimeout);
18080        this.retryTimeout = null;
18081    };
18082    XhrLoader.prototype.load = function (context, config, callbacks) {
18083        this.context = context;
18084        this.config = config;
18085        this.callbacks = callbacks;
18086        this.stats = { trequest: performance.now(), retry: 0 };
18087        this.retryDelay = config.retryDelay;
18088        this.loadInternal();
18089    };
18090    XhrLoader.prototype.loadInternal = function () {
18091        var xhr, context = this.context;
18092        xhr = this.loader = new XMLHttpRequest();
18093        var stats = this.stats;
18094        stats.tfirst = 0;
18095        stats.loaded = 0;
18096        var xhrSetup = this.xhrSetup;
18097        try {
18098            if (xhrSetup) {
18099                try {
18100                    xhrSetup(xhr, context.url);
18101                }
18102                catch (e) {
18103                    // fix xhrSetup: (xhr, url) => {xhr.setRequestHeader("Content-Language", "test");}
18104                    // not working, as xhr.setRequestHeader expects xhr.readyState === OPEN
18105                    xhr.open('GET', context.url, true);
18106                    xhrSetup(xhr, context.url);
18107                }
18108            }
18109            if (!xhr.readyState) {
18110                xhr.open('GET', context.url, true);
18111            }
18112        }
18113        catch (e) {
18114            // IE11 throws an exception on xhr.open if attempting to access an HTTP resource over HTTPS
18115            this.callbacks.onError({ code: xhr.status, text: e.message }, context, xhr);
18116            return;
18117        }
18118        if (context.rangeEnd) {
18119            xhr.setRequestHeader('Range', 'bytes=' + context.rangeStart + '-' + (context.rangeEnd - 1));
18120        }
18121        xhr.onreadystatechange = this.readystatechange.bind(this);
18122        xhr.onprogress = this.loadprogress.bind(this);
18123        xhr.responseType = context.responseType;
18124        // setup timeout before we perform request
18125        this.requestTimeout = window.setTimeout(this.loadtimeout.bind(this), this.config.timeout);
18126        xhr.send();
18127    };
18128    XhrLoader.prototype.readystatechange = function (event) {
18129        var xhr = event.currentTarget, readyState = xhr.readyState, stats = this.stats, context = this.context, config = this.config;
18130        // don't proceed if xhr has been aborted
18131        if (stats.aborted) {
18132            return;
18133        }
18134        // >= HEADERS_RECEIVED
18135        if (readyState >= 2) {
18136            // clear xhr timeout and rearm it if readyState less than 4
18137            window.clearTimeout(this.requestTimeout);
18138            if (stats.tfirst === 0) {
18139                stats.tfirst = Math.max(performance.now(), stats.trequest);
18140            }
18141            if (readyState === 4) {
18142                var status_1 = xhr.status;
18143                // http status between 200 to 299 are all successful
18144                if (status_1 >= 200 && status_1 < 300) {
18145                    stats.tload = Math.max(stats.tfirst, performance.now());
18146                    var data = void 0, len = void 0;
18147                    if (context.responseType === 'arraybuffer') {
18148                        data = xhr.response;
18149                        len = data.byteLength;
18150                    }
18151                    else {
18152                        data = xhr.responseText;
18153                        len = data.length;
18154                    }
18155                    stats.loaded = stats.total = len;
18156                    var response = { url: xhr.responseURL, data: data };
18157                    this.callbacks.onSuccess(response, stats, context, xhr);
18158                }
18159                else {
18160                    // if max nb of retries reached or if http status between 400 and 499 (such error cannot be recovered, retrying is useless), return error
18161                    if (stats.retry >= config.maxRetry || (status_1 >= 400 && status_1 < 499)) {
18162                        logger_1.logger.error(status_1 + " while loading " + context.url);
18163                        this.callbacks.onError({ code: status_1, text: xhr.statusText }, context, xhr);
18164                    }
18165                    else {
18166                        // retry
18167                        logger_1.logger.warn(status_1 + " while loading " + context.url + ", retrying in " + this.retryDelay + "...");
18168                        // aborts and resets internal state
18169                        this.destroy();
18170                        // schedule retry
18171                        this.retryTimeout = window.setTimeout(this.loadInternal.bind(this), this.retryDelay);
18172                        // set exponential backoff
18173                        this.retryDelay = Math.min(2 * this.retryDelay, config.maxRetryDelay);
18174                        stats.retry++;
18175                    }
18176                }
18177            }
18178            else {
18179                // readyState >= 2 AND readyState !==4 (readyState = HEADERS_RECEIVED || LOADING) rearm timeout as xhr not finished yet
18180                this.requestTimeout = window.setTimeout(this.loadtimeout.bind(this), config.timeout);
18181            }
18182        }
18183    };
18184    XhrLoader.prototype.loadtimeout = function () {
18185        logger_1.logger.warn("timeout while loading " + this.context.url);
18186        this.callbacks.onTimeout(this.stats, this.context, null);
18187    };
18188    XhrLoader.prototype.loadprogress = function (event) {
18189        var xhr = event.currentTarget, stats = this.stats;
18190        stats.loaded = event.loaded;
18191        if (event.lengthComputable) {
18192            stats.total = event.total;
18193        }
18194        var onProgress = this.callbacks.onProgress;
18195        if (onProgress) {
18196            // third arg is to provide on progress data
18197            onProgress(stats, this.context, null, xhr);
18198        }
18199    };
18200    return XhrLoader;
18201}());
18202exports.default = XhrLoader;
18203
18204
18205/***/ })
18205
18206
18207/******/ })["default"];
18208});
18209//# 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.