WebInterface: Add experimental browser based stream player. Test it on your local...
[enigma2-plugins.git] / webinterface / src / stream / js / vendor / hls.js
1 (function webpackUniversalModuleDefinition(root, factory) {
2         if(typeof exports === 'object' && typeof module === 'object')
3                 module.exports = factory();
4         else if(typeof define === 'function' && define.amd)
5                 define([], factory);
6         else if(typeof exports === 'object')
7                 exports["Hls"] = factory();
8         else
9                 root["Hls"] = factory();
10 })(typeof self !== 'undefined' ? self : this, function() {
11 return /******/ (function(modules) { // webpackBootstrap
12 /******/        // The module cache
13 /******/        var installedModules = {};
14 /******/
15 /******/        // The require function
16 /******/        function __webpack_require__(moduleId) {
17 /******/
18 /******/                // Check if module is in cache
19 /******/                if(installedModules[moduleId]) {
20 /******/                        return installedModules[moduleId].exports;
21 /******/                }
22 /******/                // Create a new module (and put it into the cache)
23 /******/                var module = installedModules[moduleId] = {
24 /******/                        i: moduleId,
25 /******/                        l: false,
26 /******/                        exports: {}
27 /******/                };
28 /******/
29 /******/                // Execute the module function
30 /******/                modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
31 /******/
32 /******/                // Flag the module as loaded
33 /******/                module.l = true;
34 /******/
35 /******/                // Return the exports of the module
36 /******/                return module.exports;
37 /******/        }
38 /******/
39 /******/
40 /******/        // expose the modules object (__webpack_modules__)
41 /******/        __webpack_require__.m = modules;
42 /******/
43 /******/        // expose the module cache
44 /******/        __webpack_require__.c = installedModules;
45 /******/
46 /******/        // define getter function for harmony exports
47 /******/        __webpack_require__.d = function(exports, name, getter) {
48 /******/                if(!__webpack_require__.o(exports, name)) {
49 /******/                        Object.defineProperty(exports, name, {
50 /******/                                configurable: false,
51 /******/                                enumerable: true,
52 /******/                                get: getter
53 /******/                        });
54 /******/                }
55 /******/        };
56 /******/
57 /******/        // getDefaultExport function for compatibility with non-harmony modules
58 /******/        __webpack_require__.n = function(module) {
59 /******/                var getter = module && module.__esModule ?
60 /******/                        function getDefault() { return module['default']; } :
61 /******/                        function getModuleExports() { return module; };
62 /******/                __webpack_require__.d(getter, 'a', getter);
63 /******/                return getter;
64 /******/        };
65 /******/
66 /******/        // Object.prototype.hasOwnProperty.call
67 /******/        __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
68 /******/
69 /******/        // __webpack_public_path__
70 /******/        __webpack_require__.p = "/dist/";
71 /******/
72 /******/        // Load entry module and return exports
73 /******/        return __webpack_require__(__webpack_require__.s = 9);
74 /******/ })
75 /************************************************************************/
76 /******/ ([
77 /* 0 */
78 /***/ (function(module, __webpack_exports__, __webpack_require__) {
79
80 "use strict";
81 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return enableLogs; });
82 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return logger; });
83 var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
84
85 function noop() {}
86
87 var fakeLogger = {
88   trace: noop,
89   debug: noop,
90   log: noop,
91   warn: noop,
92   info: noop,
93   error: noop
94 };
95
96 var exportedLogger = fakeLogger;
97
98 /* globals self: false */
99
100 // let lastCallTime;
101 // function formatMsgWithTimeInfo(type, msg) {
102 //   const now = Date.now();
103 //   const diff = lastCallTime ? '+' + (now - lastCallTime) : '0';
104 //   lastCallTime = now;
105 //   msg = (new Date(now)).toISOString() + ' | [' +  type + '] > ' + msg + ' ( ' + diff + ' ms )';
106 //   return msg;
107 // }
108
109 function formatMsg(type, msg) {
110   msg = '[' + type + '] > ' + msg;
111   return msg;
112 }
113
114 function consolePrintFn(type) {
115   var func = self.console[type];
116   if (func) {
117     return function () {
118       for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
119         args[_key] = arguments[_key];
120       }
121
122       if (args[0]) args[0] = formatMsg(type, args[0]);
123
124       func.apply(self.console, args);
125     };
126   }
127   return noop;
128 }
129
130 function exportLoggerFunctions(debugConfig) {
131   for (var _len2 = arguments.length, functions = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
132     functions[_key2 - 1] = arguments[_key2];
133   }
134
135   functions.forEach(function (type) {
136     exportedLogger[type] = debugConfig[type] ? debugConfig[type].bind(debugConfig) : consolePrintFn(type);
137   });
138 }
139
140 var enableLogs = function enableLogs(debugConfig) {
141   if (debugConfig === true || (typeof debugConfig === 'undefined' ? 'undefined' : _typeof(debugConfig)) === 'object') {
142     exportLoggerFunctions(debugConfig,
143     // Remove out from list here to hard-disable a log-level
144     // 'trace',
145     'debug', 'log', 'info', 'warn', 'error');
146     // Some browsers don't allow to use bind on console object anyway
147     // fallback to default if needed
148     try {
149       exportedLogger.log();
150     } catch (e) {
151       exportedLogger = fakeLogger;
152     }
153   } else {
154     exportedLogger = fakeLogger;
155   }
156 };
157
158 var logger = exportedLogger;
159
160 /***/ }),
161 /* 1 */
162 /***/ (function(module, __webpack_exports__, __webpack_require__) {
163
164 "use strict";
165 /**
166  * @readonly
167  * @enum {string}
168  */
169 var HlsEvents = {
170   // fired before MediaSource is attaching to media element - data: { media }
171   MEDIA_ATTACHING: 'hlsMediaAttaching',
172   // fired when MediaSource has been succesfully attached to media element - data: { }
173   MEDIA_ATTACHED: 'hlsMediaAttached',
174   // fired before detaching MediaSource from media element - data: { }
175   MEDIA_DETACHING: 'hlsMediaDetaching',
176   // fired when MediaSource has been detached from media element - data: { }
177   MEDIA_DETACHED: 'hlsMediaDetached',
178   // fired when we buffer is going to be reset - data: { }
179   BUFFER_RESET: 'hlsBufferReset',
180   // fired when we know about the codecs that we need buffers for to push into - data: {tracks : { container, codec, levelCodec, initSegment, metadata }}
181   BUFFER_CODECS: 'hlsBufferCodecs',
182   // fired when sourcebuffers have been created - data: { tracks : tracks }
183   BUFFER_CREATED: 'hlsBufferCreated',
184   // fired when we append a segment to the buffer - data: { segment: segment object }
185   BUFFER_APPENDING: 'hlsBufferAppending',
186   // 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}
187   BUFFER_APPENDED: 'hlsBufferAppended',
188   // fired when the stream is finished and we want to notify the media buffer that there will be no more data - data: { }
189   BUFFER_EOS: 'hlsBufferEos',
190   // fired when the media buffer should be flushed - data { startOffset, endOffset }
191   BUFFER_FLUSHING: 'hlsBufferFlushing',
192   // fired when the media buffer has been flushed - data: { }
193   BUFFER_FLUSHED: 'hlsBufferFlushed',
194   // fired to signal that a manifest loading starts - data: { url : manifestURL}
195   MANIFEST_LOADING: 'hlsManifestLoading',
196   // fired after manifest has been loaded - data: { levels : [available quality levels], audioTracks : [ available audio tracks], url : manifestURL, stats : { trequest, tfirst, tload, mtime}}
197   MANIFEST_LOADED: 'hlsManifestLoaded',
198   // fired after manifest has been parsed - data: { levels : [available quality levels], firstLevel : index of first quality level appearing in Manifest}
199   MANIFEST_PARSED: 'hlsManifestParsed',
200   // fired when a level switch is requested - data: { level : id of new level }
201   LEVEL_SWITCHING: 'hlsLevelSwitching',
202   // fired when a level switch is effective - data: { level : id of new level }
203   LEVEL_SWITCHED: 'hlsLevelSwitched',
204   // fired when a level playlist loading starts - data: { url : level URL, level : id of level being loaded}
205   LEVEL_LOADING: 'hlsLevelLoading',
206   // fired when a level playlist loading finishes - data: { details : levelDetails object, level : id of loaded level, stats : { trequest, tfirst, tload, mtime} }
207   LEVEL_LOADED: 'hlsLevelLoaded',
208   // 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 }
209   LEVEL_UPDATED: 'hlsLevelUpdated',
210   // 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 }
211   LEVEL_PTS_UPDATED: 'hlsLevelPtsUpdated',
212   // fired to notify that audio track lists has been updated - data: { audioTracks : audioTracks }
213   AUDIO_TRACKS_UPDATED: 'hlsAudioTracksUpdated',
214   // fired when an audio track switching is requested - data: { id : audio track id }
215   AUDIO_TRACK_SWITCHING: 'hlsAudioTrackSwitching',
216   // fired when an audio track switch actually occurs - data: { id : audio track id }
217   AUDIO_TRACK_SWITCHED: 'hlsAudioTrackSwitched',
218   // fired when an audio track loading starts - data: { url : audio track URL, id : audio track id }
219   AUDIO_TRACK_LOADING: 'hlsAudioTrackLoading',
220   // fired when an audio track loading finishes - data: { details : levelDetails object, id : audio track id, stats : { trequest, tfirst, tload, mtime } }
221   AUDIO_TRACK_LOADED: 'hlsAudioTrackLoaded',
222   // fired to notify that subtitle track lists has been updated - data: { subtitleTracks : subtitleTracks }
223   SUBTITLE_TRACKS_UPDATED: 'hlsSubtitleTracksUpdated',
224   // fired when an subtitle track switch occurs - data: { id : subtitle track id }
225   SUBTITLE_TRACK_SWITCH: 'hlsSubtitleTrackSwitch',
226   // fired when a subtitle track loading starts - data: { url : subtitle track URL, id : subtitle track id }
227   SUBTITLE_TRACK_LOADING: 'hlsSubtitleTrackLoading',
228   // fired when a subtitle track loading finishes - data: { details : levelDetails object, id : subtitle track id, stats : { trequest, tfirst, tload, mtime } }
229   SUBTITLE_TRACK_LOADED: 'hlsSubtitleTrackLoaded',
230   // fired when a subtitle fragment has been processed - data: { success : boolean, frag : the processed frag }
231   SUBTITLE_FRAG_PROCESSED: 'hlsSubtitleFragProcessed',
232   // fired when the first timestamp is found - data: { id : demuxer id, initPTS: initPTS, frag : fragment object }
233   INIT_PTS_FOUND: 'hlsInitPtsFound',
234   // fired when a fragment loading starts - data: { frag : fragment object }
235   FRAG_LOADING: 'hlsFragLoading',
236   // fired when a fragment loading is progressing - data: { frag : fragment object, { trequest, tfirst, loaded } }
237   FRAG_LOAD_PROGRESS: 'hlsFragLoadProgress',
238   // Identifier for fragment load aborting for emergency switch down - data: { frag : fragment object }
239   FRAG_LOAD_EMERGENCY_ABORTED: 'hlsFragLoadEmergencyAborted',
240   // fired when a fragment loading is completed - data: { frag : fragment object, payload : fragment payload, stats : { trequest, tfirst, tload, length } }
241   FRAG_LOADED: 'hlsFragLoaded',
242   // fired when a fragment has finished decrypting - data: { id : demuxer id, frag: fragment object, payload : fragment payload, stats : { tstart, tdecrypt } }
243   FRAG_DECRYPTED: 'hlsFragDecrypted',
244   // 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 }
245   FRAG_PARSING_INIT_SEGMENT: 'hlsFragParsingInitSegment',
246   // fired when parsing sei text is completed - data: { id : demuxer id, frag: fragment object, samples : [ sei samples pes ] }
247   FRAG_PARSING_USERDATA: 'hlsFragParsingUserdata',
248   // fired when parsing id3 is completed - data: { id : demuxer id, frag: fragment object, samples : [ id3 samples pes ] }
249   FRAG_PARSING_METADATA: 'hlsFragParsingMetadata',
250   // 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}
251   FRAG_PARSING_DATA: 'hlsFragParsingData',
252   // fired when fragment parsing is completed - data: { id : demuxer id, frag: fragment object }
253   FRAG_PARSED: 'hlsFragParsed',
254   // 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 } }
255   FRAG_BUFFERED: 'hlsFragBuffered',
256   // fired when fragment matching with current media position is changing - data : { id : demuxer id, frag : fragment object }
257   FRAG_CHANGED: 'hlsFragChanged',
258   // Identifier for a FPS drop event - data: { curentDropped, currentDecoded, totalDroppedFrames }
259   FPS_DROP: 'hlsFpsDrop',
260   // triggered when FPS drop triggers auto level capping - data: { level, droppedlevel }
261   FPS_DROP_LEVEL_CAPPING: 'hlsFpsDropLevelCapping',
262   // 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 }
263   ERROR: 'hlsError',
264   // 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: { }
265   DESTROYING: 'hlsDestroying',
266   // fired when a decrypt key loading starts - data: { frag : fragment object }
267   KEY_LOADING: 'hlsKeyLoading',
268   // fired when a decrypt key loading is completed - data: { frag : fragment object, payload : key payload, stats : { trequest, tfirst, tload, length } }
269   KEY_LOADED: 'hlsKeyLoaded',
270   // fired upon stream controller state transitions - data: { previousState, nextState }
271   STREAM_STATE_TRANSITION: 'hlsStreamStateTransition'
272 };
273 /* harmony default export */ __webpack_exports__["a"] = (HlsEvents);
274
275 /***/ }),
276 /* 2 */
277 /***/ (function(module, __webpack_exports__, __webpack_require__) {
278
279 "use strict";
280 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return ErrorTypes; });
281 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return ErrorDetails; });
282 var ErrorTypes = {
283   // Identifier for a network error (loading error / timeout ...)
284   NETWORK_ERROR: 'networkError',
285   // Identifier for a media Error (video/parsing/mediasource error)
286   MEDIA_ERROR: 'mediaError',
287   // EME (encrypted media extensions) errors
288   KEY_SYSTEM_ERROR: 'keySystemError',
289   // Identifier for a mux Error (demuxing/remuxing)
290   MUX_ERROR: 'muxError',
291   // Identifier for all other errors
292   OTHER_ERROR: 'otherError'
293 };
294
295 /**
296  * @enum {ErrorDetails}
297  * @typedef {string} ErrorDetail
298  */
299 var ErrorDetails = {
300   KEY_SYSTEM_NO_KEYS: 'keySystemNoKeys',
301   KEY_SYSTEM_NO_ACCESS: 'keySystemNoAccess',
302   KEY_SYSTEM_NO_SESSION: 'keySystemNoSession',
303   KEY_SYSTEM_LICENSE_REQUEST_FAILED: 'keySystemLicenseRequestFailed',
304   // Identifier for a manifest load error - data: { url : faulty URL, response : { code: error code, text: error text }}
305   MANIFEST_LOAD_ERROR: 'manifestLoadError',
306   // Identifier for a manifest load timeout - data: { url : faulty URL, response : { code: error code, text: error text }}
307   MANIFEST_LOAD_TIMEOUT: 'manifestLoadTimeOut',
308   // Identifier for a manifest parsing error - data: { url : faulty URL, reason : error reason}
309   MANIFEST_PARSING_ERROR: 'manifestParsingError',
310   // Identifier for a manifest with only incompatible codecs error - data: { url : faulty URL, reason : error reason}
311   MANIFEST_INCOMPATIBLE_CODECS_ERROR: 'manifestIncompatibleCodecsError',
312   // Identifier for a level load error - data: { url : faulty URL, response : { code: error code, text: error text }}
313   LEVEL_LOAD_ERROR: 'levelLoadError',
314   // Identifier for a level load timeout - data: { url : faulty URL, response : { code: error code, text: error text }}
315   LEVEL_LOAD_TIMEOUT: 'levelLoadTimeOut',
316   // Identifier for a level switch error - data: { level : faulty level Id, event : error description}
317   LEVEL_SWITCH_ERROR: 'levelSwitchError',
318   // Identifier for an audio track load error - data: { url : faulty URL, response : { code: error code, text: error text }}
319   AUDIO_TRACK_LOAD_ERROR: 'audioTrackLoadError',
320   // Identifier for an audio track load timeout - data: { url : faulty URL, response : { code: error code, text: error text }}
321   AUDIO_TRACK_LOAD_TIMEOUT: 'audioTrackLoadTimeOut',
322   // Identifier for fragment load error - data: { frag : fragment object, response : { code: error code, text: error text }}
323   FRAG_LOAD_ERROR: 'fragLoadError',
324   // Identifier for fragment load timeout error - data: { frag : fragment object}
325   FRAG_LOAD_TIMEOUT: 'fragLoadTimeOut',
326   // Identifier for a fragment decryption error event - data: {id : demuxer Id,frag: fragment object, reason : parsing error description }
327   FRAG_DECRYPT_ERROR: 'fragDecryptError',
328   // Identifier for a fragment parsing error event - data: { id : demuxer Id, reason : parsing error description }
329   // will be renamed DEMUX_PARSING_ERROR and switched to MUX_ERROR in the next major release
330   FRAG_PARSING_ERROR: 'fragParsingError',
331   // 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 }
332   REMUX_ALLOC_ERROR: 'remuxAllocError',
333   // Identifier for decrypt key load error - data: { frag : fragment object, response : { code: error code, text: error text }}
334   KEY_LOAD_ERROR: 'keyLoadError',
335   // Identifier for decrypt key load timeout error - data: { frag : fragment object}
336   KEY_LOAD_TIMEOUT: 'keyLoadTimeOut',
337   // Triggered when an exception occurs while adding a sourceBuffer to MediaSource - data : {  err : exception , mimeType : mimeType }
338   BUFFER_ADD_CODEC_ERROR: 'bufferAddCodecError',
339   // Identifier for a buffer append error - data: append error description
340   BUFFER_APPEND_ERROR: 'bufferAppendError',
341   // Identifier for a buffer appending error event - data: appending error description
342   BUFFER_APPENDING_ERROR: 'bufferAppendingError',
343   // Identifier for a buffer stalled error event
344   BUFFER_STALLED_ERROR: 'bufferStalledError',
345   // Identifier for a buffer full event
346   BUFFER_FULL_ERROR: 'bufferFullError',
347   // Identifier for a buffer seek over hole event
348   BUFFER_SEEK_OVER_HOLE: 'bufferSeekOverHole',
349   // Identifier for a buffer nudge on stall (playback is stuck although currentTime is in a buffered area)
350   BUFFER_NUDGE_ON_STALL: 'bufferNudgeOnStall',
351   // Identifier for an internal exception happening inside hls.js while handling an event
352   INTERNAL_EXCEPTION: 'internalException'
353 };
354
355 /***/ }),
356 /* 3 */
357 /***/ (function(module, exports, __webpack_require__) {
358
359 // see https://tools.ietf.org/html/rfc1808\r
360 \r
361 /* jshint ignore:start */\r
362 (function(root) { \r
363 /* jshint ignore:end */\r
364 \r
365   var URL_REGEX = /^((?:[a-zA-Z0-9+\-.]+:)?)(\/\/[^\/\;?#]*)?(.*?)??(;.*?)?(\?.*?)?(#.*?)?$/;\r
366   var FIRST_SEGMENT_REGEX = /^([^\/;?#]*)(.*)$/;\r
367   var SLASH_DOT_REGEX = /(?:\/|^)\.(?=\/)/g;\r
368   var SLASH_DOT_DOT_REGEX = /(?:\/|^)\.\.\/(?!\.\.\/).*?(?=\/)/g;\r
369 \r
370   var URLToolkit = { // jshint ignore:line\r
371     // If opts.alwaysNormalize is true then the path will always be normalized even when it starts with / or //\r
372     // E.g\r
373     // With opts.alwaysNormalize = false (default, spec compliant)\r
374     // http://a.com/b/cd + /e/f/../g => http://a.com/e/f/../g\r
375     // With opts.alwaysNormalize = true (not spec compliant)\r
376     // http://a.com/b/cd + /e/f/../g => http://a.com/e/g\r
377     buildAbsoluteURL: function(baseURL, relativeURL, opts) {\r
378       opts = opts || {};\r
379       // remove any remaining space and CRLF\r
380       baseURL = baseURL.trim();\r
381       relativeURL = relativeURL.trim();\r
382       if (!relativeURL) {\r
383         // 2a) If the embedded URL is entirely empty, it inherits the\r
384         // entire base URL (i.e., is set equal to the base URL)\r
385         // and we are done.\r
386         if (!opts.alwaysNormalize) {\r
387           return baseURL;\r
388         }\r
389         var basePartsForNormalise = URLToolkit.parseURL(baseURL);\r
390         if (!basePartsForNormalise) {\r
391           throw new Error('Error trying to parse base URL.');\r
392         }\r
393         basePartsForNormalise.path = URLToolkit.normalizePath(basePartsForNormalise.path);\r
394         return URLToolkit.buildURLFromParts(basePartsForNormalise);\r
395       }\r
396       var relativeParts = URLToolkit.parseURL(relativeURL);\r
397       if (!relativeParts) {\r
398         throw new Error('Error trying to parse relative URL.');\r
399       }\r
400       if (relativeParts.scheme) {\r
401         // 2b) If the embedded URL starts with a scheme name, it is\r
402         // interpreted as an absolute URL and we are done.\r
403         if (!opts.alwaysNormalize) {\r
404           return relativeURL;\r
405         }\r
406         relativeParts.path = URLToolkit.normalizePath(relativeParts.path);\r
407         return URLToolkit.buildURLFromParts(relativeParts);\r
408       }\r
409       var baseParts = URLToolkit.parseURL(baseURL);\r
410       if (!baseParts) {\r
411         throw new Error('Error trying to parse base URL.');\r
412       }\r
413       if (!baseParts.netLoc && baseParts.path && baseParts.path[0] !== '/') {\r
414         // If netLoc missing and path doesn't start with '/', assume everthing before the first '/' is the netLoc\r
415         // This causes 'example.com/a' to be handled as '//example.com/a' instead of '/example.com/a'\r
416         var pathParts = FIRST_SEGMENT_REGEX.exec(baseParts.path);\r
417         baseParts.netLoc = pathParts[1];\r
418         baseParts.path = pathParts[2];\r
419       }\r
420       if (baseParts.netLoc && !baseParts.path) {\r
421         baseParts.path = '/';\r
422       }\r
423       var builtParts = {\r
424         // 2c) Otherwise, the embedded URL inherits the scheme of\r
425         // the base URL.\r
426         scheme: baseParts.scheme,\r
427         netLoc: relativeParts.netLoc,\r
428         path: null,\r
429         params: relativeParts.params,\r
430         query: relativeParts.query,\r
431         fragment: relativeParts.fragment\r
432       };\r
433       if (!relativeParts.netLoc) {\r
434         // 3) If the embedded URL's <net_loc> is non-empty, we skip to\r
435         // Step 7.  Otherwise, the embedded URL inherits the <net_loc>\r
436         // (if any) of the base URL.\r
437         builtParts.netLoc = baseParts.netLoc;\r
438         // 4) If the embedded URL path is preceded by a slash "/", the\r
439         // path is not relative and we skip to Step 7.\r
440         if (relativeParts.path[0] !== '/') {\r
441           if (!relativeParts.path) {\r
442             // 5) If the embedded URL path is empty (and not preceded by a\r
443             // slash), then the embedded URL inherits the base URL path\r
444             builtParts.path = baseParts.path;\r
445             // 5a) if the embedded URL's <params> is non-empty, we skip to\r
446             // step 7; otherwise, it inherits the <params> of the base\r
447             // URL (if any) and\r
448             if (!relativeParts.params) {\r
449               builtParts.params = baseParts.params;\r
450               // 5b) if the embedded URL's <query> is non-empty, we skip to\r
451               // step 7; otherwise, it inherits the <query> of the base\r
452               // URL (if any) and we skip to step 7.\r
453               if (!relativeParts.query) {\r
454                 builtParts.query = baseParts.query;\r
455               }\r
456             }\r
457           } else {\r
458             // 6) The last segment of the base URL's path (anything\r
459             // following the rightmost slash "/", or the entire path if no\r
460             // slash is present) is removed and the embedded URL's path is\r
461             // appended in its place.\r
462             var baseURLPath = baseParts.path;\r
463             var newPath = baseURLPath.substring(0, baseURLPath.lastIndexOf('/') + 1) + relativeParts.path;\r
464             builtParts.path = URLToolkit.normalizePath(newPath);\r
465           }\r
466         }\r
467       }\r
468       if (builtParts.path === null) {\r
469         builtParts.path = opts.alwaysNormalize ? URLToolkit.normalizePath(relativeParts.path) : relativeParts.path;\r
470       }\r
471       return URLToolkit.buildURLFromParts(builtParts);\r
472     },\r
473     parseURL: function(url) {\r
474       var parts = URL_REGEX.exec(url);\r
475       if (!parts) {\r
476         return null;\r
477       }\r
478       return {\r
479         scheme: parts[1] || '',\r
480         netLoc: parts[2] || '',\r
481         path: parts[3] || '',\r
482         params: parts[4] || '',\r
483         query: parts[5] || '',\r
484         fragment: parts[6] || ''\r
485       };\r
486     },\r
487     normalizePath: function(path) {\r
488       // The following operations are\r
489       // then applied, in order, to the new path:\r
490       // 6a) All occurrences of "./", where "." is a complete path\r
491       // segment, are removed.\r
492       // 6b) If the path ends with "." as a complete path segment,\r
493       // that "." is removed.\r
494       path = path.split('').reverse().join('').replace(SLASH_DOT_REGEX, '');\r
495       // 6c) All occurrences of "<segment>/../", where <segment> is a\r
496       // complete path segment not equal to "..", are removed.\r
497       // Removal of these path segments is performed iteratively,\r
498       // removing the leftmost matching pattern on each iteration,\r
499       // until no matching pattern remains.\r
500       // 6d) If the path ends with "<segment>/..", where <segment> is a\r
501       // complete path segment not equal to "..", that\r
502       // "<segment>/.." is removed.\r
503       while (path.length !== (path = path.replace(SLASH_DOT_DOT_REGEX, '')).length) {} // jshint ignore:line\r
504       return path.split('').reverse().join('');\r
505     },\r
506     buildURLFromParts: function(parts) {\r
507       return parts.scheme + parts.netLoc + parts.path + parts.params + parts.query + parts.fragment;\r
508     }\r
509   };\r
510 \r
511 /* jshint ignore:start */\r
512   if(true)\r
513     module.exports = URLToolkit;\r
514   else if(typeof define === 'function' && define.amd)\r
515     define([], function() { return URLToolkit; });\r
516   else if(typeof exports === 'object')\r
517     exports["URLToolkit"] = URLToolkit;\r
518   else\r
519     root["URLToolkit"] = URLToolkit;\r
520 })(this);\r
521 /* jshint ignore:end */\r
522
523
524 /***/ }),
525 /* 4 */
526 /***/ (function(module, __webpack_exports__, __webpack_require__) {
527
528 "use strict";
529 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return utf8ArrayToStr; });
530 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
531
532 /**
533  * ID3 parser
534  */
535 var ID3 = function () {
536   function ID3() {
537     _classCallCheck(this, ID3);
538   }
539
540   /**
541    * Returns true if an ID3 header can be found at offset in data
542    * @param {Uint8Array} data - The data to search in
543    * @param {number} offset - The offset at which to start searching
544    * @return {boolean} - True if an ID3 header is found
545    */
546   ID3.isHeader = function isHeader(data, offset) {
547     /*
548     * http://id3.org/id3v2.3.0
549     * [0]     = 'I'
550     * [1]     = 'D'
551     * [2]     = '3'
552     * [3,4]   = {Version}
553     * [5]     = {Flags}
554     * [6-9]   = {ID3 Size}
555     *
556     * An ID3v2 tag can be detected with the following pattern:
557     *  $49 44 33 yy yy xx zz zz zz zz
558     * Where yy is less than $FF, xx is the 'flags' byte and zz is less than $80
559     */
560     if (offset + 10 <= data.length) {
561       // look for 'ID3' identifier
562       if (data[offset] === 0x49 && data[offset + 1] === 0x44 && data[offset + 2] === 0x33) {
563         // check version is within range
564         if (data[offset + 3] < 0xFF && data[offset + 4] < 0xFF) {
565           // check size is within range
566           if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) return true;
567         }
568       }
569     }
570
571     return false;
572   };
573
574   /**
575    * Returns true if an ID3 footer can be found at offset in data
576    * @param {Uint8Array} data - The data to search in
577    * @param {number} offset - The offset at which to start searching
578    * @return {boolean} - True if an ID3 footer is found
579    */
580
581
582   ID3.isFooter = function isFooter(data, offset) {
583     /*
584     * The footer is a copy of the header, but with a different identifier
585     */
586     if (offset + 10 <= data.length) {
587       // look for '3DI' identifier
588       if (data[offset] === 0x33 && data[offset + 1] === 0x44 && data[offset + 2] === 0x49) {
589         // check version is within range
590         if (data[offset + 3] < 0xFF && data[offset + 4] < 0xFF) {
591           // check size is within range
592           if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) return true;
593         }
594       }
595     }
596
597     return false;
598   };
599
600   /**
601    * Returns any adjacent ID3 tags found in data starting at offset, as one block of data
602    * @param {Uint8Array} data - The data to search in
603    * @param {number} offset - The offset at which to start searching
604    * @return {Uint8Array} - The block of data containing any ID3 tags found
605    */
606
607
608   ID3.getID3Data = function getID3Data(data, offset) {
609     var front = offset;
610     var length = 0;
611
612     while (ID3.isHeader(data, offset)) {
613       // ID3 header is 10 bytes
614       length += 10;
615
616       var size = ID3._readSize(data, offset + 6);
617       length += size;
618
619       if (ID3.isFooter(data, offset + 10)) {
620         // ID3 footer is 10 bytes
621         length += 10;
622       }
623
624       offset += length;
625     }
626
627     if (length > 0) return data.subarray(front, front + length);
628
629     return undefined;
630   };
631
632   ID3._readSize = function _readSize(data, offset) {
633     var size = 0;
634     size = (data[offset] & 0x7f) << 21;
635     size |= (data[offset + 1] & 0x7f) << 14;
636     size |= (data[offset + 2] & 0x7f) << 7;
637     size |= data[offset + 3] & 0x7f;
638     return size;
639   };
640
641   /**
642    * Searches for the Elementary Stream timestamp found in the ID3 data chunk
643    * @param {Uint8Array} data - Block of data containing one or more ID3 tags
644    * @return {number} - The timestamp
645    */
646
647
648   ID3.getTimeStamp = function getTimeStamp(data) {
649     var frames = ID3.getID3Frames(data);
650     for (var i = 0; i < frames.length; i++) {
651       var frame = frames[i];
652       if (ID3.isTimeStampFrame(frame)) return ID3._readTimeStamp(frame);
653     }
654
655     return undefined;
656   };
657
658   /**
659    * Returns true if the ID3 frame is an Elementary Stream timestamp frame
660    * @param {ID3 frame} frame
661    */
662
663
664   ID3.isTimeStampFrame = function isTimeStampFrame(frame) {
665     return frame && frame.key === 'PRIV' && frame.info === 'com.apple.streaming.transportStreamTimestamp';
666   };
667
668   ID3._getFrameData = function _getFrameData(data) {
669     /*
670     Frame ID       $xx xx xx xx (four characters)
671     Size           $xx xx xx xx
672     Flags          $xx xx
673     */
674     var type = String.fromCharCode(data[0], data[1], data[2], data[3]);
675     var size = ID3._readSize(data, 4);
676
677     // skip frame id, size, and flags
678     var offset = 10;
679
680     return { type: type, size: size, data: data.subarray(offset, offset + size) };
681   };
682
683   /**
684    * Returns an array of ID3 frames found in all the ID3 tags in the id3Data
685    * @param {Uint8Array} id3Data - The ID3 data containing one or more ID3 tags
686    * @return {ID3 frame[]} - Array of ID3 frame objects
687    */
688
689
690   ID3.getID3Frames = function getID3Frames(id3Data) {
691     var offset = 0;
692     var frames = [];
693
694     while (ID3.isHeader(id3Data, offset)) {
695       var size = ID3._readSize(id3Data, offset + 6);
696       // skip past ID3 header
697       offset += 10;
698       var end = offset + size;
699       // loop through frames in the ID3 tag
700       while (offset + 8 < end) {
701         var frameData = ID3._getFrameData(id3Data.subarray(offset));
702         var frame = ID3._decodeFrame(frameData);
703         if (frame) frames.push(frame);
704
705         // skip frame header and frame data
706         offset += frameData.size + 10;
707       }
708
709       if (ID3.isFooter(id3Data, offset)) offset += 10;
710     }
711
712     return frames;
713   };
714
715   ID3._decodeFrame = function _decodeFrame(frame) {
716     if (frame.type === 'PRIV') return ID3._decodePrivFrame(frame);else if (frame.type[0] === 'T') return ID3._decodeTextFrame(frame);else if (frame.type[0] === 'W') return ID3._decodeURLFrame(frame);
717
718     return undefined;
719   };
720
721   ID3._readTimeStamp = function _readTimeStamp(timeStampFrame) {
722     if (timeStampFrame.data.byteLength === 8) {
723       var data = new Uint8Array(timeStampFrame.data);
724       // timestamp is 33 bit expressed as a big-endian eight-octet number,
725       // with the upper 31 bits set to zero.
726       var pts33Bit = data[3] & 0x1;
727       var timestamp = (data[4] << 23) + (data[5] << 15) + (data[6] << 7) + data[7];
728       timestamp /= 45;
729
730       if (pts33Bit) timestamp += 47721858.84; // 2^32 / 90
731
732       return Math.round(timestamp);
733     }
734
735     return undefined;
736   };
737
738   ID3._decodePrivFrame = function _decodePrivFrame(frame) {
739     /*
740     Format: <text string>\0<binary data>
741     */
742     if (frame.size < 2) return undefined;
743
744     var owner = ID3._utf8ArrayToStr(frame.data, true);
745     var privateData = new Uint8Array(frame.data.subarray(owner.length + 1));
746
747     return { key: frame.type, info: owner, data: privateData.buffer };
748   };
749
750   ID3._decodeTextFrame = function _decodeTextFrame(frame) {
751     if (frame.size < 2) return undefined;
752
753     if (frame.type === 'TXXX') {
754       /*
755       Format:
756       [0]   = {Text Encoding}
757       [1-?] = {Description}\0{Value}
758       */
759       var index = 1;
760       var description = ID3._utf8ArrayToStr(frame.data.subarray(index));
761
762       index += description.length + 1;
763       var value = ID3._utf8ArrayToStr(frame.data.subarray(index));
764
765       return { key: frame.type, info: description, data: value };
766     } else {
767       /*
768       Format:
769       [0]   = {Text Encoding}
770       [1-?] = {Value}
771       */
772       var text = ID3._utf8ArrayToStr(frame.data.subarray(1));
773       return { key: frame.type, data: text };
774     }
775   };
776
777   ID3._decodeURLFrame = function _decodeURLFrame(frame) {
778     if (frame.type === 'WXXX') {
779       /*
780       Format:
781       [0]   = {Text Encoding}
782       [1-?] = {Description}\0{URL}
783       */
784       if (frame.size < 2) return undefined;
785
786       var index = 1;
787       var description = ID3._utf8ArrayToStr(frame.data.subarray(index));
788
789       index += description.length + 1;
790       var value = ID3._utf8ArrayToStr(frame.data.subarray(index));
791
792       return { key: frame.type, info: description, data: value };
793     } else {
794       /*
795       Format:
796       [0-?] = {URL}
797       */
798       var url = ID3._utf8ArrayToStr(frame.data);
799       return { key: frame.type, data: url };
800     }
801   };
802
803   // http://stackoverflow.com/questions/8936984/uint8array-to-string-in-javascript/22373197
804   // http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt
805   /* utf.js - UTF-8 <=> UTF-16 convertion
806    *
807    * Copyright (C) 1999 Masanao Izumo <iz@onicos.co.jp>
808    * Version: 1.0
809    * LastModified: Dec 25 1999
810    * This library is free.  You can redistribute it and/or modify it.
811    */
812
813
814   ID3._utf8ArrayToStr = function _utf8ArrayToStr(array) {
815     var exitOnNull = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
816
817     var len = array.length;
818     var c = void 0;
819     var char2 = void 0;
820     var char3 = void 0;
821     var out = '';
822     var i = 0;
823     while (i < len) {
824       c = array[i++];
825       if (c === 0x00 && exitOnNull) {
826         return out;
827       } else if (c === 0x00 || c === 0x03) {
828         // If the character is 3 (END_OF_TEXT) or 0 (NULL) then skip it
829         continue;
830       }
831       switch (c >> 4) {
832         case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:
833           // 0xxxxxxx
834           out += String.fromCharCode(c);
835           break;
836         case 12:case 13:
837           // 110x xxxx   10xx xxxx
838           char2 = array[i++];
839           out += String.fromCharCode((c & 0x1F) << 6 | char2 & 0x3F);
840           break;
841         case 14:
842           // 1110 xxxx  10xx xxxx  10xx xxxx
843           char2 = array[i++];
844           char3 = array[i++];
845           out += String.fromCharCode((c & 0x0F) << 12 | (char2 & 0x3F) << 6 | (char3 & 0x3F) << 0);
846           break;
847         default:
848       }
849     }
850     return out;
851   };
852
853   return ID3;
854 }();
855
856 var utf8ArrayToStr = ID3._utf8ArrayToStr;
857
858 /* harmony default export */ __webpack_exports__["a"] = (ID3);
859
860
861
862 /***/ }),
863 /* 5 */
864 /***/ (function(module, __webpack_exports__, __webpack_require__) {
865
866 "use strict";
867
868 // CONCATENATED MODULE: ./src/crypt/aes-crypto.js
869 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
870
871 var AESCrypto = function () {
872   function AESCrypto(subtle, iv) {
873     _classCallCheck(this, AESCrypto);
874
875     this.subtle = subtle;
876     this.aesIV = iv;
877   }
878
879   AESCrypto.prototype.decrypt = function decrypt(data, key) {
880     return this.subtle.decrypt({ name: 'AES-CBC', iv: this.aesIV }, key, data);
881   };
882
883   return AESCrypto;
884 }();
885
886 /* harmony default export */ var aes_crypto = (AESCrypto);
887 // CONCATENATED MODULE: ./src/crypt/fast-aes-key.js
888 function fast_aes_key__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
889
890 var FastAESKey = function () {
891   function FastAESKey(subtle, key) {
892     fast_aes_key__classCallCheck(this, FastAESKey);
893
894     this.subtle = subtle;
895     this.key = key;
896   }
897
898   FastAESKey.prototype.expandKey = function expandKey() {
899     return this.subtle.importKey('raw', this.key, { name: 'AES-CBC' }, false, ['encrypt', 'decrypt']);
900   };
901
902   return FastAESKey;
903 }();
904
905 /* harmony default export */ var fast_aes_key = (FastAESKey);
906 // CONCATENATED MODULE: ./src/crypt/aes-decryptor.js
907 function aes_decryptor__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
908
909 // PKCS7
910 function removePadding(buffer) {
911   var outputBytes = buffer.byteLength;
912   var paddingBytes = outputBytes && new DataView(buffer).getUint8(outputBytes - 1);
913   if (paddingBytes) return buffer.slice(0, outputBytes - paddingBytes);else return buffer;
914 }
915
916 var AESDecryptor = function () {
917   function AESDecryptor() {
918     aes_decryptor__classCallCheck(this, AESDecryptor);
919
920     // Static after running initTable
921     this.rcon = [0x0, 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36];
922     this.subMix = [new Uint32Array(256), new Uint32Array(256), new Uint32Array(256), new Uint32Array(256)];
923     this.invSubMix = [new Uint32Array(256), new Uint32Array(256), new Uint32Array(256), new Uint32Array(256)];
924     this.sBox = new Uint32Array(256);
925     this.invSBox = new Uint32Array(256);
926
927     // Changes during runtime
928     this.key = new Uint32Array(0);
929
930     this.initTable();
931   }
932
933   // Using view.getUint32() also swaps the byte order.
934
935
936   AESDecryptor.prototype.uint8ArrayToUint32Array_ = function uint8ArrayToUint32Array_(arrayBuffer) {
937     var view = new DataView(arrayBuffer);
938     var newArray = new Uint32Array(4);
939     for (var i = 0; i < 4; i++) {
940       newArray[i] = view.getUint32(i * 4);
941     }return newArray;
942   };
943
944   AESDecryptor.prototype.initTable = function initTable() {
945     var sBox = this.sBox;
946     var invSBox = this.invSBox;
947     var subMix = this.subMix;
948     var subMix0 = subMix[0];
949     var subMix1 = subMix[1];
950     var subMix2 = subMix[2];
951     var subMix3 = subMix[3];
952     var invSubMix = this.invSubMix;
953     var invSubMix0 = invSubMix[0];
954     var invSubMix1 = invSubMix[1];
955     var invSubMix2 = invSubMix[2];
956     var invSubMix3 = invSubMix[3];
957
958     var d = new Uint32Array(256);
959     var x = 0;
960     var xi = 0;
961     var i = 0;
962     for (i = 0; i < 256; i++) {
963       if (i < 128) d[i] = i << 1;else d[i] = i << 1 ^ 0x11b;
964     }
965
966     for (i = 0; i < 256; i++) {
967       var sx = xi ^ xi << 1 ^ xi << 2 ^ xi << 3 ^ xi << 4;
968       sx = sx >>> 8 ^ sx & 0xff ^ 0x63;
969       sBox[x] = sx;
970       invSBox[sx] = x;
971
972       // Compute multiplication
973       var x2 = d[x];
974       var x4 = d[x2];
975       var x8 = d[x4];
976
977       // Compute sub/invSub bytes, mix columns tables
978       var t = d[sx] * 0x101 ^ sx * 0x1010100;
979       subMix0[x] = t << 24 | t >>> 8;
980       subMix1[x] = t << 16 | t >>> 16;
981       subMix2[x] = t << 8 | t >>> 24;
982       subMix3[x] = t;
983
984       // Compute inv sub bytes, inv mix columns tables
985       t = x8 * 0x1010101 ^ x4 * 0x10001 ^ x2 * 0x101 ^ x * 0x1010100;
986       invSubMix0[sx] = t << 24 | t >>> 8;
987       invSubMix1[sx] = t << 16 | t >>> 16;
988       invSubMix2[sx] = t << 8 | t >>> 24;
989       invSubMix3[sx] = t;
990
991       // Compute next counter
992       if (!x) {
993         x = xi = 1;
994       } else {
995         x = x2 ^ d[d[d[x8 ^ x2]]];
996         xi ^= d[d[xi]];
997       }
998     }
999   };
1000
1001   AESDecryptor.prototype.expandKey = function expandKey(keyBuffer) {
1002     // convert keyBuffer to Uint32Array
1003     var key = this.uint8ArrayToUint32Array_(keyBuffer);
1004     var sameKey = true;
1005     var offset = 0;
1006
1007     while (offset < key.length && sameKey) {
1008       sameKey = key[offset] === this.key[offset];
1009       offset++;
1010     }
1011
1012     if (sameKey) return;
1013
1014     this.key = key;
1015     var keySize = this.keySize = key.length;
1016
1017     if (keySize !== 4 && keySize !== 6 && keySize !== 8) throw new Error('Invalid aes key size=' + keySize);
1018
1019     var ksRows = this.ksRows = (keySize + 6 + 1) * 4;
1020     var ksRow = void 0;
1021     var invKsRow = void 0;
1022
1023     var keySchedule = this.keySchedule = new Uint32Array(ksRows);
1024     var invKeySchedule = this.invKeySchedule = new Uint32Array(ksRows);
1025     var sbox = this.sBox;
1026     var rcon = this.rcon;
1027
1028     var invSubMix = this.invSubMix;
1029     var invSubMix0 = invSubMix[0];
1030     var invSubMix1 = invSubMix[1];
1031     var invSubMix2 = invSubMix[2];
1032     var invSubMix3 = invSubMix[3];
1033
1034     var prev = void 0;
1035     var t = void 0;
1036
1037     for (ksRow = 0; ksRow < ksRows; ksRow++) {
1038       if (ksRow < keySize) {
1039         prev = keySchedule[ksRow] = key[ksRow];
1040         continue;
1041       }
1042       t = prev;
1043
1044       if (ksRow % keySize === 0) {
1045         // Rot word
1046         t = t << 8 | t >>> 24;
1047
1048         // Sub word
1049         t = sbox[t >>> 24] << 24 | sbox[t >>> 16 & 0xff] << 16 | sbox[t >>> 8 & 0xff] << 8 | sbox[t & 0xff];
1050
1051         // Mix Rcon
1052         t ^= rcon[ksRow / keySize | 0] << 24;
1053       } else if (keySize > 6 && ksRow % keySize === 4) {
1054         // Sub word
1055         t = sbox[t >>> 24] << 24 | sbox[t >>> 16 & 0xff] << 16 | sbox[t >>> 8 & 0xff] << 8 | sbox[t & 0xff];
1056       }
1057
1058       keySchedule[ksRow] = prev = (keySchedule[ksRow - keySize] ^ t) >>> 0;
1059     }
1060
1061     for (invKsRow = 0; invKsRow < ksRows; invKsRow++) {
1062       ksRow = ksRows - invKsRow;
1063       if (invKsRow & 3) t = keySchedule[ksRow];else t = keySchedule[ksRow - 4];
1064
1065       if (invKsRow < 4 || ksRow <= 4) invKeySchedule[invKsRow] = t;else invKeySchedule[invKsRow] = invSubMix0[sbox[t >>> 24]] ^ invSubMix1[sbox[t >>> 16 & 0xff]] ^ invSubMix2[sbox[t >>> 8 & 0xff]] ^ invSubMix3[sbox[t & 0xff]];
1066
1067       invKeySchedule[invKsRow] = invKeySchedule[invKsRow] >>> 0;
1068     }
1069   };
1070
1071   // Adding this as a method greatly improves performance.
1072
1073
1074   AESDecryptor.prototype.networkToHostOrderSwap = function networkToHostOrderSwap(word) {
1075     return word << 24 | (word & 0xff00) << 8 | (word & 0xff0000) >> 8 | word >>> 24;
1076   };
1077
1078   AESDecryptor.prototype.decrypt = function decrypt(inputArrayBuffer, offset, aesIV, removePKCS7Padding) {
1079     var nRounds = this.keySize + 6;
1080     var invKeySchedule = this.invKeySchedule;
1081     var invSBOX = this.invSBox;
1082
1083     var invSubMix = this.invSubMix;
1084     var invSubMix0 = invSubMix[0];
1085     var invSubMix1 = invSubMix[1];
1086     var invSubMix2 = invSubMix[2];
1087     var invSubMix3 = invSubMix[3];
1088
1089     var initVector = this.uint8ArrayToUint32Array_(aesIV);
1090     var initVector0 = initVector[0];
1091     var initVector1 = initVector[1];
1092     var initVector2 = initVector[2];
1093     var initVector3 = initVector[3];
1094
1095     var inputInt32 = new Int32Array(inputArrayBuffer);
1096     var outputInt32 = new Int32Array(inputInt32.length);
1097
1098     var t0 = void 0,
1099         t1 = void 0,
1100         t2 = void 0,
1101         t3 = void 0;
1102     var s0 = void 0,
1103         s1 = void 0,
1104         s2 = void 0,
1105         s3 = void 0;
1106     var inputWords0 = void 0,
1107         inputWords1 = void 0,
1108         inputWords2 = void 0,
1109         inputWords3 = void 0;
1110
1111     var ksRow = void 0,
1112         i = void 0;
1113     var swapWord = this.networkToHostOrderSwap;
1114
1115     while (offset < inputInt32.length) {
1116       inputWords0 = swapWord(inputInt32[offset]);
1117       inputWords1 = swapWord(inputInt32[offset + 1]);
1118       inputWords2 = swapWord(inputInt32[offset + 2]);
1119       inputWords3 = swapWord(inputInt32[offset + 3]);
1120
1121       s0 = inputWords0 ^ invKeySchedule[0];
1122       s1 = inputWords3 ^ invKeySchedule[1];
1123       s2 = inputWords2 ^ invKeySchedule[2];
1124       s3 = inputWords1 ^ invKeySchedule[3];
1125
1126       ksRow = 4;
1127
1128       // Iterate through the rounds of decryption
1129       for (i = 1; i < nRounds; i++) {
1130         t0 = invSubMix0[s0 >>> 24] ^ invSubMix1[s1 >> 16 & 0xff] ^ invSubMix2[s2 >> 8 & 0xff] ^ invSubMix3[s3 & 0xff] ^ invKeySchedule[ksRow];
1131         t1 = invSubMix0[s1 >>> 24] ^ invSubMix1[s2 >> 16 & 0xff] ^ invSubMix2[s3 >> 8 & 0xff] ^ invSubMix3[s0 & 0xff] ^ invKeySchedule[ksRow + 1];
1132         t2 = invSubMix0[s2 >>> 24] ^ invSubMix1[s3 >> 16 & 0xff] ^ invSubMix2[s0 >> 8 & 0xff] ^ invSubMix3[s1 & 0xff] ^ invKeySchedule[ksRow + 2];
1133         t3 = invSubMix0[s3 >>> 24] ^ invSubMix1[s0 >> 16 & 0xff] ^ invSubMix2[s1 >> 8 & 0xff] ^ invSubMix3[s2 & 0xff] ^ invKeySchedule[ksRow + 3];
1134         // Update state
1135         s0 = t0;
1136         s1 = t1;
1137         s2 = t2;
1138         s3 = t3;
1139
1140         ksRow = ksRow + 4;
1141       }
1142
1143       // Shift rows, sub bytes, add round key
1144       t0 = invSBOX[s0 >>> 24] << 24 ^ invSBOX[s1 >> 16 & 0xff] << 16 ^ invSBOX[s2 >> 8 & 0xff] << 8 ^ invSBOX[s3 & 0xff] ^ invKeySchedule[ksRow];
1145       t1 = invSBOX[s1 >>> 24] << 24 ^ invSBOX[s2 >> 16 & 0xff] << 16 ^ invSBOX[s3 >> 8 & 0xff] << 8 ^ invSBOX[s0 & 0xff] ^ invKeySchedule[ksRow + 1];
1146       t2 = invSBOX[s2 >>> 24] << 24 ^ invSBOX[s3 >> 16 & 0xff] << 16 ^ invSBOX[s0 >> 8 & 0xff] << 8 ^ invSBOX[s1 & 0xff] ^ invKeySchedule[ksRow + 2];
1147       t3 = invSBOX[s3 >>> 24] << 24 ^ invSBOX[s0 >> 16 & 0xff] << 16 ^ invSBOX[s1 >> 8 & 0xff] << 8 ^ invSBOX[s2 & 0xff] ^ invKeySchedule[ksRow + 3];
1148       ksRow = ksRow + 3;
1149
1150       // Write
1151       outputInt32[offset] = swapWord(t0 ^ initVector0);
1152       outputInt32[offset + 1] = swapWord(t3 ^ initVector1);
1153       outputInt32[offset + 2] = swapWord(t2 ^ initVector2);
1154       outputInt32[offset + 3] = swapWord(t1 ^ initVector3);
1155
1156       // reset initVector to last 4 unsigned int
1157       initVector0 = inputWords0;
1158       initVector1 = inputWords1;
1159       initVector2 = inputWords2;
1160       initVector3 = inputWords3;
1161
1162       offset = offset + 4;
1163     }
1164
1165     return removePKCS7Padding ? removePadding(outputInt32.buffer) : outputInt32.buffer;
1166   };
1167
1168   AESDecryptor.prototype.destroy = function destroy() {
1169     this.key = undefined;
1170     this.keySize = undefined;
1171     this.ksRows = undefined;
1172
1173     this.sBox = undefined;
1174     this.invSBox = undefined;
1175     this.subMix = undefined;
1176     this.invSubMix = undefined;
1177     this.keySchedule = undefined;
1178     this.invKeySchedule = undefined;
1179
1180     this.rcon = undefined;
1181   };
1182
1183   return AESDecryptor;
1184 }();
1185
1186 /* harmony default export */ var aes_decryptor = (AESDecryptor);
1187 // EXTERNAL MODULE: ./src/errors.js
1188 var errors = __webpack_require__(2);
1189
1190 // EXTERNAL MODULE: ./src/utils/logger.js
1191 var logger = __webpack_require__(0);
1192
1193 // CONCATENATED MODULE: ./src/crypt/decrypter.js
1194 function decrypter__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
1195
1196
1197
1198
1199
1200
1201
1202
1203 /* globals self: false */
1204
1205 var decrypter_Decrypter = function () {
1206   function Decrypter(observer, config) {
1207     var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
1208         _ref$removePKCS7Paddi = _ref.removePKCS7Padding,
1209         removePKCS7Padding = _ref$removePKCS7Paddi === undefined ? true : _ref$removePKCS7Paddi;
1210
1211     decrypter__classCallCheck(this, Decrypter);
1212
1213     this.logEnabled = true;
1214     this.observer = observer;
1215     this.config = config;
1216     this.removePKCS7Padding = removePKCS7Padding;
1217     // built in decryptor expects PKCS7 padding
1218     if (removePKCS7Padding) {
1219       try {
1220         var browserCrypto = crypto || self.crypto;
1221         this.subtle = browserCrypto.subtle || browserCrypto.webkitSubtle;
1222       } catch (e) {}
1223     }
1224     this.disableWebCrypto = !this.subtle;
1225   }
1226
1227   Decrypter.prototype.isSync = function isSync() {
1228     return this.disableWebCrypto && this.config.enableSoftwareAES;
1229   };
1230
1231   Decrypter.prototype.decrypt = function decrypt(data, key, iv, callback) {
1232     var _this = this;
1233
1234     if (this.disableWebCrypto && this.config.enableSoftwareAES) {
1235       if (this.logEnabled) {
1236         logger["b" /* logger */].log('JS AES decrypt');
1237         this.logEnabled = false;
1238       }
1239       var decryptor = this.decryptor;
1240       if (!decryptor) this.decryptor = decryptor = new aes_decryptor();
1241
1242       decryptor.expandKey(key);
1243       callback(decryptor.decrypt(data, 0, iv, this.removePKCS7Padding));
1244     } else {
1245       if (this.logEnabled) {
1246         logger["b" /* logger */].log('WebCrypto AES decrypt');
1247         this.logEnabled = false;
1248       }
1249       var subtle = this.subtle;
1250       if (this.key !== key) {
1251         this.key = key;
1252         this.fastAesKey = new fast_aes_key(subtle, key);
1253       }
1254
1255       this.fastAesKey.expandKey().then(function (aesKey) {
1256         // decrypt using web crypto
1257         var crypto = new aes_crypto(subtle, iv);
1258         crypto.decrypt(data, aesKey).catch(function (err) {
1259           _this.onWebCryptoError(err, data, key, iv, callback);
1260         }).then(function (result) {
1261           callback(result);
1262         });
1263       }).catch(function (err) {
1264         _this.onWebCryptoError(err, data, key, iv, callback);
1265       });
1266     }
1267   };
1268
1269   Decrypter.prototype.onWebCryptoError = function onWebCryptoError(err, data, key, iv, callback) {
1270     if (this.config.enableSoftwareAES) {
1271       logger["b" /* logger */].log('WebCrypto Error, disable WebCrypto API');
1272       this.disableWebCrypto = true;
1273       this.logEnabled = true;
1274       this.decrypt(data, key, iv, callback);
1275     } else {
1276       logger["b" /* logger */].error('decrypting error : ' + err.message);
1277       this.observer.trigger(Event.ERROR, { type: errors["b" /* ErrorTypes */].MEDIA_ERROR, details: errors["a" /* ErrorDetails */].FRAG_DECRYPT_ERROR, fatal: true, reason: err.message });
1278     }
1279   };
1280
1281   Decrypter.prototype.destroy = function destroy() {
1282     var decryptor = this.decryptor;
1283     if (decryptor) {
1284       decryptor.destroy();
1285       this.decryptor = undefined;
1286     }
1287   };
1288
1289   return Decrypter;
1290 }();
1291
1292 /* harmony default export */ var decrypter = __webpack_exports__["a"] = (decrypter_Decrypter);
1293
1294 /***/ }),
1295 /* 6 */
1296 /***/ (function(module, exports) {
1297
1298 // Copyright Joyent, Inc. and other Node contributors.
1299 //
1300 // Permission is hereby granted, free of charge, to any person obtaining a
1301 // copy of this software and associated documentation files (the
1302 // "Software"), to deal in the Software without restriction, including
1303 // without limitation the rights to use, copy, modify, merge, publish,
1304 // distribute, sublicense, and/or sell copies of the Software, and to permit
1305 // persons to whom the Software is furnished to do so, subject to the
1306 // following conditions:
1307 //
1308 // The above copyright notice and this permission notice shall be included
1309 // in all copies or substantial portions of the Software.
1310 //
1311 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1312 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1313 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
1314 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
1315 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
1316 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
1317 // USE OR OTHER DEALINGS IN THE SOFTWARE.
1318
1319 function EventEmitter() {
1320   this._events = this._events || {};
1321   this._maxListeners = this._maxListeners || undefined;
1322 }
1323 module.exports = EventEmitter;
1324
1325 // Backwards-compat with node 0.10.x
1326 EventEmitter.EventEmitter = EventEmitter;
1327
1328 EventEmitter.prototype._events = undefined;
1329 EventEmitter.prototype._maxListeners = undefined;
1330
1331 // By default EventEmitters will print a warning if more than 10 listeners are
1332 // added to it. This is a useful default which helps finding memory leaks.
1333 EventEmitter.defaultMaxListeners = 10;
1334
1335 // Obviously not all Emitters should be limited to 10. This function allows
1336 // that to be increased. Set to zero for unlimited.
1337 EventEmitter.prototype.setMaxListeners = function(n) {
1338   if (!isNumber(n) || n < 0 || isNaN(n))
1339     throw TypeError('n must be a positive number');
1340   this._maxListeners = n;
1341   return this;
1342 };
1343
1344 EventEmitter.prototype.emit = function(type) {
1345   var er, handler, len, args, i, listeners;
1346
1347   if (!this._events)
1348     this._events = {};
1349
1350   // If there is no 'error' event listener then throw.
1351   if (type === 'error') {
1352     if (!this._events.error ||
1353         (isObject(this._events.error) && !this._events.error.length)) {
1354       er = arguments[1];
1355       if (er instanceof Error) {
1356         throw er; // Unhandled 'error' event
1357       } else {
1358         // At least give some kind of context to the user
1359         var err = new Error('Uncaught, unspecified "error" event. (' + er + ')');
1360         err.context = er;
1361         throw err;
1362       }
1363     }
1364   }
1365
1366   handler = this._events[type];
1367
1368   if (isUndefined(handler))
1369     return false;
1370
1371   if (isFunction(handler)) {
1372     switch (arguments.length) {
1373       // fast cases
1374       case 1:
1375         handler.call(this);
1376         break;
1377       case 2:
1378         handler.call(this, arguments[1]);
1379         break;
1380       case 3:
1381         handler.call(this, arguments[1], arguments[2]);
1382         break;
1383       // slower
1384       default:
1385         args = Array.prototype.slice.call(arguments, 1);
1386         handler.apply(this, args);
1387     }
1388   } else if (isObject(handler)) {
1389     args = Array.prototype.slice.call(arguments, 1);
1390     listeners = handler.slice();
1391     len = listeners.length;
1392     for (i = 0; i < len; i++)
1393       listeners[i].apply(this, args);
1394   }
1395
1396   return true;
1397 };
1398
1399 EventEmitter.prototype.addListener = function(type, listener) {
1400   var m;
1401
1402   if (!isFunction(listener))
1403     throw TypeError('listener must be a function');
1404
1405   if (!this._events)
1406     this._events = {};
1407
1408   // To avoid recursion in the case that type === "newListener"! Before
1409   // adding it to the listeners, first emit "newListener".
1410   if (this._events.newListener)
1411     this.emit('newListener', type,
1412               isFunction(listener.listener) ?
1413               listener.listener : listener);
1414
1415   if (!this._events[type])
1416     // Optimize the case of one listener. Don't need the extra array object.
1417     this._events[type] = listener;
1418   else if (isObject(this._events[type]))
1419     // If we've already got an array, just append.
1420     this._events[type].push(listener);
1421   else
1422     // Adding the second element, need to change to array.
1423     this._events[type] = [this._events[type], listener];
1424
1425   // Check for listener leak
1426   if (isObject(this._events[type]) && !this._events[type].warned) {
1427     if (!isUndefined(this._maxListeners)) {
1428       m = this._maxListeners;
1429     } else {
1430       m = EventEmitter.defaultMaxListeners;
1431     }
1432
1433     if (m && m > 0 && this._events[type].length > m) {
1434       this._events[type].warned = true;
1435       console.error('(node) warning: possible EventEmitter memory ' +
1436                     'leak detected. %d listeners added. ' +
1437                     'Use emitter.setMaxListeners() to increase limit.',
1438                     this._events[type].length);
1439       if (typeof console.trace === 'function') {
1440         // not supported in IE 10
1441         console.trace();
1442       }
1443     }
1444   }
1445
1446   return this;
1447 };
1448
1449 EventEmitter.prototype.on = EventEmitter.prototype.addListener;
1450
1451 EventEmitter.prototype.once = function(type, listener) {
1452   if (!isFunction(listener))
1453     throw TypeError('listener must be a function');
1454
1455   var fired = false;
1456
1457   function g() {
1458     this.removeListener(type, g);
1459
1460     if (!fired) {
1461       fired = true;
1462       listener.apply(this, arguments);
1463     }
1464   }
1465
1466   g.listener = listener;
1467   this.on(type, g);
1468
1469   return this;
1470 };
1471
1472 // emits a 'removeListener' event iff the listener was removed
1473 EventEmitter.prototype.removeListener = function(type, listener) {
1474   var list, position, length, i;
1475
1476   if (!isFunction(listener))
1477     throw TypeError('listener must be a function');
1478
1479   if (!this._events || !this._events[type])
1480     return this;
1481
1482   list = this._events[type];
1483   length = list.length;
1484   position = -1;
1485
1486   if (list === listener ||
1487       (isFunction(list.listener) && list.listener === listener)) {
1488     delete this._events[type];
1489     if (this._events.removeListener)
1490       this.emit('removeListener', type, listener);
1491
1492   } else if (isObject(list)) {
1493     for (i = length; i-- > 0;) {
1494       if (list[i] === listener ||
1495           (list[i].listener && list[i].listener === listener)) {
1496         position = i;
1497         break;
1498       }
1499     }
1500
1501     if (position < 0)
1502       return this;
1503
1504     if (list.length === 1) {
1505       list.length = 0;
1506       delete this._events[type];
1507     } else {
1508       list.splice(position, 1);
1509     }
1510
1511     if (this._events.removeListener)
1512       this.emit('removeListener', type, listener);
1513   }
1514
1515   return this;
1516 };
1517
1518 EventEmitter.prototype.removeAllListeners = function(type) {
1519   var key, listeners;
1520
1521   if (!this._events)
1522     return this;
1523
1524   // not listening for removeListener, no need to emit
1525   if (!this._events.removeListener) {
1526     if (arguments.length === 0)
1527       this._events = {};
1528     else if (this._events[type])
1529       delete this._events[type];
1530     return this;
1531   }
1532
1533   // emit removeListener for all listeners on all events
1534   if (arguments.length === 0) {
1535     for (key in this._events) {
1536       if (key === 'removeListener') continue;
1537       this.removeAllListeners(key);
1538     }
1539     this.removeAllListeners('removeListener');
1540     this._events = {};
1541     return this;
1542   }
1543
1544   listeners = this._events[type];
1545
1546   if (isFunction(listeners)) {
1547     this.removeListener(type, listeners);
1548   } else if (listeners) {
1549     // LIFO order
1550     while (listeners.length)
1551       this.removeListener(type, listeners[listeners.length - 1]);
1552   }
1553   delete this._events[type];
1554
1555   return this;
1556 };
1557
1558 EventEmitter.prototype.listeners = function(type) {
1559   var ret;
1560   if (!this._events || !this._events[type])
1561     ret = [];
1562   else if (isFunction(this._events[type]))
1563     ret = [this._events[type]];
1564   else
1565     ret = this._events[type].slice();
1566   return ret;
1567 };
1568
1569 EventEmitter.prototype.listenerCount = function(type) {
1570   if (this._events) {
1571     var evlistener = this._events[type];
1572
1573     if (isFunction(evlistener))
1574       return 1;
1575     else if (evlistener)
1576       return evlistener.length;
1577   }
1578   return 0;
1579 };
1580
1581 EventEmitter.listenerCount = function(emitter, type) {
1582   return emitter.listenerCount(type);
1583 };
1584
1585 function isFunction(arg) {
1586   return typeof arg === 'function';
1587 }
1588
1589 function isNumber(arg) {
1590   return typeof arg === 'number';
1591 }
1592
1593 function isObject(arg) {
1594   return typeof arg === 'object' && arg !== null;
1595 }
1596
1597 function isUndefined(arg) {
1598   return arg === void 0;
1599 }
1600
1601
1602 /***/ }),
1603 /* 7 */
1604 /***/ (function(module, __webpack_exports__, __webpack_require__) {
1605
1606 "use strict";
1607 /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__utils_logger__ = __webpack_require__(0);
1608 /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__events__ = __webpack_require__(1);
1609 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
1610
1611 /**
1612  * MP4 demuxer
1613  */
1614
1615
1616
1617 var UINT32_MAX = Math.pow(2, 32) - 1;
1618
1619 var MP4Demuxer = function () {
1620   function MP4Demuxer(observer, remuxer) {
1621     _classCallCheck(this, MP4Demuxer);
1622
1623     this.observer = observer;
1624     this.remuxer = remuxer;
1625   }
1626
1627   MP4Demuxer.prototype.resetTimeStamp = function resetTimeStamp(initPTS) {
1628     this.initPTS = initPTS;
1629   };
1630
1631   MP4Demuxer.prototype.resetInitSegment = function resetInitSegment(initSegment, audioCodec, videoCodec, duration) {
1632     // jshint unused:false
1633     if (initSegment && initSegment.byteLength) {
1634       var initData = this.initData = MP4Demuxer.parseInitSegment(initSegment);
1635
1636       // default audio codec if nothing specified
1637       // TODO : extract that from initsegment
1638       if (audioCodec == null) audioCodec = 'mp4a.40.5';
1639
1640       if (videoCodec == null) videoCodec = 'avc1.42e01e';
1641
1642       var tracks = {};
1643       if (initData.audio && initData.video) {
1644         tracks.audiovideo = { container: 'video/mp4', codec: audioCodec + ',' + videoCodec, initSegment: duration ? initSegment : null };
1645       } else {
1646         if (initData.audio) tracks.audio = { container: 'audio/mp4', codec: audioCodec, initSegment: duration ? initSegment : null };
1647
1648         if (initData.video) tracks.video = { container: 'video/mp4', codec: videoCodec, initSegment: duration ? initSegment : null };
1649       }
1650       this.observer.trigger(__WEBPACK_IMPORTED_MODULE_1__events__["a" /* default */].FRAG_PARSING_INIT_SEGMENT, { tracks: tracks });
1651     } else {
1652       if (audioCodec) this.audioCodec = audioCodec;
1653
1654       if (videoCodec) this.videoCodec = videoCodec;
1655     }
1656   };
1657
1658   MP4Demuxer.probe = function probe(data) {
1659     // ensure we find a moof box in the first 16 kB
1660     return MP4Demuxer.findBox({ data: data, start: 0, end: Math.min(data.length, 16384) }, ['moof']).length > 0;
1661   };
1662
1663   MP4Demuxer.bin2str = function bin2str(buffer) {
1664     return String.fromCharCode.apply(null, buffer);
1665   };
1666
1667   MP4Demuxer.readUint16 = function readUint16(buffer, offset) {
1668     if (buffer.data) {
1669       offset += buffer.start;
1670       buffer = buffer.data;
1671     }
1672
1673     var val = buffer[offset] << 8 | buffer[offset + 1];
1674
1675     return val < 0 ? 65536 + val : val;
1676   };
1677
1678   MP4Demuxer.readUint32 = function readUint32(buffer, offset) {
1679     if (buffer.data) {
1680       offset += buffer.start;
1681       buffer = buffer.data;
1682     }
1683
1684     var val = buffer[offset] << 24 | buffer[offset + 1] << 16 | buffer[offset + 2] << 8 | buffer[offset + 3];
1685     return val < 0 ? 4294967296 + val : val;
1686   };
1687
1688   MP4Demuxer.writeUint32 = function writeUint32(buffer, offset, value) {
1689     if (buffer.data) {
1690       offset += buffer.start;
1691       buffer = buffer.data;
1692     }
1693     buffer[offset] = value >> 24;
1694     buffer[offset + 1] = value >> 16 & 0xff;
1695     buffer[offset + 2] = value >> 8 & 0xff;
1696     buffer[offset + 3] = value & 0xff;
1697   };
1698
1699   // Find the data for a box specified by its path
1700
1701
1702   MP4Demuxer.findBox = function findBox(data, path) {
1703     var results = [],
1704         i = void 0,
1705         size = void 0,
1706         type = void 0,
1707         end = void 0,
1708         subresults = void 0,
1709         start = void 0,
1710         endbox = void 0;
1711
1712     if (data.data) {
1713       start = data.start;
1714       end = data.end;
1715       data = data.data;
1716     } else {
1717       start = 0;
1718       end = data.byteLength;
1719     }
1720
1721     if (!path.length) {
1722       // short-circuit the search for empty paths
1723       return null;
1724     }
1725
1726     for (i = start; i < end;) {
1727       size = MP4Demuxer.readUint32(data, i);
1728       type = MP4Demuxer.bin2str(data.subarray(i + 4, i + 8));
1729       endbox = size > 1 ? i + size : end;
1730
1731       if (type === path[0]) {
1732         if (path.length === 1) {
1733           // this is the end of the path and we've found the box we were
1734           // looking for
1735           results.push({ data: data, start: i + 8, end: endbox });
1736         } else {
1737           // recursively search for the next box along the path
1738           subresults = MP4Demuxer.findBox({ data: data, start: i + 8, end: endbox }, path.slice(1));
1739           if (subresults.length) results = results.concat(subresults);
1740         }
1741       }
1742       i = endbox;
1743     }
1744
1745     // we've finished searching all of data
1746     return results;
1747   };
1748
1749   MP4Demuxer.parseSegmentIndex = function parseSegmentIndex(initSegment) {
1750     var moov = MP4Demuxer.findBox(initSegment, ['moov'])[0];
1751     var moovEndOffset = moov ? moov.end : null; // we need this in case we need to chop of garbage of the end of current data
1752
1753     var index = 0;
1754     var sidx = MP4Demuxer.findBox(initSegment, ['sidx']);
1755     var references = void 0;
1756
1757     if (!sidx || !sidx[0]) return null;
1758
1759     references = [];
1760     sidx = sidx[0];
1761
1762     var version = sidx.data[0];
1763
1764     // set initial offset, we skip the reference ID (not needed)
1765     index = version === 0 ? 8 : 16;
1766
1767     var timescale = MP4Demuxer.readUint32(sidx, index);
1768     index += 4;
1769
1770     // TODO: parse earliestPresentationTime and firstOffset
1771     // usually zero in our case
1772     var earliestPresentationTime = 0;
1773     var firstOffset = 0;
1774
1775     if (version === 0) index += 8;else index += 16;
1776
1777     // skip reserved
1778     index += 2;
1779
1780     var startByte = sidx.end + firstOffset;
1781
1782     var referencesCount = MP4Demuxer.readUint16(sidx, index);
1783     index += 2;
1784
1785     for (var i = 0; i < referencesCount; i++) {
1786       var referenceIndex = index;
1787
1788       var referenceInfo = MP4Demuxer.readUint32(sidx, referenceIndex);
1789       referenceIndex += 4;
1790
1791       var referenceSize = referenceInfo & 0x7FFFFFFF;
1792       var referenceType = (referenceInfo & 0x80000000) >>> 31;
1793
1794       if (referenceType === 1) {
1795         console.warn('SIDX has hierarchical references (not supported)');
1796         return;
1797       }
1798
1799       var subsegmentDuration = MP4Demuxer.readUint32(sidx, referenceIndex);
1800       referenceIndex += 4;
1801
1802       references.push({
1803         referenceSize: referenceSize,
1804         subsegmentDuration: subsegmentDuration, // unscaled
1805         info: {
1806           duration: subsegmentDuration / timescale,
1807           start: startByte,
1808           end: startByte + referenceSize - 1
1809         }
1810       });
1811
1812       startByte += referenceSize;
1813
1814       // Skipping 1 bit for |startsWithSap|, 3 bits for |sapType|, and 28 bits
1815       // for |sapDelta|.
1816       referenceIndex += 4;
1817
1818       // skip to next ref
1819       index = referenceIndex;
1820     }
1821
1822     return {
1823       earliestPresentationTime: earliestPresentationTime,
1824       timescale: timescale,
1825       version: version,
1826       referencesCount: referencesCount,
1827       references: references,
1828       moovEndOffset: moovEndOffset
1829     };
1830   };
1831
1832   /**
1833    * Parses an MP4 initialization segment and extracts stream type and
1834    * timescale values for any declared tracks. Timescale values indicate the
1835    * number of clock ticks per second to assume for time-based values
1836    * elsewhere in the MP4.
1837    *
1838    * To determine the start time of an MP4, you need two pieces of
1839    * information: the timescale unit and the earliest base media decode
1840    * time. Multiple timescales can be specified within an MP4 but the
1841    * base media decode time is always expressed in the timescale from
1842    * the media header box for the track:
1843    * ```
1844    * moov > trak > mdia > mdhd.timescale
1845    * moov > trak > mdia > hdlr
1846    * ```
1847    * @param init {Uint8Array} the bytes of the init segment
1848    * @return {object} a hash of track type to timescale values or null if
1849    * the init segment is malformed.
1850    */
1851
1852
1853   MP4Demuxer.parseInitSegment = function parseInitSegment(initSegment) {
1854     var result = [];
1855     var traks = MP4Demuxer.findBox(initSegment, ['moov', 'trak']);
1856
1857     traks.forEach(function (trak) {
1858       var tkhd = MP4Demuxer.findBox(trak, ['tkhd'])[0];
1859       if (tkhd) {
1860         var version = tkhd.data[tkhd.start];
1861         var index = version === 0 ? 12 : 20;
1862         var trackId = MP4Demuxer.readUint32(tkhd, index);
1863
1864         var mdhd = MP4Demuxer.findBox(trak, ['mdia', 'mdhd'])[0];
1865         if (mdhd) {
1866           version = mdhd.data[mdhd.start];
1867           index = version === 0 ? 12 : 20;
1868           var timescale = MP4Demuxer.readUint32(mdhd, index);
1869
1870           var hdlr = MP4Demuxer.findBox(trak, ['mdia', 'hdlr'])[0];
1871           if (hdlr) {
1872             var hdlrType = MP4Demuxer.bin2str(hdlr.data.subarray(hdlr.start + 8, hdlr.start + 12));
1873             var type = { 'soun': 'audio', 'vide': 'video' }[hdlrType];
1874             if (type) {
1875               // extract codec info. TODO : parse codec details to be able to build MIME type
1876               var codecBox = MP4Demuxer.findBox(trak, ['mdia', 'minf', 'stbl', 'stsd']);
1877               if (codecBox.length) {
1878                 codecBox = codecBox[0];
1879                 var codecType = MP4Demuxer.bin2str(codecBox.data.subarray(codecBox.start + 12, codecBox.start + 16));
1880                 __WEBPACK_IMPORTED_MODULE_0__utils_logger__["b" /* logger */].log('MP4Demuxer:' + type + ':' + codecType + ' found');
1881               }
1882               result[trackId] = { timescale: timescale, type: type };
1883               result[type] = { timescale: timescale, id: trackId };
1884             }
1885           }
1886         }
1887       }
1888     });
1889     return result;
1890   };
1891
1892   /**
1893   * Determine the base media decode start time, in seconds, for an MP4
1894   * fragment. If multiple fragments are specified, the earliest time is
1895   * returned.
1896   *
1897   * The base media decode time can be parsed from track fragment
1898   * metadata:
1899   * ```
1900   * moof > traf > tfdt.baseMediaDecodeTime
1901   * ```
1902   * It requires the timescale value from the mdhd to interpret.
1903   *
1904   * @param timescale {object} a hash of track ids to timescale values.
1905   * @return {number} the earliest base media decode start time for the
1906   * fragment, in seconds
1907   */
1908
1909
1910   MP4Demuxer.getStartDTS = function getStartDTS(initData, fragment) {
1911     var trafs = void 0,
1912         baseTimes = void 0,
1913         result = void 0;
1914
1915     // we need info from two childrend of each track fragment box
1916     trafs = MP4Demuxer.findBox(fragment, ['moof', 'traf']);
1917
1918     // determine the start times for each track
1919     baseTimes = [].concat.apply([], trafs.map(function (traf) {
1920       return MP4Demuxer.findBox(traf, ['tfhd']).map(function (tfhd) {
1921         var id = void 0,
1922             scale = void 0,
1923             baseTime = void 0;
1924
1925         // get the track id from the tfhd
1926         id = MP4Demuxer.readUint32(tfhd, 4);
1927         // assume a 90kHz clock if no timescale was specified
1928         scale = initData[id].timescale || 90e3;
1929
1930         // get the base media decode time from the tfdt
1931         baseTime = MP4Demuxer.findBox(traf, ['tfdt']).map(function (tfdt) {
1932           var version = void 0,
1933               result = void 0;
1934
1935           version = tfdt.data[tfdt.start];
1936           result = MP4Demuxer.readUint32(tfdt, 4);
1937           if (version === 1) {
1938             result *= Math.pow(2, 32);
1939
1940             result += MP4Demuxer.readUint32(tfdt, 8);
1941           }
1942           return result;
1943         })[0];
1944         // convert base time to seconds
1945         return baseTime / scale;
1946       });
1947     }));
1948
1949     // return the minimum
1950     result = Math.min.apply(null, baseTimes);
1951     return isFinite(result) ? result : 0;
1952   };
1953
1954   MP4Demuxer.offsetStartDTS = function offsetStartDTS(initData, fragment, timeOffset) {
1955     MP4Demuxer.findBox(fragment, ['moof', 'traf']).map(function (traf) {
1956       return MP4Demuxer.findBox(traf, ['tfhd']).map(function (tfhd) {
1957         // get the track id from the tfhd
1958         var id = MP4Demuxer.readUint32(tfhd, 4);
1959         // assume a 90kHz clock if no timescale was specified
1960         var timescale = initData[id].timescale || 90e3;
1961
1962         // get the base media decode time from the tfdt
1963         MP4Demuxer.findBox(traf, ['tfdt']).map(function (tfdt) {
1964           var version = tfdt.data[tfdt.start];
1965           var baseMediaDecodeTime = MP4Demuxer.readUint32(tfdt, 4);
1966           if (version === 0) {
1967             MP4Demuxer.writeUint32(tfdt, 4, baseMediaDecodeTime - timeOffset * timescale);
1968           } else {
1969             baseMediaDecodeTime *= Math.pow(2, 32);
1970             baseMediaDecodeTime += MP4Demuxer.readUint32(tfdt, 8);
1971             baseMediaDecodeTime -= timeOffset * timescale;
1972             baseMediaDecodeTime = Math.max(baseMediaDecodeTime, 0);
1973             var upper = Math.floor(baseMediaDecodeTime / (UINT32_MAX + 1));
1974             var lower = Math.floor(baseMediaDecodeTime % (UINT32_MAX + 1));
1975             MP4Demuxer.writeUint32(tfdt, 4, upper);
1976             MP4Demuxer.writeUint32(tfdt, 8, lower);
1977           }
1978         });
1979       });
1980     });
1981   };
1982
1983   // feed incoming data to the front of the parsing pipeline
1984
1985
1986   MP4Demuxer.prototype.append = function append(data, timeOffset, contiguous, accurateTimeOffset) {
1987     var initData = this.initData;
1988     if (!initData) {
1989       this.resetInitSegment(data, this.audioCodec, this.videoCodec, false);
1990       initData = this.initData;
1991     }
1992     var startDTS = void 0,
1993         initPTS = this.initPTS;
1994     if (initPTS === undefined) {
1995       var _startDTS = MP4Demuxer.getStartDTS(initData, data);
1996       this.initPTS = initPTS = _startDTS - timeOffset;
1997       this.observer.trigger(__WEBPACK_IMPORTED_MODULE_1__events__["a" /* default */].INIT_PTS_FOUND, { initPTS: initPTS });
1998     }
1999     MP4Demuxer.offsetStartDTS(initData, data, initPTS);
2000     startDTS = MP4Demuxer.getStartDTS(initData, data);
2001     this.remuxer.remux(initData.audio, initData.video, null, null, startDTS, contiguous, accurateTimeOffset, data);
2002   };
2003
2004   MP4Demuxer.prototype.destroy = function destroy() {};
2005
2006   return MP4Demuxer;
2007 }();
2008
2009 /* harmony default export */ __webpack_exports__["a"] = (MP4Demuxer);
2010
2011 /***/ }),
2012 /* 8 */
2013 /***/ (function(module, __webpack_exports__, __webpack_require__) {
2014
2015 "use strict";
2016
2017 // EXTERNAL MODULE: ./src/events.js
2018 var events = __webpack_require__(1);
2019
2020 // EXTERNAL MODULE: ./src/errors.js
2021 var errors = __webpack_require__(2);
2022
2023 // EXTERNAL MODULE: ./src/crypt/decrypter.js + 3 modules
2024 var crypt_decrypter = __webpack_require__(5);
2025
2026 // EXTERNAL MODULE: ./src/utils/logger.js
2027 var logger = __webpack_require__(0);
2028
2029 // CONCATENATED MODULE: ./src/demux/adts.js
2030 /**
2031  *  ADTS parser helper
2032  */
2033
2034
2035
2036 function getAudioConfig(observer, data, offset, audioCodec) {
2037   var adtsObjectType = void 0,
2038       // :int
2039   adtsSampleingIndex = void 0,
2040       // :int
2041   adtsExtensionSampleingIndex = void 0,
2042       // :int
2043   adtsChanelConfig = void 0,
2044       // :int
2045   config = void 0,
2046       userAgent = navigator.userAgent.toLowerCase(),
2047       manifestCodec = audioCodec,
2048       adtsSampleingRates = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350];
2049   // byte 2
2050   adtsObjectType = ((data[offset + 2] & 0xC0) >>> 6) + 1;
2051   adtsSampleingIndex = (data[offset + 2] & 0x3C) >>> 2;
2052   if (adtsSampleingIndex > adtsSampleingRates.length - 1) {
2053     observer.trigger(Event.ERROR, { type: errors["b" /* ErrorTypes */].MEDIA_ERROR, details: errors["a" /* ErrorDetails */].FRAG_PARSING_ERROR, fatal: true, reason: 'invalid ADTS sampling index:' + adtsSampleingIndex });
2054     return;
2055   }
2056   adtsChanelConfig = (data[offset + 2] & 0x01) << 2;
2057   // byte 3
2058   adtsChanelConfig |= (data[offset + 3] & 0xC0) >>> 6;
2059   logger["b" /* logger */].log('manifest codec:' + audioCodec + ',ADTS data:type:' + adtsObjectType + ',sampleingIndex:' + adtsSampleingIndex + '[' + adtsSampleingRates[adtsSampleingIndex] + 'Hz],channelConfig:' + adtsChanelConfig);
2060   // firefox: freq less than 24kHz = AAC SBR (HE-AAC)
2061   if (/firefox/i.test(userAgent)) {
2062     if (adtsSampleingIndex >= 6) {
2063       adtsObjectType = 5;
2064       config = new Array(4);
2065       // HE-AAC uses SBR (Spectral Band Replication) , high frequencies are constructed from low frequencies
2066       // there is a factor 2 between frame sample rate and output sample rate
2067       // multiply frequency by 2 (see table below, equivalent to substract 3)
2068       adtsExtensionSampleingIndex = adtsSampleingIndex - 3;
2069     } else {
2070       adtsObjectType = 2;
2071       config = new Array(2);
2072       adtsExtensionSampleingIndex = adtsSampleingIndex;
2073     }
2074     // Android : always use AAC
2075   } else if (userAgent.indexOf('android') !== -1) {
2076     adtsObjectType = 2;
2077     config = new Array(2);
2078     adtsExtensionSampleingIndex = adtsSampleingIndex;
2079   } else {
2080     /*  for other browsers (Chrome/Vivaldi/Opera ...)
2081         always force audio type to be HE-AAC SBR, as some browsers do not support audio codec switch properly (like Chrome ...)
2082     */
2083     adtsObjectType = 5;
2084     config = new Array(4);
2085     // if (manifest codec is HE-AAC or HE-AACv2) OR (manifest codec not specified AND frequency less than 24kHz)
2086     if (audioCodec && (audioCodec.indexOf('mp4a.40.29') !== -1 || audioCodec.indexOf('mp4a.40.5') !== -1) || !audioCodec && adtsSampleingIndex >= 6) {
2087       // HE-AAC uses SBR (Spectral Band Replication) , high frequencies are constructed from low frequencies
2088       // there is a factor 2 between frame sample rate and output sample rate
2089       // multiply frequency by 2 (see table below, equivalent to substract 3)
2090       adtsExtensionSampleingIndex = adtsSampleingIndex - 3;
2091     } else {
2092       // if (manifest codec is AAC) AND (frequency less than 24kHz AND nb channel is 1) OR (manifest codec not specified and mono audio)
2093       // Chrome fails to play back with low frequency AAC LC mono when initialized with HE-AAC.  This is not a problem with stereo.
2094       if (audioCodec && audioCodec.indexOf('mp4a.40.2') !== -1 && (adtsSampleingIndex >= 6 && adtsChanelConfig === 1 || /vivaldi/i.test(userAgent)) || !audioCodec && adtsChanelConfig === 1) {
2095         adtsObjectType = 2;
2096         config = new Array(2);
2097       }
2098       adtsExtensionSampleingIndex = adtsSampleingIndex;
2099     }
2100   }
2101   /* refer to http://wiki.multimedia.cx/index.php?title=MPEG-4_Audio#Audio_Specific_Config
2102       ISO 14496-3 (AAC).pdf - Table 1.13 — Syntax of AudioSpecificConfig()
2103     Audio Profile / Audio Object Type
2104     0: Null
2105     1: AAC Main
2106     2: AAC LC (Low Complexity)
2107     3: AAC SSR (Scalable Sample Rate)
2108     4: AAC LTP (Long Term Prediction)
2109     5: SBR (Spectral Band Replication)
2110     6: AAC Scalable
2111    sampling freq
2112     0: 96000 Hz
2113     1: 88200 Hz
2114     2: 64000 Hz
2115     3: 48000 Hz
2116     4: 44100 Hz
2117     5: 32000 Hz
2118     6: 24000 Hz
2119     7: 22050 Hz
2120     8: 16000 Hz
2121     9: 12000 Hz
2122     10: 11025 Hz
2123     11: 8000 Hz
2124     12: 7350 Hz
2125     13: Reserved
2126     14: Reserved
2127     15: frequency is written explictly
2128     Channel Configurations
2129     These are the channel configurations:
2130     0: Defined in AOT Specifc Config
2131     1: 1 channel: front-center
2132     2: 2 channels: front-left, front-right
2133   */
2134   // audioObjectType = profile => profile, the MPEG-4 Audio Object Type minus 1
2135   config[0] = adtsObjectType << 3;
2136   // samplingFrequencyIndex
2137   config[0] |= (adtsSampleingIndex & 0x0E) >> 1;
2138   config[1] |= (adtsSampleingIndex & 0x01) << 7;
2139   // channelConfiguration
2140   config[1] |= adtsChanelConfig << 3;
2141   if (adtsObjectType === 5) {
2142     // adtsExtensionSampleingIndex
2143     config[1] |= (adtsExtensionSampleingIndex & 0x0E) >> 1;
2144     config[2] = (adtsExtensionSampleingIndex & 0x01) << 7;
2145     // adtsObjectType (force to 2, chrome is checking that object type is less than 5 ???
2146     //    https://chromium.googlesource.com/chromium/src.git/+/master/media/formats/mp4/aac.cc
2147     config[2] |= 2 << 2;
2148     config[3] = 0;
2149   }
2150   return { config: config, samplerate: adtsSampleingRates[adtsSampleingIndex], channelCount: adtsChanelConfig, codec: 'mp4a.40.' + adtsObjectType, manifestCodec: manifestCodec };
2151 }
2152
2153 function isHeaderPattern(data, offset) {
2154   return data[offset] === 0xff && (data[offset + 1] & 0xf6) === 0xf0;
2155 }
2156
2157 function getHeaderLength(data, offset) {
2158   return data[offset + 1] & 0x01 ? 7 : 9;
2159 }
2160
2161 function getFullFrameLength(data, offset) {
2162   return (data[offset + 3] & 0x03) << 11 | data[offset + 4] << 3 | (data[offset + 5] & 0xE0) >>> 5;
2163 }
2164
2165 function isHeader(data, offset) {
2166   // Look for ADTS header | 1111 1111 | 1111 X00X | where X can be either 0 or 1
2167   // Layer bits (position 14 and 15) in header should be always 0 for ADTS
2168   // More info https://wiki.multimedia.cx/index.php?title=ADTS
2169   if (offset + 1 < data.length && isHeaderPattern(data, offset)) return true;
2170
2171   return false;
2172 }
2173
2174 function adts_probe(data, offset) {
2175   // same as isHeader but we also check that ADTS frame follows last ADTS frame
2176   // or end of data is reached
2177   if (offset + 1 < data.length && isHeaderPattern(data, offset)) {
2178     // ADTS header Length
2179     var headerLength = getHeaderLength(data, offset);
2180     // ADTS frame Length
2181     var frameLength = headerLength;
2182     if (offset + 5 < data.length) frameLength = getFullFrameLength(data, offset);
2183
2184     var newOffset = offset + frameLength;
2185     if (newOffset === data.length || newOffset + 1 < data.length && isHeaderPattern(data, newOffset)) return true;
2186   }
2187   return false;
2188 }
2189
2190 function initTrackConfig(track, observer, data, offset, audioCodec) {
2191   if (!track.samplerate) {
2192     var config = getAudioConfig(observer, data, offset, audioCodec);
2193     track.config = config.config;
2194     track.samplerate = config.samplerate;
2195     track.channelCount = config.channelCount;
2196     track.codec = config.codec;
2197     track.manifestCodec = config.manifestCodec;
2198     logger["b" /* logger */].log('parsed codec:' + track.codec + ',rate:' + config.samplerate + ',nb channel:' + config.channelCount);
2199   }
2200 }
2201
2202 function getFrameDuration(samplerate) {
2203   return 1024 * 90000 / samplerate;
2204 }
2205
2206 function parseFrameHeader(data, offset, pts, frameIndex, frameDuration) {
2207   var headerLength = void 0,
2208       frameLength = void 0,
2209       stamp = void 0;
2210   var length = data.length;
2211
2212   // The protection skip bit tells us if we have 2 bytes of CRC data at the end of the ADTS header
2213   headerLength = getHeaderLength(data, offset);
2214   // retrieve frame size
2215   frameLength = getFullFrameLength(data, offset);
2216   frameLength -= headerLength;
2217
2218   if (frameLength > 0 && offset + headerLength + frameLength <= length) {
2219     stamp = pts + frameIndex * frameDuration;
2220     // logger.log(`AAC frame, offset/length/total/pts:${offset+headerLength}/${frameLength}/${data.byteLength}/${(stamp/90).toFixed(0)}`);
2221     return { headerLength: headerLength, frameLength: frameLength, stamp: stamp };
2222   }
2223
2224   return undefined;
2225 }
2226
2227 function appendFrame(track, data, offset, pts, frameIndex) {
2228   var frameDuration = getFrameDuration(track.samplerate);
2229   var header = parseFrameHeader(data, offset, pts, frameIndex, frameDuration);
2230   if (header) {
2231     var stamp = header.stamp;
2232     var headerLength = header.headerLength;
2233     var frameLength = header.frameLength;
2234
2235     // logger.log(`AAC frame, offset/length/total/pts:${offset+headerLength}/${frameLength}/${data.byteLength}/${(stamp/90).toFixed(0)}`);
2236     var aacSample = {
2237       unit: data.subarray(offset + headerLength, offset + headerLength + frameLength),
2238       pts: stamp,
2239       dts: stamp
2240     };
2241
2242     track.samples.push(aacSample);
2243     track.len += frameLength;
2244
2245     return { sample: aacSample, length: frameLength + headerLength };
2246   }
2247
2248   return undefined;
2249 }
2250 // EXTERNAL MODULE: ./src/demux/id3.js
2251 var id3 = __webpack_require__(4);
2252
2253 // CONCATENATED MODULE: ./src/demux/aacdemuxer.js
2254 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
2255
2256 /**
2257  * AAC demuxer
2258  */
2259
2260
2261
2262
2263 var aacdemuxer_AACDemuxer = function () {
2264   function AACDemuxer(observer, remuxer, config) {
2265     _classCallCheck(this, AACDemuxer);
2266
2267     this.observer = observer;
2268     this.config = config;
2269     this.remuxer = remuxer;
2270   }
2271
2272   AACDemuxer.prototype.resetInitSegment = function resetInitSegment(initSegment, audioCodec, videoCodec, duration) {
2273     this._audioTrack = { container: 'audio/adts', type: 'audio', id: 0, sequenceNumber: 0, isAAC: true, samples: [], len: 0, manifestCodec: audioCodec, duration: duration, inputTimeScale: 90000 };
2274   };
2275
2276   AACDemuxer.prototype.resetTimeStamp = function resetTimeStamp() {};
2277
2278   AACDemuxer.probe = function probe(data) {
2279     if (!data) return false;
2280
2281     // Check for the ADTS sync word
2282     // Look for ADTS header | 1111 1111 | 1111 X00X | where X can be either 0 or 1
2283     // Layer bits (position 14 and 15) in header should be always 0 for ADTS
2284     // More info https://wiki.multimedia.cx/index.php?title=ADTS
2285     var id3Data = id3["a" /* default */].getID3Data(data, 0) || [];
2286     var offset = id3Data.length;
2287
2288     for (var length = data.length; offset < length; offset++) {
2289       if (adts_probe(data, offset)) {
2290         logger["b" /* logger */].log('ADTS sync word found !');
2291         return true;
2292       }
2293     }
2294     return false;
2295   };
2296
2297   // feed incoming data to the front of the parsing pipeline
2298
2299
2300   AACDemuxer.prototype.append = function append(data, timeOffset, contiguous, accurateTimeOffset) {
2301     var track = this._audioTrack;
2302     var id3Data = id3["a" /* default */].getID3Data(data, 0) || [];
2303     var timestamp = id3["a" /* default */].getTimeStamp(id3Data);
2304     var pts = timestamp ? 90 * timestamp : timeOffset * 90000;
2305     var frameIndex = 0;
2306     var stamp = pts;
2307     var length = data.length;
2308     var offset = id3Data.length;
2309
2310     var id3Samples = [{ pts: stamp, dts: stamp, data: id3Data }];
2311
2312     while (offset < length - 1) {
2313       if (isHeader(data, offset) && offset + 5 < length) {
2314         initTrackConfig(track, this.observer, data, offset, track.manifestCodec);
2315         var frame = appendFrame(track, data, offset, pts, frameIndex);
2316         if (frame) {
2317           offset += frame.length;
2318           stamp = frame.sample.pts;
2319           frameIndex++;
2320         } else {
2321           logger["b" /* logger */].log('Unable to parse AAC frame');
2322           break;
2323         }
2324       } else if (id3["a" /* default */].isHeader(data, offset)) {
2325         id3Data = id3["a" /* default */].getID3Data(data, offset);
2326         id3Samples.push({ pts: stamp, dts: stamp, data: id3Data });
2327         offset += id3Data.length;
2328       } else {
2329         // nothing found, keep looking
2330         offset++;
2331       }
2332     }
2333
2334     this.remuxer.remux(track, { samples: [] }, { samples: id3Samples, inputTimeScale: 90000 }, { samples: [] }, timeOffset, contiguous, accurateTimeOffset);
2335   };
2336
2337   AACDemuxer.prototype.destroy = function destroy() {};
2338
2339   return AACDemuxer;
2340 }();
2341
2342 /* harmony default export */ var aacdemuxer = (aacdemuxer_AACDemuxer);
2343 // EXTERNAL MODULE: ./src/demux/mp4demuxer.js
2344 var mp4demuxer = __webpack_require__(7);
2345
2346 // CONCATENATED MODULE: ./src/demux/mpegaudio.js
2347 /**
2348  *  MPEG parser helper
2349  */
2350
2351 var MpegAudio = {
2352
2353   BitratesMap: [32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160],
2354
2355   SamplingRateMap: [44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000],
2356
2357   SamplesCoefficients: [
2358   // MPEG 2.5
2359   [0, // Reserved
2360   72, // Layer3
2361   144, // Layer2
2362   12 // Layer1
2363   ],
2364   // Reserved
2365   [0, // Reserved
2366   0, // Layer3
2367   0, // Layer2
2368   0 // Layer1
2369   ],
2370   // MPEG 2
2371   [0, // Reserved
2372   72, // Layer3
2373   144, // Layer2
2374   12 // Layer1
2375   ],
2376   // MPEG 1
2377   [0, // Reserved
2378   144, // Layer3
2379   144, // Layer2
2380   12 // Layer1
2381   ]],
2382
2383   BytesInSlot: [0, // Reserved
2384   1, // Layer3
2385   1, // Layer2
2386   4 // Layer1
2387   ],
2388
2389   appendFrame: function appendFrame(track, data, offset, pts, frameIndex) {
2390     // Using http://www.datavoyage.com/mpgscript/mpeghdr.htm as a reference
2391     if (offset + 24 > data.length) return undefined;
2392
2393     var header = this.parseHeader(data, offset);
2394     if (header && offset + header.frameLength <= data.length) {
2395       var frameDuration = header.samplesPerFrame * 90000 / header.sampleRate;
2396       var stamp = pts + frameIndex * frameDuration;
2397       var sample = { unit: data.subarray(offset, offset + header.frameLength), pts: stamp, dts: stamp };
2398
2399       track.config = [];
2400       track.channelCount = header.channelCount;
2401       track.samplerate = header.sampleRate;
2402       track.samples.push(sample);
2403       track.len += header.frameLength;
2404
2405       return { sample: sample, length: header.frameLength };
2406     }
2407
2408     return undefined;
2409   },
2410
2411   parseHeader: function parseHeader(data, offset) {
2412     var headerB = data[offset + 1] >> 3 & 3;
2413     var headerC = data[offset + 1] >> 1 & 3;
2414     var headerE = data[offset + 2] >> 4 & 15;
2415     var headerF = data[offset + 2] >> 2 & 3;
2416     var headerG = data[offset + 2] >> 1 & 1;
2417     if (headerB !== 1 && headerE !== 0 && headerE !== 15 && headerF !== 3) {
2418       var columnInBitrates = headerB === 3 ? 3 - headerC : headerC === 3 ? 3 : 4;
2419       var bitRate = MpegAudio.BitratesMap[columnInBitrates * 14 + headerE - 1] * 1000;
2420       var columnInSampleRates = headerB === 3 ? 0 : headerB === 2 ? 1 : 2;
2421       var sampleRate = MpegAudio.SamplingRateMap[columnInSampleRates * 3 + headerF];
2422       var channelCount = data[offset + 3] >> 6 === 3 ? 1 : 2; // If bits of channel mode are `11` then it is a single channel (Mono)
2423       var sampleCoefficient = MpegAudio.SamplesCoefficients[headerB][headerC];
2424       var bytesInSlot = MpegAudio.BytesInSlot[headerC];
2425       var samplesPerFrame = sampleCoefficient * 8 * bytesInSlot;
2426       var frameLength = parseInt(sampleCoefficient * bitRate / sampleRate + headerG, 10) * bytesInSlot;
2427
2428       return { sampleRate: sampleRate, channelCount: channelCount, frameLength: frameLength, samplesPerFrame: samplesPerFrame };
2429     }
2430
2431     return undefined;
2432   },
2433
2434   isHeaderPattern: function isHeaderPattern(data, offset) {
2435     return data[offset] === 0xff && (data[offset + 1] & 0xe0) === 0xe0 && (data[offset + 1] & 0x06) !== 0x00;
2436   },
2437
2438   isHeader: function isHeader(data, offset) {
2439     // Look for MPEG header | 1111 1111 | 111X XYZX | where X can be either 0 or 1 and Y or Z should be 1
2440     // Layer bits (position 14 and 15) in header should be always different from 0 (Layer I or Layer II or Layer III)
2441     // More info http://www.mp3-tech.org/programmer/frame_header.html
2442     if (offset + 1 < data.length && this.isHeaderPattern(data, offset)) return true;
2443
2444     return false;
2445   },
2446
2447   probe: function probe(data, offset) {
2448     // same as isHeader but we also check that MPEG frame follows last MPEG frame
2449     // or end of data is reached
2450     if (offset + 1 < data.length && this.isHeaderPattern(data, offset)) {
2451       // MPEG header Length
2452       var headerLength = 4;
2453       // MPEG frame Length
2454       var header = this.parseHeader(data, offset);
2455       var frameLength = headerLength;
2456       if (header && header.frameLength) frameLength = header.frameLength;
2457
2458       var newOffset = offset + frameLength;
2459       if (newOffset === data.length || newOffset + 1 < data.length && this.isHeaderPattern(data, newOffset)) return true;
2460     }
2461     return false;
2462   }
2463 };
2464
2465 /* harmony default export */ var mpegaudio = (MpegAudio);
2466 // CONCATENATED MODULE: ./src/demux/exp-golomb.js
2467 function exp_golomb__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
2468
2469 /**
2470  * Parser for exponential Golomb codes, a variable-bitwidth number encoding scheme used by h264.
2471 */
2472
2473
2474
2475 var exp_golomb_ExpGolomb = function () {
2476   function ExpGolomb(data) {
2477     exp_golomb__classCallCheck(this, ExpGolomb);
2478
2479     this.data = data;
2480     // the number of bytes left to examine in this.data
2481     this.bytesAvailable = data.byteLength;
2482     // the current word being examined
2483     this.word = 0; // :uint
2484     // the number of bits left to examine in the current word
2485     this.bitsAvailable = 0; // :uint
2486   }
2487
2488   // ():void
2489
2490
2491   ExpGolomb.prototype.loadWord = function loadWord() {
2492     var data = this.data,
2493         bytesAvailable = this.bytesAvailable,
2494         position = data.byteLength - bytesAvailable,
2495         workingBytes = new Uint8Array(4),
2496         availableBytes = Math.min(4, bytesAvailable);
2497     if (availableBytes === 0) throw new Error('no bytes available');
2498
2499     workingBytes.set(data.subarray(position, position + availableBytes));
2500     this.word = new DataView(workingBytes.buffer).getUint32(0);
2501     // track the amount of this.data that has been processed
2502     this.bitsAvailable = availableBytes * 8;
2503     this.bytesAvailable -= availableBytes;
2504   };
2505
2506   // (count:int):void
2507
2508
2509   ExpGolomb.prototype.skipBits = function skipBits(count) {
2510     var skipBytes = void 0; // :int
2511     if (this.bitsAvailable > count) {
2512       this.word <<= count;
2513       this.bitsAvailable -= count;
2514     } else {
2515       count -= this.bitsAvailable;
2516       skipBytes = count >> 3;
2517       count -= skipBytes >> 3;
2518       this.bytesAvailable -= skipBytes;
2519       this.loadWord();
2520       this.word <<= count;
2521       this.bitsAvailable -= count;
2522     }
2523   };
2524
2525   // (size:int):uint
2526
2527
2528   ExpGolomb.prototype.readBits = function readBits(size) {
2529     var bits = Math.min(this.bitsAvailable, size),
2530         // :uint
2531     valu = this.word >>> 32 - bits; // :uint
2532     if (size > 32) logger["b" /* logger */].error('Cannot read more than 32 bits at a time');
2533
2534     this.bitsAvailable -= bits;
2535     if (this.bitsAvailable > 0) this.word <<= bits;else if (this.bytesAvailable > 0) this.loadWord();
2536
2537     bits = size - bits;
2538     if (bits > 0 && this.bitsAvailable) return valu << bits | this.readBits(bits);else return valu;
2539   };
2540
2541   // ():uint
2542
2543
2544   ExpGolomb.prototype.skipLZ = function skipLZ() {
2545     var leadingZeroCount = void 0; // :uint
2546     for (leadingZeroCount = 0; leadingZeroCount < this.bitsAvailable; ++leadingZeroCount) {
2547       if ((this.word & 0x80000000 >>> leadingZeroCount) !== 0) {
2548         // the first bit of working word is 1
2549         this.word <<= leadingZeroCount;
2550         this.bitsAvailable -= leadingZeroCount;
2551         return leadingZeroCount;
2552       }
2553     }
2554     // we exhausted word and still have not found a 1
2555     this.loadWord();
2556     return leadingZeroCount + this.skipLZ();
2557   };
2558
2559   // ():void
2560
2561
2562   ExpGolomb.prototype.skipUEG = function skipUEG() {
2563     this.skipBits(1 + this.skipLZ());
2564   };
2565
2566   // ():void
2567
2568
2569   ExpGolomb.prototype.skipEG = function skipEG() {
2570     this.skipBits(1 + this.skipLZ());
2571   };
2572
2573   // ():uint
2574
2575
2576   ExpGolomb.prototype.readUEG = function readUEG() {
2577     var clz = this.skipLZ(); // :uint
2578     return this.readBits(clz + 1) - 1;
2579   };
2580
2581   // ():int
2582
2583
2584   ExpGolomb.prototype.readEG = function readEG() {
2585     var valu = this.readUEG(); // :int
2586     if (0x01 & valu) {
2587       // the number is odd if the low order bit is set
2588       return 1 + valu >>> 1; // add 1 to make it even, and divide by 2
2589     } else {
2590       return -1 * (valu >>> 1); // divide by two then make it negative
2591     }
2592   };
2593
2594   // Some convenience functions
2595   // :Boolean
2596
2597
2598   ExpGolomb.prototype.readBoolean = function readBoolean() {
2599     return this.readBits(1) === 1;
2600   };
2601
2602   // ():int
2603
2604
2605   ExpGolomb.prototype.readUByte = function readUByte() {
2606     return this.readBits(8);
2607   };
2608
2609   // ():int
2610
2611
2612   ExpGolomb.prototype.readUShort = function readUShort() {
2613     return this.readBits(16);
2614   };
2615   // ():int
2616
2617
2618   ExpGolomb.prototype.readUInt = function readUInt() {
2619     return this.readBits(32);
2620   };
2621
2622   /**
2623    * Advance the ExpGolomb decoder past a scaling list. The scaling
2624    * list is optionally transmitted as part of a sequence parameter
2625    * set and is not relevant to transmuxing.
2626    * @param count {number} the number of entries in this scaling list
2627    * @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1
2628    */
2629
2630
2631   ExpGolomb.prototype.skipScalingList = function skipScalingList(count) {
2632     var lastScale = 8,
2633         nextScale = 8,
2634         j = void 0,
2635         deltaScale = void 0;
2636     for (j = 0; j < count; j++) {
2637       if (nextScale !== 0) {
2638         deltaScale = this.readEG();
2639         nextScale = (lastScale + deltaScale + 256) % 256;
2640       }
2641       lastScale = nextScale === 0 ? lastScale : nextScale;
2642     }
2643   };
2644
2645   /**
2646    * Read a sequence parameter set and return some interesting video
2647    * properties. A sequence parameter set is the H264 metadata that
2648    * describes the properties of upcoming video frames.
2649    * @param data {Uint8Array} the bytes of a sequence parameter set
2650    * @return {object} an object with configuration parsed from the
2651    * sequence parameter set, including the dimensions of the
2652    * associated video frames.
2653    */
2654
2655
2656   ExpGolomb.prototype.readSPS = function readSPS() {
2657     var frameCropLeftOffset = 0,
2658         frameCropRightOffset = 0,
2659         frameCropTopOffset = 0,
2660         frameCropBottomOffset = 0,
2661         profileIdc = void 0,
2662         profileCompat = void 0,
2663         levelIdc = void 0,
2664         numRefFramesInPicOrderCntCycle = void 0,
2665         picWidthInMbsMinus1 = void 0,
2666         picHeightInMapUnitsMinus1 = void 0,
2667         frameMbsOnlyFlag = void 0,
2668         scalingListCount = void 0,
2669         i = void 0,
2670         readUByte = this.readUByte.bind(this),
2671         readBits = this.readBits.bind(this),
2672         readUEG = this.readUEG.bind(this),
2673         readBoolean = this.readBoolean.bind(this),
2674         skipBits = this.skipBits.bind(this),
2675         skipEG = this.skipEG.bind(this),
2676         skipUEG = this.skipUEG.bind(this),
2677         skipScalingList = this.skipScalingList.bind(this);
2678
2679     readUByte();
2680     profileIdc = readUByte(); // profile_idc
2681     profileCompat = readBits(5); // constraint_set[0-4]_flag, u(5)
2682     skipBits(3); // reserved_zero_3bits u(3),
2683     levelIdc = readUByte(); // level_idc u(8)
2684     skipUEG(); // seq_parameter_set_id
2685     // some profiles have more optional data we don't need
2686     if (profileIdc === 100 || profileIdc === 110 || profileIdc === 122 || profileIdc === 244 || profileIdc === 44 || profileIdc === 83 || profileIdc === 86 || profileIdc === 118 || profileIdc === 128) {
2687       var chromaFormatIdc = readUEG();
2688       if (chromaFormatIdc === 3) skipBits(1); // separate_colour_plane_flag
2689
2690       skipUEG(); // bit_depth_luma_minus8
2691       skipUEG(); // bit_depth_chroma_minus8
2692       skipBits(1); // qpprime_y_zero_transform_bypass_flag
2693       if (readBoolean()) {
2694         // seq_scaling_matrix_present_flag
2695         scalingListCount = chromaFormatIdc !== 3 ? 8 : 12;
2696         for (i = 0; i < scalingListCount; i++) {
2697           if (readBoolean()) {
2698             // seq_scaling_list_present_flag[ i ]
2699             if (i < 6) skipScalingList(16);else skipScalingList(64);
2700           }
2701         }
2702       }
2703     }
2704     skipUEG(); // log2_max_frame_num_minus4
2705     var picOrderCntType = readUEG();
2706     if (picOrderCntType === 0) {
2707       readUEG(); // log2_max_pic_order_cnt_lsb_minus4
2708     } else if (picOrderCntType === 1) {
2709       skipBits(1); // delta_pic_order_always_zero_flag
2710       skipEG(); // offset_for_non_ref_pic
2711       skipEG(); // offset_for_top_to_bottom_field
2712       numRefFramesInPicOrderCntCycle = readUEG();
2713       for (i = 0; i < numRefFramesInPicOrderCntCycle; i++) {
2714         skipEG();
2715       } // offset_for_ref_frame[ i ]
2716     }
2717     skipUEG(); // max_num_ref_frames
2718     skipBits(1); // gaps_in_frame_num_value_allowed_flag
2719     picWidthInMbsMinus1 = readUEG();
2720     picHeightInMapUnitsMinus1 = readUEG();
2721     frameMbsOnlyFlag = readBits(1);
2722     if (frameMbsOnlyFlag === 0) skipBits(1); // mb_adaptive_frame_field_flag
2723
2724     skipBits(1); // direct_8x8_inference_flag
2725     if (readBoolean()) {
2726       // frame_cropping_flag
2727       frameCropLeftOffset = readUEG();
2728       frameCropRightOffset = readUEG();
2729       frameCropTopOffset = readUEG();
2730       frameCropBottomOffset = readUEG();
2731     }
2732     var pixelRatio = [1, 1];
2733     if (readBoolean()) {
2734       // vui_parameters_present_flag
2735       if (readBoolean()) {
2736         // aspect_ratio_info_present_flag
2737         var aspectRatioIdc = readUByte();
2738         switch (aspectRatioIdc) {
2739           case 1:
2740             pixelRatio = [1, 1];break;
2741           case 2:
2742             pixelRatio = [12, 11];break;
2743           case 3:
2744             pixelRatio = [10, 11];break;
2745           case 4:
2746             pixelRatio = [16, 11];break;
2747           case 5:
2748             pixelRatio = [40, 33];break;
2749           case 6:
2750             pixelRatio = [24, 11];break;
2751           case 7:
2752             pixelRatio = [20, 11];break;
2753           case 8:
2754             pixelRatio = [32, 11];break;
2755           case 9:
2756             pixelRatio = [80, 33];break;
2757           case 10:
2758             pixelRatio = [18, 11];break;
2759           case 11:
2760             pixelRatio = [15, 11];break;
2761           case 12:
2762             pixelRatio = [64, 33];break;
2763           case 13:
2764             pixelRatio = [160, 99];break;
2765           case 14:
2766             pixelRatio = [4, 3];break;
2767           case 15:
2768             pixelRatio = [3, 2];break;
2769           case 16:
2770             pixelRatio = [2, 1];break;
2771           case 255:
2772             {
2773               pixelRatio = [readUByte() << 8 | readUByte(), readUByte() << 8 | readUByte()];
2774               break;
2775             }
2776         }
2777       }
2778     }
2779     return {
2780       width: Math.ceil((picWidthInMbsMinus1 + 1) * 16 - frameCropLeftOffset * 2 - frameCropRightOffset * 2),
2781       height: (2 - frameMbsOnlyFlag) * (picHeightInMapUnitsMinus1 + 1) * 16 - (frameMbsOnlyFlag ? 2 : 4) * (frameCropTopOffset + frameCropBottomOffset),
2782       pixelRatio: pixelRatio
2783     };
2784   };
2785
2786   ExpGolomb.prototype.readSliceType = function readSliceType() {
2787     // skip NALu type
2788     this.readUByte();
2789     // discard first_mb_in_slice
2790     this.readUEG();
2791     // return slice_type
2792     return this.readUEG();
2793   };
2794
2795   return ExpGolomb;
2796 }();
2797
2798 /* harmony default export */ var exp_golomb = (exp_golomb_ExpGolomb);
2799 // CONCATENATED MODULE: ./src/demux/sample-aes.js
2800 function sample_aes__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
2801
2802 /**
2803  * SAMPLE-AES decrypter
2804 */
2805
2806
2807
2808 var sample_aes_SampleAesDecrypter = function () {
2809   function SampleAesDecrypter(observer, config, decryptdata, discardEPB) {
2810     sample_aes__classCallCheck(this, SampleAesDecrypter);
2811
2812     this.decryptdata = decryptdata;
2813     this.discardEPB = discardEPB;
2814     this.decrypter = new crypt_decrypter["a" /* default */](observer, config, { removePKCS7Padding: false });
2815   }
2816
2817   SampleAesDecrypter.prototype.decryptBuffer = function decryptBuffer(encryptedData, callback) {
2818     this.decrypter.decrypt(encryptedData, this.decryptdata.key.buffer, this.decryptdata.iv.buffer, callback);
2819   };
2820
2821   // AAC - encrypt all full 16 bytes blocks starting from offset 16
2822
2823
2824   SampleAesDecrypter.prototype.decryptAacSample = function decryptAacSample(samples, sampleIndex, callback, sync) {
2825     var curUnit = samples[sampleIndex].unit;
2826     var encryptedData = curUnit.subarray(16, curUnit.length - curUnit.length % 16);
2827     var encryptedBuffer = encryptedData.buffer.slice(encryptedData.byteOffset, encryptedData.byteOffset + encryptedData.length);
2828
2829     var localthis = this;
2830     this.decryptBuffer(encryptedBuffer, function (decryptedData) {
2831       decryptedData = new Uint8Array(decryptedData);
2832       curUnit.set(decryptedData, 16);
2833
2834       if (!sync) localthis.decryptAacSamples(samples, sampleIndex + 1, callback);
2835     });
2836   };
2837
2838   SampleAesDecrypter.prototype.decryptAacSamples = function decryptAacSamples(samples, sampleIndex, callback) {
2839     for (;; sampleIndex++) {
2840       if (sampleIndex >= samples.length) {
2841         callback();
2842         return;
2843       }
2844
2845       if (samples[sampleIndex].unit.length < 32) continue;
2846
2847       var sync = this.decrypter.isSync();
2848
2849       this.decryptAacSample(samples, sampleIndex, callback, sync);
2850
2851       if (!sync) return;
2852     }
2853   };
2854
2855   // AVC - encrypt one 16 bytes block out of ten, starting from offset 32
2856
2857
2858   SampleAesDecrypter.prototype.getAvcEncryptedData = function getAvcEncryptedData(decodedData) {
2859     var encryptedDataLen = Math.floor((decodedData.length - 48) / 160) * 16 + 16;
2860     var encryptedData = new Int8Array(encryptedDataLen);
2861     var outputPos = 0;
2862     for (var inputPos = 32; inputPos <= decodedData.length - 16; inputPos += 160, outputPos += 16) {
2863       encryptedData.set(decodedData.subarray(inputPos, inputPos + 16), outputPos);
2864     }return encryptedData;
2865   };
2866
2867   SampleAesDecrypter.prototype.getAvcDecryptedUnit = function getAvcDecryptedUnit(decodedData, decryptedData) {
2868     decryptedData = new Uint8Array(decryptedData);
2869     var inputPos = 0;
2870     for (var outputPos = 32; outputPos <= decodedData.length - 16; outputPos += 160, inputPos += 16) {
2871       decodedData.set(decryptedData.subarray(inputPos, inputPos + 16), outputPos);
2872     }return decodedData;
2873   };
2874
2875   SampleAesDecrypter.prototype.decryptAvcSample = function decryptAvcSample(samples, sampleIndex, unitIndex, callback, curUnit, sync) {
2876     var decodedData = this.discardEPB(curUnit.data);
2877     var encryptedData = this.getAvcEncryptedData(decodedData);
2878     var localthis = this;
2879
2880     this.decryptBuffer(encryptedData.buffer, function (decryptedData) {
2881       curUnit.data = localthis.getAvcDecryptedUnit(decodedData, decryptedData);
2882
2883       if (!sync) localthis.decryptAvcSamples(samples, sampleIndex, unitIndex + 1, callback);
2884     });
2885   };
2886
2887   SampleAesDecrypter.prototype.decryptAvcSamples = function decryptAvcSamples(samples, sampleIndex, unitIndex, callback) {
2888     for (;; sampleIndex++, unitIndex = 0) {
2889       if (sampleIndex >= samples.length) {
2890         callback();
2891         return;
2892       }
2893
2894       var curUnits = samples[sampleIndex].units;
2895       for (;; unitIndex++) {
2896         if (unitIndex >= curUnits.length) break;
2897
2898         var curUnit = curUnits[unitIndex];
2899         if (curUnit.length <= 48 || curUnit.type !== 1 && curUnit.type !== 5) continue;
2900
2901         var sync = this.decrypter.isSync();
2902
2903         this.decryptAvcSample(samples, sampleIndex, unitIndex, callback, curUnit, sync);
2904
2905         if (!sync) return;
2906       }
2907     }
2908   };
2909
2910   return SampleAesDecrypter;
2911 }();
2912
2913 /* harmony default export */ var sample_aes = (sample_aes_SampleAesDecrypter);
2914 // CONCATENATED MODULE: ./src/demux/tsdemuxer.js
2915 function tsdemuxer__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
2916
2917 /**
2918  * highly optimized TS demuxer:
2919  * parse PAT, PMT
2920  * extract PES packet from audio and video PIDs
2921  * extract AVC/H264 NAL units and AAC/ADTS samples from PES packet
2922  * trigger the remuxer upon parsing completion
2923  * 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.
2924  * it also controls the remuxing process :
2925  * upon discontinuity or level switch detection, it will also notifies the remuxer so that it can reset its state.
2926 */
2927
2928
2929
2930
2931
2932
2933 // import Hex from '../utils/hex';
2934
2935
2936
2937 // We are using fixed track IDs for driving the MP4 remuxer
2938 // instead of following the TS PIDs.
2939 // There is no reason not to do this and some browsers/SourceBuffer-demuxers
2940 // may not like if there are TrackID "switches"
2941 // See https://github.com/video-dev/hls.js/issues/1331
2942 // Here we are mapping our internal track types to constant MP4 track IDs
2943 // With MSE currently one can only have one track of each, and we are muxing
2944 // whatever video/audio rendition in them.
2945 var RemuxerTrackIdConfig = {
2946   video: 0,
2947   audio: 1,
2948   id3: 2,
2949   text: 3
2950 };
2951
2952 var tsdemuxer_TSDemuxer = function () {
2953   function TSDemuxer(observer, remuxer, config, typeSupported) {
2954     tsdemuxer__classCallCheck(this, TSDemuxer);
2955
2956     this.observer = observer;
2957     this.config = config;
2958     this.typeSupported = typeSupported;
2959     this.remuxer = remuxer;
2960     this.sampleAes = null;
2961   }
2962
2963   TSDemuxer.prototype.setDecryptData = function setDecryptData(decryptdata) {
2964     if (decryptdata != null && decryptdata.key != null && decryptdata.method === 'SAMPLE-AES') this.sampleAes = new sample_aes(this.observer, this.config, decryptdata, this.discardEPB);else this.sampleAes = null;
2965   };
2966
2967   TSDemuxer.probe = function probe(data) {
2968     var syncOffset = TSDemuxer._syncOffset(data);
2969     if (syncOffset < 0) {
2970       return false;
2971     } else {
2972       if (syncOffset) logger["b" /* logger */].warn('MPEG2-TS detected but first sync word found @ offset ' + syncOffset + ', junk ahead ?');
2973
2974       return true;
2975     }
2976   };
2977
2978   TSDemuxer._syncOffset = function _syncOffset(data) {
2979     // scan 1000 first bytes
2980     var scanwindow = Math.min(1000, data.length - 3 * 188);
2981     var i = 0;
2982     while (i < scanwindow) {
2983       // a TS fragment should contain at least 3 TS packets, a PAT, a PMT, and one PID, each starting with 0x47
2984       if (data[i] === 0x47 && data[i + 188] === 0x47 && data[i + 2 * 188] === 0x47) return i;else i++;
2985     }
2986     return -1;
2987   };
2988
2989   /**
2990    * Creates a track model internal to demuxer used to drive remuxing input
2991    *
2992    * @param {string} type 'audio' | 'video' | 'id3' | 'text'
2993    * @param {number} duration
2994    * @return {object} TSDemuxer's internal track model
2995    */
2996
2997
2998   TSDemuxer.createTrack = function createTrack(type, duration) {
2999     return {
3000       container: type === 'video' || type === 'audio' ? 'video/mp2t' : undefined,
3001       type: type,
3002       id: RemuxerTrackIdConfig[type],
3003       pid: -1,
3004       inputTimeScale: 90000,
3005       sequenceNumber: 0,
3006       samples: [],
3007       len: 0,
3008       dropped: type === 'video' ? 0 : undefined,
3009       isAAC: type === 'audio' ? true : undefined,
3010       duration: type === 'audio' ? duration : undefined
3011     };
3012   };
3013
3014   /**
3015    * Initializes a new init segment on the demuxer/remuxer interface. Needed for discontinuities/track-switches (or at stream start)
3016    * Resets all internal track instances of the demuxer.
3017    *
3018    * @override Implements generic demuxing/remuxing interface (see DemuxerInline)
3019    * @param {object} initSegment
3020    * @param {string} audioCodec
3021    * @param {string} videoCodec
3022    * @param {number} duration (in TS timescale = 90kHz)
3023    */
3024
3025
3026   TSDemuxer.prototype.resetInitSegment = function resetInitSegment(initSegment, audioCodec, videoCodec, duration) {
3027     this.pmtParsed = false;
3028     this._pmtId = -1;
3029
3030     this._avcTrack = TSDemuxer.createTrack('video', duration);
3031     this._audioTrack = TSDemuxer.createTrack('audio', duration);
3032     this._id3Track = TSDemuxer.createTrack('id3', duration);
3033     this._txtTrack = TSDemuxer.createTrack('text', duration);
3034
3035     // flush any partial content
3036     this.aacOverFlow = null;
3037     this.aacLastPTS = null;
3038     this.avcSample = null;
3039     this.audioCodec = audioCodec;
3040     this.videoCodec = videoCodec;
3041     this._duration = duration;
3042   };
3043
3044   /**
3045    *
3046    * @override
3047    */
3048
3049
3050   TSDemuxer.prototype.resetTimeStamp = function resetTimeStamp() {};
3051
3052   // feed incoming data to the front of the parsing pipeline
3053
3054
3055   TSDemuxer.prototype.append = function append(data, timeOffset, contiguous, accurateTimeOffset) {
3056     var start = void 0,
3057         len = data.length,
3058         stt = void 0,
3059         pid = void 0,
3060         atf = void 0,
3061         offset = void 0,
3062         pes = void 0,
3063         unknownPIDs = false;
3064     this.contiguous = contiguous;
3065     var pmtParsed = this.pmtParsed,
3066         avcTrack = this._avcTrack,
3067         audioTrack = this._audioTrack,
3068         id3Track = this._id3Track,
3069         avcId = avcTrack.pid,
3070         audioId = audioTrack.pid,
3071         id3Id = id3Track.pid,
3072         pmtId = this._pmtId,
3073         avcData = avcTrack.pesData,
3074         audioData = audioTrack.pesData,
3075         id3Data = id3Track.pesData,
3076         parsePAT = this._parsePAT,
3077         parsePMT = this._parsePMT,
3078         parsePES = this._parsePES,
3079         parseAVCPES = this._parseAVCPES.bind(this),
3080         parseAACPES = this._parseAACPES.bind(this),
3081         parseMPEGPES = this._parseMPEGPES.bind(this),
3082         parseID3PES = this._parseID3PES.bind(this);
3083
3084     var syncOffset = TSDemuxer._syncOffset(data);
3085
3086     // don't parse last TS packet if incomplete
3087     len -= (len + syncOffset) % 188;
3088
3089     // loop through TS packets
3090     for (start = syncOffset; start < len; start += 188) {
3091       if (data[start] === 0x47) {
3092         stt = !!(data[start + 1] & 0x40);
3093         // pid is a 13-bit field starting at the last bit of TS[1]
3094         pid = ((data[start + 1] & 0x1f) << 8) + data[start + 2];
3095         atf = (data[start + 3] & 0x30) >> 4;
3096         // if an adaption field is present, its length is specified by the fifth byte of the TS packet header.
3097         if (atf > 1) {
3098           offset = start + 5 + data[start + 4];
3099           // continue if there is only adaptation field
3100           if (offset === start + 188) continue;
3101         } else {
3102           offset = start + 4;
3103         }
3104         switch (pid) {
3105           case avcId:
3106             if (stt) {
3107               if (avcData && (pes = parsePES(avcData)) && pes.pts !== undefined) parseAVCPES(pes, false);
3108
3109               avcData = { data: [], size: 0 };
3110             }
3111             if (avcData) {
3112               avcData.data.push(data.subarray(offset, start + 188));
3113               avcData.size += start + 188 - offset;
3114             }
3115             break;
3116           case audioId:
3117             if (stt) {
3118               if (audioData && (pes = parsePES(audioData)) && pes.pts !== undefined) {
3119                 if (audioTrack.isAAC) parseAACPES(pes);else parseMPEGPES(pes);
3120               }
3121               audioData = { data: [], size: 0 };
3122             }
3123             if (audioData) {
3124               audioData.data.push(data.subarray(offset, start + 188));
3125               audioData.size += start + 188 - offset;
3126             }
3127             break;
3128           case id3Id:
3129             if (stt) {
3130               if (id3Data && (pes = parsePES(id3Data)) && pes.pts !== undefined) parseID3PES(pes);
3131
3132               id3Data = { data: [], size: 0 };
3133             }
3134             if (id3Data) {
3135               id3Data.data.push(data.subarray(offset, start + 188));
3136               id3Data.size += start + 188 - offset;
3137             }
3138             break;
3139           case 0:
3140             if (stt) offset += data[offset] + 1;
3141
3142             pmtId = this._pmtId = parsePAT(data, offset);
3143             break;
3144           case pmtId:
3145             if (stt) offset += data[offset] + 1;
3146
3147             var parsedPIDs = parsePMT(data, offset, this.typeSupported.mpeg === true || this.typeSupported.mp3 === true, this.sampleAes != null);
3148
3149             // only update track id if track PID found while parsing PMT
3150             // this is to avoid resetting the PID to -1 in case
3151             // track PID transiently disappears from the stream
3152             // this could happen in case of transient missing audio samples for example
3153             // NOTE this is only the PID of the track as found in TS,
3154             // but we are not using this for MP4 track IDs.
3155             avcId = parsedPIDs.avc;
3156             if (avcId > 0) avcTrack.pid = avcId;
3157
3158             audioId = parsedPIDs.audio;
3159             if (audioId > 0) {
3160               audioTrack.pid = audioId;
3161               audioTrack.isAAC = parsedPIDs.isAAC;
3162             }
3163             id3Id = parsedPIDs.id3;
3164             if (id3Id > 0) id3Track.pid = id3Id;
3165
3166             if (unknownPIDs && !pmtParsed) {
3167               logger["b" /* logger */].log('reparse from beginning');
3168               unknownPIDs = false;
3169               // we set it to -188, the += 188 in the for loop will reset start to 0
3170               start = syncOffset - 188;
3171             }
3172             pmtParsed = this.pmtParsed = true;
3173             break;
3174           case 17:
3175           case 0x1fff:
3176             break;
3177           default:
3178             unknownPIDs = true;
3179             break;
3180         }
3181       } else {
3182         this.observer.trigger(events["a" /* default */].ERROR, { type: errors["b" /* ErrorTypes */].MEDIA_ERROR, details: errors["a" /* ErrorDetails */].FRAG_PARSING_ERROR, fatal: false, reason: 'TS packet did not start with 0x47' });
3183       }
3184     }
3185     // try to parse last PES packets
3186     if (avcData && (pes = parsePES(avcData)) && pes.pts !== undefined) {
3187       parseAVCPES(pes, true);
3188       avcTrack.pesData = null;
3189     } else {
3190       // either avcData null or PES truncated, keep it for next frag parsing
3191       avcTrack.pesData = avcData;
3192     }
3193
3194     if (audioData && (pes = parsePES(audioData)) && pes.pts !== undefined) {
3195       if (audioTrack.isAAC) parseAACPES(pes);else parseMPEGPES(pes);
3196
3197       audioTrack.pesData = null;
3198     } else {
3199       if (audioData && audioData.size) logger["b" /* logger */].log('last AAC PES packet truncated,might overlap between fragments');
3200
3201       // either audioData null or PES truncated, keep it for next frag parsing
3202       audioTrack.pesData = audioData;
3203     }
3204
3205     if (id3Data && (pes = parsePES(id3Data)) && pes.pts !== undefined) {
3206       parseID3PES(pes);
3207       id3Track.pesData = null;
3208     } else {
3209       // either id3Data null or PES truncated, keep it for next frag parsing
3210       id3Track.pesData = id3Data;
3211     }
3212
3213     if (this.sampleAes == null) this.remuxer.remux(audioTrack, avcTrack, id3Track, this._txtTrack, timeOffset, contiguous, accurateTimeOffset);else this.decryptAndRemux(audioTrack, avcTrack, id3Track, this._txtTrack, timeOffset, contiguous, accurateTimeOffset);
3214   };
3215
3216   TSDemuxer.prototype.decryptAndRemux = function decryptAndRemux(audioTrack, videoTrack, id3Track, textTrack, timeOffset, contiguous, accurateTimeOffset) {
3217     if (audioTrack.samples && audioTrack.isAAC) {
3218       var localthis = this;
3219       this.sampleAes.decryptAacSamples(audioTrack.samples, 0, function () {
3220         localthis.decryptAndRemuxAvc(audioTrack, videoTrack, id3Track, textTrack, timeOffset, contiguous, accurateTimeOffset);
3221       });
3222     } else {
3223       this.decryptAndRemuxAvc(audioTrack, videoTrack, id3Track, textTrack, timeOffset, contiguous, accurateTimeOffset);
3224     }
3225   };
3226
3227   TSDemuxer.prototype.decryptAndRemuxAvc = function decryptAndRemuxAvc(audioTrack, videoTrack, id3Track, textTrack, timeOffset, contiguous, accurateTimeOffset) {
3228     if (videoTrack.samples) {
3229       var localthis = this;
3230       this.sampleAes.decryptAvcSamples(videoTrack.samples, 0, 0, function () {
3231         localthis.remuxer.remux(audioTrack, videoTrack, id3Track, textTrack, timeOffset, contiguous, accurateTimeOffset);
3232       });
3233     } else {
3234       this.remuxer.remux(audioTrack, videoTrack, id3Track, textTrack, timeOffset, contiguous, accurateTimeOffset);
3235     }
3236   };
3237
3238   TSDemuxer.prototype.destroy = function destroy() {
3239     this._initPTS = this._initDTS = undefined;
3240     this._duration = 0;
3241   };
3242
3243   TSDemuxer.prototype._parsePAT = function _parsePAT(data, offset) {
3244     // skip the PSI header and parse the first PMT entry
3245     return (data[offset + 10] & 0x1F) << 8 | data[offset + 11];
3246     // logger.log('PMT PID:'  + this._pmtId);
3247   };
3248
3249   TSDemuxer.prototype._parsePMT = function _parsePMT(data, offset, mpegSupported, isSampleAes) {
3250     var sectionLength = void 0,
3251         tableEnd = void 0,
3252         programInfoLength = void 0,
3253         pid = void 0,
3254         result = { audio: -1, avc: -1, id3: -1, isAAC: true };
3255     sectionLength = (data[offset + 1] & 0x0f) << 8 | data[offset + 2];
3256     tableEnd = offset + 3 + sectionLength - 4;
3257     // to determine where the table is, we have to figure out how
3258     // long the program info descriptors are
3259     programInfoLength = (data[offset + 10] & 0x0f) << 8 | data[offset + 11];
3260     // advance the offset to the first entry in the mapping table
3261     offset += 12 + programInfoLength;
3262     while (offset < tableEnd) {
3263       pid = (data[offset + 1] & 0x1F) << 8 | data[offset + 2];
3264       switch (data[offset]) {
3265         case 0xcf:
3266           // SAMPLE-AES AAC
3267           if (!isSampleAes) {
3268             logger["b" /* logger */].log('unkown stream type:' + data[offset]);
3269             break;
3270           }
3271         /* falls through */
3272
3273         // ISO/IEC 13818-7 ADTS AAC (MPEG-2 lower bit-rate audio)
3274         case 0x0f:
3275           // logger.log('AAC PID:'  + pid);
3276           if (result.audio === -1) result.audio = pid;
3277
3278           break;
3279
3280         // Packetized metadata (ID3)
3281         case 0x15:
3282           // logger.log('ID3 PID:'  + pid);
3283           if (result.id3 === -1) result.id3 = pid;
3284
3285           break;
3286
3287         case 0xdb:
3288           // SAMPLE-AES AVC
3289           if (!isSampleAes) {
3290             logger["b" /* logger */].log('unkown stream type:' + data[offset]);
3291             break;
3292           }
3293         /* falls through */
3294
3295         // ITU-T Rec. H.264 and ISO/IEC 14496-10 (lower bit-rate video)
3296         case 0x1b:
3297           // logger.log('AVC PID:'  + pid);
3298           if (result.avc === -1) result.avc = pid;
3299
3300           break;
3301
3302         // ISO/IEC 11172-3 (MPEG-1 audio)
3303         // or ISO/IEC 13818-3 (MPEG-2 halved sample rate audio)
3304         case 0x03:
3305         case 0x04:
3306           // logger.log('MPEG PID:'  + pid);
3307           if (!mpegSupported) {
3308             logger["b" /* logger */].log('MPEG audio found, not supported in this browser for now');
3309           } else if (result.audio === -1) {
3310             result.audio = pid;
3311             result.isAAC = false;
3312           }
3313           break;
3314
3315         case 0x24:
3316           logger["b" /* logger */].warn('HEVC stream type found, not supported for now');
3317           break;
3318
3319         default:
3320           logger["b" /* logger */].log('unkown stream type:' + data[offset]);
3321           break;
3322       }
3323       // move to the next table entry
3324       // skip past the elementary stream descriptors, if present
3325       offset += ((data[offset + 3] & 0x0F) << 8 | data[offset + 4]) + 5;
3326     }
3327     return result;
3328   };
3329
3330   TSDemuxer.prototype._parsePES = function _parsePES(stream) {
3331     var i = 0,
3332         frag = void 0,
3333         pesFlags = void 0,
3334         pesPrefix = void 0,
3335         pesLen = void 0,
3336         pesHdrLen = void 0,
3337         pesData = void 0,
3338         pesPts = void 0,
3339         pesDts = void 0,
3340         payloadStartOffset = void 0,
3341         data = stream.data;