PageSourceSearch

https://learnercommunity.com/Scripts/akamai/resources/js/dash.all.debug.js

js learnercommunity.com collected 2026-10-04 03:29:20 UTC 1,978,135 bytes, 52,150 lines download raw bytes

vendor: 4,300 bytes, lines 1-129
1(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
2/* $Date: 2007-06-12 18:02:31 $ */
3
4// from: http://bannister.us/weblog/2007/06/09/simple-base64-encodedecode-javascript/
5// Handles encode/decode of ASCII and Unicode strings.
6
7'use strict';
8
9var UTF8 = {};
10UTF8.encode = function (s) {
11    var u = [];
12    for (var i = 0; i < s.length; ++i) {
13        var c = s.charCodeAt(i);
14        if (c < 0x80) {
15            u.push(c);
16        } else if (c < 0x800) {
17            u.push(0xC0 | c >> 6);
18            u.push(0x80 | 63 & c);
19        } else if (c < 0x10000) {
20            u.push(0xE0 | c >> 12);
21            u.push(0x80 | 63 & c >> 6);
22            u.push(0x80 | 63 & c);
23        } else {
24            u.push(0xF0 | c >> 18);
25            u.push(0x80 | 63 & c >> 12);
26            u.push(0x80 | 63 & c >> 6);
27            u.push(0x80 | 63 & c);
28        }
29    }
30    return u;
31};
32UTF8.decode = function (u) {
33    var a = [];
34    var i = 0;
35    while (i < u.length) {
36        var v = u[i++];
37        if (v < 0x80) {
38            // no need to mask byte
39        } else if (v < 0xE0) {
40                v = (31 & v) << 6;
41                v |= 63 & u[i++];
42            } else if (v < 0xF0) {
43                v = (15 & v) << 12;
44                v |= (63 & u[i++]) << 6;
45                v |= 63 & u[i++];
46            } else {
47                v = (7 & v) << 18;
48                v |= (63 & u[i++]) << 12;
49                v |= (63 & u[i++]) << 6;
50                v |= 63 & u[i++];
51            }
52        a.push(String.fromCharCode(v));
53    }
54    return a.join('');
55};
56
57var BASE64 = {};
58(function (T) {
59    var encodeArray = function encodeArray(u) {
60        var i = 0;
61        var a = [];
62        var n = 0 | u.length / 3;
63        while (0 < n--) {
64            var v = (u[i] << 16) + (u[i + 1] << 8) + u[i + 2];
65            i += 3;
66            a.push(T.charAt(63 & v >> 18));
67            a.push(T.charAt(63 & v >> 12));
68            a.push(T.charAt(63 & v >> 6));
69            a.push(T.charAt(63 & v));
70        }
71        if (2 == u.length - i) {
72            var v = (u[i] << 16) + (u[i + 1] << 8);
73            a.push(T.charAt(63 & v >> 18));
74            a.push(T.charAt(63 & v >> 12));
75            a.push(T.charAt(63 & v >> 6));
76            a.push('=');
77        } else if (1 == u.length - i) {
78            var v = u[i] << 16;
79            a.push(T.charAt(63 & v >> 18));
80            a.push(T.charAt(63 & v >> 12));
81            a.push('==');
82        }
83        return a.join('');
84    };
85    var R = (function () {
86        var a = [];
87        for (var i = 0; i < T.length; ++i) {
88            a[T.charCodeAt(i)] = i;
89        }
90        a['='.charCodeAt(0)] = 0;
91        return a;
92    })();
93    var decodeArray = function decodeArray(s) {
94        var i = 0;
95        var u = [];
96        var n = 0 | s.length / 4;
97        while (0 < n--) {
98            var v = (R[s.charCodeAt(i)] << 18) + (R[s.charCodeAt(i + 1)] << 12) + (R[s.charCodeAt(i + 2)] << 6) + R[s.charCodeAt(i + 3)];
99            u.push(255 & v >> 16);
100            u.push(255 & v >> 8);
101            u.push(255 & v);
102            i += 4;
103        }
104        if (u) {
105            if ('=' == s.charAt(i - 2)) {
106                u.pop();
107                u.pop();
108            } else if ('=' == s.charAt(i - 1)) {
109                u.pop();
110            }
111        }
112        return u;
113    };
114    var ASCII = {};
115    ASCII.encode = function (s) {
116        var u = [];
117        for (var i = 0; i < s.length; ++i) {
118            u.push(s.charCodeAt(i));
119        }
120        return u;
121    };
122    ASCII.decode = function (u) {
123        for (var i = 0; i < s.length; ++i) {
124            a[i] = String.fromCharCode(a[i]);
125        }
126        return a.join('');
127    };
128    BASE64.decodeArray = function (s) {
129        var u = decodeArray(s);
130        return new Uint8Array(u);
131    };
132    BASE64.encodeASCII = function (s) {
133        var u = ASCII.encode(s);
134        return encodeArray(u);
135    };
136    BASE64.decodeASCII = function (s) {
137        var a = decodeArray(s);
138        return ASCII.decode(a);
139    };
140    BASE64.encode = function (s) {
141        var u = UTF8.encode(s);
142        return encodeArray(u);
143    };
144    BASE64.decode = function (s) {
145        var u = decodeArray(s);
146        return UTF8.decode(u);
147    };
148})("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
149
150/*The following polyfills are not used in dash.js but have caused multiplayer integration issues.
151 Therefore commenting them out.
152if (undefined === btoa) {
153    var btoa = BASE64.encode;
154}
155if (undefined === atob) {
156    var atob = BASE64.decode;
157}
158*/
159
160if (typeof exports !== 'undefined') {
161    exports.decode = BASE64.decode;
162    exports.decodeArray = BASE64.decodeArray;
163}
164
165},{}],2:[function(_dereq_,module,exports){
166/**
167 * The copyright in this software is being made available under the BSD License,
168 * included below. This software may be subject to other third party and contributor
169 * rights, including patent rights, and no such rights are granted under this license.
170 *
171 * Copyright (c) 2015-2016, DASH Industry Forum.
172 * All rights reserved.
173 *
174 * Redistribution and use in source and binary forms, with or without modification,
175 * are permitted provided that the following conditions are met:
176 *  1. Redistributions of source code must retain the above copyright notice, this
177 *  list of conditions and the following disclaimer.
178 *  * Redistributions in binary form must reproduce the above copyright notice,
179 *  this list of conditions and the following disclaimer in the documentation and/or
180 *  other materials provided with the distribution.
181 *  2. Neither the name of Dash Industry Forum nor the names of its
182 *  contributors may be used to endorse or promote products derived from this software
183 *  without specific prior written permission.
184 *
185 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
186 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
187 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
188 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
189 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
190 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
191 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
192 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
193 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
194 *  POSSIBILITY OF SUCH DAMAGE.
195 */
196'use strict';
197
198(function (exports) {
199
200    "use strict";
201
202    /**
203     *  Exceptions from regular ASCII. CodePoints are mapped to UTF-16 codes
204     */
205
206    var specialCea608CharsCodes = {
207        0x2a: 0xe1, // lowercase a, acute accent
208        0x5c: 0xe9, // lowercase e, acute accent
209        0x5e: 0xed, // lowercase i, acute accent
210        0x5f: 0xf3, // lowercase o, acute accent
211        0x60: 0xfa, // lowercase u, acute accent
212        0x7b: 0xe7, // lowercase c with cedilla
213        0x7c: 0xf7, // division symbol
214        0x7d: 0xd1, // uppercase N tilde
215        0x7e: 0xf1, // lowercase n tilde
216        0x7f: 0x2588, // Full block
217        // THIS BLOCK INCLUDES THE 16 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS
218        // THAT COME FROM HI BYTE=0x11 AND LOW BETWEEN 0x30 AND 0x3F
219        // THIS MEANS THAT \x50 MUST BE ADDED TO THE VALUES
220        0x80: 0xae, // Registered symbol (R)
221        0x81: 0xb0, // degree sign
222        0x82: 0xbd, // 1/2 symbol
223        0x83: 0xbf, // Inverted (open) question mark
224        0x84: 0x2122, // Trademark symbol (TM)
225        0x85: 0xa2, // Cents symbol
226        0x86: 0xa3, // Pounds sterling
227        0x87: 0x266a, // Music 8'th note
228        0x88: 0xe0, // lowercase a, grave accent
229        0x89: 0x20, // transparent space (regular)
230        0x8a: 0xe8, // lowercase e, grave accent
231        0x8b: 0xe2, // lowercase a, circumflex accent
232        0x8c: 0xea, // lowercase e, circumflex accent
233        0x8d: 0xee, // lowercase i, circumflex accent
234        0x8e: 0xf4, // lowercase o, circumflex accent
235        0x8f: 0xfb, // lowercase u, circumflex accent
236        // THIS BLOCK INCLUDES THE 32 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS
237        // THAT COME FROM HI BYTE=0x12 AND LOW BETWEEN 0x20 AND 0x3F
238        0x90: 0xc1, // capital letter A with acute
239        0x91: 0xc9, // capital letter E with acute
240        0x92: 0xd3, // capital letter O with acute
241        0x93: 0xda, // capital letter U with acute
242        0x94: 0xdc, // capital letter U with diaresis
243        0x95: 0xfc, // lowercase letter U with diaeresis
244        0x96: 0x2018, // opening single quote
245        0x97: 0xa1, // inverted exclamation mark
246        0x98: 0x2a, // asterisk
247        0x99: 0x2019, // closing single quote
248        0x9a: 0x2501, // box drawings heavy horizontal
249        0x9b: 0xa9, // copyright sign
250        0x9c: 0x2120, // Service mark
251        0x9d: 0x2022, // (round) bullet
252        0x9e: 0x201c, // Left double quotation mark
253        0x9f: 0x201d, // Right double quotation mark
254        0xa0: 0xc0, // uppercase A, grave accent
255        0xa1: 0xc2, // uppercase A, circumflex
256        0xa2: 0xc7, // uppercase C with cedilla
257        0xa3: 0xc8, // uppercase E, grave accent
258        0xa4: 0xca, // uppercase E, circumflex
259        0xa5: 0xcb, // capital letter E with diaresis
260        0xa6: 0xeb, // lowercase letter e with diaresis
261        0xa7: 0xce, // uppercase I, circumflex
262        0xa8: 0xcf, // uppercase I, with diaresis
263        0xa9: 0xef, // lowercase i, with diaresis
264        0xaa: 0xd4, // uppercase O, circumflex
265        0xab: 0xd9, // uppercase U, grave accent
266        0xac: 0xf9, // lowercase u, grave accent
267        0xad: 0xdb, // uppercase U, circumflex
268        0xae: 0xab, // left-pointing double angle quotation mark
269        0xaf: 0xbb, // right-pointing double angle quotation mark
270        // THIS BLOCK INCLUDES THE 32 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS
271        // THAT COME FROM HI BYTE=0x13 AND LOW BETWEEN 0x20 AND 0x3F
272        0xb0: 0xc3, // Uppercase A, tilde
273        0xb1: 0xe3, // Lowercase a, tilde
274        0xb2: 0xcd, // Uppercase I, acute accent
275        0xb3: 0xcc, // Uppercase I, grave accent
276        0xb4: 0xec, // Lowercase i, grave accent
277        0xb5: 0xd2, // Uppercase O, grave accent
278        0xb6: 0xf2, // Lowercase o, grave accent
279        0xb7: 0xd5, // Uppercase O, tilde
280        0xb8: 0xf5, // Lowercase o, tilde
281        0xb9: 0x7b, // Open curly brace
282        0xba: 0x7d, // Closing curly brace
283        0xbb: 0x5c, // Backslash
284        0xbc: 0x5e, // Caret
285        0xbd: 0x5f, // Underscore
286        0xbe: 0x7c, // Pipe (vertical line)
287        0xbf: 0x223c, // Tilde operator
288        0xc0: 0xc4, // Uppercase A, umlaut
289        0xc1: 0xe4, // Lowercase A, umlaut
290        0xc2: 0xd6, // Uppercase O, umlaut
291        0xc3: 0xf6, // Lowercase o, umlaut
292        0xc4: 0xdf, // Esszett (sharp S)
293        0xc5: 0xa5, // Yen symbol
294        0xc6: 0xa4, // Generic currency sign
295        0xc7: 0x2503, // Box drawings heavy vertical
296        0xc8: 0xc5, // Uppercase A, ring
297        0xc9: 0xe5, // Lowercase A, ring
298        0xca: 0xd8, // Uppercase O, stroke
299        0xcb: 0xf8, // Lowercase o, strok
300        0xcc: 0x250f, // Box drawings heavy down and right
301        0xcd: 0x2513, // Box drawings heavy down and left
302        0xce: 0x2517, // Box drawings heavy up and right
303        0xcf: 0x251b // Box drawings heavy up and left
304    };
305
306    /**
307     * Get Unicode Character from CEA-608 byte code
308     */
309    var getCharForByte = function getCharForByte(byte) {
310        var charCode = byte;
311        if (specialCea608CharsCodes.hasOwnProperty(byte)) {
312            charCode = specialCea608CharsCodes[byte];
313        }
314        return String.fromCharCode(charCode);
315    };
316
317    var NR_ROWS = 15,
318        NR_COLS = 32;
319    // Tables to look up row from PAC data
320    var rowsLowCh1 = { 0x11: 1, 0x12: 3, 0x15: 5, 0x16: 7, 0x17: 9, 0x10: 11, 0x13: 12, 0x14: 14 };
321    var rowsHighCh1 = { 0x11: 2, 0x12: 4, 0x15: 6, 0x16: 8, 0x17: 10, 0x13
vendor: 22,304 bytes, lines 321-951
321: 13, 0x14: 15 };
322    var rowsLowCh2 = { 0x19: 1, 0x1A: 3, 0x1D: 5, 0x1E: 7, 0x1F: 9, 0x18: 11, 0x1B: 12, 0x1C: 14 };
323    var rowsHighCh2 = { 0x19: 2, 0x1A: 4, 0x1D: 6, 0x1E: 8, 0x1F: 10, 0x1B: 13, 0x1C: 15 };
324
325    var backgroundColors = ['white', 'green', 'blue', 'cyan', 'red', 'yellow', 'magenta', 'black', 'transparent'];
326
327    /**
328     * Simple logger class to be able to write with time-stamps and filter on level.
329     */
330    var logger = {
331        verboseFilter: { 'DATA': 3, 'DEBUG': 3, 'INFO': 2, 'WARNING': 2, 'TEXT': 1, 'ERROR': 0 },
332        time: null,
333        verboseLevel: 0, // Only write errors
334        setTime: function setTime(newTime) {
335            this.time = newTime;
336        },
337        log: function log(severity, msg) {
338            var minLevel = this.verboseFilter[severity];
339            if (this.verboseLevel >= minLevel) {
340                console.log(this.time + " [" + severity + "] " + msg);
341            }
342        }
343    };
344
345    var numArrayToHexArray = function numArrayToHexArray(numArray) {
346        var hexArray = [];
347        for (var j = 0; j < numArray.length; j++) {
348            hexArray.push(numArray[j].toString(16));
349        }
350        return hexArray;
351    };
352
353    /**
354     * State of CEA-608 pen or character
355     * @constructor
356     */
357    var PenState = function PenState(foreground, underline, italics, background, flash) {
358        this.foreground = foreground || "white";
359        this.underline = underline || false;
360        this.italics = italics || false;
361        this.background = background || "black";
362        this.flash = flash || false;
363    };
364
365    PenState.prototype = {
366
367        reset: function reset() {
368            this.foreground = "white";
369            this.underline = false;
370            this.italics = false;
371            this.background = "black";
372            this.flash = false;
373        },
374
375        setStyles: function setStyles(styles) {
376            var attribs = ["foreground", "underline", "italics", "background", "flash"];
377            for (var i = 0; i < attribs.length; i++) {
378                var style = attribs[i];
379                if (styles.hasOwnProperty(style)) {
380                    this[style] = styles[style];
381                }
382            }
383        },
384
385        isDefault: function isDefault() {
386            return this.foreground === "white" && !this.underline && !this.italics && this.background === "black" && !this.flash;
387        },
388
389        equals: function equals(other) {
390            return this.foreground === other.foreground && this.underline === other.underline && this.italics === other.italics && this.background === other.background && this.flash === other.flash;
391        },
392
393        copy: function copy(newPenState) {
394            this.foreground = newPenState.foreground;
395            this.underline = newPenState.underline;
396            this.italics = newPenState.italics;
397            this.background = newPenState.background;
398            this.flash = newPenState.flash;
399        },
400
401        toString: function toString() {
402            return "color=" + this.foreground + ", underline=" + this.underline + ", italics=" + this.italics + ", background=" + this.background + ", flash=" + this.flash;
403        }
404    };
405
406    /**
407     * Unicode character with styling and background.
408     * @constructor
409     */
410    var StyledUnicodeChar = function StyledUnicodeChar(uchar, foreground, underline, italics, background, flash) {
411        this.uchar = uchar || ' '; // unicode character
412        this.penState = new PenState(foreground, underline, italics, background, flash);
413    };
414
415    StyledUnicodeChar.prototype = {
416
417        reset: function reset() {
418            this.uchar = ' ';
419            this.penState.reset();
420        },
421
422        setChar: function setChar(uchar, newPenState) {
423            this.uchar = uchar;
424            this.penState.copy(newPenState);
425        },
426
427        setPenState: function setPenState(newPenState) {
428            this.penState.copy(newPenState);
429        },
430
431        equals: function equals(other) {
432            return this.uchar === other.uchar && this.penState.equals(other.penState);
433        },
434
435        copy: function copy(newChar) {
436            this.uchar = newChar.uchar;
437            this.penState.copy(newChar.penState);
438        },
439
440        isEmpty: function isEmpty() {
441            return this.uchar === ' ' && this.penState.isDefault();
442        }
443    };
444
445    /**
446     * CEA-608 row consisting of NR_COLS instances of StyledUnicodeChar.
447     * @constructor
448     */
449    var Row = function Row() {
450        this.chars = [];
451        for (var i = 0; i < NR_COLS; i++) {
452            this.chars.push(new StyledUnicodeChar());
453        }
454        this.pos = 0;
455        this.currPenState = new PenState();
456    };
457
458    Row.prototype = {
459
460        equals: function equals(other) {
461            var equal = true;
462            for (var i = 0; i < NR_COLS; i++) {
463                if (!this.chars[i].equals(other.chars[i])) {
464                    equal = false;
465                    break;
466                }
467            }
468            return equal;
469        },
470
471        copy: function copy(other) {
472            for (var i = 0; i < NR_COLS; i++) {
473                this.chars[i].copy(other.chars[i]);
474            }
475        },
476
477        isEmpty: function isEmpty() {
478            var empty = true;
479            for (var i = 0; i < NR_COLS; i++) {
480                if (!this.chars[i].isEmpty()) {
481                    empty = false;
482                    break;
483                }
484            }
485            return empty;
486        },
487
488        /**
489         *  Set the cursor to a valid column.
490         */
491        setCursor: function setCursor(absPos) {
492            if (this.pos !== absPos) {
493                this.pos = absPos;
494            }
495            if (this.pos < 0) {
496                logger.log("ERROR", "Negative cursor position " + this.pos);
497                this.pos = 0;
498            } else if (this.pos > NR_COLS) {
499                logger.log("ERROR", "Too large cursor position " + this.pos);
500                this.pos = NR_COLS;
501            }
502        },
503
504        /** 
505         * Move the cursor relative to current position.
506         */
507        moveCursor: function moveCursor(relPos) {
508            var newPos = this.pos + relPos;
509            if (relPos > 1) {
510                for (var i = this.pos + 1; i < newPos + 1; i++) {
511                    this.chars[i].setPenState(this.currPenState);
512                }
513            }
514            this.setCursor(newPos);
515        },
516
517        /**
518         * Backspace, move one step back and clear character.
519         */
520        backSpace: function backSpace() {
521            this.moveCursor(-1);
522            this.chars[this.pos].setChar(' ', this.currPenState);
523        },
524
525        insertChar: function insertChar(byte) {
526            if (byte >= 0x90) {
527                //Extended char
528                this.backSpace();
529            }
530            var char = getCharForByte(byte);
531            if (this.pos >= NR_COLS) {
532                logger.log("ERROR", "Cannot insert " + byte.toString(16) + " (" + char + ") at position " + this.pos + ". Skipping it!");
533                return;
534            }
535            this.chars[this.pos].setChar(char, this.currPenState);
536            this.moveCursor(1);
537        },
538
539        clearFromPos: function clearFromPos(startPos) {
540            var i;
541            for (i = startPos; i < NR_COLS; i++) {
542                this.chars[i].reset();
543            }
544        },
545
546        clear: function clear() {
547            this.clearFromPos(0);
548            this.pos = 0;
549            this.currPenState.reset();
550        },
551
552        clearToEndOfRow: function clearToEndOfRow() {
553            this.clearFromPos(this.pos);
554        },
555
556        getTextString: function getTextString() {
557            var chars = [];
558            var empty = true;
559            for (var i = 0; i < NR_COLS; i++) {
560                var char = this.chars[i].uchar;
561                if (char !== " ") {
562                    empty = false;
563                }
564                chars.push(char);
565            }
566            if (empty) {
567                return "";
568            } else {
569                return chars.join("");
570            }
571        },
572
573        setPenStyles: function setPenStyles(styles) {
574            this.currPenState.setStyles(styles);
575            var currChar = this.chars[this.pos];
576            currChar.setPenState(this.currPenState);
577        }
578    };
579
580    /**
581     * Keep a CEA-608 screen of 32x15 styled characters
582     * @constructor
583    */
584    var CaptionScreen = function CaptionScreen() {
585
586        this.rows = [];
587        for (var i = 0; i < NR_ROWS; i++) {
588            this.rows.push(new Row()); // Note that we use zero-based numbering (0-14)
589        }
590        this.currRow = NR_ROWS - 1;
591        this.nrRollUpRows = null;
592        this.reset();
593    };
594
595    CaptionScreen.prototype = {
596
597        reset: function reset() {
598            for (var i = 0; i < NR_ROWS; i++) {
599                this.rows[i].clear();
600            }
601            this.currRow = NR_ROWS - 1;
602        },
603
604        equals: function equals(other) {
605            var equal = true;
606            for (var i = 0; i < NR_ROWS; i++) {
607                if (!this.rows[i].equals(other.rows[i])) {
608                    equal = false;
609                    break;
610                }
611            }
612            return equal;
613        },
614
615        copy: function copy(other) {
616            for (var i = 0; i < NR_ROWS; i++) {
617                this.rows[i].copy(other.rows[i]);
618            }
619        },
620
621        isEmpty: function isEmpty() {
622            var empty = true;
623            for (var i = 0; i < NR_ROWS; i++) {
624                if (!this.rows[i].isEmpty()) {
625                    empty = false;
626                    break;
627                }
628            }
629            return empty;
630        },
631
632        backSpace: function backSpace() {
633            var row = this.rows[this.currRow];
634            row.backSpace();
635        },
636
637        clearToEndOfRow: function clearToEndOfRow() {
638            var row = this.rows[this.currRow];
639            row.clearToEndOfRow();
640        },
641
642        /**
643         * Insert a character (without styling) in the current row.
644         */
645        insertChar: function insertChar(char) {
646            var row = this.rows[this.currRow];
647            row.insertChar(char);
648        },
649
650        setPen: function setPen(styles) {
651            var row = this.rows[this.currRow];
652            row.setPenStyles(styles);
653        },
654
655        moveCursor: function moveCursor(relPos) {
656            var row = this.rows[this.currRow];
657            row.moveCursor(relPos);
658        },
659
660        setCursor: function setCursor(absPos) {
661            logger.log("INFO", "setCursor: " + absPos);
662            var row = this.rows[this.currRow];
663            row.setCursor(absPos);
664        },
665
666        setPAC: function setPAC(pacData) {
667            logger.log("INFO", "pacData = " + JSON.stringify(pacData));
668            var newRow = pacData.row - 1;
669            if (this.nrRollUpRows && newRow < this.nrRollUpRows - 1) {
670                newRow = this.nrRollUpRows - 1;
671            }
672            this.currRow = newRow;
673            var row = this.rows[this.currRow];
674            if (pacData.indent !== null) {
675                var indent = pacData.indent;
676                var prevPos = Math.max(indent - 1, 0);
677                row.setCursor(pacData.indent);
678                pacData.color = row.chars[prevPos].penState.foreground;
679            }
680            var styles = { foreground: pacData.color, underline: pacData.underline, italics: pacData.italics, background: 'black', flash: false };
681            this.setPen(styles);
682        },
683
684        /**
685         * Set background/extra foreground, but first do back_space, and then insert space (backwards compatibility).
686         */
687        setBkgData: function setBkgData(bkgData) {
688
689            logger.log("INFO", "bkgData = " + JSON.stringify(bkgData));
690            this.backSpace();
691            this.setPen(bkgData);
692            this.insertChar(0x20); //Space
693        },
694
695        setRollUpRows: function setRollUpRows(nrRows) {
696            this.nrRollUpRows = nrRows;
697        },
698
699        rollUp: function rollUp() {
700            if (this.nrRollUpRows === null) {
701                logger.log("DEBUG", "roll_up but nrRollUpRows not set yet");
702                return; //Not properly setup
703            }
704            logger.log("TEXT", this.getDisplayText());
705            var topRowIndex = this.currRow + 1 - this.nrRollUpRows;
706            var topRow = this.rows.splice(topRowIndex, 1)[0];
707            topRow.clear();
708            this.rows.splice(this.currRow, 0, topRow);
709            logger.log("INFO", "Rolling up");
710            //logger.log("TEXT", this.get_display_text())
711        },
712
713        /**
714         * Get all non-empty rows with as unicode text. 
715         */
716        getDisplayText: function getDisplayText(asOneRow) {
717            asOneRow = asOneRow || false;
718            var displayText = [];
719            var text = "";
720            var rowNr = -1;
721            for (var i = 0; i < NR_ROWS; i++) {
722                var rowText = this.rows[i].getTextString();
723                if (rowText) {
724                    rowNr = i + 1;
725                    if (asOneRow) {
726                        displayText.push("Row " + rowNr + ': "' + rowText + '"');
727                    } else {
728                        displayText.push(rowText.trim());
729                    }
730                }
731            }
732            if (displayText.length > 0) {
733                if (asOneRow) {
734                    text = "[" + displayText.join(" | ") + "]";
735                } else {
736                    text = displayText.join("\n");
737                }
738            }
739            return text;
740        },
741
742        getTextAndFormat: function getTextAndFormat() {
743            return this.rows;
744        }
745    };
746
747    /**
748     * Handle a CEA-608 channel and send decoded data to outputFilter
749     * @constructor
750     * @param {Number} channelNumber (1 or 2)
751     * @param {CueHandler} outputFilter Output from channel1 newCue(startTime, endTime, captionScreen)
752    */
753    var Cea608Channel = function Cea608Channel(channelNumber, outputFilter) {
754
755        this.chNr = channelNumber;
756        this.outputFilter = outputFilter;
757        this.mode = null;
758        this.verbose = 0;
759        this.displayedMemory = new CaptionScreen();
760        this.nonDisplayedMemory = new CaptionScreen();
761        this.lastOutputScreen = new CaptionScreen();
762        this.currRollUpRow = this.displayedMemory.rows[NR_ROWS - 1];
763        this.writeScreen = this.displayedMemory;
764        this.mode = null;
765        this.cueStartTime = null; // Keeps track of where a cue started.
766    };
767
768    Cea608Channel.prototype = {
769
770        modes: ["MODE_ROLL-UP", "MODE_POP-ON", "MODE_PAINT-ON", "MODE_TEXT"],
771
772        reset: function reset() {
773            this.mode = null;
774            this.displayedMemory.reset();
775            this.nonDisplayedMemory.reset();
776            this.lastOutputScreen.reset();
777            this.currRollUpRow = this.displayedMemory.rows[NR_ROWS - 1];
778            this.writeScreen = this.displayedMemory;
779            this.mode = null;
780            this.cueStartTime = null;
781            this.lastCueEndTime = null;
782        },
783
784        getHandler: function getHandler() {
785            return this.outputFilter;
786        },
787
788        setHandler: function setHandler(newHandler) {
789            this.outputFilter = newHandler;
790        },
791
792        setPAC: function setPAC(pacData) {
793            this.writeScreen.setPAC(pacData);
794        },
795
796        setBkgData: function setBkgData(bkgData) {
797            this.writeScreen.setBkgData(bkgData);
798        },
799
800        setMode: function setMode(newMode) {
801            if (newMode === this.mode) {
802                return;
803            }
804            this.mode = newMode;
805            logger.log("INFO", "MODE=" + newMode);
806            if (this.mode == "MODE_POP-ON") {
807                this.writeScreen = this.nonDisplayedMemory;
808            } else {
809                this.writeScreen = this.displayedMemory;
810                this.writeScreen.reset();
811            }
812            if (this.mode !== "MODE_ROLL-UP") {
813                this.displayedMemory.nrRollUpRows = null;
814                this.nonDisplayedMemory.nrRollUpRows = null;
815            }
816            this.mode = newMode;
817        },
818
819        insertChars: function insertChars(chars) {
820            for (var i = 0; i < chars.length; i++) {
821                this.writeScreen.insertChar(chars[i]);
822            }
823            var screen = this.writeScreen === this.displayedMemory ? "DISP" : "NON_DISP";
824            logger.log("INFO", screen + ": " + this.writeScreen.getDisplayText(true));
825            if (this.mode === "MODE_PAINT-ON" || this.mode === "MODE_ROLL-UP") {
826                logger.log("TEXT", "DISPLAYED: " + this.displayedMemory.getDisplayText(true));
827                this.outputDataUpdate();
828            }
829        },
830
831        cc_RCL: function cc_RCL() {
832            // Resume Caption Loading (switch mode to Pop On)
833            logger.log("INFO", "RCL - Resume Caption Loading");
834            this.setMode("MODE_POP-ON");
835        },
836        cc_BS: function cc_BS() {
837            // BackSpace
838            logger.log("INFO", "BS - BackSpace");
839            if (this.mode === "MODE_TEXT") {
840                return;
841            }
842            this.writeScreen.backSpace();
843            if (this.writeScreen === this.displayedMemory) {
844                this.outputDataUpdate();
845            }
846        },
847        cc_AOF: function cc_AOF() {
848            // Reserved (formerly Alarm Off)
849            return;
850        },
851        cc_AON: function cc_AON() {
852            // Reserved (formerly Alarm On)
853            return;
854        },
855        cc_DER: function cc_DER() {
856            // Delete to End of Row
857            logger.log("INFO", "DER- Delete to End of Row");
858            this.writeScreen.clearToEndOfRow();
859            this.outputDataUpdate();
860        },
861        cc_RU: function cc_RU(nrRows) {
862            //Roll-Up Captions-2,3,or 4 Rows
863            logger.log("INFO", "RU(" + nrRows + ") - Roll Up");
864            this.writeScreen = this.displayedMemory;
865            this.setMode("MODE_ROLL-UP");
866            this.writeScreen.setRollUpRows(nrRows);
867        },
868        cc_FON: function cc_FON() {
869            //Flash On
870            logger.log("INFO", "FON - Flash On");
871            this.writeScreen.setPen({ flash: true });
872        },
873        cc_RDC: function cc_RDC() {
874            // Resume Direct Captioning (switch mode to PaintOn)
875            logger.log("INFO", "RDC - Resume Direct Captioning");
876            this.setMode("MODE_PAINT-ON");
877        },
878        cc_TR: function cc_TR() {
879            // Text Restart in text mode (not supported, however)
880            logger.log("INFO", "TR");
881            this.setMode("MODE_TEXT");
882        },
883        cc_RTD: function cc_RTD() {
884            // Resume Text Display in Text mode (not supported, however)
885            logger.log("INFO", "RTD");
886            this.setMode("MODE_TEXT");
887        },
888        cc_EDM: function cc_EDM() {
889            // Erase Displayed Memory
890            logger.log("INFO", "EDM - Erase Displayed Memory");
891            this.displayedMemory.reset();
892            this.outputDataUpdate();
893        },
894        cc_CR: function cc_CR() {
895            // Carriage Return
896            logger.log("CR - Carriage Return");
897            this.writeScreen.rollUp();
898            this.outputDataUpdate();
899        },
900        cc_ENM: function cc_ENM() {
901            //Erase Non-Displayed Memory
902            logger.log("INFO", "ENM - Erase Non-displayed Memory");
903            this.nonDisplayedMemory.reset();
904        },
905        cc_EOC: function cc_EOC() {
906            //End of Caption (Flip Memories)
907            logger.log("INFO", "EOC - End Of Caption");
908            if (this.mode === "MODE_POP-ON") {
909                var tmp = this.displayedMemory;
910                this.displayedMemory = this.nonDisplayedMemory;
911                this.nonDisplayedMemory = tmp;
912                this.writeScreen = this.nonDisplayedMemory;
913                logger.log("TEXT", "DISP: " + this.displayedMemory.getDisplayText());
914            }
915            this.outputDataUpdate();
916        },
917        cc_TO: function cc_TO(nrCols) {
918            // Tab Offset 1,2, or 3 columns
919            logger.log("INFO", "TO(" + nrCols + ") - Tab Offset");
920            this.writeScreen.moveCursor(nrCols);
921        },
922        cc_MIDROW: function cc_MIDROW(secondByte) {
923            // Parse MIDROW command
924            var styles = { flash: false };
925            styles.underline = secondByte % 2 === 1;
926            styles.italics = secondByte >= 0x2e;
927            if (!styles.italics) {
928                var colorIndex = Math.floor(secondByte / 2) - 0x10;
929                var colors = ["white", "green", "blue", "cyan", "red", "yellow", "magenta"];
930                styles.foreground = colors[colorIndex];
931            } else {
932                styles.foreground = "white";
933            }
934            logger.log("INFO", "MIDROW: " + JSON.stringify(styles));
935            this.writeScreen.setPen(styles);
936        },
937
938        outputDataUpdate: function outputDataUpdate() {
939            var t = logger.time;
940            if (t === null) {
941                return;
942            }
943            if (this.outputFilter) {
944                if (this.outputFilter.updateData) {
945                    this.outputFilter.updateData(t, this.displayedMemory);
946                }
947                if (this.cueStartTime === null && !this.displayedMemory.isEmpty()) {
948                    // Start of a new cue
949                    this.cueStartTime = t;
950                } else {
951                    if (!this.displayedMemory.equals(this.lastOutputScreen)
vendor: 6,140 bytes, lines 951-1104
951) {
952                        if (this.outputFilter.newCue) {
953                            this.outputFilter.newCue(this.cueStartTime, t, this.lastOutputScreen);
954                        }
955                        this.cueStartTime = this.displayedMemory.isEmpty() ? null : t;
956                    }
957                }
958                this.lastOutputScreen.copy(this.displayedMemory);
959            }
960        },
961
962        cueSplitAtTime: function cueSplitAtTime(t) {
963            if (this.outputFilter) {
964                if (!this.displayedMemory.isEmpty()) {
965                    if (this.outputFilter.newCue) {
966                        this.outputFilter.newCue(this.cueStartTime, t, this.displayedMemory);
967                    }
968                    this.cueStartTime = t;
969                }
970            }
971        }
972    };
973
974    /**
975     * Parse CEA-608 data and send decoded data to out1 and out2.
976     * @constructor
977     * @param {Number} field  CEA-608 field (1 or 2)
978     * @param {CueHandler} out1 Output from channel1 newCue(startTime, endTime, captionScreen)
979     * @param {CueHandler} out2 Output from channel2 newCue(startTime, endTime, captionScreen)
980     */
981    var Cea608Parser = function Cea608Parser(field, out1, out2) {
982        this.field = field || 1;
983        this.outputs = [out1, out2];
984        this.channels = [new Cea608Channel(1, out1), new Cea608Channel(2, out2)];
985        this.currChNr = -1; // Will be 1 or 2
986        this.lastCmdA = null; // First byte of last command
987        this.lastCmdB = null; // Second byte of last command
988        this.bufferedData = [];
989        this.startTime = null;
990        this.lastTime = null;
991        this.dataCounters = { 'padding': 0, 'char': 0, 'cmd': 0, 'other': 0 };
992    };
993
994    Cea608Parser.prototype = {
995
996        getHandler: function getHandler(index) {
997            return this.channels[index].getHandler();
998        },
999
1000        setHandler: function setHandler(index, newHandler) {
1001            this.channels[index].setHandler(newHandler);
1002        },
1003
1004        /**
1005         * Add data for time t in forms of list of bytes (unsigned ints). The bytes are treated as pairs.
1006         */
1007        addData: function addData(t, byteList) {
1008            var cmdFound,
1009                a,
1010                b,
1011                charsFound = false;
1012
1013            this.lastTime = t;
1014            logger.setTime(t);
1015
1016            for (var i = 0; i < byteList.length; i += 2) {
1017                a = byteList[i] & 0x7f;
1018                b = byteList[i + 1] & 0x7f;
1019
1020                if (a >= 0x10 && a <= 0x1f && a === this.lastCmdA && b === this.lastCmdB) {
1021                    this.lastCmdA = null;
1022                    this.lastCmdB = null;
1023                    logger.log("DEBUG", "Repeated command (" + numArrayToHexArray([a, b]) + ") is dropped");
1024                    continue; // Repeated commands are dropped (once)
1025                }
1026
1027                if (a === 0 && b === 0) {
1028                    this.dataCounters.padding += 2;
1029                    continue;
1030                } else {
1031                    logger.log("DATA", "[" + numArrayToHexArray([byteList[i], byteList[i + 1]]) + "] -> (" + numArrayToHexArray([a, b]) + ")");
1032                }
1033                cmdFound = this.parseCmd(a, b);
1034                if (!cmdFound) {
1035                    cmdFound = this.parseMidrow(a, b);
1036                }
1037                if (!cmdFound) {
1038                    cmdFound = this.parsePAC(a, b);
1039                }
1040                if (!cmdFound) {
1041                    cmdFound = this.parseBackgroundAttributes(a, b);
1042                }
1043                if (!cmdFound) {
1044                    charsFound = this.parseChars(a, b);
1045                    if (charsFound) {
1046                        if (this.currChNr && this.currChNr >= 0) {
1047                            var channel = this.channels[this.currChNr - 1];
1048                            channel.insertChars(charsFound);
1049                        } else {
1050                            logger.log("WARNING", "No channel found yet. TEXT-MODE?");
1051                        }
1052                    }
1053                }
1054                if (cmdFound) {
1055                    this.dataCounters.cmd += 2;
1056                } else if (charsFound) {
1057                    this.dataCounters.char += 2;
1058                } else {
1059                    this.dataCounters.other += 2;
1060                    logger.log("WARNING", "Couldn't parse cleaned data " + numArrayToHexArray([a, b]) + " orig: " + numArrayToHexArray([byteList[i], byteList[i + 1]]));
1061                }
1062            }
1063        },
1064
1065        /**
1066         * Parse Command.
1067         * @returns {Boolean} Tells if a command was found
1068         */
1069        parseCmd: function parseCmd(a, b) {
1070            var chNr = null;
1071
1072            var cond1 = (a === 0x14 || a === 0x15 || a === 0x1C || a === 0x1D) && 0x20 <= b && b <= 0x2F;
1073            var cond2 = (a === 0x17 || a === 0x1F) && 0x21 <= b && b <= 0x23;
1074            if (!(cond1 || cond2)) {
1075                return false;
1076            }
1077
1078            if (a === 0x14 || a === 0x15 || a === 0x17) {
1079                chNr = 1;
1080            } else {
1081                chNr = 2; // (a === 0x1C || a === 0x1D || a=== 0x1f)
1082            }
1083
1084            var channel = this.channels[chNr - 1];
1085
1086            if (a === 0x14 || a === 0x15 || a === 0x1C || a === 0x1D) {
1087                if (b === 0x20) {
1088                    channel.cc_RCL();
1089                } else if (b === 0x21) {
1090                    channel.cc_BS();
1091                } else if (b === 0x22) {
1092                    channel.cc_AOF();
1093                } else if (b === 0x23) {
1094                    channel.cc_AON();
1095                } else if (b === 0x24) {
1096                    channel.cc_DER();
1097                } else if (b === 0x25) {
1098                    channel.cc_RU(2);
1099                } else if (b === 0x26) {
1100                    channel.cc_RU(3);
1101                } else if (b === 0x27) {
1102                    channel.cc_RU(4);
1103                } else if (b === 0x28) {
1104                    channel.cc_FON();
vendor: 8,978 bytes, lines 1105-1345
1105                } else if (b === 0x29) {
1106                    channel.cc_RDC();
1107                } else if (b === 0x2A) {
1108                    channel.cc_TR();
1109                } else if (b === 0x2B) {
1110                    channel.cc_RTD();
1111                } else if (b === 0x2C) {
1112                    channel.cc_EDM();
1113                } else if (b === 0x2D) {
1114                    channel.cc_CR();
1115                } else if (b === 0x2E) {
1116                    channel.cc_ENM();
1117                } else if (b === 0x2F) {
1118                    channel.cc_EOC();
1119                }
1120            } else {
1121                //a == 0x17 || a == 0x1F
1122                channel.cc_TO(b - 0x20);
1123            }
1124            this.lastCmdA = a;
1125            this.lastCmdB = b;
1126            this.currChNr = chNr;
1127            return true;
1128        },
1129
1130        /**
1131         * Parse midrow styling command
1132         * @returns {Boolean}
1133         */
1134        parseMidrow: function parseMidrow(a, b) {
1135            var chNr = null;
1136
1137            if ((a === 0x11 || a === 0x19) && 0x20 <= b && b <= 0x2f) {
1138                if (a === 0x11) {
1139                    chNr = 1;
1140                } else {
1141                    chNr = 2;
1142                }
1143                if (chNr !== this.currChNr) {
1144                    logger.log("ERROR", "Mismatch channel in midrow parsing");
1145                    return false;
1146                }
1147                var channel = this.channels[chNr - 1];
1148                // cea608 spec says midrow codes should inject a space
1149                channel.insertChars([0x20]);
1150                channel.cc_MIDROW(b);
1151                logger.log("DEBUG", "MIDROW (" + numArrayToHexArray([a, b]) + ")");
1152                this.lastCmdA = a;
1153                this.lastCmdB = b;
1154                return true;
1155            }
1156            return false;
1157        },
1158        /**
1159         * Parse Preable Access Codes (Table 53).
1160         * @returns {Boolean} Tells if PAC found
1161         */
1162        parsePAC: function parsePAC(a, b) {
1163
1164            var chNr = null;
1165            var row = null;
1166
1167            var case1 = (0x11 <= a && a <= 0x17 || 0x19 <= a && a <= 0x1F) && 0x40 <= b && b <= 0x7F;
1168            var case2 = (a === 0x10 || a === 0x18) && 0x40 <= b && b <= 0x5F;
1169            if (!(case1 || case2)) {
1170                return false;
1171            }
1172
1173            chNr = a <= 0x17 ? 1 : 2;
1174
1175            if (0x40 <= b && b <= 0x5F) {
1176                row = chNr === 1 ? rowsLowCh1[a] : rowsLowCh2[a];
1177            } else {
1178                // 0x60 <= b <= 0x7F
1179                row = chNr === 1 ? rowsHighCh1[a] : rowsHighCh2[a];
1180            }
1181            var pacData = this.interpretPAC(row, b);
1182            var channel = this.channels[chNr - 1];
1183            channel.setPAC(pacData);
1184            this.lastCmdA = a;
1185            this.lastCmdB = b;
1186            this.currChNr = chNr;
1187            return true;
1188        },
1189
1190        /**
1191         * Interpret the second byte of the pac, and return the information.
1192         * @returns {Object} pacData with style parameters.
1193         */
1194        interpretPAC: function interpretPAC(row, byte) {
1195            var pacIndex = byte;
1196            var pacData = { color: null, italics: false, indent: null, underline: false, row: row };
1197
1198            if (byte > 0x5F) {
1199                pacIndex = byte - 0x60;
1200            } else {
1201                pacIndex = byte - 0x40;
1202            }
1203            pacData.underline = (pacIndex & 1) === 1;
1204            if (pacIndex <= 0xd) {
1205                pacData.color = ['white', 'green', 'blue', 'cyan', 'red', 'yellow', 'magenta', 'white'][Math.floor(pacIndex / 2)];
1206            } else if (pacIndex <= 0xf) {
1207                pacData.italics = true;
1208                pacData.color = 'white';
1209            } else {
1210                pacData.indent = Math.floor((pacIndex - 0x10) / 2) * 4;
1211            }
1212            return pacData; // Note that row has zero offset. The spec uses 1.
1213        },
1214
1215        /**
1216         * Parse characters.
1217         * @returns An array with 1 to 2 codes corresponding to chars, if found. null otherwise.
1218         */
1219        parseChars: function parseChars(a, b) {
1220
1221            var channelNr = null,
1222                charCodes = null,
1223                charCode1 = null,
1224                charCode2 = null;
1225
1226            if (a >= 0x19) {
1227                channelNr = 2;
1228                charCode1 = a - 8;
1229            } else {
1230                channelNr = 1;
1231                charCode1 = a;
1232            }
1233            if (0x11 <= charCode1 && charCode1 <= 0x13) {
1234                // Special character
1235                var oneCode = b;
1236                if (charCode1 === 0x11) {
1237                    oneCode = b + 0x50;
1238                } else if (charCode1 === 0x12) {
1239                    oneCode = b + 0x70;
1240                } else {
1241                    oneCode = b + 0x90;
1242                }
1243                logger.log("INFO", "Special char '" + getCharForByte(oneCode) + "' in channel " + channelNr);
1244                charCodes = [oneCode];
1245                this.lastCmdA = a;
1246                this.lastCmdB = b;
1247            } else if (0x20 <= a && a <= 0x7f) {
1248                charCodes = b === 0 ? [a] : [a, b];
1249                this.lastCmdA = null;
1250                this.lastCmdB = null;
1251            }
1252            if (charCodes) {
1253                var hexCodes = numArrayToHexArray(charCodes);
1254                logger.log("DEBUG", "Char codes =  " + hexCodes.join(","));
1255            }
1256            return charCodes;
1257        },
1258
1259        /**
1260        * Parse extended background attributes as well as new foreground color black.
1261        * @returns{Boolean} Tells if background attributes are found
1262        */
1263        parseBackgroundAttributes: function parseBackgroundAttributes(a, b) {
1264            var bkgData, index, chNr, channel;
1265
1266            var case1 = (a === 0x10 || a === 0x18) && 0x20 <= b && b <= 0x2f;
1267            var case2 = (a === 0x17 || a === 0x1f) && 0x2d <= b && b <= 0x2f;
1268            if (!(case1 || case2)) {
1269                return false;
1270            }
1271            bkgData = {};
1272            if (a === 0x10 || a === 0x18) {
1273                index = Math.floor((b - 0x20) / 2);
1274                bkgData.background = backgroundColors[index];
1275                if (b % 2 === 1) {
1276                    bkgData.background = bkgData.background + "_semi";
1277                }
1278            } else if (b === 0x2d) {
1279                bkgData.background = "transparent";
1280            } else {
1281                bkgData.foreground = "black";
1282                if (b === 0x2f) {
1283                    bkgData.underline = true;
1284                }
1285            }
1286            chNr = a < 0x18 ? 1 : 2;
1287            channel = this.channels[chNr - 1];
1288            channel.setBkgData(bkgData);
1289            this.lastCmdA = a;
1290            this.lastCmdB = b;
1291            return true;
1292        },
1293
1294        /**
1295         * Reset state of parser and its channels.
1296         */
1297        reset: function reset() {
1298            for (var i = 0; i < this.channels.length; i++) {
1299                if (this.channels[i]) {
1300                    this.channels[i].reset();
1301                }
1302            }
1303            this.lastCmdA = null;
1304            this.lastCmdB = null;
1305        },
1306
1307        /**
1308         * Trigger the generation of a cue, and the start of a new one if displayScreens are not empty.
1309         */
1310        cueSplitAtTime: function cueSplitAtTime(t) {
1311            for (var i = 0; i < this.channels.length; i++) {
1312                if (this.channels[i]) {
1313                    this.channels[i].cueSplitAtTime(t);
1314                }
1315            }
1316        }
1317    };
1318
1319    /**
1320     * Find ranges corresponding to SEA CEA-608 NALUS in sizeprepended NALU array.
1321     * @param {raw} dataView of binary data
1322     * @param {startPos} start position in raw
1323     * @param {size} total size of data in raw to consider
1324     * @returns 
1325     */
1326    var findCea608Nalus = function findCea608Nalus(raw, startPos, size) {
1327        var nalSize = 0,
1328            cursor = startPos,
1329            nalType = 0,
1330            cea608NaluRanges = [],
1331
1332        // Check SEI data according to ANSI-SCTE 128
1333        isCEA608SEI = function isCEA608SEI(payloadType, payloadSize, raw, pos) {
1334            if (payloadType !== 4 || payloadSize < 8) {
1335                return null;
1336            }
1337            var countryCode = raw.getUint8(pos);
1338            var providerCode = raw.getUint16(pos + 1);
1339            var userIdentifier = raw.getUint32(pos + 3);
1340            var userDataTypeCode = raw.getUint8(pos + 7);
1341            return countryCode == 0xB5 && providerCode == 0x31 && userIdentifier == 0x47413934 && userDataTypeCode == 0x3;
1342        };
1343        while (cursor < startPos + size) {
1344            nalSize = raw.getUint32(cursor);
1345            nalType = raw.getUint8(cursor + 4) & 0x1F;
vendor: 4,442 bytes, lines 1346-1476
1346            //console.log(time + "  NAL " + nalType);
1347            if (nalType === 6) {
1348                // SEI NAL Unit. The NAL header is the first byte
1349                //console.log("SEI NALU of size " + nalSize + " at time " + time);
1350                var pos = cursor + 5;
1351                var payloadType = -1;
1352                while (pos < cursor + 4 + nalSize - 1) {
1353                    // The last byte should be rbsp_trailing_bits
1354                    payloadType = 0;
1355                    var b = 0xFF;
1356                    while (b === 0xFF) {
1357                        b = raw.getUint8(pos);
1358                        payloadType += b;
1359                        pos++;
1360                    }
1361                    var payloadSize = 0;
1362                    b = 0xFF;
1363                    while (b === 0xFF) {
1364                        b = raw.getUint8(pos);
1365                        payloadSize += b;
1366                        pos++;
1367                    }
1368                    if (isCEA608SEI(payloadType, payloadSize, raw, pos)) {
1369                        //console.log("CEA608 SEI " + time + " " + payloadSize);
1370                        cea608NaluRanges.push([pos, payloadSize]);
1371                    }
1372                    pos += payloadSize;
1373                }
1374            }
1375            cursor += nalSize + 4;
1376        }
1377        return cea608NaluRanges;
1378    };
1379
1380    var extractCea608DataFromRange = function extractCea608DataFromRange(raw, cea608Range) {
1381        var pos = cea608Range[0];
1382        var fieldData = [[], []];
1383
1384        pos += 8; // Skip the identifier up to userDataTypeCode
1385        var ccCount = raw.getUint8(pos) & 0x1f;
1386        pos += 2; // Advance 1 and skip reserved byte
1387
1388        for (var i = 0; i < ccCount; i++) {
1389            var byte = raw.getUint8(pos);
1390            var ccValid = byte & 0x4;
1391            var ccType = byte & 0x3;
1392            pos++;
1393            var ccData1 = raw.getUint8(pos); // Keep parity bit
1394            pos++;
1395            var ccData2 = raw.getUint8(pos); // Keep parity bit
1396            pos++;
1397            if (ccValid && (ccData1 & 0x7f) + (ccData2 & 0x7f) !== 0) {
1398                //Check validity and non-empty data
1399                if (ccType === 0) {
1400                    fieldData[0].push(ccData1);
1401                    fieldData[0].push(ccData2);
1402                } else if (ccType === 1) {
1403                    fieldData[1].push(ccData1);
1404                    fieldData[1].push(ccData2);
1405                }
1406            }
1407        }
1408        return fieldData;
1409    };
1410
1411    exports.logger = logger;
1412    exports.PenState = PenState;
1413    exports.CaptionScreen = CaptionScreen;
1414    exports.Cea608Parser = Cea608Parser;
1415    exports.findCea608Nalus = findCea608Nalus;
1416    exports.extractCea608DataFromRange = extractCea608DataFromRange;
1417})(typeof exports === 'undefined' ? undefined.cea608parser = {} : exports);
1418
1419},{}],3:[function(_dereq_,module,exports){
1420/*
1421 *
1422 * Licensed under the Apache License, Version 2.0 (the "License");
1423 * you may not use this file except in compliance with the License.
1424 * You may obtain a copy of the License at
1425 *
1426 *     http://www.apache.org/licenses/LICENSE-2.0
1427 *
1428 * Unless required by applicable law or agreed to in writing, software
1429 * distributed under the License is distributed on an "AS IS" BASIS,
1430 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1431 * See the License for the specific language governing permissions and
1432 * limitations under the License.
1433 *
1434 * author Digital Primates
1435 * copyright dash-if 2012
1436 */
1437
1438/*
1439 * var parent,
1440 *     child,
1441 *     properties = [
1442                    {
1443                        name: 'profiles',
1444                        merge: false
1445                    }
1446                ];
1447 *
1448 * parent = {};
1449 * parent.name = "ParentNode";
1450 * parent.isRoor = false;
1451 * parent.isArray = false;
1452 * parent.children = [];
1453 * parent.properties = properties;
1454 *
1455 * child = {};
1456 * child.name = "ChildNode";
1457 * child.isRoor = false;
1458 * child.isArray = true;
1459 * child.children = null;
1460 * child.properties = properties;
1461 * parent.children.push(child);
1462 *
1463 */
1464
1465'use strict';
1466
1467Object.defineProperty(exports, '__esModule', {
1468    value: true
1469});
1470function ObjectIron(map) {
1471
1472    var lookup, len, i;
1473
1474    // create a list of top level items to search for
1475    lookup = [];
1476    for (i = 0, len = map.length; i < len; i += 1) {
1477        if (map[i].isRoot) {
1478            lookup.push("root");
1479        } else {
1480            lookup.push(map[i].name);
1481        }
1482    }
1483
1484    var mergeValues = function mergeValues(parentItem, childItem) {
1485        var name, parentValue, childValue;
1486
1487        if (parentItem === null || childItem === null) {
1488            return;
1489        }
1490
1491        for (name in parentItem) {
1492            if (parentItem.hasOwnProperty(name)) {
1493                if (!childItem.hasOwnProperty(name)) {
1494                    childItem[name] = parentItem[name];
1495                }
1496            }
1497        }
1498    },
1499        mapProperties = function mapProperties(properties, parent, child) {
1500        var i, len, property, parentValue, childValue;
1501
1502        if (properties === null || properties.length === 0) {
1503            return;
1504        }
1505
1506        for (i = 0, len = properties.length; i < len; i += 1) {
1507            property = properties[i];
1508
1509            if (parent.hasOwnProperty(property.name)) {
1510                if (child.hasOwnProperty(property.name)) {
1511                    // check to see if we should merge
1512                    if (property.merge) {
1513                        parentValue = parent[property.name];
1514                        childValue = child[property.name];
1515
1516                        // complex objects; merge properties
1517                        if (typeof parentValue === 'object' && typeof childValue === 'object') {
1518                            mergeValues(parentValue, childValue);
1519                        }
1520                        // simple objects; merge them together
1521                        else {
1522                                if (property.mergeFunction != null) {
1523                                    child[property.name] = property.mergeFunction(parentValue, childValue);
1524                                } else {
1525                                    child[property.name] = parentValue + childValue;
1526                                }
1527                            }
1528                    }
1529                } else {
1530                    // just add the property
1531                    child[property.name] = parent[property.name];
1532                }
1533            }
1534        }
1535    },
1536        mapItem = function mapItem(obj, node) {
1537        var item = obj,
1538            i,
1539            len,
1540            v,
1541            len2,
1542            array,
1543            childItem,
1544            childNode,
1545            property;
1546
1547        if (item.children === null || item.children.length === 0) {
1548            return;
1549        }
1550
1551        for (i = 0, len = item.children.length; i < len; i += 1) {
1552            childItem = item.children[i];
1553
1554            if (node.hasOwnProperty(childItem.name)) {
1555                if (childItem.isArray) {
1556                    array = node[childItem.name + "_asArray"];
1557                    for (v = 0, len2 = array.length; v < len2; v += 1) {
1558                        childNode = array[v];
1559                        mapProperties(item.properties, node, childNode);
1560                        mapItem(childItem, childNode);
1561                    }
1562                } else {
1563                    childNode = node[childItem.name];
1564                    mapProperties(item.properties, node, childNode);
1565                    mapItem(childItem, childNode);
1566                }
1567            }
1568        }
1569    },
1570        performMapping = function performMapping(source) {
1571        var i, len, pi, pp, item, node, array;
1572
1573        if (source === null) {
1574            return source;
1575        }
1576
1577        if (typeof source !== 'object') {
1578            return source;
1579        }
1580
1581        // first look to see if anything cares about the root node
1582        for (i = 0, len = lookup.length; i < len; i += 1) {
1583            if (lookup[i] === "root") {
1584                item = map[i];
1585                node = source;
1586                mapItem(item, node);
1587            }
1588        }
1589
1590        // iterate over the objects and look for any of the items we care about
1591        for (pp in source) {
1592            if (source.hasOwnProperty(pp) && pp != "__children") {
1593                pi = lookup.indexOf(pp);
1594                if (pi !== -1) {
1595                    item = map[pi];
1596
1597                    if (item.isArray) {
1598                        array = source[pp + "_asArray"];
1599                        for (i = 0, len = array.length; i < len; i += 1) {
1600                            node = array[i];
1601                            mapItem(item, node);
1602                        }
1603                    } else {
1604                        node = source[pp];
1605                        mapItem(item, node);
1606                    }
1607                }
1608                // now check this to see if he has any of the properties we care about
1609                performMapping(source[pp]);
1610            }
1611        }
1612
1613        return source;
1614    };
1615
1616    return {
1617        run: performMapping
1618    };
1619}
1620
1621exports['default'] = ObjectIron;
1622module.exports = exports['default'];
1623
1624},{}],4:[function(_dereq_,module,exports){
1625/*
1626 Copyright 2011-2013 Abdulla Abdurakhmanov
1627 Original sources are available at https://code.google.com/p/x2js/
1628
1629 Licensed under the Apache License, Version 2.0 (the "License");
vendor: 10,993 bytes, lines 1630-1905
1630 you may not use this file except in compliance with the License.
1631 You may obtain a copy of the License at
1632
1633 http://www.apache.org/licenses/LICENSE-2.0
1634
1635 Unless required by applicable law or agreed to in writing, software
1636 distributed under the License is distributed on an "AS IS" BASIS,
1637 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1638 See the License for the specific language governing permissions and
1639 limitations under the License.
1640 */
1641
1642/*
1643  Further modified for dashjs to:
1644  - keep track of children nodes in order in attribute __children.
1645  - add type conversion matchers
1646  - re-add ignoreRoot
1647  - allow zero-length attributePrefix
1648  - don't add white-space text nodes
1649  - remove explicit RequireJS support
1650*/
1651
1652"use strict";
1653
1654Object.defineProperty(exports, "__esModule", {
1655    value: true
1656});
1657function X2JS(config) {
1658    'use strict';
1659
1660    var VERSION = "1.2.0";
1661
1662    config = config || {};
1663    initConfigDefaults();
1664    initRequiredPolyfills();
1665
1666    function initConfigDefaults() {
1667        if (config.escapeMode === undefined) {
1668            config.escapeMode = true;
1669        }
1670
1671        if (config.attributePrefix === undefined) {
1672            config.attributePrefix = "_";
1673        }
1674
1675        config.arrayAccessForm = config.arrayAccessForm || "none";
1676        config.emptyNodeForm = config.emptyNodeForm || "text";
1677
1678        if (config.enableToStringFunc === undefined) {
1679            config.enableToStringFunc = true;
1680        }
1681        config.arrayAccessFormPaths = config.arrayAccessFormPaths || [];
1682        if (config.skipEmptyTextNodesForObj === undefined) {
1683            config.skipEmptyTextNodesForObj = true;
1684        }
1685        if (config.stripWhitespaces === undefined) {
1686            config.stripWhitespaces = true;
1687        }
1688        config.datetimeAccessFormPaths = config.datetimeAccessFormPaths || [];
1689
1690        if (config.useDoubleQuotes === undefined) {
1691            config.useDoubleQuotes = false;
1692        }
1693
1694        config.xmlElementsFilter = config.xmlElementsFilter || [];
1695        config.jsonPropertiesFilter = config.jsonPropertiesFilter || [];
1696
1697        if (config.keepCData === undefined) {
1698            config.keepCData = false;
1699        }
1700
1701        if (config.ignoreRoot === undefined) {
1702            config.ignoreRoot = false;
1703        }
1704    }
1705
1706    var DOMNodeTypes = {
1707        ELEMENT_NODE: 1,
1708        TEXT_NODE: 3,
1709        CDATA_SECTION_NODE: 4,
1710        COMMENT_NODE: 8,
1711        DOCUMENT_NODE: 9
1712    };
1713
1714    function initRequiredPolyfills() {}
1715
1716    function getNodeLocalName(node) {
1717        var nodeLocalName = node.localName;
1718        if (nodeLocalName == null) // Yeah, this is IE!!
1719            nodeLocalName = node.baseName;
1720        if (nodeLocalName == null || nodeLocalName == "") // =="" is IE too
1721            nodeLocalName = node.nodeName;
1722        return nodeLocalName;
1723    }
1724
1725    function getNodePrefix(node) {
1726        return node.prefix;
1727    }
1728
1729    function escapeXmlChars(str) {
1730        if (typeof str == "string") return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&apos;');else return str;
1731    }
1732
1733    function unescapeXmlChars(str) {
1734        return str.replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '"').replace(/&apos;/g, "'").replace(/&amp;/g, '&');
1735    }
1736
1737    function checkInStdFiltersArrayForm(stdFiltersArrayForm, obj, name, path) {
1738        var idx = 0;
1739        for (; idx < stdFiltersArrayForm.length; idx++) {
1740            var filterPath = stdFiltersArrayForm[idx];
1741            if (typeof filterPath === "string") {
1742                if (filterPath == path) break;
1743            } else if (filterPath instanceof RegExp) {
1744                if (filterPath.test(path)) break;
1745            } else if (typeof filterPath === "function") {
1746                if (filterPath(obj, name, path)) break;
1747            }
1748        }
1749        return idx != stdFiltersArrayForm.length;
1750    }
1751
1752    function toArrayAccessForm(obj, childName, path) {
1753        switch (config.arrayAccessForm) {
1754            case "property":
1755                if (!(obj[childName] instanceof Array)) obj[childName + "_asArray"] = [obj[childName]];else obj[childName + "_asArray"] = obj[childName];
1756                break;
1757            /*case "none":
1758                break;*/
1759        }
1760
1761        if (!(obj[childName] instanceof Array) && config.arrayAccessFormPaths.length > 0) {
1762            if (checkInStdFiltersArrayForm(config.arrayAccessFormPaths, obj, childName, path)) {
1763                obj[childName] = [obj[childName]];
1764            }
1765        }
1766    }
1767
1768    function fromXmlDateTime(prop) {
1769        // Implementation based up on http://stackoverflow.com/questions/8178598/xml-datetime-to-javascript-date-object
1770        // Improved to support full spec and optional parts
1771        var bits = prop.split(/[-T:+Z]/g);
1772
1773        var d = new Date(bits[0], bits[1] - 1, bits[2]);
1774        var secondBits = bits[5].split("\.");
1775        d.setHours(bits[3], bits[4], secondBits[0]);
1776        if (secondBits.length > 1) d.setMilliseconds(secondBits[1]);
1777
1778        // Get supplied time zone offset in minutes
1779        if (bits[6] && bits[7]) {
1780            var offsetMinutes = bits[6] * 60 + Number(bits[7]);
1781            var sign = /\d\d-\d\d:\d\d$/.test(prop) ? '-' : '+';
1782
1783            // Apply the sign
1784            offsetMinutes = 0 + (sign == '-' ? -1 * offsetMinutes : offsetMinutes);
1785
1786            // Apply offset and local timezone
1787            d.setMinutes(d.getMinutes() - offsetMinutes - d.getTimezoneOffset());
1788        } else if (prop.indexOf("Z", prop.length - 1) !== -1) {
1789            d = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds()));
1790        }
1791
1792        // d is now a local time equivalent to the supplied time
1793        return d;
1794    }
1795
1796    function checkFromXmlDateTimePaths(value, childName, fullPath) {
1797        if (config.datetimeAccessFormPaths.length > 0) {
1798            var path = fullPath.split("\.#")[0];
1799            if (checkInStdFiltersArrayForm(config.datetimeAccessFormPaths, value, childName, path)) {
1800                return fromXmlDateTime(value);
1801            } else return value;
1802        } else return value;
1803    }
1804
1805    function checkXmlElementsFilter(obj, childType, childName, childPath) {
1806        if (childType == DOMNodeTypes.ELEMENT_NODE && config.xmlElementsFilter.length > 0) {
1807            return checkInStdFiltersArrayForm(config.xmlElementsFilter, obj, childName, childPath);
1808        } else return true;
1809    }
1810
1811    function parseDOMChildren(node, path) {
1812        if (node.nodeType == DOMNodeTypes.DOCUMENT_NODE) {
1813            var result = new Object();
1814            var nodeChildren = node.childNodes;
1815            // Alternative for firstElementChild which is not supported in some environments
1816            for (var cidx = 0; cidx < nodeChildren.length; cidx++) {
1817                var child = nodeChildren[cidx];
1818                if (child.nodeType == DOMNodeTypes.ELEMENT_NODE) {
1819                    if (config.ignoreRoot) {
1820                        result = parseDOMChildren(child);
1821                    } else {
1822                        result = {};
1823                        var childName = getNodeLocalName(child);
1824                        result[childName] = parseDOMChildren(child);
1825                    }
1826                }
1827            }
1828            return result;
1829        } else if (node.nodeType == DOMNodeTypes.ELEMENT_NODE) {
1830            var result = new Object();
1831            result.__cnt = 0;
1832
1833            var children = [];
1834            var nodeChildren = node.childNodes;
1835
1836            // Children nodes
1837            for (var cidx = 0; cidx < nodeChildren.length; cidx++) {
1838                var child = nodeChildren[cidx];
1839                var childName = getNodeLocalName(child);
1840
1841                if (child.nodeType != DOMNodeTypes.COMMENT_NODE) {
1842                    var childPath = path + "." + childName;
1843                    if (checkXmlElementsFilter(result, child.nodeType, childName, childPath)) {
1844                        result.__cnt++;
1845                        if (result[childName] == null) {
1846                            var c = parseDOMChildren(child, childPath);
1847                            if (childName != "#text" || /[^\s]/.test(c)) {
1848                                var o = {};
1849                                o[childName] = c;
1850                                children.push(o);
1851                            }
1852                            result[childName] = c;
1853                            toArrayAccessForm(result, childName, childPath);
1854                        } else {
1855                            if (result[childName] != null) {
1856                                if (!(result[childName] instanceof Array)) {
1857                                    result[childName] = [result[childName]];
1858                                    toArrayAccessForm(result, childName, childPath);
1859                                }
1860                            }
1861
1862                            var c = parseDOMChildren(child, childPath);
1863                            if (childName != "#text" || /[^\s]/.test(c)) {
1864                                // Don't add white-space text nodes
1865                                var o = {};
1866                                o[childName] = c;
1867                                children.push(o);
1868                            }
1869                            result[childName][result[childName].length] = c;
1870                        }
1871                    }
1872                }
1873            }
1874
1875            result.__children = children;
1876
1877            // Attributes
1878            var nodeLocalName = getNodeLocalName(node);
1879            for (var aidx = 0; aidx < node.attributes.length; aidx++) {
1880                var attr = node.attributes[aidx];
1881                result.__cnt++;
1882
1883                var value2 = attr.value;
1884                for (var m = 0, ml = config.matchers.length; m < ml; m++) {
1885                    var matchobj = config.matchers[m];
1886                    if (matchobj.test(attr, nodeLocalName)) value2 = matchobj.converter(attr.value);
1887                }
1888
1889                result[config.attributePrefix + attr.name] = value2;
1890            }
1891
1892            // Node namespace prefix
1893            var nodePrefix = getNodePrefix(node);
1894            if (nodePrefix != null && nodePrefix != "") {
1895                result.__cnt++;
1896                result.__prefix = nodePrefix;
1897            }
1898
1899            if (result["#text"] != null) {
1900                result.__text = result["#text"];
1901                if (result.__text instanceof Array) {
1902                    result.__text = result.__text.join("\n");
1903                }
1904                //if(config.escapeMode)
1905                //	result.__text = unescapeXmlChars(result.__text);
vendor: 11,966 bytes, lines 1906-2189
1906                if (config.stripWhitespaces) result.__text = result.__text.trim();
1907                delete result["#text"];
1908                if (config.arrayAccessForm == "property") delete result["#text_asArray"];
1909                result.__text = checkFromXmlDateTimePaths(result.__text, childName, path + "." + childName);
1910            }
1911            if (result["#cdata-section"] != null) {
1912                result.__cdata = result["#cdata-section"];
1913                delete result["#cdata-section"];
1914                if (config.arrayAccessForm == "property") delete result["#cdata-section_asArray"];
1915            }
1916
1917            if (result.__cnt == 0 && config.emptyNodeForm == "text") {
1918                result = '';
1919            } else if (result.__cnt == 1 && result.__text != null) {
1920                result = result.__text;
1921            } else if (result.__cnt == 1 && result.__cdata != null && !config.keepCData) {
1922                result = result.__cdata;
1923            } else if (result.__cnt > 1 && result.__text != null && config.skipEmptyTextNodesForObj) {
1924                if (config.stripWhitespaces && result.__text == "" || result.__text.trim() == "") {
1925                    delete result.__text;
1926                }
1927            }
1928            delete result.__cnt;
1929
1930            if (config.enableToStringFunc && (result.__text != null || result.__cdata != null)) {
1931                result.toString = function () {
1932                    return (this.__text != null ? this.__text : '') + (this.__cdata != null ? this.__cdata : '');
1933                };
1934            }
1935
1936            return result;
1937        } else if (node.nodeType == DOMNodeTypes.TEXT_NODE || node.nodeType == DOMNodeTypes.CDATA_SECTION_NODE) {
1938            return node.nodeValue;
1939        }
1940    }
1941
1942    function startTag(jsonObj, element, attrList, closed) {
1943        var resultStr = "<" + (jsonObj != null && jsonObj.__prefix != null ? jsonObj.__prefix + ":" : "") + element;
1944        if (attrList != null) {
1945            for (var aidx = 0; aidx < attrList.length; aidx++) {
1946                var attrName = attrList[aidx];
1947                var attrVal = jsonObj[attrName];
1948                if (config.escapeMode) attrVal = escapeXmlChars(attrVal);
1949                resultStr += " " + attrName.substr(config.attributePrefix.length) + "=";
1950                if (config.useDoubleQuotes) resultStr += '"' + attrVal + '"';else resultStr += "'" + attrVal + "'";
1951            }
1952        }
1953        if (!closed) resultStr += ">";else resultStr += "/>";
1954        return resultStr;
1955    }
1956
1957    function endTag(jsonObj, elementName) {
1958        return "</" + (jsonObj.__prefix != null ? jsonObj.__prefix + ":" : "") + elementName + ">";
1959    }
1960
1961    function endsWith(str, suffix) {
1962        return str.indexOf(suffix, str.length - suffix.length) !== -1;
1963    }
1964
1965    function jsonXmlSpecialElem(jsonObj, jsonObjField) {
1966        if (config.arrayAccessForm == "property" && endsWith(jsonObjField.toString(), "_asArray") || jsonObjField.toString().indexOf(config.attributePrefix) == 0 || jsonObjField.toString().indexOf("__") == 0 || jsonObj[jsonObjField] instanceof Function) return true;else return false;
1967    }
1968
1969    function jsonXmlElemCount(jsonObj) {
1970        var elementsCnt = 0;
1971        if (jsonObj instanceof Object) {
1972            for (var it in jsonObj) {
1973                if (jsonXmlSpecialElem(jsonObj, it)) continue;
1974                elementsCnt++;
1975            }
1976        }
1977        return elementsCnt;
1978    }
1979
1980    function checkJsonObjPropertiesFilter(jsonObj, propertyName, jsonObjPath) {
1981        return config.jsonPropertiesFilter.length == 0 || jsonObjPath == "" || checkInStdFiltersArrayForm(config.jsonPropertiesFilter, jsonObj, propertyName, jsonObjPath);
1982    }
1983
1984    function parseJSONAttributes(jsonObj) {
1985        var attrList = [];
1986        if (jsonObj instanceof Object) {
1987            for (var ait in jsonObj) {
1988                if (ait.toString().indexOf("__") == -1 && ait.toString().indexOf(config.attributePrefix) == 0) {
1989                    attrList.push(ait);
1990                }
1991            }
1992        }
1993        return attrList;
1994    }
1995
1996    function parseJSONTextAttrs(jsonTxtObj) {
1997        var result = "";
1998
1999        if (jsonTxtObj.__cdata != null) {
2000            result += "<![CDATA[" + jsonTxtObj.__cdata + "]]>";
2001        }
2002
2003        if (jsonTxtObj.__text != null) {
2004            if (config.escapeMode) result += escapeXmlChars(jsonTxtObj.__text);else result += jsonTxtObj.__text;
2005        }
2006        return result;
2007    }
2008
2009    function parseJSONTextObject(jsonTxtObj) {
2010        var result = "";
2011
2012        if (jsonTxtObj instanceof Object) {
2013            result += parseJSONTextAttrs(jsonTxtObj);
2014        } else if (jsonTxtObj != null) {
2015            if (config.escapeMode) result += escapeXmlChars(jsonTxtObj);else result += jsonTxtObj;
2016        }
2017
2018        return result;
2019    }
2020
2021    function getJsonPropertyPath(jsonObjPath, jsonPropName) {
2022        if (jsonObjPath === "") {
2023            return jsonPropName;
2024        } else return jsonObjPath + "." + jsonPropName;
2025    }
2026
2027    function parseJSONArray(jsonArrRoot, jsonArrObj, attrList, jsonObjPath) {
2028        var result = "";
2029        if (jsonArrRoot.length == 0) {
2030            result += startTag(jsonArrRoot, jsonArrObj, attrList, true);
2031        } else {
2032            for (var arIdx = 0; arIdx < jsonArrRoot.length; arIdx++) {
2033                result += startTag(jsonArrRoot[arIdx], jsonArrObj, parseJSONAttributes(jsonArrRoot[arIdx]), false);
2034                result += parseJSONObject(jsonArrRoot[arIdx], getJsonPropertyPath(jsonObjPath, jsonArrObj));
2035                result += endTag(jsonArrRoot[arIdx], jsonArrObj);
2036            }
2037        }
2038        return result;
2039    }
2040
2041    function parseJSONObject(jsonObj, jsonObjPath) {
2042        var result = "";
2043
2044        var elementsCnt = jsonXmlElemCount(jsonObj);
2045
2046        if (elementsCnt > 0) {
2047            for (var it in jsonObj) {
2048
2049                if (jsonXmlSpecialElem(jsonObj, it) || jsonObjPath != "" && !checkJsonObjPropertiesFilter(jsonObj, it, getJsonPropertyPath(jsonObjPath, it))) continue;
2050
2051                var subObj = jsonObj[it];
2052
2053                var attrList = parseJSONAttributes(subObj);
2054
2055                if (subObj == null || subObj == undefined) {
2056                    result += startTag(subObj, it, attrList, true);
2057                } else if (subObj instanceof Object) {
2058
2059                    if (subObj instanceof Array) {
2060                        result += parseJSONArray(subObj, it, attrList, jsonObjPath);
2061                    } else if (subObj instanceof Date) {
2062                        result += startTag(subObj, it, attrList, false);
2063                        result += subObj.toISOString();
2064                        result += endTag(subObj, it);
2065                    } else {
2066                        var subObjElementsCnt = jsonXmlElemCount(subObj);
2067                        if (subObjElementsCnt > 0 || subObj.__text != null || subObj.__cdata != null) {
2068                            result += startTag(subObj, it, attrList, false);
2069                            result += parseJSONObject(subObj, getJsonPropertyPath(jsonObjPath, it));
2070                            result += endTag(subObj, it);
2071                        } else {
2072                            result += startTag(subObj, it, attrList, true);
2073                        }
2074                    }
2075                } else {
2076                    result += startTag(subObj, it, attrList, false);
2077                    result += parseJSONTextObject(subObj);
2078                    result += endTag(subObj, it);
2079                }
2080            }
2081        }
2082        result += parseJSONTextObject(jsonObj);
2083
2084        return result;
2085    }
2086
2087    this.parseXmlString = function (xmlDocStr) {
2088        var isIEParser = window.ActiveXObject || "ActiveXObject" in window;
2089        if (xmlDocStr === undefined) {
2090            return null;
2091        }
2092        var xmlDoc;
2093        if (window.DOMParser) {
2094            var parser = new window.DOMParser();
2095            var parsererrorNS = null;
2096            // IE9+ now is here
2097            if (!isIEParser) {
2098                try {
2099                    parsererrorNS = parser.parseFromString("INVALID", "text/xml").getElementsByTagName("parsererror")[0].namespaceURI;
2100                } catch (err) {
2101                    parsererrorNS = null;
2102                }
2103            }
2104            try {
2105                xmlDoc = parser.parseFromString(xmlDocStr, "text/xml");
2106                if (parsererrorNS != null && xmlDoc.getElementsByTagNameNS(parsererrorNS, "parsererror").length > 0) {
2107                    //throw new Error('Error parsing XML: '+xmlDocStr);
2108                    xmlDoc = null;
2109                }
2110            } catch (err) {
2111                xmlDoc = null;
2112            }
2113        } else {
2114            // IE :(
2115            if (xmlDocStr.indexOf("<?") == 0) {
2116                xmlDocStr = xmlDocStr.substr(xmlDocStr.indexOf("?>") + 2);
2117            }
2118            xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
2119            xmlDoc.async = "false";
2120            xmlDoc.loadXML(xmlDocStr);
2121        }
2122        return xmlDoc;
2123    };
2124
2125    this.asArray = function (prop) {
2126        if (prop === undefined || prop == null) return [];else if (prop instanceof Array) return prop;else return [prop];
2127    };
2128
2129    this.toXmlDateTime = function (dt) {
2130        if (dt instanceof Date) return dt.toISOString();else if (typeof dt === 'number') return new Date(dt).toISOString();else return null;
2131    };
2132
2133    this.asDateTime = function (prop) {
2134        if (typeof prop == "string") {
2135            return fromXmlDateTime(prop);
2136        } else return prop;
2137    };
2138
2139    this.xml2json = function (xmlDoc) {
2140        return parseDOMChildren(xmlDoc);
2141    };
2142
2143    this.xml_str2json = function (xmlDocStr) {
2144        var xmlDoc = this.parseXmlString(xmlDocStr);
2145        if (xmlDoc != null) return this.xml2json(xmlDoc);else return null;
2146    };
2147
2148    this.json2xml_str = function (jsonObj) {
2149        return parseJSONObject(jsonObj, "");
2150    };
2151
2152    this.json2xml = function (jsonObj) {
2153        var xmlDocStr = this.json2xml_str(jsonObj);
2154        return this.parseXmlString(xmlDocStr);
2155    };
2156
2157    this.getVersion = function () {
2158        return VERSION;
2159    };
2160}
2161
2162exports["default"] = X2JS;
2163module.exports = exports["default"];
2164
2165},{}],5:[function(_dereq_,module,exports){
2166/**
2167 * The copyright in this software is being made available under the BSD License,
2168 * included below. This software may be subject to other third party and contributor
2169 * rights, including patent rights, and no such rights are granted under this license.
2170 *
2171 * Copyright (c) 2013, Dash Industry Forum.
2172 * All rights reserved.
2173 *
2174 * Redistribution and use in source and binary forms, with or without modification,
2175 * are permitted provided that the following conditions are met:
2176 *  * Redistributions of source code must retain the above copyright notice, this
2177 *  list of conditions and the following disclaimer.
2178 *  * Redistributions in binary form must reproduce the above copyright notice,
2179 *  this list of conditions and the following disclaimer in the documentation and/or
2180 *  other materials provided with the distribution.
2181 *  * Neither the name of Dash Industry Forum nor the names of its
2182 *  contributors may be used to endorse or promote products derived from this software
2183 *  without specific prior written permission.
2184 *
2185 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
2186 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2187 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2188 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
2189 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
2189INCLUDING, BUT
2190 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2191 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2192 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2193 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2194 *  POSSIBILITY OF SUCH DAMAGE.
2195 */
2196
2197'use strict';
2198
2199Object.defineProperty(exports, '__esModule', {
2200  value: true
2201});
2202
2203function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
2204
2205_dereq_(6);
2206
2207var _srcStreamingMetricsMetricsReporting = _dereq_(116);
2208
2209var _srcStreamingMetricsMetricsReporting2 = _interopRequireDefault(_srcStreamingMetricsMetricsReporting);
2210
2211var _srcStreamingProtectionProtection = _dereq_(147);
2212
2213var _srcStreamingProtectionProtection2 = _interopRequireDefault(_srcStreamingProtectionProtection);
2214
2215var _srcStreamingMediaPlayerFactory = _dereq_(95);
2216
2217var _srcStreamingMediaPlayerFactory2 = _interopRequireDefault(_srcStreamingMediaPlayerFactory);
2218
2219dashjs.Protection = _srcStreamingProtectionProtection2['default'];
2220dashjs.MetricsReporting = _srcStreamingMetricsMetricsReporting2['default'];
2221dashjs.MediaPlayerFactory = _srcStreamingMediaPlayerFactory2['default'];
2222
2223exports['default'] = dashjs;
2224exports.Protection = _srcStreamingProtectionProtection2['default'];
2225exports.MetricsReporting = _srcStreamingMetricsMetricsReporting2['default'];
2226exports.MediaPlayerFactory = _srcStreamingMediaPlayerFactory2['default'];
2227
2228},{"116":116,"147":147,"6":6,"95":95}],6:[function(_dereq_,module,exports){
2229(function (global){
2230/**
2231 * The copyright in this software is being made available under the BSD License,
2232 * included below. This software may be subject to other third party and contributor
2233 * rights, including patent rights, and no such rights are granted under this license.
2234 *
2235 * Copyright (c) 2013, Dash Industry Forum.
2236 * All rights reserved.
2237 *
2238 * Redistribution and use in source and binary forms, with or without modification,
2239 * are permitted provided that the following conditions are met:
2240 *  * Redistributions of source code must retain the above copyright notice, this
2241 *  list of conditions and the following disclaimer.
2242 *  * Redistributions in binary form must reproduce the above copyright notice,
2243 *  this list of conditions and the following disclaimer in the documentation and/or
2244 *  other materials provided with the distribution.
2245 *  * Neither the name of Dash Industry Forum nor the names of its
2246 *  contributors may be used to endorse or promote products derived from this software
2247 *  without specific prior written permission.
2248 *
2249 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
2250 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2251 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2252 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
2253 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2254 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2255 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2256 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2257 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2258 *  POSSIBILITY OF SUCH DAMAGE.
2259 */
2260
2261'use strict';
2262
2263Object.defineProperty(exports, '__esModule', {
2264  value: true
2265});
2266
2267function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
2268
2269var _srcStreamingMediaPlayer = _dereq_(93);
2270
2271var _srcStreamingMediaPlayer2 = _interopRequireDefault(_srcStreamingMediaPlayer);
2272
2273var _srcCoreFactoryMaker = _dereq_(51);
2274
2275var _srcCoreFactoryMaker2 = _interopRequireDefault(_srcCoreFactoryMaker);
2276
2277var _srcCoreVersion = _dereq_(52);
2278
2279// Shove both of these into the global scope
2280var context = typeof window !== 'undefined' && window || global;
2281
2282var dashjs = context.dashjs;
2283if (!dashjs) {
2284  dashjs = context.dashjs = {};
2285}
2286
2287dashjs.MediaPlayer = _srcStreamingMediaPlayer2['default'];
2288dashjs.FactoryMaker = _srcCoreFactoryMaker2['default'];
2289dashjs.Version = (0, _srcCoreVersion.getVersionString)();
2290
2291exports['default'] = dashjs;
2292exports.MediaPlayer = _srcStreamingMediaPlayer2['default'];
2293exports.FactoryMaker = _srcCoreFactoryMaker2['default'];
2294
2295}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
2296
2297},{"51":51,"52":52,"93":93}],7:[function(_dereq_,module,exports){
2298var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
2298+/';
2299
2300;(function (exports) {
2301	'use strict';
2302
2303  var Arr = (typeof Uint8Array !== 'undefined')
2304    ? Uint8Array
2305    : Array
2306
2307	var PLUS   = '+'.charCodeAt(0)
2308	var SLASH  = '/'.charCodeAt(0)
2309	var NUMBER = '0'.charCodeAt(0)
2310	var LOWER  = 'a'.charCodeAt(0)
2311	var UPPER  = 'A'.charCodeAt(0)
2312	var PLUS_URL_SAFE = '-'.charCodeAt(0)
2313	var SLASH_URL_SAFE = '_'.charCodeAt(0)
2314
2315	function decode (elt) {
2316		var code = elt.charCodeAt(0)
2317		if (code === PLUS ||
2318		    code === PLUS_URL_SAFE)
2319			return 62 // '+'
2320		if (code === SLASH ||
2321		    code === SLASH_URL_SAFE)
2322			return 63 // '/'
2323		if (code < NUMBER)
2324			return -1 //no match
2325		if (code < NUMBER + 10)
2326			return code - NUMBER + 26 + 26
2327		if (code < UPPER + 26)
2328			return code - UPPER
2329		if (code < LOWER + 26)
2330			return code - LOWER + 26
2331	}
2332
2333	function b64ToByteArray (b64) {
2334		var i, j, l, tmp, placeHolders, arr
2335
2336		if (b64.length % 4 > 0) {
2337			throw new Error('Invalid string. Length must be a multiple of 4')
2338		}
2339
2340		// the number of equal signs (place holders)
2341		// if there are two placeholders, than the two characters before it
2342		// represent one byte
2343		// if there is only one, then the three characters before it represent 2 bytes
2344		// this is just a cheap hack to not do indexOf twice
2345		var len = b64.length
2346		placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
2347
2348		// base64 is 4/3 + up to two characters of the original data
2349		arr = new Arr(b64.length * 3 / 4 - placeHolders)
2350
2351		// if there are placeholders, only get up to the last complete 4 chars
2352		l = placeHolders > 0 ? b64.length - 4 : b64.length
2353
2354		var L = 0
2355
2356		function push (v) {
2357			arr[L++] = v
2358		}
2359
2360		for (i = 0, j = 0; i < l; i += 4, j += 3) {
2361			tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
2362			push((tmp & 0xFF0000) >> 16)
2363			push((tmp & 0xFF00) >> 8)
2364			push(tmp & 0xFF)
2365		}
2366
2367		if (placeHolders === 2) {
2368			tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
2369			push(tmp & 0xFF)
2370		} else if (placeHolders === 1) {
2371			tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
2372			push((tmp >> 8) & 0xFF)
2373			push(tmp & 0xFF)
2374		}
2375
2376		return arr
2377	}
2378
2379	function uint8ToBase64 (uint8) {
2380		var i,
2381			extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
2382			output = "",
2383			temp, length
2384
2385		function encode (num) {
2386			return lookup.charAt(num)
2387		}
2388
2389		function tripletToBase64 (num) {
2390			return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
2391		}
2392
2393		// go through the array every three bytes, we'll deal with trailing stuff later
2394		for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
2395			temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
2396			output += tripletToBase64(temp)
2397		}
2398
2399		// pad the end with zeros, but make sure to not forget the extra bytes
2400		switch (extraBytes) {
2401			case 1:
2402				temp = uint8[uint8.length - 1]
2403				output += encode(temp >> 2)
2404				output += encode((temp << 4) & 0x3F)
2405				output += '=='
2406				break
2407			case 2:
2408				temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
2409				output += encode(temp >> 10)
2410				output += encode((temp >> 4) & 0x3F)
2411				output += encode((temp << 2) & 0x3F)
2412				output += '='
2413				break
2414		}
2415
2416		return output
2417	}
2418
2419	exports.toByteArray = b64ToByteArray
2420	exports.fromByteArray = uint8ToBase64
2421}(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
2422
2423},{}],8:[function(_dereq_,module,exports){
2424
2425},{}],9:[function(_dereq_,module,exports){
2426// Copyright Joyent, Inc. and other Node contributors.
2427//
2428// Permission is hereby granted, free of charge, to any person obtaining a
2429// copy of this software and associated documentation files (the
2430// "Software"), to deal in the Software without restriction, including
2431// without limitation the rights to use, copy, modify, merge, publish,
2432// distribute, sublicense, and/or sell copies of the Software, and to permit
2433// persons to whom the Software is furnished to do so, subject to the
2434// following conditions:
2435//
2436// The above copyright notice and this permission notice shall be included
2437// in all copies or substantial portions of the Software.
2438//
2439// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2440// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2441// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
2442// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
2443// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
2444// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
2445// USE OR OTHER DEALINGS IN THE SOFTWARE.
2446
2447var Buffer = _dereq_(10).Buffer;
2448
2449var isBufferEncoding = Buffer.isEncoding
2450  || function(encoding) {
2451       switch (encoding && encoding.toLowerCase()) {
2452         case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true;
2453         default: return false;
2454       }
2455     }
2456
2457
2458function assertEncoding(encoding) {
2459  if (encoding && !isBufferEncoding(encoding)) {
2460    throw new Error('Unknown encoding: ' + encoding);
2461  }
2462}
2463
2464// StringDecoder provides an interface for efficiently splitting a series of
2465// buffers into a series of JS strings without breaking apart multi-byte
2466// characters. CESU-8 is handled as part of the UTF-8 encoding.
2467//
2468// @TODO Handling all encodings inside a single object makes it very difficult
2469// to reason about this code, so it should be split up in the future.
2470// @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code
2471// points as used by CESU-8.
2472var StringDecoder = exports.StringDecoder = function(encoding) {
2473  this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, '');
2474  assertEncoding(encoding);
2475  switch (this.encoding) {
2476    case 'utf8':
2477      // CESU-8 represents each of Surrogate Pair by 3-bytes
2478      this.surrogateSize = 3;
2479      break;
2480    case 'ucs2':
2481    case 'utf16le':
2482      // UTF-16 represents each of Surrogate Pair by 2-bytes
2483      this.surrogateSize = 2;
2484      this.detectIncompleteChar = utf16DetectIncompleteChar;
2485      break;
2486    case 'base64':
2487      // Base-64 stores 3 bytes in 4 chars, and pads the remainder.
2488      this.surrogateSize = 3;
2489      this.detectIncompleteChar = base64DetectIncompleteChar;
2490      break;
2491    default:
2492      this.write = passThroughWrite;
2493      return;
2494  }
2495
2496  // Enough space to store all bytes of a single character. UTF-8 needs 4
2497  // bytes, but CESU-8 may require up to 6 (3 bytes per surrogate).
2498  this.charBuffer = new Buffer(6);
2499  // Number of bytes received for the current incomplete multi-byte character.
2500  this.charReceived = 0;
2501  // Number of bytes expected for the current incomplete multi-byte character.
2502  this.charLength = 0;
2503};
2504
2505
2506// write decodes the given buffer and returns it as JS string that is
2507// guaranteed to not contain any partial multi-byte characters. Any partial
vendor: 5,462 bytes, lines 2508-2683
2508// character found at the end of the buffer is buffered up, and will be
2509// returned when calling write again with the remaining bytes.
2510//
2511// Note: Converting a Buffer containing an orphan surrogate to a String
2512// currently works, but converting a String to a Buffer (via `new Buffer`, or
2513// Buffer#write) will replace incomplete surrogates with the unicode
2514// replacement character. See https://codereview.chromium.org/121173009/ .
2515StringDecoder.prototype.write = function(buffer) {
2516  var charStr = '';
2517  // if our last write ended with an incomplete multibyte character
2518  while (this.charLength) {
2519    // determine how many remaining bytes this buffer has to offer for this char
2520    var available = (buffer.length >= this.charLength - this.charReceived) ?
2521        this.charLength - this.charReceived :
2522        buffer.length;
2523
2524    // add the new bytes to the char buffer
2525    buffer.copy(this.charBuffer, this.charReceived, 0, available);
2526    this.charReceived += available;
2527
2528    if (this.charReceived < this.charLength) {
2529      // still not enough chars in this buffer? wait for more ...
2530      return '';
2531    }
2532
2533    // remove bytes belonging to the current character from the buffer
2534    buffer = buffer.slice(available, buffer.length);
2535
2536    // get the character that was split
2537    charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding);
2538
2539    // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
2540    var charCode = charStr.charCodeAt(charStr.length - 1);
2541    if (charCode >= 0xD800 && charCode <= 0xDBFF) {
2542      this.charLength += this.surrogateSize;
2543      charStr = '';
2544      continue;
2545    }
2546    this.charReceived = this.charLength = 0;
2547
2548    // if there are no more bytes in this buffer, just emit our char
2549    if (buffer.length === 0) {
2550      return charStr;
2551    }
2552    break;
2553  }
2554
2555  // determine and set charLength / charReceived
2556  this.detectIncompleteChar(buffer);
2557
2558  var end = buffer.length;
2559  if (this.charLength) {
2560    // buffer the incomplete character bytes we got
2561    buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end);
2562    end -= this.charReceived;
2563  }
2564
2565  charStr += buffer.toString(this.encoding, 0, end);
2566
2567  var end = charStr.length - 1;
2568  var charCode = charStr.charCodeAt(end);
2569  // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
2570  if (charCode >= 0xD800 && charCode <= 0xDBFF) {
2571    var size = this.surrogateSize;
2572    this.charLength += size;
2573    this.charReceived += size;
2574    this.charBuffer.copy(this.charBuffer, size, 0, size);
2575    buffer.copy(this.charBuffer, 0, 0, size);
2576    return charStr.substring(0, end);
2577  }
2578
2579  // or just emit the charStr
2580  return charStr;
2581};
2582
2583// detectIncompleteChar determines if there is an incomplete UTF-8 character at
2584// the end of the given buffer. If so, it sets this.charLength to the byte
2585// length that character, and sets this.charReceived to the number of bytes
2586// that are available for this character.
2587StringDecoder.prototype.detectIncompleteChar = function(buffer) {
2588  // determine how many bytes we have to check at the end of this buffer
2589  var i = (buffer.length >= 3) ? 3 : buffer.length;
2590
2591  // Figure out if one of the last i bytes of our buffer announces an
2592  // incomplete char.
2593  for (; i > 0; i--) {
2594    var c = buffer[buffer.length - i];
2595
2596    // See http://en.wikipedia.org/wiki/UTF-8#Description
2597
2598    // 110XXXXX
2599    if (i == 1 && c >> 5 == 0x06) {
2600      this.charLength = 2;
2601      break;
2602    }
2603
2604    // 1110XXXX
2605    if (i <= 2 && c >> 4 == 0x0E) {
2606      this.charLength = 3;
2607      break;
2608    }
2609
2610    // 11110XXX
2611    if (i <= 3 && c >> 3 == 0x1E) {
2612      this.charLength = 4;
2613      break;
2614    }
2615  }
2616  this.charReceived = i;
2617};
2618
2619StringDecoder.prototype.end = function(buffer) {
2620  var res = '';
2621  if (buffer && buffer.length)
2622    res = this.write(buffer);
2623
2624  if (this.charReceived) {
2625    var cr = this.charReceived;
2626    var buf = this.charBuffer;
2627    var enc = this.encoding;
2628    res += buf.slice(0, cr).toString(enc);
2629  }
2630
2631  return res;
2632};
2633
2634function passThroughWrite(buffer) {
2635  return buffer.toString(this.encoding);
2636}
2637
2638function utf16DetectIncompleteChar(buffer) {
2639  this.charReceived = buffer.length % 2;
2640  this.charLength = this.charReceived ? 2 : 0;
2641}
2642
2643function base64DetectIncompleteChar(buffer) {
2644  this.charReceived = buffer.length % 3;
2645  this.charLength = this.charReceived ? 3 : 0;
2646}
2647
2648},{"10":10}],10:[function(_dereq_,module,exports){
2649(function (global){
2650/*!
2651 * The buffer module from node.js, for the browser.
2652 *
2653 * @author   Feross Aboukhadijeh <[email protected]> <http://feross.org>
2654 * @license  MIT
2655 */
2656/* eslint-disable no-proto */
2657
2658'use strict'
2659
2660var base64 = _dereq_(7)
2661var ieee754 = _dereq_(17)
2662var isArray = _dereq_(27)
2663
2664exports.Buffer = Buffer
2665exports.SlowBuffer = SlowBuffer
2666exports.INSPECT_MAX_BYTES = 50
2667Buffer.poolSize = 8192 // not used by this implementation
2668
2669var rootParent = {}
2670
2671/**
2672 * If `Buffer.TYPED_ARRAY_SUPPORT`:
2673 *   === true    Use Uint8Array implementation (fastest)
2674 *   === false   Use Object implementation (most compatible, even IE6)
2675 *
2676 * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
2677 * Opera 11.6+, iOS 4.2+.
2678 *
2679 * Due to various browser bugs, sometimes the Object implementation will be used even
2680 * when the browser supports typed arrays.
2681 *
2682 * Note:
2683 *
2684 *   - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
2685 *     See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
2686 *
2687 *   - Safari 5-7 lacks support for changing the `Object.prototype.constructor` property
2688 *     on objects.
2689 *
2690 *   - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
2691 *
2692 *   - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
2693 *     incorrect length in some situations.
2694
2695 * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
2696 * get the Object implementation, which is slower but behaves correctly.
2697 */
2698Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined
2699  ? global.TYPED_ARRAY_SUPPORT
2700  : typedArraySupport()
2701
2702function typedArraySupport () {
2703  function Bar () {}
2704  try {
2705    var arr = new Uint8Array(1)
2706    arr.foo = function () { return 42 }
2707    arr.constructor = Bar
2708    return arr.foo() === 42 && // typed array instances can be augmented
2709        arr.constructor === Bar && // constructor can be set
2710        typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
2711        arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
2712  } catch (e) {
2713    return false
2714  }
2715}
2716
2717function kMaxLength () {
2718  return Buffer.TYPED_ARRAY_SUPPORT
2719    ? 0x7fffffff
2720    : 0x3fffffff
2721}
2722
2723/**
2724 * Class: Buffer
2725 * =============
2726 *
2727 * The Buffer constructor returns instances of `Uint8Array` that are augmented
2728 * with function properties for all the node `Buffer` API functions. We use
2729 * `Uint8Array` so that square bracket notation works as expected -- it returns
2730 * a single octet.
2731 *
2732 * By augmenting the instances, we can avoid modifying the `Uint8Array`
2733 * prototype.
2734 */
2735function Buffer (arg) {
2736  if (!(this instanceof Buffer)) {
2737    // Avoid going through an ArgumentsAdaptorTrampoline in the common case.
2738    if (arguments.length > 1) return new Buffer(arg, arguments[1])
2739    return new Buffer(arg)
2740  }
2741
2742  if (!Buffer.TYPED_ARRAY_SUPPORT) {
2743    this.length = 0
2744    this.parent = undefined
2745  }
2746
2747  // Common case.
2748  if (typeof arg === 'number') {
2749    return fromNumber(this, arg)
2750  }
2751
2752  // Slightly less common case.
2753  if (typeof arg === 'string') {
2754    return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8')
2755  }
2756
2757  // Unusual.
2758  return fromObject(this, arg)
2759}
2760
2761function fromNumber (that, length) {
2762  that = allocate(that, length < 0 ? 0 : checked(length) | 0)
2763  if (!Buffer.TYPED_ARRAY_SUPPORT) {
2764    for (var i = 0; i < length; i++) {
2765      that[i] = 0
2766    }
2767  }
2768  return that
2769}
2770
2771function fromString (that, string, encoding) {
2772  if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8'
2773
2774  // Assumption: byteLength() return value is always < kMaxLength.
2775  var length = byteLength(string, encoding) | 0
2776  that = allocate(that, length)
2777
2778  that.write(string, encoding)
2779  return that
2780}
2781
2782function fromObject (that, object) {
2783  if (Buffer.isBuffer(object)) return fromBuffer(that, object)
2784
2785  if (isArray(object)) return fromArray(that, object)
2786
2787  if (object == null) {
2788    throw new TypeError('must start with number, buffer, array or string')
2789  }
2790
2791  if (typeof ArrayBuffer !== 'undefined') {
2792    if (object.buffer instanceof ArrayBuffer) {
2793      return fromTypedArray(that, object)
2794    }
2795    if (object instanceof ArrayBuffer) {
2796      return fromArrayBuffer(that, object)
2797    }
2798  }
2799
2800  if (object.length) return fromArrayLike(that, object)
2801
2802  return fromJsonObject(that, object)
2803}
2804
2805function fromBuffer (that, buffer) {
2806  var length = checked(buffer.length) | 0
2807  that = allocate(that, length)
2808  buffer.copy(that, 0, 0, length)
2809  return that
2810}
2811
2812function fromArray (that, array) {
2813  var length = checked(array.length) | 0
2814  that = allocate(that, length)
2815  for (var i = 0; i < length; i += 1) {
2816    that[i] = array[i] & 255
2817  }
2818  return that
2819}
2820
2821// Duplicate of fromArray() to keep fromArray() monomorphic.
2822function fromTypedArray (that, array) {
2823  var length = checked(array.length) | 0
2824  that = allocate(that, length)
2825  // Truncating the elements is probably not what people expect from typed
2826  // arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior
2827  // of the old Buffer constructor.
2828  for (var i = 0; i < length; i += 1) {
2829    that[i] = array[i] & 255
2830  }
2831  return that
2832}
2833
2834function fromArrayBuffer (that, array) {
2835  if (Buffer.TYPED_ARRAY_SUPPORT) {
2836    // Return an augmented `Uint8Array` instance, for best performance
2837    array.byteLength
2838    that = Buffer._augment(new Uint8Array(array))
2839  } else {
2840    // Fallback: Return an object instance of the Buffer class
2841    that = fromTypedArray(that, new Uint8Array(array))
2842  }
2843  return that
2844}
2845
2846function fromArrayLike (that, array) {
2847  var length = checked(array.length) | 0
2848  that = allocate(that, length)
2849  for (var i = 0; i < length; i += 1) {
2850    that[i] = array[i] & 255
2851  }
2852  return that
2853}
2854
2855// Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object.
2856// Returns a zero-length buffer for inputs that don't conform to the spec.
2857function fromJsonObject (that, object) {
2858  var array
2859  var length = 0
2860
2861  if (object.type === 'Buffer' && isArray(object.data)) {
2862    array = object.data
2863    length = checked(array.length) | 0
2864  }
2865  that = allocate(that, length)
2866
2867  for (var i = 0; i < length; i += 1) {
2868    that[i] = array[i] & 255
2869  }
2870  return that
2871}
2872
2873if (Buffer.TYPED_ARRAY_SUPPORT) {
2874  Buffer.prototype.__proto__ = Uint8Array.prototype
2875  Buffer.__proto__ = Uint8Array
2876} else {
2877  // pre-set for values that may exist in the future
2878  Buffer.prototype.length = undefined
2879  Buffer.prototype.parent = undefined
2880}
2881
2882function allocate (that, length) {
2883  if (Buffer.TYPED_ARRAY_SUPPORT) {
2884    // Return an augmented `Uint8Array` instance, for best performance
2885    that = Buffer._augment(new Uint8Array(length))
2886    that.__proto__ = Buffer.prototype
2887  } else {
2888    // Fallback: Return an object instance of the Buffer class
2889    that.length = length
2890    that._isBuffer = true
2891  }
2892
2893  var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1
2894  if (fromPool) that.parent = rootParent
2895
2896  return that
2897}
2898
2899function checked (length) {
2900  // Note: cannot use `length < kMaxLength` here because that fails when
2901  // length is NaN (which is otherwise coerced to zero.)
2902  if (length >= kMaxLength()) {
2903    throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
2904                         'size: 0x' + kMaxLength().toString(16) + ' bytes')
2905  }
2906  return length | 0
2907}
2908
2909function SlowBuffer (subject, encoding) {
2910  if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding)
2911
2912  var buf = new Buffer(subject, encoding)
2913  delete buf.parent
2914  return buf
2915}
2916
2917Buffer.isBuffer = function isBuffer (b) {
2918  return !!(b != null && b._isBuffer)
2919}
2920
2921Buffer.compare = function compare (a, b) {
2922  if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
2923    throw new TypeError('Arguments must be Buffers')
2924  }
2925
2926  if (a === b) return 0
2927
2928  var x = a.length
2929  var y = b.length
2930
2931  var i = 0
2932  var len = Math.min(x, y)
2933  while (i < len) {
2934    if (a[i] !== b[i]) break
2935
2936    ++i
2937  }
2938
2939  if (i !== len) {
2940    x = a[i]
2941    y = b[i]
2942  }
2943
2944  if (x < y) return -1
2945  if (y < x) return 1
2946  return 0
2947}
2948
2949Buffer.isEncoding = function isEncoding (encoding) {
2950  switch (String(encoding).toLowerCase()) {
2951    case 'hex':
2952    case 'utf8':
2953    case 'utf-8':
2954    case 'ascii':
2955    case 'binary':
2956    case 'base64':
2957    case 'raw':
2958    case 'ucs2':
2959    case 'ucs-2':
2960    case 'utf16le':
2961    case 'utf-16le':
2962      return true
2963    default:
2964      return false
2965  }
2966}
2967
2968Buffer.concat = function concat (list, length) {
2969  if (!isArray(list)) throw new TypeError('list argument must be an Array of Buffers.')
2970
2971  if (list.length === 0) {
2972    return new Buffer(0)
2973  }
2974
2975  var i
2976  if (length === undefined) {
2977    length = 0
2978    for (i = 0; i < list.length; i++) {
2979      length += list[i].length
2980    }
2981  }
2982
2983  var buf = new Buffer(length)
2984  var pos = 0
2985  for (i = 0; i < list.length; i++) {
2986    var item = list[i]
2987    item.copy(buf, pos)
2988    pos += item.length
2989  }
2990  return buf
2991}
2992
2993function byteLength (string, encoding) {
2994  if (typeof string !== 'string') string = '' + string
2995
2996  var len = string.length
2997  if (len === 0) return 0
2998
2999  // Use a for loop to avoid recursion
3000  var loweredCase = false
3001  for (;;) {
3002    switch (encoding) {
3003      case 'ascii':
3004      case 'binary':
3005      // Deprecated
3006      case 'raw':
3007      case 'raws':
3008        return len
3009      case 'utf8':
3010      case 'utf-8':
3011        return utf8ToBytes(string).length
3012      case 'ucs2':
3013      case 'ucs-2':
3014      case 'utf16le':
3015      case 'utf-16le':
3016        return len * 2
3017      case 'hex':
3018        return len >>> 1
3019      case 'base64':
3020        return base64ToBytes(string).length
3021      default:
3022        if (loweredCase) return utf8ToBytes(string).length // assume utf8
3023        encoding = ('' + encoding).toLowerCase()
3024        loweredCase = true
3025    }
3026  }
3027}
3028Buffer.byteLength = byteLength
3029
3030function slowToString (encoding, start, end) {
3031  var loweredCase = false
3032
3033  start = start | 0
3034  end = end === undefined || end === Infinity ? this.length : end | 0
3035
3036  if (!encoding) encoding = 'utf8'
3037  if (start < 0) start = 0
3038  if (end > this.length) end = this.length
3039  if (end <= start) return ''
3040
3041  while (true) {
3042    switch (encoding) {
3043      case 'hex':
3044        return hexSlice(this, start, end)
3045
3046      case 'utf8':
3047      case 'utf-8':
3048        return utf8Slice(this, start, end)
3049
3050      case 'ascii':
3051        return asciiSlice(this, start, end)
3052
3053      case 'binary':
3054        return binarySlice(this, start, end)
3055
3056      case 'base64':
3057        return base64Slice(this, start, end)
3058
3059      case 'ucs2':
3060      case 'ucs-2':
3061      case 'utf16le':
3062      case 'utf-16le':
3063        return utf16leSlice(this, start, end)
3064
3065      default:
3066        if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
3067        encoding = (encoding + '').toLowerCase()
3068        loweredCase = true
3069    }
3070  }
3071}
3072
3073Buffer.prototype.toString = function toString () {
3074  var length = this.length | 0
3075  if (length === 0) return ''
3076  if (arguments.length === 0) return utf8Slice(this, 0, length)
3077  return slowToString.apply(this, arguments)
3078}
3079
3080Buffer.prototype.equals = function equals (b) {
3081  if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
3082  if (this === b) return true
3083  return Buffer.compare(this, b) === 0
3084}
3085
3086Buffer.prototype.inspect = function inspect () {
3087  var str = ''
3088  var max = exports.INSPECT_MAX_BYTES
3089  if (this.length > 0) {
3090    str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
3091    if (this.length > max) str += ' ... '
3092  }
3093  return '<Buffer ' + str + '>'
3094}
3095
3096Buffer.prototype.compare = function compare (b) {
3097  if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
3098  if (this === b) return 0
3099  return Buffer.compare(this, b)
3100}
3101
3102Buffer.prototype.indexOf = function indexOf (val, byteOffset) {
3103  if (byteOffset > 0x7fffffff) byteOffset = 0x7fffffff
3104  else if (byteOffset < -0x80000000) byteOffset = -0x80000000
3105  byteOffset >>= 0
3106
3107  if (this.length === 0) return -1
3108  if (byteOffset >= this.length) return -1
3109
3110  // Negative offsets start from the end of the buffer
3111  if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0)
3112
3113  if (typeof val === 'string') {
3114    if (val.length === 0) return -1 // special case: looking for empty string always fails
3115    return String.prototype.indexOf.call(this, val, byteOffset)
3116  }
3117  if (Buffer.isBuffer(val)) {
3118    return arrayIndexOf(this, val, byteOffset)
3119  }
3120  if (typeof val === 'number') {
3121    if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') {
3122      return Uint8Array.prototype.indexOf.call(this, val, byteOffset)
3123    }
3124    return arrayIndexOf(this, [ val ], byteOffset)
3125  }
3126
3127  function arrayIndexOf (arr, val, byteOffset) {
3128    var foundIndex = -1
3129    for (var i = 0; byteOffset + i < arr.length; i++) {
3130      if (arr[byteOffset + i] === val[foundIndex === -1 ? 0 : i - foundIndex]) {
3131        if (foundIndex === -1) foundIndex = i
3132        if (i - foundIndex + 1 === val.length) return byteOffset + foundIndex
3133      } else {
3134        foundIndex = -1
3135      }
3136    }
3137    return -1
3138  }
3139
3140  throw new TypeError('val must be string, number or Buffer')
3141}
3142
3143// `get` is deprecated
3144Buffer.prototype.get = function get (offset) {
3145  console.log('.get() is deprecated. Access using array indexes instead.')
3146  return this.readUInt8(offset)
3147}
3148
3149// `set` is deprecated
3150Buffer.prototype.set = function set (v, offset) {
3151  console.log('.set() is deprecated. Access using array indexes instead.')
3152  return this.writeUInt8(v, offset)
3153}
3154
3155function hexWrite (buf, string, offset, length) {
3156  offset = Number(offset) || 0
3157  var remaining = buf.length - offset
3158  if (!length) {
3159    length = remaining
3160  } else {
3161    length = Number(length)
3162    if (length > remaining) {
3163      length = remaining
3164    }
3165  }
3166
3167  // must be an even number of digits
3168  var strLen = string.length
3169  if (strLen % 2 !== 0) throw new Error('Invalid hex string')
3170
3171  if (length > strLen / 2) {
3172    length = strLen / 2
3173  }
3174  for (var i = 0; i < length; i++) {
3175    var parsed = parseInt(string.substr(i * 2, 2), 16)
3176    if (isNaN(parsed)) throw new Error('Invalid hex string')
3177    buf[offset + i] = parsed
3178  }
3179  return i
3180}
3181
3182function utf8Write (buf, string, offset, length) {
3183  return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
3184}
3185
3186function asciiWrite (buf, string, offset, length) {
3187  return blitBuffer(asciiToBytes(string), buf, offset, length)
3188}
3189
3190function binaryWrite (buf, string, offset, length) {
3191  return asciiWrite(buf, string, offset, length)
3192}
3193
3194function base64Write (buf, string, offset, length) {
3195  return blitBuffer(base64ToBytes(string), buf, offset, length)
3196}
3197
3198function ucs2Write (buf, string, offset, length) {
3199  return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
3200}
3201
3202Buffer.prototype.write = function write (string, offset, length, encoding) {
3203  // Buffer#write(string)
3204  if (offset === undefined) {
3205    encoding = 'utf8'
3206    length = this.length
3207    offset = 0
3208  // Buffer#write(string, encoding)
3209  } else if (length === undefined && typeof offset === 'string') {
3210    encoding = offset
3211    length = this.length
3212    offset = 0
3213  // Buffer#write(string, offset[, length][, encoding])
3214  } else if (isFinite(offset)) {
3215    offset = offset | 0
3216    if (isFinite(length)) {
3217      length = length | 0
3218      if (encoding === undefined) encoding = 'utf8'
3219    } else {
3220      encoding = length
3221      length = undefined
3222    }
3223  // legacy write(string, encoding, offset, length) - remove in v0.13
3224  } else {
3225    var swap = encoding
3226    encoding = offset
3227    offset = length | 0
3228    length = swap
3229  }
3230
3231  var remaining = this.length - offset
3232  if (length === undefined || length > remaining) length = remaining
3233
3234  if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
3235    throw new RangeError('attempt to write outside buffer bounds')
3236  }
3237
3238  if (!encoding) encoding = 'utf8'
3239
3240  var loweredCase = false
3241  for (;;) {
3242    switch (encoding) {
3243      case 'hex':
3244        return hexWrite(this, string, offset, length)
3245
3246      case 'utf8':
3247      case 'utf-8':
3248        return utf8Write(this, string, offset, length)
3249
3250      case 'ascii':
3251        return asciiWrite(this, string, offset, length)
3252
3253      case 'binary':
3254        return binaryWrite(this, string, offset, length)
3255
3256      case 'base64':
3257        // Warning: maxLength not taken into account in base64Write
3258        return base64Write(this, string, offset, length)
3259
3260      case 'ucs2':
3261      case 'ucs-2':
3262      case 'utf16le':
3263      case 'utf-16le':
3264        return ucs2Write(this, string, offset, length)
3265
3266      default:
3267        if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
3268        encoding = ('' + encoding).toLowerCase()
3269        loweredCase = true
3270    }
3271  }
3272}
3273
3274Buffer.prototype.toJSON = function toJSON () {
3275  return {
3276    type: 'Buffer',
3277    data: Array.prototype.slice.call(this._arr || this, 0)
3278  }
3279}
3280
3281function base64Slice (buf, start, end) {
3282  if (start === 0 && end === buf.length) {
3283    return base64.fromByteArray(buf)
3284  } else {
3285    return base64.fromByteArray(buf.slice(start, end))
3286  }
3287}
3288
3289function utf8Slice (buf, start, end) {
3290  end = Math.min(buf.length, end)
3291  var res = []
3292
3293  var i = start
3294  while (i < end) {
3295    var firstByte = buf[i]
3296    var codePoint = null
3297    var bytesPerSequence = (firstByte > 0xEF) ? 4
3298      : (firstByte > 0xDF) ? 3
3299      : (firstByte > 0xBF) ? 2
3300      : 1
3301
3302    if (i + bytesPerSequence <= end) {
3303      var secondByte, thirdByte, fourthByte, tempCodePoint
3304
3305      switch (bytesPerSequence) {
3306        case 1:
3307          if (firstByte < 0x80) {
3308            codePoint = firstByte
3309          }
3310          break
3311        case 2:
3312          secondByte = buf[i + 1]
3313          if ((secondByte & 0xC0) === 0x80) {
3314            tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
3315            if (tempCodePoint > 0x7F) {
3316              codePoint = tempCodePoint
3317            }
3318          }
3319          break
3320        case 3:
3321          secondByte = buf[i + 1]
3322          thirdByte = buf[i + 2]
3323          if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
3324            tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
3325            if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
3326              codePoint = tempCodePoint
3327            }
3328          }
3329          break
3330        case 4:
3331          secondByte = buf[i + 1]
3332          thirdByte = buf[i + 2]
3333          fourthByte = buf[i + 3]
3334          if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
3335            tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
3336            if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
3337              codePoint = tempCodePoint
3338            }
3339          }
3340      }
3341    }
3342
3343    if (codePoint === null) {
3344      // we did not generate a valid codePoint so insert a
3345      // replacement char (U+FFFD) and advance only 1 byte
3346      codePoint = 0xFFFD
3347      bytesPerSequence = 1
3348    } else if (codePoint > 0xFFFF) {
3349      // encode to utf16 (surrogate pair dance)
3350      codePoint -= 0x10000
3351      res.push(codePoint >>>
vendor: 2,580 bytes, lines 3351-3466
3351 10 & 0x3FF | 0xD800)
3352      codePoint = 0xDC00 | codePoint & 0x3FF
3353    }
3354
3355    res.push(codePoint)
3356    i += bytesPerSequence
3357  }
3358
3359  return decodeCodePointsArray(res)
3360}
3361
3362// Based on http://stackoverflow.com/a/22747272/680742, the browser with
3363// the lowest limit is Chrome, with 0x10000 args.
3364// We go 1 magnitude less, for safety
3365var MAX_ARGUMENTS_LENGTH = 0x1000
3366
3367function decodeCodePointsArray (codePoints) {
3368  var len = codePoints.length
3369  if (len <= MAX_ARGUMENTS_LENGTH) {
3370    return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
3371  }
3372
3373  // Decode in chunks to avoid "call stack size exceeded".
3374  var res = ''
3375  var i = 0
3376  while (i < len) {
3377    res += String.fromCharCode.apply(
3378      String,
3379      codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
3380    )
3381  }
3382  return res
3383}
3384
3385function asciiSlice (buf, start, end) {
3386  var ret = ''
3387  end = Math.min(buf.length, end)
3388
3389  for (var i = start; i < end; i++) {
3390    ret += String.fromCharCode(buf[i] & 0x7F)
3391  }
3392  return ret
3393}
3394
3395function binarySlice (buf, start, end) {
3396  var ret = ''
3397  end = Math.min(buf.length, end)
3398
3399  for (var i = start; i < end; i++) {
3400    ret += String.fromCharCode(buf[i])
3401  }
3402  return ret
3403}
3404
3405function hexSlice (buf, start, end) {
3406  var len = buf.length
3407
3408  if (!start || start < 0) start = 0
3409  if (!end || end < 0 || end > len) end = len
3410
3411  var out = ''
3412  for (var i = start; i < end; i++) {
3413    out += toHex(buf[i])
3414  }
3415  return out
3416}
3417
3418function utf16leSlice (buf, start, end) {
3419  var bytes = buf.slice(start, end)
3420  var res = ''
3421  for (var i = 0; i < bytes.length; i += 2) {
3422    res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
3423  }
3424  return res
3425}
3426
3427Buffer.prototype.slice = function slice (start, end) {
3428  var len = this.length
3429  start = ~~start
3430  end = end === undefined ? len : ~~end
3431
3432  if (start < 0) {
3433    start += len
3434    if (start < 0) start = 0
3435  } else if (start > len) {
3436    start = len
3437  }
3438
3439  if (end < 0) {
3440    end += len
3441    if (end < 0) end = 0
3442  } else if (end > len) {
3443    end = len
3444  }
3445
3446  if (end < start) end = start
3447
3448  var newBuf
3449  if (Buffer.TYPED_ARRAY_SUPPORT) {
3450    newBuf = Buffer._augment(this.subarray(start, end))
3451  } else {
3452    var sliceLen = end - start
3453    newBuf = new Buffer(sliceLen, undefined)
3454    for (var i = 0; i < sliceLen; i++) {
3455      newBuf[i] = this[i + start]
3456    }
3457  }
3458
3459  if (newBuf.length) newBuf.parent = this.parent || this
3460
3461  return newBuf
3462}
3463
3464/*
3465 * Need to make sure that buffer isn't trying to write out of bounds.
3466 */
vendor: 10,066 bytes, lines 3467-3795
3467function checkOffset (offset, ext, length) {
3468  if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
3469  if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
3470}
3471
3472Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
3473  offset = offset | 0
3474  byteLength = byteLength | 0
3475  if (!noAssert) checkOffset(offset, byteLength, this.length)
3476
3477  var val = this[offset]
3478  var mul = 1
3479  var i = 0
3480  while (++i < byteLength && (mul *= 0x100)) {
3481    val += this[offset + i] * mul
3482  }
3483
3484  return val
3485}
3486
3487Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
3488  offset = offset | 0
3489  byteLength = byteLength | 0
3490  if (!noAssert) {
3491    checkOffset(offset, byteLength, this.length)
3492  }
3493
3494  var val = this[offset + --byteLength]
3495  var mul = 1
3496  while (byteLength > 0 && (mul *= 0x100)) {
3497    val += this[offset + --byteLength] * mul
3498  }
3499
3500  return val
3501}
3502
3503Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
3504  if (!noAssert) checkOffset(offset, 1, this.length)
3505  return this[offset]
3506}
3507
3508Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
3509  if (!noAssert) checkOffset(offset, 2, this.length)
3510  return this[offset] | (this[offset + 1] << 8)
3511}
3512
3513Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
3514  if (!noAssert) checkOffset(offset, 2, this.length)
3515  return (this[offset] << 8) | this[offset + 1]
3516}
3517
3518Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
3519  if (!noAssert) checkOffset(offset, 4, this.length)
3520
3521  return ((this[offset]) |
3522      (this[offset + 1] << 8) |
3523      (this[offset + 2] << 16)) +
3524      (this[offset + 3] * 0x1000000)
3525}
3526
3527Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
3528  if (!noAssert) checkOffset(offset, 4, this.length)
3529
3530  return (this[offset] * 0x1000000) +
3531    ((this[offset + 1] << 16) |
3532    (this[offset + 2] << 8) |
3533    this[offset + 3])
3534}
3535
3536Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
3537  offset = offset | 0
3538  byteLength = byteLength | 0
3539  if (!noAssert) checkOffset(offset, byteLength, this.length)
3540
3541  var val = this[offset]
3542  var mul = 1
3543  var i = 0
3544  while (++i < byteLength && (mul *= 0x100)) {
3545    val += this[offset + i] * mul
3546  }
3547  mul *= 0x80
3548
3549  if (val >= mul) val -= Math.pow(2, 8 * byteLength)
3550
3551  return val
3552}
3553
3554Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
3555  offset = offset | 0
3556  byteLength = byteLength | 0
3557  if (!noAssert) checkOffset(offset, byteLength, this.length)
3558
3559  var i = byteLength
3560  var mul = 1
3561  var val = this[offset + --i]
3562  while (i > 0 && (mul *= 0x100)) {
3563    val += this[offset + --i] * mul
3564  }
3565  mul *= 0x80
3566
3567  if (val >= mul) val -= Math.pow(2, 8 * byteLength)
3568
3569  return val
3570}
3571
3572Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
3573  if (!noAssert) checkOffset(offset, 1, this.length)
3574  if (!(this[offset] & 0x80)) return (this[offset])
3575  return ((0xff - this[offset] + 1) * -1)
3576}
3577
3578Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
3579  if (!noAssert) checkOffset(offset, 2, this.length)
3580  var val = this[offset] | (this[offset + 1] << 8)
3581  return (val & 0x8000) ? val | 0xFFFF0000 : val
3582}
3583
3584Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
3585  if (!noAssert) checkOffset(offset, 2, this.length)
3586  var val = this[offset + 1] | (this[offset] << 8)
3587  return (val & 0x8000) ? val | 0xFFFF0000 : val
3588}
3589
3590Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
3591  if (!noAssert) checkOffset(offset, 4, this.length)
3592
3593  return (this[offset]) |
3594    (this[offset + 1] << 8) |
3595    (this[offset + 2] << 16) |
3596    (this[offset + 3] << 24)
3597}
3598
3599Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
3600  if (!noAssert) checkOffset(offset, 4, this.length)
3601
3602  return (this[offset] << 24) |
3603    (this[offset + 1] << 16) |
3604    (this[offset + 2] << 8) |
3605    (this[offset + 3])
3606}
3607
3608Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
3609  if (!noAssert) checkOffset(offset, 4, this.length)
3610  return ieee754.read(this, offset, true, 23, 4)
3611}
3612
3613Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
3614  if (!noAssert) checkOffset(offset, 4, this.length)
3615  return ieee754.read(this, offset, false, 23, 4)
3616}
3617
3618Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
3619  if (!noAssert) checkOffset(offset, 8, this.length)
3620  return ieee754.read(this, offset, true, 52, 8)
3621}
3622
3623Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
3624  if (!noAssert) checkOffset(offset, 8, this.length)
3625  return ieee754.read(this, offset, false, 52, 8)
3626}
3627
3628function checkInt (buf, value, offset, ext, max, min) {
3629  if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance')
3630  if (value > max || value < min) throw new RangeError('value is out of bounds')
3631  if (offset + ext > buf.length) throw new RangeError('index out of range')
3632}
3633
3634Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
3635  value = +value
3636  offset = offset | 0
3637  byteLength = byteLength | 0
3638  if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
3639
3640  var mul = 1
3641  var i = 0
3642  this[offset] = value & 0xFF
3643  while (++i < byteLength && (mul *= 0x100)) {
3644    this[offset + i] = (value / mul) & 0xFF
3645  }
3646
3647  return offset + byteLength
3648}
3649
3650Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
3651  value = +value
3652  offset = offset | 0
3653  byteLength = byteLength | 0
3654  if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
3655
3656  var i = byteLength - 1
3657  var mul = 1
3658  this[offset + i] = value & 0xFF
3659  while (--i >= 0 && (mul *= 0x100)) {
3660    this[offset + i] = (value / mul) & 0xFF
3661  }
3662
3663  return offset + byteLength
3664}
3665
3666Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
3667  value = +value
3668  offset = offset | 0
3669  if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
3670  if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
3671  this[offset] = (value & 0xff)
3672  return offset + 1
3673}
3674
3675function objectWriteUInt16 (buf, value, offset, littleEndian) {
3676  if (value < 0) value = 0xffff + value + 1
3677  for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) {
3678    buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
3679      (littleEndian ? i : 1 - i) * 8
3680  }
3681}
3682
3683Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
3684  value = +value
3685  offset = offset | 0
3686  if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
3687  if (Buffer.TYPED_ARRAY_SUPPORT) {
3688    this[offset] = (value & 0xff)
3689    this[offset + 1] = (value >>> 8)
3690  } else {
3691    objectWriteUInt16(this, value, offset, true)
3692  }
3693  return offset + 2
3694}
3695
3696Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
3697  value = +value
3698  offset = offset | 0
3699  if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
3700  if (Buffer.TYPED_ARRAY_SUPPORT) {
3701    this[offset] = (value >>> 8)
3702    this[offset + 1] = (value & 0xff)
3703  } else {
3704    objectWriteUInt16(this, value, offset, false)
3705  }
3706  return offset + 2
3707}
3708
3709function objectWriteUInt32 (buf, value, offset, littleEndian) {
3710  if (value < 0) value = 0xffffffff + value + 1
3711  for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) {
3712    buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
3713  }
3714}
3715
3716Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
3717  value = +value
3718  offset = offset | 0
3719  if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
3720  if (Buffer.TYPED_ARRAY_SUPPORT) {
3721    this[offset + 3] = (value >>> 24)
3722    this[offset + 2] = (value >>> 16)
3723    this[offset + 1] = (value >>> 8)
3724    this[offset] = (value & 0xff)
3725  } else {
3726    objectWriteUInt32(this, value, offset, true)
3727  }
3728  return offset + 4
3729}
3730
3731Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
3732  value = +value
3733  offset = offset | 0
3734  if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
3735  if (Buffer.TYPED_ARRAY_SUPPORT) {
3736    this[offset] = (value >>> 24)
3737    this[offset + 1] = (value >>> 16)
3738    this[offset + 2] = (value >>> 8)
3739    this[offset + 3] = (value & 0xff)
3740  } else {
3741    objectWriteUInt32(this, value, offset, false)
3742  }
3743  return offset + 4
3744}
3745
3746Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
3747  value = +value
3748  offset = offset | 0
3749  if (!noAssert) {
3750    var limit = Math.pow(2, 8 * byteLength - 1)
3751
3752    checkInt(this, value, offset, byteLength, limit - 1, -limit)
3753  }
3754
3755  var i = 0
3756  var mul = 1
3757  var sub = value < 0 ? 1 : 0
3758  this[offset] = value & 0xFF
3759  while (++i < byteLength && (mul *= 0x100)) {
3760    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
3761  }
3762
3763  return offset + byteLength
3764}
3765
3766Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
3767  value = +value
3768  offset = offset | 0
3769  if (!noAssert) {
3770    var limit = Math.pow(2, 8 * byteLength - 1)
3771
3772    checkInt(this, value, offset, byteLength, limit - 1, -limit)
3773  }
3774
3775  var i = byteLength - 1
3776  var mul = 1
3777  var sub = value < 0 ? 1 : 0
3778  this[offset + i] = value & 0xFF
3779  while (--i >= 0 && (mul *= 0x100)) {
3780    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
3781  }
3782
3783  return offset + byteLength
3784}
3785
3786Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
3787  value = +value
3788  offset = offset | 0
3789  if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
3790  if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
3791  if (value < 0) value = 0xff + value + 1
3792  this[offset] = (value & 0xff)
3793  return offset + 1
3794}
3795
vendor: 4,257 bytes, lines 3796-3919
3796Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
3797  value = +value
3798  offset = offset | 0
3799  if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
3800  if (Buffer.TYPED_ARRAY_SUPPORT) {
3801    this[offset] = (value & 0xff)
3802    this[offset + 1] = (value >>> 8)
3803  } else {
3804    objectWriteUInt16(this, value, offset, true)
3805  }
3806  return offset + 2
3807}
3808
3809Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
3810  value = +value
3811  offset = offset | 0
3812  if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
3813  if (Buffer.TYPED_ARRAY_SUPPORT) {
3814    this[offset] = (value >>> 8)
3815    this[offset + 1] = (value & 0xff)
3816  } else {
3817    objectWriteUInt16(this, value, offset, false)
3818  }
3819  return offset + 2
3820}
3821
3822Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
3823  value = +value
3824  offset = offset | 0
3825  if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
3826  if (Buffer.TYPED_ARRAY_SUPPORT) {
3827    this[offset] = (value & 0xff)
3828    this[offset + 1] = (value >>> 8)
3829    this[offset + 2] = (value >>> 16)
3830    this[offset + 3] = (value >>> 24)
3831  } else {
3832    objectWriteUInt32(this, value, offset, true)
3833  }
3834  return offset + 4
3835}
3836
3837Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
3838  value = +value
3839  offset = offset | 0
3840  if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
3841  if (value < 0) value = 0xffffffff + value + 1
3842  if (Buffer.TYPED_ARRAY_SUPPORT) {
3843    this[offset] = (value >>> 24)
3844    this[offset + 1] = (value >>> 16)
3845    this[offset + 2] = (value >>> 8)
3846    this[offset + 3] = (value & 0xff)
3847  } else {
3848    objectWriteUInt32(this, value, offset, false)
3849  }
3850  return offset + 4
3851}
3852
3853function checkIEEE754 (buf, value, offset, ext, max, min) {
3854  if (value > max || value < min) throw new RangeError('value is out of bounds')
3855  if (offset + ext > buf.length) throw new RangeError('index out of range')
3856  if (offset < 0) throw new RangeError('index out of range')
3857}
3858
3859function writeFloat (buf, value, offset, littleEndian, noAssert) {
3860  if (!noAssert) {
3861    checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
3862  }
3863  ieee754.write(buf, value, offset, littleEndian, 23, 4)
3864  return offset + 4
3865}
3866
3867Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
3868  return writeFloat(this, value, offset, true, noAssert)
3869}
3870
3871Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
3872  return writeFloat(this, value, offset, false, noAssert)
3873}
3874
3875function writeDouble (buf, value, offset, littleEndian, noAssert) {
3876  if (!noAssert) {
3877    checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
3878  }
3879  ieee754.write(buf, value, offset, littleEndian, 52, 8)
3880  return offset + 8
3881}
3882
3883Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
3884  return writeDouble(this, value, offset, true, noAssert)
3885}
3886
3887Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
3888  return writeDouble(this, value, offset, false, noAssert)
3889}
3890
3891// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
3892Buffer.prototype.copy = function copy (target, targetStart, start, end) {
3893  if (!start) start = 0
3894  if (!end && end !== 0) end = this.length
3895  if (targetStart >= target.length) targetStart = target.length
3896  if (!targetStart) targetStart = 0
3897  if (end > 0 && end < start) end = start
3898
3899  // Copy 0 bytes; we're done
3900  if (end === start) return 0
3901  if (target.length === 0 || this.length === 0) return 0
3902
3903  // Fatal error conditions
3904  if (targetStart < 0) {
3905    throw new RangeError('targetStart out of bounds')
3906  }
3907  if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')
3908  if (end < 0) throw new RangeError('sourceEnd out of bounds')
3909
3910  // Are we oob?
3911  if (end > this.length) end = this.length
3912  if (target.length - targetStart < end - start) {
3913    end = target.length - targetStart + start
3914  }
3915
3916  var len = end - start
3917  var i
3918
3919  if (this === target && start < targetStart && targetStart < end) {
3920    // descending copy from end
3921    for (i = len - 1; i >= 0; i--) {
3922      target[i + targetStart] = this[i + start]
3923    }
3924  } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
3925    // ascending copy from start
3926    for (i = 0; i < len; i++) {
3927      target[i + targetStart] = this[i + start]
3928    }
3929  } else {
3930    target._set(this.subarray(start, start + len), targetStart)
3931  }
3932
3933  return len
3934}
3935
3936// fill(value, start=0, end=buffer.length)
3937Buffer.prototype.fill = function fill (value, start, end) {
3938  if (!value) value = 0
3939  if (!start) start = 0
3940  if (!end) end = this.length
3941
3942  if (end < start) throw new RangeError('end < start')
3943
3944  // Fill 0 bytes; we're done
3945  if (end === start) return
3946  if (this.length === 0) return
3947
3948  if (start < 0 || start >= this.length) throw new RangeError('start out of bounds')
3949  if (end < 0 || end > this.length) throw new RangeError('end out of bounds')
3950
3951  var i
3952  if (typeof value === 'number') {
3953    for (i = start; i < end; i++) {
3954      this[i] = value
3955    }
3956  } else {
3957    var bytes = utf8ToBytes(value.toString())
3958    var len = bytes.length
3959    for (i = start; i < end; i++) {
3960      this[i] = bytes[i % len]
3961    }
3962  }
3963
3964  return this
3965}
3966
3967/**
3968 * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.
3969 * Added in Node 0.12. Only available in browsers that support ArrayBuffer.
3970 */
3971Buffer.prototype.toArrayBuffer = function toArrayBuffer () {
3972  if (typeof Uint8Array !== 'undefined') {
3973    if (Buffer.TYPED_ARRAY_SUPPORT) {
3974      return (new Buffer(this)).buffer
3975    } else {
3976      var buf = new Uint8Array(this.length)
3977      for (var i = 0, len = buf.length; i < len; i += 1) {
3978        buf[i] = this[i]
3979      }
3980      return buf.buffer
3981    }
3982  } else {
3983    throw new TypeError('Buffer.toArrayBuffer not supported in this browser')
3984  }
3985}
3986
3987// HELPER FUNCTIONS
3988// ================
3989
3990var BP = Buffer.prototype
3991
3992/**
3993 * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods
3994 */
3995Buffer._augment = function _augment (arr) {
3996  arr.constructor = Buffer
3997  arr._isBuffer = true
3998
3999  // save reference to original Uint8Array set method before overwriting
4000  arr._set = arr.set
4001
4002  // deprecated
4003  arr.get = BP.get
4004  arr.set = BP.set
4005
4006  arr.write = BP.write
4007  arr.toString = BP.toString
4008  arr.toLocaleString = BP.toString
4009  arr.toJSON = BP.toJSON
4010  arr.equals = BP.equals
4011  arr.compare = BP.compare
4012  arr.indexOf = BP.indexOf
4013  arr.copy = BP.copy
4014  arr.slice = BP.slice
4015  arr.readUIntLE = BP.readUIntLE
4016  arr.readUIntBE = BP.readUIntBE
4017  arr.readUInt8 = BP.readUInt8
4018  arr.readUInt16LE = BP.readUInt16LE
4019  arr.readUInt16BE = BP.readUInt16BE
4020  arr.readUInt32LE = BP.readUInt32LE
4021  arr.readUInt32BE = BP.readUInt32BE
4022  arr.readIntLE = BP.readIntLE
4023  arr.readIntBE = BP.readIntBE
4024  arr.readInt8 = BP.readInt8
4025  arr.readInt16LE = BP.readInt16LE
4026  arr.readInt16BE = BP.readInt16BE
4027  arr.readInt32LE = BP.readInt32LE
4028  arr.readInt32BE = BP.readInt32BE
4029  arr.readFloatLE = BP.readFloatLE
4030  arr.readFloatBE = BP.readFloatBE
4031  arr.readDoubleLE = BP.readDoubleLE
4032  arr.readDoubleBE = BP.readDoubleBE
4033  arr.writeUInt8 = BP.writeUInt8
4034  arr.writeUIntLE = BP.writeUIntLE
4035  arr.writeUIntBE = BP.writeUIntBE
4036  arr.writeUInt16LE = BP.writeUInt16LE
4037  arr.writeUInt16BE = BP.writeUInt16BE
4038  arr.writeUInt32LE = BP.writeUInt32LE
4039  arr.writeUInt32BE = BP.writeUInt32BE
4040  arr.writeIntLE = BP.writeIntLE
4041  arr.writeIntBE = BP.writeIntBE
4042  arr.writeInt8 = BP.writeInt8
4043  arr.writeInt16LE = BP.writeInt16LE
4044  arr.writeInt16BE = BP.writeInt16BE
4045  arr.writeInt32LE = BP.writeInt32LE
4046  arr.writeInt32BE = BP.writeInt32BE
4047  arr.writeFloatLE = BP.writeFloatLE
4048  arr.writeFloatBE = BP.writeFloatBE
4049  arr.writeDoubleLE = BP.writeDoubleLE
4050  arr.writeDoubleBE = BP.writeDoubleBE
4051  arr.fill = BP.fill
4052  arr.inspect = BP.inspect
4053  arr.toArrayBuffer = BP.toArrayBuffer
4054
4055  return arr
4056}
4057
4058var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g
4059
4060function base64clean (str) {
4061  // Node strips out invalid characters like \n and \t from the string, base64-js does not
4062  str = stringtrim(str).replace(INVALID_BASE64_RE, '')
4063  // Node converts strings with length < 2 to ''
4064  if (str.length < 2) return ''
4065  // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
4066  while (str.length % 4 !== 0) {
4067    str = str + '='
4068  }
4069  return str
4070}
4071
4072function stringtrim (str) {
4073  if (str.trim) return str.trim()
4074  return str.replace(/^\s+|\s+$/g, '')
4075}
4076
4077function toHex (n) {
4078  if (n < 16) return '0' + n.toString(16)
4079  return n.toString(16)
4080}
4081
4082function utf8ToBytes (string, units) {
4083  units = units || Infinity
4084  var codePoint
4085  var length = string.length
4086  var leadSurrogate = null
4087  var bytes = []
4088
4089  for (var i = 0; i < length; i++) {
4090    codePoint = string.charCodeAt(i)
4091
4092    // is surrogate component
4093    if (codePoint > 0xD7FF && codePoint < 0xE000) {
4094      // last char was a lead
4095      if (!leadSurrogate) {
4096        // no lead yet
4097        if (codePoint > 0xDBFF) {
4098          // unexpected trail
4099          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
4100          continue
4101        } else if (i + 1 === length) {
4102          // unpaired lead
4103          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
4104          continue
4105        }
4106
4107        // valid lead
4108        leadSurrogate = codePoint
4109
4110        continue
4111      }
4112
4113      // 2 leads in a row
4114      if (codePoint < 0xDC00) {
4115        if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
4116        leadSurrogate = codePoint
4117        continue
4118      }
4119
4120      // valid surrogate pair
4121      codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
4122    } else if (leadSurrogate) {
4123      // valid bmp char, but last char was a lead
4124      if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
4125    }
4126
4127    leadSurrogate = null
4128
4129    // encode utf8
4130    if (codePoint < 0x80) {
4131      if ((units -= 1) < 0) break
4132      bytes.push(codePoint)
4133    } else if (codePoint < 0x800) {
4134      if ((units -= 2) < 0) break
4135      bytes.push(
4136        codePoint >> 0x6 | 0xC0,
4137        codePoint & 0x3F | 0x80
4138      )
4139    } else if (codePoint < 0x10000) {
4140      if ((units -= 3) < 0) break
4141      bytes.push(
4142        codePoint >> 0xC | 0xE0,
4143        codePoint >> 0x6 & 0x3F | 0x80,
4144        codePoint & 0x3F | 0x80
4145      )
4146    } else if (codePoint < 0x110000) {
4147      if ((units -= 4) < 0) break
4148      bytes.push(
4149        codePoint >> 0x12 | 0xF0,
4150        codePoint >> 0xC & 0x3F | 0x80,
4151        codePoint >> 0x6 & 0x3F | 0x80,
4152        codePoint & 0x3F | 0x80
4153      )
4154    } else {
4155      throw new Error('Invalid code point')
4156    }
4157  }
4158
4159  return bytes
4160}
4161
4162function asciiToBytes (str) {
4163  var byteArray = []
4164  for (var i = 0; i < str.length; i++) {
4165    // Node's code seems to be doing this and not & 0x7F..
vendor: 5,825 bytes, lines 4166-4368
4166    byteArray.push(str.charCodeAt(i) & 0xFF)
4167  }
4168  return byteArray
4169}
4170
4171function utf16leToBytes (str, units) {
4172  var c, hi, lo
4173  var byteArray = []
4174  for (var i = 0; i < str.length; i++) {
4175    if ((units -= 2) < 0) break
4176
4177    c = str.charCodeAt(i)
4178    hi = c >> 8
4179    lo = c % 256
4180    byteArray.push(lo)
4181    byteArray.push(hi)
4182  }
4183
4184  return byteArray
4185}
4186
4187function base64ToBytes (str) {
4188  return base64.toByteArray(base64clean(str))
4189}
4190
4191function blitBuffer (src, dst, offset, length) {
4192  for (var i = 0; i < length; i++) {
4193    if ((i + offset >= dst.length) || (i >= src.length)) break
4194    dst[i + offset] = src[i]
4195  }
4196  return i
4197}
4198
4199}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
4200
4201},{"17":17,"27":27,"7":7}],11:[function(_dereq_,module,exports){
4202/*! codem-isoboxer v0.3.4 https://github.com/madebyhiro/codem-isoboxer/blob/master/LICENSE.txt */
4203var ISOBoxer = {};
4204
4205ISOBoxer.parseBuffer = function(arrayBuffer) {
4206  return new ISOFile(arrayBuffer).parse();
4207};
4208
4209ISOBoxer.addBoxProcessor = function(type, parser) {
4210  if (typeof type !== 'string' || typeof parser !== 'function') {
4211    return;
4212  }
4213  ISOBox.prototype._boxProcessors[type] = parser;
4214};
4215
4216ISOBoxer.createFile = function() {
4217  return new ISOFile();
4218};
4219
4220// See ISOBoxer.append() for 'pos' parameter syntax
4221ISOBoxer.createBox = function(type, parent, pos) {
4222  var newBox = ISOBox.create(type);
4223  if (parent) {
4224    parent.append(newBox, pos);
4225  }
4226  return newBox;
4227};
4228
4229// See ISOBoxer.append() for 'pos' parameter syntax
4230ISOBoxer.createFullBox = function(type, parent, pos) {
4231  var newBox = ISOBoxer.createBox(type, parent, pos);
4232  newBox.version = 0;
4233  newBox.flags = 0;
4234  return newBox;
4235};
4236
4237ISOBoxer.Utils = {};
4238ISOBoxer.Utils.dataViewToString = function(dataView, encoding) {
4239  var impliedEncoding = encoding || 'utf-8';
4240  if (typeof TextDecoder !== 'undefined') {
4241    return new TextDecoder(impliedEncoding).decode(dataView);
4242  }
4243  var a = [];
4244  var i = 0;
4245
4246  if (impliedEncoding === 'utf-8') {
4247    /* The following algorithm is essentially a rewrite of the UTF8.decode at
4248    http://bannister.us/weblog/2007/simple-base64-encodedecode-javascript/
4249    */
4250
4251    while (i < dataView.byteLength) {
4252      var c = dataView.getUint8(i++);
4253      if (c < 0x80) {
4254        // 1-byte character (7 bits)
4255      } else if (c < 0xe0) {
4256        // 2-byte character (11 bits)
4257        c = (c & 0x1f) << 6;
4258        c |= (dataView.getUint8(i++) & 0x3f);
4259      } else if (c < 0xf0) {
4260        // 3-byte character (16 bits)
4261        c = (c & 0xf) << 12;
4262        c |= (dataView.getUint8(i++) & 0x3f) << 6;
4263        c |= (dataView.getUint8(i++) & 0x3f);
4264      } else {
4265        // 4-byte character (21 bits)
4266        c = (c & 0x7) << 18;
4267        c |= (dataView.getUint8(i++) & 0x3f) << 12;
4268        c |= (dataView.getUint8(i++) & 0x3f) << 6;
4269        c |= (dataView.getUint8(i++) & 0x3f);
4270      }
4271      a.push(String.fromCharCode(c));
4272    }
4273  } else { // Just map byte-by-byte (probably wrong)
4274    while (i < dataView.byteLength) {
4275      a.push(String.fromCharCode(dataView.getUint8(i++)));
4276    }
4277  }
4278  return a.join('');
4279};
4280
4281ISOBoxer.Utils.utf8ToByteArray = function(string) {
4282  // Only UTF-8 encoding is supported by TextEncoder
4283  var u, i;
4284  if (typeof TextEncoder !== 'undefined') {
4285    u = new TextEncoder().encode(string);
4286  } else {
4287    u = [];
4288    for (i = 0; i < string.length; ++i) {
4289      var c = string.charCodeAt(i);
4290      if (c < 0x80) {
4291        u.push(c);
4292      } else if (c < 0x800) {
4293        u.push(0xC0 | (c >> 6));
4294        u.push(0x80 | (63 & c));
4295      } else if (c < 0x10000) {
4296        u.push(0xE0 | (c >> 12));
4297        u.push(0x80 | (63 & (c >> 6)));
4298        u.push(0x80 | (63 & c));
4299      } else {
4300        u.push(0xF0 | (c >> 18));
4301        u.push(0x80 | (63 & (c >> 12)));
4302        u.push(0x80 | (63 & (c >> 6)));
4303        u.push(0x80 | (63 & c));
4304      }
4305    }
4306  }
4307  return u;
4308};
4309
4310// Method to append a box in the list of child boxes
4311// The 'pos' parameter can be either:
4312//   - (number) a position index at which to insert the new box
4313//   - (string) the type of the box after which to insert the new box
4314//   - (object) the box after which to insert the new box
4315ISOBoxer.Utils.appendBox = function(parent, box, pos) {
4316  box._offset = parent._cursor.offset;
4317  box._root = (parent._root ? parent._root : parent);
4318  box._raw = parent._raw;
4319  box._parent = parent;
4320
4321  if (pos === -1) {
4322    // The new box is a sub-box of the parent but not added in boxes array,
4323    // for example when the new box is set as an entry (see dref and stsd for example)
4324    return;
4325  }
4326
4327  if (pos === undefined || pos === null) {
4328    parent.boxes.push(box);
4329    return;
4330  }
4331
4332  var index = -1,
4333      type;
4334
4335  if (typeof pos === "number") {
4336    index = pos;
4337  } else {
4338    if (typeof pos === "string") {
4339      type = pos;
4340    } else if (typeof pos === "object" && pos.type) {
4341      type = pos.type;
4342    } else {
4343      parent.boxes.push(box);
4344      return;
4345    }
4346
4347    for (var i = 0; i < parent.boxes.length; i++) {
4348      if (type === parent.boxes[i].type) {
4349        index = i + 1;
4350        break;
4351      }
4352    }
4353  }
4354  parent.boxes.splice(index, 0, box);
4355};
4356
4357if (typeof exports !== 'undefined') {
4358  exports.parseBuffer     = ISOBoxer.parseBuffer;
4359  exports.addBoxProcessor = ISOBoxer.addBoxProcessor;
4360  exports.createFile      = ISOBoxer.createFile;
4361  exports.createBox       = ISOBoxer.createBox;
4362  exports.createFullBox   = ISOBoxer.createFullBox;
4363  exports.Utils           = ISOBoxer.Utils;
4364}
4365
4366ISOBoxer.Cursor = function(initialOffset) {
4367  this.offset = (typeof initialOffset == 'undefined' ? 0 : initialOffset);
4368};
vendor: 32,838 bytes, lines 4369-5329
4369
4370var ISOFile = function(arrayBuffer) {
4371  this._cursor = new ISOBoxer.Cursor();
4372  this.boxes = [];
4373  if (arrayBuffer) {
4374    this._raw = new DataView(arrayBuffer);
4375  }
4376};
4377
4378ISOFile.prototype.fetch = function(type) {
4379  var result = this.fetchAll(type, true);
4380  return (result.length ? result[0] : null);
4381};
4382
4383ISOFile.prototype.fetchAll = function(type, returnEarly) {
4384  var result = [];
4385  ISOFile._sweep.call(this, type, result, returnEarly);
4386  return result;
4387};
4388
4389ISOFile.prototype.parse = function() {
4390  this._cursor.offset = 0;
4391  this.boxes = [];
4392  while (this._cursor.offset < this._raw.byteLength) {
4393    var box = ISOBox.parse(this);
4394
4395    // Box could not be parsed
4396    if (typeof box.type === 'undefined') break;
4397
4398    this.boxes.push(box);
4399  }
4400  return this;
4401};
4402
4403ISOFile._sweep = function(type, result, returnEarly) {
4404  if (this.type && this.type == type) result.push(this);
4405  for (var box in this.boxes) {
4406    if (result.length && returnEarly) return;
4407    ISOFile._sweep.call(this.boxes[box], type, result, returnEarly);
4408  }
4409};
4410
4411ISOFile.prototype.write = function() {
4412
4413  var length = 0,
4414      i;
4415
4416  for (i = 0; i < this.boxes.length; i++) {
4417    length += this.boxes[i].getLength(false);
4418  }
4419
4420  var bytes = new Uint8Array(length);
4421  this._rawo = new DataView(bytes.buffer);
4422  this.bytes = bytes;
4423  this._cursor.offset = 0;
4424
4425  for (i = 0; i < this.boxes.length; i++) {
4426    this.boxes[i].write();
4427  }
4428
4429  return bytes.buffer;
4430};
4431
4432ISOFile.prototype.append = function(box, pos) {
4433  ISOBoxer.Utils.appendBox(this, box, pos);
4434};
4435var ISOBox = function() {
4436  this._cursor = new ISOBoxer.Cursor();
4437};
4438
4439ISOBox.parse = function(parent) {
4440  var newBox = new ISOBox();
4441  newBox._offset = parent._cursor.offset;
4442  newBox._root = (parent._root ? parent._root : parent);
4443  newBox._raw = parent._raw;
4444  newBox._parent = parent;
4445  newBox._parseBox();
4446  parent._cursor.offset = newBox._raw.byteOffset + newBox._raw.byteLength;
4447  return newBox;
4448};
4449
4450ISOBox.create = function(type) {
4451  var newBox = new ISOBox();
4452  newBox.type = type;
4453  newBox.boxes = [];
4454  return newBox;
4455};
4456
4457ISOBox.prototype._boxContainers = ['dinf', 'edts', 'mdia', 'meco', 'mfra', 'minf', 'moof', 'moov', 'mvex', 'stbl', 'strk', 'traf', 'trak', 'tref', 'udta', 'vttc', 'sinf', 'schi', 'encv', 'enca'];
4458
4459ISOBox.prototype._boxProcessors = {};
4460
4461///////////////////////////////////////////////////////////////////////////////////////////////////
4462// Generic read/write functions
4463
4464ISOBox.prototype._procField = function (name, type, size) {
4465  if (this._parsing) {
4466    this[name] = this._readField(type, size);
4467  }
4468  else {
4469    this._writeField(type, size, this[name]);
4470  }
4471};
4472
4473ISOBox.prototype._procFieldArray = function (name, length, type, size) {
4474  var i;
4475  if (this._parsing) {
4476    this[name] = [];
4477    for (i = 0; i < length; i++) {
4478      this[name][i] = this._readField(type, size);
4479    }
4480  }
4481  else {
4482    for (i = 0; i < this[name].length; i++) {
4483      this._writeField(type, size, this[name][i]);
4484    }
4485  }
4486};
4487
4488ISOBox.prototype._procFullBox = function() {
4489  this._procField('version', 'uint', 8);
4490  this._procField('flags', 'uint', 24);
4491};
4492
4493ISOBox.prototype._procEntries = function(name, length, fn) {
4494  var i;
4495  if (this._parsing) {
4496    this[name] = [];
4497    for (i = 0; i < length; i++) {
4498      this[name].push({});
4499      fn.call(this, this[name][i]);
4500    }
4501  }
4502  else {
4503    for (i = 0; i < length; i++) {
4504      fn.call(this, this[name][i]);
4505    }
4506  }
4507};
4508
4509ISOBox.prototype._procSubEntries = function(entry, name, length, fn) {
4510  var i;
4511  if (this._parsing) {
4512    entry[name] = [];
4513    for (i = 0; i < length; i++) {
4514      entry[name].push({});
4515      fn.call(this, entry[name][i]);
4516    }
4517  }
4518  else {
4519    for (i = 0; i < length; i++) {
4520      fn.call(this, entry[name][i]);
4521    }
4522  }
4523};
4524
4525ISOBox.prototype._procEntryField = function (entry, name, type, size) {
4526  if (this._parsing) {
4527    entry[name] = this._readField(type, size);
4528  }
4529  else {
4530    this._writeField(type, size, entry[name]);
4531  }
4532};
4533
4534ISOBox.prototype._procSubBoxes = function(name, length) {
4535  var i;
4536  if (this._parsing) {
4537    this[name] = [];
4538    for (i = 0; i < length; i++) {
4539      this[name].push(ISOBox.parse(this));
4540    }
4541  }
4542  else {
4543    for (i = 0; i < length; i++) {
4544      if (this._rawo) {
4545        this[name][i].write();
4546      } else {
4547        this.size += this[name][i].getLength();
4548      }
4549    }
4550  }
4551};
4552
4553///////////////////////////////////////////////////////////////////////////////////////////////////
4554// Read/parse functions
4555
4556ISOBox.prototype._readField = function(type, size) {
4557  switch (type) {
4558    case 'uint':
4559      return this._readUint(size);
4560    case 'int':
4561      return this._readInt(size);
4562    case 'template':
4563      return this._readTemplate(size);
4564    case 'string':
4565      return (size === -1) ? this._readTerminatedString() : this._readString(size);
4566    case 'data':
4567      return this._readData(size);
4568    case 'utf8':
4569      return this._readUTF8String();
4570    default:
4571      return -1;
4572  }
4573};
4574
4575ISOBox.prototype._readInt = function(size) {
4576  var result = null,
4577      offset = this._cursor.offset - this._raw.byteOffset;
4578  switch(size) {
4579  case 8:
4580    result = this._raw.getInt8(offset);
4581    break;
4582  case 16:
4583    result = this._raw.getInt16(offset);
4584    break;
4585  case 32:
4586    result = this._raw.getInt32(offset);
4587    break;
4588  case 64:
4589    // Warning: JavaScript cannot handle 64-bit integers natively.
4590    // This will give unexpected results for integers >= 2^53
4591    var s1 = this._raw.getInt32(offset);
4592    var s2 = this._raw.getInt32(offset + 4);
4593    result = (s1 * Math.pow(2,32)) + s2;
4594    break;
4595  }
4596  this._cursor.offset += (size >> 3);
4597  return result;
4598};
4599
4600ISOBox.prototype._readUint = function(size) {
4601  var result = null,
4602      offset = this._cursor.offset - this._raw.byteOffset,
4603      s1, s2;
4604  switch(size) {
4605  case 8:
4606    result = this._raw.getUint8(offset);
4607    break;
4608  case 16:
4609    result = this._raw.getUint16(offset);
4610    break;
4611  case 24:
4612    s1 = this._raw.getUint16(offset);
4613    s2 = this._raw.getUint8(offset + 2);
4614    result = (s1 << 8) + s2;
4615    break;
4616  case 32:
4617    result = this._raw.getUint32(offset);
4618    break;
4619  case 64:
4620    // Warning: JavaScript cannot handle 64-bit integers natively.
4621    // This will give unexpected results for integers >= 2^53
4622    s1 = this._raw.getUint32(offset);
4623    s2 = this._raw.getUint32(offset + 4);
4624    result = (s1 * Math.pow(2,32)) + s2;
4625    break;
4626  }
4627  this._cursor.offset += (size >> 3);
4628  return result;
4629};
4630
4631ISOBox.prototype._readString = function(length) {
4632  var str = '';
4633  for (var c = 0; c < length; c++) {
4634    var char = this._readUint(8);
4635    str += String.fromCharCode(char);
4636  }
4637  return str;
4638};
4639
4640ISOBox.prototype._readTemplate = function(size) {
4641  var pre = this._readUint(size / 2);
4642  var post = this._readUint(size / 2);
4643  return pre + (post / Math.pow(2, size / 2));
4644};
4645
4646ISOBox.prototype._readTerminatedString = function() {
4647  var str = '';
4648  while (this._cursor.offset - this._offset < this._raw.byteLength) {
4649    var char = this._readUint(8);
4650    if (char === 0) break;
4651    str += String.fromCharCode(char);
4652  }
4653  return str;
4654};
4655
4656ISOBox.prototype._readData = function(size) {
4657  var length = (size > 0) ? size : (this._raw.byteLength - (this._cursor.offset - this._offset));
4658  var data = new DataView(this._raw.buffer, this._cursor.offset, length);
4659  this._cursor.offset += length;
4660  return data;
4661};
4662
4663ISOBox.prototype._readUTF8String = function() {
4664  var data = this._readData();
4665  return ISOBoxer.Utils.dataViewToString(data);
4666};
4667
4668ISOBox.prototype._parseBox = function() {
4669  this._parsing = true;
4670  this._cursor.offset = this._offset;
4671
4672  // return immediately if there are not enough bytes to read the header
4673  if (this._offset + 8 > this._raw.buffer.byteLength) {
4674    this._root._incomplete = true;
4675    return;
4676  }
4677
4678  this._procField('size', 'uint', 32);
4679  this._procField('type', 'string', 4);
4680
4681  if (this.size === 1)      { this._procField('largesize', 'uint', 64); }
4682  if (this.type === 'uuid') { this._procFieldArray('usertype', 16, 'uint', 8); }
4683
4684  switch(this.size) {
4685  case 0:
4686    this._raw = new DataView(this._raw.buffer, this._offset, (this._raw.byteLength - this._cursor.offset + 8));
4687    break;
4688  case 1:
4689    if (this._offset + this.size > this._raw.buffer.byteLength) {
4690      this._incomplete = true;
4691      this._root._incomplete = true;
4692    } else {
4693      this._raw = new DataView(this._raw.buffer, this._offset, this.largesize);
4694    }
4695    break;
4696  default:
4697    if (this._offset + this.size > this._raw.buffer.byteLength) {
4698      this._incomplete = true;
4699      this._root._incomplete = true;
4700    } else {
4701      this._raw = new DataView(this._raw.buffer, this._offset, this.size);
4702    }
4703  }
4704
4705  // additional parsing
4706  if (!this._incomplete) {
4707    if (this._boxProcessors[this.type]) {
4708      this._boxProcessors[this.type].call(this);
4709    }
4710    if (this._boxContainers.indexOf(this.type) !== -1) {
4711      this._parseContainerBox();
4712    } else{
4713      // Unknown box => read and store box content
4714      this._data = this._readData();
4715    }
4716  }
4717};
4718
4719ISOBox.prototype._parseFullBox = function() {
4720  this.version = this._readUint(8);
4721  this.flags = this._readUint(24);
4722};
4723
4724ISOBox.prototype._parseContainerBox = function() {
4725  this.boxes = [];
4726  while (this._cursor.offset - this._raw.byteOffset < this._raw.byteLength) {
4727    this.boxes.push(ISOBox.parse(this));
4728  }
4729};
4730
4731///////////////////////////////////////////////////////////////////////////////////////////////////
4732// Write functions
4733
4734ISOBox.prototype.append = function(box, pos) {
4735  ISOBoxer.Utils.appendBox(this, box, pos);
4736};
4737
4738ISOBox.prototype.getLength = function() {
4739  this._parsing = false;
4740  this._rawo = null;
4741
4742  this.size = 0;
4743  this._procField('size', 'uint', 32);
4744  this._procField('type', 'string', 4);
4745
4746  if (this.size === 1)      { this._procField('largesize', 'uint', 64); }
4747  if (this.type === 'uuid') { this._procFieldArray('usertype', 16, 'uint', 8); }
4748
4749  if (this._boxProcessors[this.type]) {
4750    this._boxProcessors[this.type].call(this);
4751  }
4752
4753  if (this._boxContainers.indexOf(this.type) !== -1) {
4754    for (var i = 0; i < this.boxes.length; i++) {
4755      this.size += this.boxes[i].getLength();
4756    }
4757  } 
4758
4759  if (this._data) {
4760    this._writeData(this._data);
4761  }
4762
4763  return this.size;
4764};
4765
4766ISOBox.prototype.write = function() {
4767  this._parsing = false;
4768  this._cursor.offset = this._parent._cursor.offset;
4769
4770  switch(this.size) {
4771  case 0:
4772    this._rawo = new DataView(this._parent._rawo.buffer, this._cursor.offset, (this.parent._rawo.byteLength - this._cursor.offset));
4773    break;
4774  case 1:
4775      this._rawo = new DataView(this._parent._rawo.buffer, this._cursor.offset, this.largesize);
4776    break;
4777  default:
4778      this._rawo = new DataView(this._parent._rawo.buffer, this._cursor.offset, this.size);
4779  }
4780
4781  this._procField('size', 'uint', 32);
4782  this._procField('type', 'string', 4);
4783
4784  if (this.size === 1)      { this._procField('largesize', 'uint', 64); }
4785  if (this.type === 'uuid') { this._procFieldArray('usertype', 16, 'uint', 8); }
4786
4787  if (this._boxProcessors[this.type]) {
4788    this._boxProcessors[this.type].call(this);
4789  }
4790
4791  if (this._boxContainers.indexOf(this.type) !== -1) {
4792    for (var i = 0; i < this.boxes.length; i++) {
4793      this.boxes[i].write();
4794    }
4795  } 
4796
4797  if (this._data) {
4798    this._writeData(this._data);
4799  }
4800
4801  this._parent._cursor.offset += this.size;
4802
4803  return this.size;
4804};
4805
4806ISOBox.prototype._writeInt = function(size, value) {
4807  if (this._rawo) {
4808    var offset = this._cursor.offset - this._rawo.byteOffset;
4809    switch(size) {
4810    case 8:
4811      this._rawo.setInt8(offset, value);
4812      break;
4813    case 16:
4814      this._rawo.setInt16(offset, value);
4815      break;
4816    case 32:
4817      this._rawo.setInt32(offset, value);
4818      break;
4819    case 64:
4820      // Warning: JavaScript cannot handle 64-bit integers natively.
4821      // This will give unexpected results for integers >= 2^53
4822      var s1 = Math.floor(value / Math.pow(2,32));
4823      var s2 = value - (s1 * Math.pow(2,32));
4824      this._rawo.setUint32(offset, s1);
4825      this._rawo.setUint32(offset + 4, s2);
4826      break;
4827    }
4828    this._cursor.offset += (size >> 3);
4829  } else {
4830    this.size += (size >> 3);
4831  }
4832};
4833
4834ISOBox.prototype._writeUint = function(size, value) {
4835
4836  if (this._rawo) {
4837    var offset = this._cursor.offset - this._rawo.byteOffset,
4838        s1, s2;
4839    switch(size) {
4840    case 8:
4841      this._rawo.setUint8(offset, value);
4842      break;
4843    case 16:
4844      this._rawo.setUint16(offset, value);
4845      break;
4846    case 24:
4847      s1 = (value & 0xFFFF00) >> 8;
4848      s2 = (value & 0x0000FF);
4849      this._rawo.setUint16(offset, s1);
4850      this._rawo.setUint8(offset + 2, s2);
4851      break;
4852    case 32:
4853      this._rawo.setUint32(offset, value);
4854      break;
4855    case 64:
4856      // Warning: JavaScript cannot handle 64-bit integers natively.
4857      // This will give unexpected results for integers >= 2^53
4858      s1 = Math.floor(value / Math.pow(2,32));
4859      s2 = value - (s1 * Math.pow(2,32));
4860      this._rawo.setUint32(offset, s1);
4861      this._rawo.setUint32(offset + 4, s2);
4862      break;
4863    }
4864    this._cursor.offset += (size >> 3);
4865  } else {
4866    this.size += (size >> 3);
4867  }
4868};
4869
4870ISOBox.prototype._writeString = function(size, str) {
4871  for (var c = 0; c < size; c++) {
4872    this._writeUint(8, str.charCodeAt(c));
4873  }
4874};
4875
4876ISOBox.prototype._writeTerminatedString = function(str) {
4877  if (str.length === 0) {
4878    return;
4879  }
4880  for (var c = 0; c < str.length; c++) {
4881    this._writeUint(8, str.charCodeAt(c));
4882  }
4883  this._writeUint(8, 0);
4884};
4885
4886ISOBox.prototype._writeTemplate = function(size, value) {
4887  var pre = Math.floor(value);
4888  var post = (value - pre) * Math.pow(2, size / 2);
4889  this._writeUint(size / 2, pre);
4890  this._writeUint(size / 2, post);
4891};
4892
4893ISOBox.prototype._writeData = function(data) {
4894  var i;
4895  if (data instanceof Array) {
4896    if (!Uint8Array.from) {
4897      var typedArray = new Uint8Array(data.length);
4898      for (i = 0; i < data.length; i++) {
4899        typedArray[i] = data[i];
4900      }
4901      data = new DataView(typedArray.buffer);
4902    } else {
4903      data = new DataView(Uint8Array.from(data).buffer);
4904    }
4905  }
4906  if (data instanceof Uint8Array) {
4907    data = new DataView(data.buffer);
4908  }
4909  if (this._rawo) {
4910    var offset = this._cursor.offset - this._rawo.byteOffset;
4911    for (i = 0; i < data.byteLength; i++) {
4912        this._rawo.setUint8(offset + i, data.getUint8(i));
4913    }
4914    this._cursor.offset += data.byteLength;
4915  } else {
4916    this.size += data.byteLength;
4917  }
4918};
4919
4920ISOBox.prototype._writeUTF8String = function(string) {
4921  var u = ISOBoxer.Utils.utf8ToByteArray(string);
4922  if (this._rawo) {
4923    var dataView = new DataView(this._rawo.buffer, this._cursor.offset, u.length);
4924    for (var i = 0; i < u.length; i++) {
4925      dataView.setUint8(i, u[i]);
4926    }
4927  } else {
4928    this.size += u.length;
4929  }
4930};
4931
4932ISOBox.prototype._writeField = function(type, size, value) {
4933  switch (type) {
4934  case 'uint':
4935    this._writeUint(size, value);
4936    break;
4937  case 'int':
4938    this._writeInt(size, value);
4939    break;
4940  case 'template':
4941    this._writeTemplate(size, value);
4942    break;
4943  case 'string':
4944      if (size == -1) {
4945        this._writeTerminatedString(value);
4946      } else {
4947        this._writeString(size, value);
4948      }
4949      break;
4950  case 'data':
4951    this._writeData(value);
4952    break;
4953  case 'utf8':
4954    this._writeUTF8String(value);
4955    break;
4956  default:
4957    break;
4958  }
4959};
4960
4961// ISO/IEC 14496-15:2014 - avc1 box
4962ISOBox.prototype._boxProcessors['avc1'] = ISOBox.prototype._boxProcessors['encv'] = function() {
4963  // SampleEntry fields
4964  this._procFieldArray('reserved1', 6,    'uint', 8);
4965  this._procField('data_reference_index', 'uint', 16);
4966  // VisualSampleEntry fields
4967  this._procField('pre_defined1',         'uint',     16);
4968  this._procField('reserved2',            'uint',     16);
4969  this._procFieldArray('pre_defined2', 3, 'uint',     32);
4970  this._procField('width',                'uint',     16);
4971  this._procField('height',               'uint',     16);
4972  this._procField('horizresolution',      'template', 32);
4973  this._procField('vertresolution',       'template', 32);
4974  this._procField('reserved3',            'uint',     32);
4975  this._procField('frame_count',          'uint',     16);
4976  this._procFieldArray('compressorname', 32,'uint',    8);
4977  this._procField('depth',                'uint',     16);
4978  this._procField('pre_defined3',         'int',      16);
4979  // AVCSampleEntry fields
4980  this._procField('config', 'data', -1);
4981};
4982
4983// ISO/IEC 14496-12:2012 - 8.7.2 Data Reference Box
4984ISOBox.prototype._boxProcessors['dref'] = function() {
4985  this._procFullBox();
4986  this._procField('entry_count', 'uint', 32);
4987  this._procSubBoxes('entries', this.entry_count);
4988};
4989
4990// ISO/IEC 14496-12:2012 - 8.6.6 Edit List Box
4991ISOBox.prototype._boxProcessors['elst'] = function() {
4992  this._procFullBox();
4993  this._procField('entry_count', 'uint', 32);
4994  this._procEntries('entries', this.entry_count, function(entry) {
4995    this._procEntryField(entry, 'segment_duration',     'uint', (this.version === 1) ? 64 : 32);
4996    this._procEntryField(entry, 'media_time',           'int',  (this.version === 1) ? 64 : 32);
4997    this._procEntryField(entry, 'media_rate_integer',   'int',  16);
4998    this._procEntryField(entry, 'media_rate_fraction',  'int',  16);
4999  });
5000};
5001
5002// ISO/IEC 23009-1:2014 - 5.10.3.3 Event Message Box
5003ISOBox.prototype._boxProcessors['emsg'] = function() {
5004  this._procFullBox();
5005  this._procField('scheme_id_uri',            'string', -1);
5006  this._procField('value',                    'string', -1);
5007  this._procField('timescale',                'uint',   32);
5008  this._procField('presentation_time_delta',  'uint',   32);
5009  this._procField('event_duration',           'uint',   32);
5010  this._procField('id',                       'uint',   32);
5011  this._procField('message_data',             'data',   -1);
5012};
5013
5014// ISO/IEC 14496-12:2012 - 8.1.2 Free Space Box
5015ISOBox.prototype._boxProcessors['free'] = ISOBox.prototype._boxProcessors['skip'] = function() {
5016  this._procField('data', 'data', -1);
5017};
5018
5019// ISO/IEC 14496-12:2012 - 8.12.2 Original Format Box
5020ISOBox.prototype._boxProcessors['frma'] = function() {
5021  this._procField('data_format', 'uint', 32);
5022};
5023// ISO/IEC 14496-12:2012 - 4.3 File Type Box / 8.16.2 Segment Type Box
5024ISOBox.prototype._boxProcessors['ftyp'] =
5025ISOBox.prototype._boxProcessors['styp'] = function() {
5026  this._procField('major_brand', 'string', 4);
5027  this._procField('minor_version', 'uint', 32);
5028  var nbCompatibleBrands = -1;
5029  if (this._parsing) {
5030    nbCompatibleBrands = (this._raw.byteLength - (this._cursor.offset - this._raw.byteOffset)) / 4;
5031  }
5032  this._procFieldArray('compatible_brands', nbCompatibleBrands, 'string', 4);
5033};
5034
5035// ISO/IEC 14496-12:2012 - 8.4.3 Handler Reference Box
5036ISOBox.prototype._boxProcessors['hdlr'] = function() {
5037  this._procFullBox();
5038  this._procField('pre_defined',      'uint',   32);
5039  this._procField('handler_type',     'string', 4);
5040  this._procFieldArray('reserved', 3, 'uint', 32);
5041  this._procField('name',             'string', -1);
5042};
5043
5044// ISO/IEC 14496-12:2012 - 8.1.1 Media Data Box
5045ISOBox.prototype._boxProcessors['mdat'] = function() {
5046  this._procField('data', 'data', -1);
5047};
5048
5049// ISO/IEC 14496-12:2012 - 8.4.2 Media Header Box
5050ISOBox.prototype._boxProcessors['mdhd'] = function() {
5051  this._procFullBox();
5052  this._procField('creation_time',      'uint', (this.version == 1) ? 64 : 32);
5053  this._procField('modification_time',  'uint', (this.version == 1) ? 64 : 32);
5054  this._procField('timescale',          'uint', 32);
5055  this._procField('duration',           'uint', (this.version == 1) ? 64 : 32);
5056  if (!this._parsing && typeof this.language === 'string') {
5057    // In case of writing and language has been set as a string, then convert it into char codes array
5058    this.language = ((this.language.charCodeAt(0) - 0x60) << 10) |
5059                    ((this.language.charCodeAt(1) - 0x60) << 5) |
5060                    ((this.language.charCodeAt(2) - 0x60));
5061  }
5062  this._procField('language',           'uint', 16);
5063  if (this._parsing) {
5064    this.language = String.fromCharCode(((this.language >> 10) & 0x1F) + 0x60,
5065                                        ((this.language >> 5) & 0x1F) + 0x60,
5066                                        (this.language & 0x1F) + 0x60);
5067  }
5068  this._procField('pre_defined',        'uint', 16);
5069};
5070
5071// ISO/IEC 14496-12:2012 - 8.8.2 Movie Extends Header Box
5072ISOBox.prototype._boxProcessors['mehd'] = function() {
5073  this._procFullBox();
5074  this._procField('fragment_duration', 'uint', (this.version == 1) ? 64 : 32);
5075};
5076
5077// ISO/IEC 14496-12:2012 - 8.8.5 Movie Fragment Header Box
5078ISOBox.prototype._boxProcessors['mfhd'] = function() {
5079  this._procFullBox();
5080  this._procField('sequence_number', 'uint', 32);
5081};
5082
5083// ISO/IEC 14496-12:2012 - 8.8.11 Movie Fragment Random Access Box
5084ISOBox.prototype._boxProcessors['mfro'] = function() {
5085  this._procFullBox();
5086  this._procField('mfra_size', 'uint', 32); // Called mfra_size to distinguish from the normal "size" attribute of a box
5087};
5088
5089
5090// ISO/IEC 14496-12:2012 - 8.5.2.2 mp4a box (use AudioSampleEntry definition and naming)
5091ISOBox.prototype._boxProcessors['mp4a'] = ISOBox.prototype._boxProcessors['enca'] = function() {
5092  // SampleEntry fields
5093  this._procFieldArray('reserved1', 6,    'uint', 8);
5094  this._procField('data_reference_index', 'uint', 16);
5095  // AudioSampleEntry fields
5096  this._procFieldArray('reserved2', 2,    'uint', 32);
5097  this._procField('channelcount',         'uint', 16);
5098  this._procField('samplesize',           'uint', 16);
5099  this._procField('pre_defined',          'uint', 16);
5100  this._procField('reserved3',            'uint', 16);
5101  this._procField('samplerate',           'template', 32);
5102  // ESDescriptor fields
5103  this._procField('esds',                 'data', -1);
5104};
5105
5106// ISO/IEC 14496-12:2012 - 8.2.2 Movie Header Box
5107ISOBox.prototype._boxProcessors['mvhd'] = function() {
5108  this._procFullBox();
5109  this._procField('creation_time',      'uint',     (this.version == 1) ? 64 : 32);
5110  this._procField('modification_time',  'uint',     (this.version == 1) ? 64 : 32);
5111  this._procField('timescale',          'uint',     32);
5112  this._procField('duration',           'uint',     (this.version == 1) ? 64 : 32);
5113  this._procField('rate',               'template', 32);
5114  this._procField('volume',             'template', 16);
5115  this._procField('reserved1',          'uint',  16);
5116  this._procFieldArray('reserved2', 2,  'uint',     32);
5117  this._procFieldArray('matrix', 9,     'template', 32);
5118  this._procFieldArray('pre_defined', 6,'uint',   32);
5119  this._procField('next_track_ID',      'uint',     32);
5120};
5121
5122// ISO/IEC 14496-30:2014 - WebVTT Cue Payload Box.
5123ISOBox.prototype._boxProcessors['payl'] = function() {
5124  this._procField('cue_text', 'utf8');
5125};
5126
5127//ISO/IEC 23001-7:2011 - 8.1 Protection System Specific Header Box
5128ISOBox.prototype._boxProcessors['pssh'] = function() {
5129  this._procFullBox();
5130  
5131  this._procFieldArray('SystemID', 16, 'uint', 8);
5132  this._procField('DataSize', 'uint', 32);
5133  this._procFieldArray('Data', this.DataSize, 'uint', 8);
5134};
5135// ISO/IEC 14496-12:2012 - 8.12.5 Scheme Type Box
5136ISOBox.prototype._boxProcessors['schm'] = function() {
5137    this._procFullBox();
5138    
5139    this._procField('scheme_type', 'uint', 32);
5140    this._procField('scheme_version', 'uint', 32);
5141
5142    if (this.flags & 0x000001) {
5143        this._procField('scheme_uri', 'string', -1);
5144    }
5145};
5146// ISO/IEC 14496-12:2012 - 8.6.4.1 sdtp box 
5147ISOBox.prototype._boxProcessors['sdtp'] = function() {
5148  this._procFullBox();
5149
5150  var sample_count = -1;
5151  if (this._parsing) {
5152    sample_count = (this._raw.byteLength - (this._cursor.offset - this._raw.byteOffset));
5153  }
5154
5155  this._procFieldArray('sample_dependency_table', sample_count, 'uint', 8);
5156};
5157
5158// ISO/IEC 14496-12:2012 - 8.16.3 Segment Index Box
5159ISOBox.prototype._boxProcessors['sidx'] = function() {
5160  this._procFullBox();
5161  this._procField('reference_ID', 'uint', 32);
5162  this._procField('timescale', 'uint', 32);
5163  this._procField('earliest_presentation_time', 'uint', (this.version == 1) ? 64 : 32);
5164  this._procField('first_offset', 'uint', (this.version == 1) ? 64 : 32);
5165  this._procField('reserved', 'uint', 16);
5166  this._procField('reference_count', 'uint', 16);
5167  this._procEntries('references', this.reference_count, function(entry) {
5168    if (!this._parsing) {
5169      entry.reference  = (entry.reference_type  & 0x00000001) << 31;
5170      entry.reference |= (entry.referenced_size & 0x7FFFFFFF);
5171      entry.sap  = (entry.starts_with_SAP & 0x00000001) << 31;
5172      entry.sap |= (entry.SAP_type        & 0x00000003) << 28;
5173      entry.sap |= (entry.SAP_delta_time  & 0x0FFFFFFF);
5174    }
5175    this._procEntryField(entry, 'reference', 'uint', 32);
5176    this._procEntryField(entry, 'subsegment_duration', 'uint', 32);
5177    this._procEntryField(entry, 'sap', 'uint', 32);
5178    if (this._parsing) {
5179      entry.reference_type = (entry.reference >> 31) & 0x00000001;
5180      entry.referenced_size = entry.reference & 0x7FFFFFFF;
5181      entry.starts_with_SAP  = (entry.sap >> 31) & 0x00000001;
5182      entry.SAP_type = (entry.sap >> 28) & 0x00000007;
5183      entry.SAP_delta_time = (entry.sap  & 0x0FFFFFFF);
5184    }
5185  });
5186};
5187
5188// ISO/IEC 14496-12:2012 - 8.4.5.3 Sound Media Header Box
5189ISOBox.prototype._boxProcessors['smhd'] = function() {
5190  this._procFullBox();
5191  this._procField('balance',  'uint', 16);
5192  this._procField('reserved', 'uint', 16);
5193};
5194
5195// ISO/IEC 14496-12:2012 - 8.16.4 Subsegment Index Box
5196ISOBox.prototype._boxProcessors['ssix'] = function() {
5197  this._procFullBox();
5198  this._procField('subsegment_count', 'uint', 32);
5199  this._procEntries('subsegments', this.subsegment_count, function(subsegment) {
5200    this._procEntryField(subsegment, 'ranges_count', 'uint', 32);
5201    this._procSubEntries(subsegment, 'ranges', subsegment.ranges_count, function(range) {
5202      this._procEntryField(range, 'level', 'uint', 8);
5203      this._procEntryField(range, 'range_size', 'uint', 24);
5204    });
5205  });
5206};
5207
5208// ISO/IEC 14496-12:2012 - 8.5.2 Sample Description Box
5209ISOBox.prototype._boxProcessors['stsd'] = function() {
5210  this._procFullBox();
5211  this._procField('entry_count', 'uint', 32);
5212  this._procSubBoxes('entries', this.entry_count);
5213};
5214
5215// ISO/IEC 14496-12:2015 - 8.7.7 Sub-Sample Information Box
5216ISOBox.prototype._boxProcessors['subs'] = function () {
5217  this._procFullBox();
5218  this._procField('entry_count', 'uint', 32);
5219  this._procEntries('entries', this.entry_count, function(entry) {
5220    this._procEntryField(entry, 'sample_delta', 'uint', 32);
5221    this._procEntryField(entry, 'subsample_count', 'uint', 16);
5222    this._procSubEntries(entry, 'subsamples', entry.subsample_count, function(subsample) {
5223      this._procEntryField(subsample, 'subsample_size', 'uint', (this.version === 1) ? 32 : 16);
5224      this._procEntryField(subsample, 'subsample_priority', 'uint', 8);
5225      this._procEntryField(subsample, 'discardable', 'uint', 8);
5226      this._procEntryField(subsample, 'codec_specific_parameters', 'uint', 32);
5227    });
5228  });
5229};
5230
5231//ISO/IEC 23001-7:2011 - 8.2 Track Encryption Box
5232ISOBox.prototype._boxProcessors['tenc'] = function() {
5233    this._procFullBox();
5234
5235    this._procField('default_IsEncrypted', 'uint', 24);
5236    this._procField('default_IV_size', 'uint', 8);
5237    this._procFieldArray('default_KID', 16,    'uint', 8);
5238 };
5239
5240// ISO/IEC 14496-12:2012 - 8.8.12 Track Fragmnent Decode Time
5241ISOBox.prototype._boxProcessors['tfdt'] = function() {
5242  this._procFullBox();
5243  this._procField('baseMediaDecodeTime', 'uint', (this.version == 1) ? 64 : 32);
5244};
5245
5246// ISO/IEC 14496-12:2012 - 8.8.7 Track Fragment Header Box
5247ISOBox.prototype._boxProcessors['tfhd'] = function() {
5248  this._procFullBox();
5249  this._procField('track_ID', 'uint', 32);
5250  if (this.flags & 0x01) this._procField('base_data_offset',          'uint', 64);
5251  if (this.flags & 0x02) this._procField('sample_description_offset', 'uint', 32);
5252  if (this.flags & 0x08) this._procField('default_sample_duration',   'uint', 32);
5253  if (this.flags & 0x10) this._procField('default_sample_size',       'uint', 32);
5254  if (this.flags & 0x20) this._procField('default_sample_flags',      'uint', 32);
5255};
5256
5257// ISO/IEC 14496-12:2012 - 8.8.10 Track Fragment Random Access Box
5258ISOBox.prototype._boxProcessors['tfra'] = function() {
5259  this._procFullBox();
5260  this._procField('track_ID', 'uint', 32);
5261  if (!this._parsing) {
5262    this.reserved = 0;
5263    this.reserved |= (this.length_size_of_traf_num  & 0x00000030) << 4;
5264    this.reserved |= (this.length_size_of_trun_num  & 0x0000000C) << 2;
5265    this.reserved |= (this.length_size_of_sample_num  & 0x00000003);
5266  }
5267  this._procField('reserved', 'uint', 32);
5268  if (this._parsing) {
5269    this.length_size_of_traf_num = (this.reserved & 0x00000030) >> 4;
5270    this.length_size_of_trun_num = (this.reserved & 0x0000000C) >> 2;
5271    this.length_size_of_sample_num = (this.reserved & 0x00000003);
5272  }
5273  this._procField('number_of_entry', 'uint', 32);
5274  this._procEntries('entries', this.number_of_entry, function(entry) {
5275    this._procEntryField(entry, 'time', 'uint', (this.version === 1) ? 64 : 32);
5276    this._procEntryField(entry, 'moof_offset', 'uint', (this.version === 1) ? 64 : 32);
5277    this._procEntryField(entry, 'traf_number', 'uint', (this.length_size_of_traf_num + 1) * 8);
5278    this._procEntryField(entry, 'trun_number', 'uint', (this.length_size_of_trun_num + 1) * 8);
5279    this._procEntryField(entry, 'sample_number', 'uint', (this.length_size_of_sample_num + 1) * 8);
5280  });
5281};
5282
5283// ISO/IEC 14496-12:2012 - 8.3.2 Track Header Box
5284ISOBox.prototype._boxProcessors['tkhd'] = function() {
5285  this._procFullBox();
5286  this._procField('creation_time',      'uint',     (this.version == 1) ? 64 : 32);
5287  this._procField('modification_time',  'uint',     (this.version == 1) ? 64 : 32);
5288  this._procField('track_ID',           'uint',     32);
5289  this._procField('reserved1',          'uint',     32);
5290  this._procField('duration',           'uint',     (this.version == 1) ? 64 : 32);
5291  this._procFieldArray('reserved2', 2,  'uint',     32);
5292  this._procField('layer',              'uint',     16);
5293  this._procField('alternate_group',    'uint',     16);
5294  this._procField('volume',             'template', 16);
5295  this._procField('reserved3',          'uint',     16);
5296  this._procFieldArray('matrix', 9,     'template', 32);
5297  this._procField('width',              'template', 32);
5298  this._procField('height',             'template', 32);
5299};
5300
5301// ISO/IEC 14496-12:2012 - 8.8.3 Track Extends Box
5302ISOBox.prototype._boxProcessors['trex'] = function() {
5303  this._procFullBox();
5304  this._procField('track_ID',                         'uint', 32);
5305  this._procField('default_sample_description_index', 'uint', 32);
5306  this._procField('default_sample_duration',          'uint', 32);
5307  this._procField('default_sample_size',              'uint', 32);
5308  this._procField('default_sample_flags',             'uint', 32);
5309};
5310
5311// ISO/IEC 14496-12:2012 - 8.8.8 Track Run Box
5312// Note: the 'trun' box has a direct relation to the 'tfhd' box for defaults.
5313// These defaults are not set explicitly here, but are left to resolve for the user.
5314ISOBox.prototype._boxProcessors['trun'] = function() {
5315  this._procFullBox();
5316  this._procField('sample_count', 'uint', 32);
5317  if (this.flags & 0x1) this._procField('data_offset', 'int', 32);
5318  if (this.flags & 0x4) this._procField('first_sample_flags', 'uint', 32);
5319  this._procEntries('samples', this.sample_count, function(sample) {
5320    if (this.flags & 0x100) this._procEntryField(sample, 'sample_duration', 'uint', 32);
5321    if (this.flags & 0x200) this._procEntryField(sample, 'sample_size', 'uint', 32);
5322    if (this.flags & 0x400) this._procEntryField(sample, 'sample_flags', 'uint', 32);
5323    if (this.flags & 0x800) this._procEntryField(sample, 'sample_composition_time_offset', (this.version === 1) ? 'int' : 'uint',  32);
5324  });
5325};
5326
5327// ISO/IEC 14496-12:2012 - 8.7.2 Data Reference Box
5328ISOBox.prototype._boxProcessors['url '] = ISOBox.prototype._boxProcessors['urn '] = function() {
5329  this._procFullBox();
5330  if (this.type === 'urn ') {
5331    this._procField('name', 'string', -1);
5332  }
5333  this._procField('location', 'string', -1);
5334};
5335
5336// ISO/IEC 14496-30:2014 - WebVTT Source Label Box
5337ISOBox.prototype._boxProcessors['vlab'] = function() {
5338  this._procField('source_label', 'utf8');
5339};
5340
5341// ISO/IEC 14496-12:2012 - 8.4.5.2 Video Media Header Box
5342ISOBox.prototype._boxProcessors['vmhd'] = function() {
5343  this._procFullBox();
5344  this._procField('graphicsmode', 'uint', 16);
5345  this._procFieldArray('opcolor', 3, 'uint', 16);
5346};
5347
5348// ISO/IEC 14496-30:2014 - WebVTT Configuration Box
5349ISOBox.prototype._boxProcessors['vttC'] = function() {
5350  this._procField('config', 'utf8');
5351};
5352
5353// ISO/IEC 14496-30:2014 - WebVTT Empty Sample Box
5354ISOBox.prototype._boxProcessors['vtte'] = function() {
5355  // Nothing should happen here.
5356};
5357
5358},{}],12:[function(_dereq_,module,exports){
5359(function (Buffer){
5360// Copyright Joyent, Inc. and other Node contributors.
5361//
5362// Permission is hereby granted, free of charge, to any person obtaining a
5363// copy of this software and associated documentation files (the
5364// "Software"), to deal in the Software without restriction, including
5365// without limitation the rights to use, copy, modify, merge, publish,
5366// distribute, sublicense, and/or sell copies of the Software, and to permit
5367// persons to whom the Software is furnished to do so, subject to the
5368// following conditions:
5369//
5370// The above copyright notice and this permission notice shall be included
5371// in all copies or substantial portions of the Software.
5372//
5373// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
5374// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
5375// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
5376// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
5377// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
5378// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
5379// USE OR OTHER DEALINGS IN THE SOFTWARE.
5380
5381// NOTE: These type checking functions intentionally don't use `instanceof`
5382// because it is fragile and can be easily faked with `Object.create()`.
5383
5384function isArray(arg) {
5385  if (Array.isArray) {
5386    return Array.isArray(arg);
5387  }
5388  return objectToString(arg) === '[object Array]';
5389}
5390exports.isArray = isArray;
5391
5392function isBoolean(arg) {
5393  return typeof arg === 'boolean';
5394}
5395exports.isBoolean = isBoolean;
5396
5397function isNull(arg) {
5398  return arg === null;
5399}
5400exports.isNull = isNull;
5401
5402function isNullOrUndefined(arg) {
5403  return arg == null;
5404}
5405exports.isNullOrUndefined = isNullOrUndefined;
5406
5407function isNumber(arg) {
5408  return typeof arg === 'number';
5409}
5410exports.isNumber = isNumber;
5411
5412function isString(arg) {
5413  return typeof arg === 'string';
5414}
5415exports.isString = isString;
5416
5417function isSymbol(arg) {
5418  return typeof arg === 'symbol';
5419}
5420exports.isSymbol = isSymbol;
5421
5422function isUndefined(arg) {
5423  return arg === void 0;
5424}
5425exports.isUndefined = isUndefined;
5426
5427function isRegExp(re) {
5428  return objectToString(re) === '[object RegExp]';
5429}
5430exports.isRegExp = isRegExp;
5431
5432function isObject(arg) {
5433  return typeof arg === 'object' && arg !== null;
5434}
5435exports.isObject = isObject;
5436
5437function isDate(d) {
5438  return objectToString(d) === '[object Date]';
5439}
5440exports.isDate = isDate;
5441
5442function isError(e) {
5443  return (objectToString(e) === '[object Error]' || e instanceof Error);
5444}
5445exports.isError = isError;
5446
5447function isFunction(arg) {
5448  return typeof arg === 'function';
5449}
5450exports.isFunction = isFunction;
5451
5452function isPrimitive(arg) {
5453  return arg === null ||
5454         typeof arg === 'boolean' ||
5455         typeof arg === 'number' ||
5456         typeof arg === 'string' ||
5457         typeof arg === 'symbol' ||  // ES6 symbol
5458         typeof arg === 'undefined';
5459}
5460exports.isPrimitive = isPrimitive;
5461
5462exports.isBuffer = Buffer.isBuffer;
5463
5464function objectToString(o) {
5465  return Object.prototype.toString.call(o);
5466}
5467
5468}).call(this,{"isBuffer":_dereq_(26)})
5469
5470},{"26":26}],13:[function(_dereq_,module,exports){
5471var pSlice = Array.prototype.slice;
5472var objectKeys = _dereq_(15);
5473var isArguments = _dereq_(14);
5474
5475var deepEqual = module.exports = function (actual, expected, opts) {
5476  if (!opts) opts = {};
5477  // 7.1. All identical values are equivalent, as determined by ===.
5478  if (actual === expected) {
5479    return true;
5480
5481  } else if (actual instanceof Date && expected instanceof Date) {
5482    return actual.getTime() === expected.getTime();
5483
5484  // 7.3. Other pairs that do not both pass typeof value == 'object',
5485  // equivalence is determined by ==.
5486  } else if (!actual || !expected || typeof actual != 'object' && typeof expected != 'object') {
5487    return opts.strict ? actual === expected : actual == expected;
5488
5489  // 7.4. For all other Object pairs, including Array objects, equivalence is
5490  // determined by having the same number of owned properties (as verified
5491  // with Object.prototype.hasOwnProperty.call), the same set of keys
5492  // (although not necessarily the same order), equivalent values for every
5493  // corresponding key, and an identical 'prototype' property. Note: this
5494  // accounts for both named and indexed properties on Arrays.
5495  } else {
5496    return objEquiv(actual, expected, opts);
5497  }
5498}
5499
5500function isUndefinedOrNull(value) {
5501  return value === null || value === undefined;
5502}
5503
5504function isBuffer (x) {
5505  if (!x || typeof x !== 'object' || typeof x.length !== 'number') return false;
5506  if (typeof x.copy !== 'function' || typeof x.slice !== 'function') {
5507    return false;
5508  }
5509  if (x.length > 0 && typeof x[0] !== 'number') return false;
5510  return true;
5511}
5512
5513function objEquiv(a, b, opts) {
5514  var i, key;
5515  if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
5516    return false;
5517  // an identical 'prototype' property.
5518  if (a.prototype !== b.prototype) return false;
5519  //~~~I've managed to break Object.keys through screwy arguments passing.
5520  //   Converting to array solves the problem.
5521  if (isArguments(a)) {
5522    if (!isArguments(b)) {
5523      return false;
5524    }
5525    a = pSlice.call(a);
5526    b = pSlice.call(b);
5527    return deepEqual(a, b, opts);
5528  }
5529  if (isBuffer(a)) {
5530    if (!isBuffer(b)) {
5531      return false;
5532    }
5533    if (a.length !== b.length) return false;
5534    for (i = 0; i < a.length; i++) {
5535      if (a[i] !== b[i]) return false;
5536    }
5537    return true;
5538  }
5539  try {
5540    var ka = objectKeys(a),
5541        kb = objectKeys(b);
5542  } catch (e) {//happens when one is a string literal and the other isn't
5543    return false;
5544  }
5545  // having the same number of owned properties (keys incorporates
5546  // hasOwnProperty)
5547  if (ka.length != kb.length)
5548    return false;
5549  //the same set of keys (although not necessarily the same order),
5550  ka.sort();
5551  kb.sort();
5552  //~~~cheap key test
5553  for (i = ka.length - 1; i >= 0; i--) {
5554    if (ka[i] != kb[i])
5555      return false;
5556  }
5557  //equivalent values for every corresponding key, and
5558  //~~~possibly expensive deep test
5559  for (i = ka.length - 1; i >= 0; i--) {
5560    key = ka[i];
5561    if (!deepEqual(a[key], b[key], opts)) return false;
5562  }
5563  return typeof a === typeof b;
5564}
5565
5566},{"14":14,"15":15}],14:[function(_dereq_,module,exports){
5567var supportsArgumentsClass = (function(){
5568  return Object.prototype.toString.call(arguments)
5569})() == '[object Arguments]';
5570
5571exports = module.exports = supportsArgumentsClass ? supported : unsupported;
5572
5573exports.supported = supported;
5574function supported(object) {
5575  return Object.prototype.toString.call(object) == '[object Arguments]';
5576};
5577
5578exports.unsupported = unsupported;
5579function unsupported(object){
5580  return object &&
5581    typeof object == 'object' &&
5582    typeof object.length == 'number' &&
5583    Object.prototype.hasOwnProperty.call(object, 'callee') &&
5584    !Object.prototype.propertyIsEnumerable.call(object, 'callee') ||
5585    false;
5586};
5587
5588},{}],15:[function(_dereq_,module,exports){
5589exports = module.exports = typeof Object.keys === 'function'
5590  ? Object.keys : shim;
5591
5592exports.shim = shim;
5593function shim (obj) {
5594  var keys = [];
5595  for (var key in obj) keys.push(key);
5596  return keys;
5597}
5598
5599},{}],16:[function(_dereq_,module,exports){
5600// Copyright Joyent, Inc. and other Node contributors.
5601//
5602// Permission is hereby granted, free of charge, to any person obtaining a
5603// copy of this software and associated documentation files (the
5604// "Software"), to deal in the Software without restriction, including
5605// without limitation the rights to use, copy, modify, merge, publish,
5606// distribute, sublicense, and/or sell copies of the Software, and to permit
5607// persons to whom the Software is furnished to do so, subject to the
5608// following conditions:
5609//
5610// The above copyright notice and this permission notice shall be included
5611// in all copies or substantial portions of the Software.
5612//
5613// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
5614// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
5615// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
5616// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
5617// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
5618// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
5619// USE OR OTHER DEALINGS IN THE SOFTWARE.
5620
5621function EventEmitter() {
5622  this._events = this._events || {};
5623  this._maxListeners = this._maxListeners || undefined;
5624}
5625module.exports = EventEmitter;
5626
5627// Backwards-compat with node 0.10.x
5628EventEmitter.EventEmitter = EventEmitter;
5629
5630EventEmitter.prototype._events = undefined;
5631EventEmitter.prototype._maxListeners = undefined;
5632
5633// By default EventEmitters will print a warning if more than 10 listeners are
5634// added to it. This is a useful default which helps finding memory leaks.
5635EventEmitter.defaultMaxListeners = 10;
5636
5637// Obviously not all Emitters should be limited to 10. This function allows
5638// that to be increased. Set to zero for unlimited.
5639EventEmitter.prototype.setMaxListeners = function(n) {
5640  if (!isNumber(n) || n < 0 || isNaN(n))
5641    throw TypeError('n must be a positive number');
5642  this._maxListeners = n;
5643  return this;
5644};
vendor: 4,148 bytes, lines 5645-5795
5645
5646EventEmitter.prototype.emit = function(type) {
5647  var er, handler, len, args, i, listeners;
5648
5649  if (!this._events)
5650    this._events = {};
5651
5652  // If there is no 'error' event listener then throw.
5653  if (type === 'error') {
5654    if (!this._events.error ||
5655        (isObject(this._events.error) && !this._events.error.length)) {
5656      er = arguments[1];
5657      if (er instanceof Error) {
5658        throw er; // Unhandled 'error' event
5659      }
5660      throw TypeError('Uncaught, unspecified "error" event.');
5661    }
5662  }
5663
5664  handler = this._events[type];
5665
5666  if (isUndefined(handler))
5667    return false;
5668
5669  if (isFunction(handler)) {
5670    switch (arguments.length) {
5671      // fast cases
5672      case 1:
5673        handler.call(this);
5674        break;
5675      case 2:
5676        handler.call(this, arguments[1]);
5677        break;
5678      case 3:
5679        handler.call(this, arguments[1], arguments[2]);
5680        break;
5681      // slower
5682      default:
5683        len = arguments.length;
5684        args = new Array(len - 1);
5685        for (i = 1; i < len; i++)
5686          args[i - 1] = arguments[i];
5687        handler.apply(this, args);
5688    }
5689  } else if (isObject(handler)) {
5690    len = arguments.length;
5691    args = new Array(len - 1);
5692    for (i = 1; i < len; i++)
5693      args[i - 1] = arguments[i];
5694
5695    listeners = handler.slice();
5696    len = listeners.length;
5697    for (i = 0; i < len; i++)
5698      listeners[i].apply(this, args);
5699  }
5700
5701  return true;
5702};
5703
5704EventEmitter.prototype.addListener = function(type, listener) {
5705  var m;
5706
5707  if (!isFunction(listener))
5708    throw TypeError('listener must be a function');
5709
5710  if (!this._events)
5711    this._events = {};
5712
5713  // To avoid recursion in the case that type === "newListener"! Before
5714  // adding it to the listeners, first emit "newListener".
5715  if (this._events.newListener)
5716    this.emit('newListener', type,
5717              isFunction(listener.listener) ?
5718              listener.listener : listener);
5719
5720  if (!this._events[type])
5721    // Optimize the case of one listener. Don't need the extra array object.
5722    this._events[type] = listener;
5723  else if (isObject(this._events[type]))
5724    // If we've already got an array, just append.
5725    this._events[type].push(listener);
5726  else
5727    // Adding the second element, need to change to array.
5728    this._events[type] = [this._events[type], listener];
5729
5730  // Check for listener leak
5731  if (isObject(this._events[type]) && !this._events[type].warned) {
5732    var m;
5733    if (!isUndefined(this._maxListeners)) {
5734      m = this._maxListeners;
5735    } else {
5736      m = EventEmitter.defaultMaxListeners;
5737    }
5738
5739    if (m && m > 0 && this._events[type].length > m) {
5740      this._events[type].warned = true;
5741      console.error('(node) warning: possible EventEmitter memory ' +
5742                    'leak detected. %d listeners added. ' +
5743                    'Use emitter.setMaxListeners() to increase limit.',
5744                    this._events[type].length);
5745      if (typeof console.trace === 'function') {
5746        // not supported in IE 10
5747        console.trace();
5748      }
5749    }
5750  }
5751
5752  return this;
5753};
5754
5755EventEmitter.prototype.on = EventEmitter.prototype.addListener;
5756
5757EventEmitter.prototype.once = function(type, listener) {
5758  if (!isFunction(listener))
5759    throw TypeError('listener must be a function');
5760
5761  var fired = false;
5762
5763  function g() {
5764    this.removeListener(type, g);
5765
5766    if (!fired) {
5767      fired = true;
5768      listener.apply(this, arguments);
5769    }
5770  }
5771
5772  g.listener = listener;
5773  this.on(type, g);
5774
5775  return this;
5776};
5777
5778// emits a 'removeListener' event iff the listener was removed
5779EventEmitter.prototype.removeListener = function(type, listener) {
5780  var list, position, length, i;
5781
5782  if (!isFunction(listener))
5783    throw TypeError('listener must be a function');
5784
5785  if (!this._events || !this._events[type])
5786    return this;
5787
5788  list = this._events[type];
5789  length = list.length;
5790  position = -1;
5791
5792  if (list === listener ||
5793      (isFunction(list.listener) && list.listener === listener)) {
5794    delete this._events[type];
5795    if (this._events.removeListener)
vendor: 4,461 bytes, lines 5796-5983
5796      this.emit('removeListener', type, listener);
5797
5798  } else if (isObject(list)) {
5799    for (i = length; i-- > 0;) {
5800      if (list[i] === listener ||
5801          (list[i].listener && list[i].listener === listener)) {
5802        position = i;
5803        break;
5804      }
5805    }
5806
5807    if (position < 0)
5808      return this;
5809
5810    if (list.length === 1) {
5811      list.length = 0;
5812      delete this._events[type];
5813    } else {
5814      list.splice(position, 1);
5815    }
5816
5817    if (this._events.removeListener)
5818      this.emit('removeListener', type, listener);
5819  }
5820
5821  return this;
5822};
5823
5824EventEmitter.prototype.removeAllListeners = function(type) {
5825  var key, listeners;
5826
5827  if (!this._events)
5828    return this;
5829
5830  // not listening for removeListener, no need to emit
5831  if (!this._events.removeListener) {
5832    if (arguments.length === 0)
5833      this._events = {};
5834    else if (this._events[type])
5835      delete this._events[type];
5836    return this;
5837  }
5838
5839  // emit removeListener for all listeners on all events
5840  if (arguments.length === 0) {
5841    for (key in this._events) {
5842      if (key === 'removeListener') continue;
5843      this.removeAllListeners(key);
5844    }
5845    this.removeAllListeners('removeListener');
5846    this._events = {};
5847    return this;
5848  }
5849
5850  listeners = this._events[type];
5851
5852  if (isFunction(listeners)) {
5853    this.removeListener(type, listeners);
5854  } else {
5855    // LIFO order
5856    while (listeners.length)
5857      this.removeListener(type, listeners[listeners.length - 1]);
5858  }
5859  delete this._events[type];
5860
5861  return this;
5862};
5863
5864EventEmitter.prototype.listeners = function(type) {
5865  var ret;
5866  if (!this._events || !this._events[type])
5867    ret = [];
5868  else if (isFunction(this._events[type]))
5869    ret = [this._events[type]];
5870  else
5871    ret = this._events[type].slice();
5872  return ret;
5873};
5874
5875EventEmitter.listenerCount = function(emitter, type) {
5876  var ret;
5877  if (!emitter._events || !emitter._events[type])
5878    ret = 0;
5879  else if (isFunction(emitter._events[type]))
5880    ret = 1;
5881  else
5882    ret = emitter._events[type].length;
5883  return ret;
5884};
5885
5886function isFunction(arg) {
5887  return typeof arg === 'function';
5888}
5889
5890function isNumber(arg) {
5891  return typeof arg === 'number';
5892}
5893
5894function isObject(arg) {
5895  return typeof arg === 'object' && arg !== null;
5896}
5897
5898function isUndefined(arg) {
5899  return arg === void 0;
5900}
5901
5902},{}],17:[function(_dereq_,module,exports){
5903exports.read = function (buffer, offset, isLE, mLen, nBytes) {
5904  var e, m
5905  var eLen = nBytes * 8 - mLen - 1
5906  var eMax = (1 << eLen) - 1
5907  var eBias = eMax >> 1
5908  var nBits = -7
5909  var i = isLE ? (nBytes - 1) : 0
5910  var d = isLE ? -1 : 1
5911  var s = buffer[offset + i]
5912
5913  i += d
5914
5915  e = s & ((1 << (-nBits)) - 1)
5916  s >>= (-nBits)
5917  nBits += eLen
5918  for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
5919
5920  m = e & ((1 << (-nBits)) - 1)
5921  e >>= (-nBits)
5922  nBits += mLen
5923  for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
5924
5925  if (e === 0) {
5926    e = 1 - eBias
5927  } else if (e === eMax) {
5928    return m ? NaN : ((s ? -1 : 1) * Infinity)
5929  } else {
5930    m = m + Math.pow(2, mLen)
5931    e = e - eBias
5932  }
5933  return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
5934}
5935
5936exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
5937  var e, m, c
5938  var eLen = nBytes * 8 - mLen - 1
5939  var eMax = (1 << eLen) - 1
5940  var eBias = eMax >> 1
5941  var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
5942  var i = isLE ? 0 : (nBytes - 1)
5943  var d = isLE ? 1 : -1
5944  var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
5945
5946  value = Math.abs(value)
5947
5948  if (isNaN(value) || value === Infinity) {
5949    m = isNaN(value) ? 1 : 0
5950    e = eMax
5951  } else {
5952    e = Math.floor(Math.log(value) / Math.LN2)
5953    if (value * (c = Math.pow(2, -e)) < 1) {
5954      e--
5955      c *= 2
5956    }
5957    if (e + eBias >= 1) {
5958      value += rt / c
5959    } else {
5960      value += rt * Math.pow(2, 1 - eBias)
5961    }
5962    if (value * c >= 2) {
5963      e++
5964      c /= 2
5965    }
5966
5967    if (e + eBias >= eMax) {
5968      m = 0
5969      e = eMax
5970    } else if (e + eBias >= 1) {
5971      m = (value * c - 1) * Math.pow(2, mLen)
5972      e = e + eBias
5973    } else {
5974      m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
5975      e = 0
5976    }
5977  }
5978
5979  for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
5980
5981  e = (e << mLen) | m
5982  eLen += mLen
5983  for (; eLen > 0;
vendor: 11,395 bytes, lines 5983-6348
5983 buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
5984
5985  buffer[offset + i - d] |= s * 128
5986}
5987
5988},{}],18:[function(_dereq_,module,exports){
5989/* 
5990 * Copyright (c) 2016, Pierre-Anthony Lemieux <[email protected]>
5991 * All rights reserved.
5992 *
5993 * Redistribution and use in source and binary forms, with or without
5994 * modification, are permitted provided that the following conditions are met:
5995 *
5996 * * Redistributions of source code must retain the above copyright notice, this
5997 *   list of conditions and the following disclaimer.
5998 * * Redistributions in binary form must reproduce the above copyright notice,
5999 *   this list of conditions and the following disclaimer in the documentation
6000 *   and/or other materials provided with the distribution.
6001 *
6002 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
6003 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
6004 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
6005 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
6006 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
6007 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
6008 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
6009 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
6010 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
6011 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
6012 * POSSIBILITY OF SUCH DAMAGE.
6013 */
6014
6015/**
6016 * @module imscDoc
6017 */
6018
6019;
6020(function (imscDoc, sax, imscNames, imscStyles, imscUtils) {
6021
6022
6023    /**
6024     * Allows a client to provide callbacks to handle children of the <metadata> element
6025     * @typedef {Object} MetadataHandler
6026     * @property {?OpenTagCallBack} onOpenTag
6027     * @property {?CloseTagCallBack} onCloseTag
6028     * @property {?TextCallBack} onText
6029     */
6030
6031    /**
6032     * Called when the opening tag of an element node is encountered.
6033     * @callback OpenTagCallBack
6034     * @param {string} ns Namespace URI of the element
6035     * @param {string} name Local name of the element
6036     * @param {Object[]} attributes List of attributes, each consisting of a
6037     *                              `uri`, `name` and `value`
6038     */
6039
6040    /**
6041     * Called when the closing tag of an element node is encountered.
6042     * @callback CloseTagCallBack
6043     */
6044
6045    /**
6046     * Called when a text node is encountered.
6047     * @callback TextCallBack
6048     * @param {string} contents Contents of the text node
6049     */
6050
6051    /**
6052     * Parses an IMSC1 document into an opaque in-memory representation that exposes
6053     * a single method <pre>getMediaTimeEvents()</pre> that returns a list of time
6054     * offsets (in seconds) of the ISD, i.e. the points in time where the visual
6055     * representation of the document change. `metadataHandler` allows the caller to
6056     * be called back when nodes are present in <metadata> elements. 
6057     * 
6058     * @param {string} xmlstring XML document
6059     * @param {?module:imscUtils.ErrorHandler} errorHandler Error callback
6060     * @param {?MetadataHandler} metadataHandler Callback for <Metadata> elements
6061     * @returns {Object} Opaque in-memory representation of an IMSC1 document
6062     */
6063
6064    imscDoc.fromXML = function (xmlstring, errorHandler, metadataHandler) {
6065        var p = sax.parser(true, {xmlns: true});
6066        var estack = [];
6067        var xmllangstack = [];
6068        var xmlspacestack = [];
6069        var metadata_depth = 0;
6070        var doc = null;
6071
6072        p.onclosetag = function (node) {
6073
6074            if (estack[0] instanceof Styling) {
6075
6076                /* flatten chained referential styling */
6077
6078                for (var sid in estack[0].styles) {
6079
6080                    mergeChainedStyles(estack[0], estack[0].styles[sid], errorHandler);
6081
6082                }
6083
6084            } else if (estack[0] instanceof P || estack[0] instanceof Span) {
6085
6086                /* merge anonymous spans */
6087
6088                if (estack[0].contents.length > 1) {
6089
6090                    var cs = [estack[0].contents[0]];
6091
6092                    var c;
6093
6094                    for (c = 1; c < estack[0].contents.length; c++) {
6095
6096                        if (estack[0].contents[c] instanceof AnonymousSpan &&
6097                            cs[cs.length - 1] instanceof AnonymousSpan) {
6098
6099                            cs[cs.length - 1].text += estack[0].contents[c].text;
6100
6101                        } else {
6102
6103                            cs.push(estack[0].contents[c]);
6104
6105                        }
6106
6107                    }
6108
6109                    estack[0].contents = cs;
6110
6111                }
6112
6113                // remove redundant nested anonymous spans (9.3.3(1)(c))
6114
6115                if (estack[0] instanceof Span &&
6116                    estack[0].contents.length === 1 &&
6117                    estack[0].contents[0] instanceof AnonymousSpan &&
6118                    estack[0].text === null) {
6119
6120                    estack[0].text = estack[0].contents[0].text;
6121                    delete estack[0].contents;
6122
6123                }
6124
6125            } else if (estack[0] instanceof ForeignElement) {
6126
6127                if (estack[0].node.uri === imscNames.ns_tt &&
6128                    estack[0].node.local === 'metadata') {
6129
6130                    /* leave the metadata element */
6131
6132                    metadata_depth--;
6133
6134                } else if (metadata_depth > 0 &&
6135                    metadataHandler &&
6136                    'onCloseTag' in metadataHandler) {
6137
6138                    /* end of child of metadata element */
6139
6140                    metadataHandler.onCloseTag();
6141
6142                }
6143
6144            }
6145
6146            // TODO: delete stylerefs?
6147
6148            // maintain the xml:space stack
6149
6150            xmlspacestack.shift();
6151
6152            // maintain the xml:lang stack
6153
6154            xmllangstack.shift();
6155
6156            // prepare for the next element
6157
6158            estack.shift();
6159        };
6160
6161        p.ontext = function (str) {
6162
6163            if (estack[0] === undefined) {
6164
6165                /* ignoring text outside of elements */
6166
6167            } else if (estack[0] instanceof Span || estack[0] instanceof P) {
6168
6169                /* create an anonymous span */
6170                
6171                var s = new AnonymousSpan();
6172              
6173                s.initFromText(doc, estack[0], str, xmlspacestack[0], errorHandler);
6174
6175                estack[0].contents.push(s);
6176
6177            } else if (estack[0] instanceof ForeignElement &&
6178                metadata_depth > 0 &&
6179                metadataHandler &&
6180                'onText' in metadataHandler) {
6181
6182                /* text node within a child of metadata element */
6183
6184                metadataHandler.onText(str);
6185
6186            }
6187
6188        };
6189
6190
6191        p.onopentag = function (node) {
6192
6193            // maintain the xml:space stack
6194
6195            var xmlspace = node.attributes["xml:space"];
6196
6197            if (xmlspace) {
6198
6199                xmlspacestack.unshift(xmlspace.value);
6200
6201            } else {
6202
6203                if (xmlspacestack.length === 0) {
6204
6205                    xmlspacestack.unshift("default");
6206
6207                } else {
6208
6209                    xmlspacestack.unshift(xmlspacestack[0]);
6210
6211                }
6212
6213            }
6214
6215            /* maintain the xml:lang stack */
6216
6217
6218            var xmllang = node.attributes["xml:lang"];
6219
6220            if (xmllang) {
6221
6222                xmllangstack.unshift(xmllang.value);
6223
6224            } else {
6225
6226                if (xmllangstack.length === 0) {
6227
6228                    xmllangstack.unshift("");
6229
6230                } else {
6231
6232                    xmllangstack.unshift(xmllangstack[0]);
6233
6234                }
6235
6236            }
6237
6238
6239            /* process the element */
6240
6241            if (node.uri === imscNames.ns_tt) {
6242
6243                if (node.local === 'tt') {
6244
6245                    if (doc !== null) {
6246
6247                        reportFatal("Two <tt> elements at (" + this.line + "," + this.column + ")");
6248
6249                    }
6250
6251                    doc = new TT();
6252
6253                    doc.initFromNode(node, errorHandler);
6254
6255                    estack.unshift(doc);
6256
6257                } else if (node.local === 'head') {
6258
6259                    if (!(estack[0] instanceof TT)) {
6260                        reportFatal("Parent of <head> element is not <tt> at (" + this.line + "," + this.column + ")");
6261                    }
6262
6263                    if (doc.head !== null) {
6264                        reportFatal("Second <head> element at (" + this.line + "," + this.column + ")");
6265                    }
6266
6267                    doc.head = new Head();
6268
6269                    estack.unshift(doc.head);
6270
6271                } else if (node.local === 'styling') {
6272
6273                    if (!(estack[0] instanceof Head)) {
6274                        reportFatal("Parent of <styling> element is not <head> at (" + this.line + "," + this.column + ")");
6275                    }
6276
6277                    if (doc.head.styling !== null) {
6278                        reportFatal("Second <styling> element at (" + this.line + "," + this.column + ")");
6279                    }
6280
6281                    doc.head.styling = new Styling();
6282
6283                    estack.unshift(doc.head.styling);
6284
6285                } else if (node.local === 'style') {
6286
6287                    var s;
6288
6289                    if (estack[0] instanceof Styling) {
6290
6291                        s = new Style();
6292
6293                        s.initFromNode(node, errorHandler);
6294
6295                        /* ignore <style> element missing @id */
6296
6297                        if (!s.id) {
6298
6299                            reportError("<style> element missing @id attribute");
6300
6301                        } else {
6302
6303                            doc.head.styling.styles[s.id] = s;
6304
6305                        }
6306
6307                        estack.unshift(s);
6308
6309                    } else if (estack[0] instanceof Region) {
6310
6311                        /* nested styles can be merged with specified styles
6312                         * immediately, with lower priority
6313                         * (see 8.4.4.2(3) at TTML1 )
6314                         */
6315
6316                        s = new Style();
6317
6318                        s.initFromNode(node, errorHandler);
6319
6320                        mergeStylesIfNotPresent(s.styleAttrs, estack[0].styleAttrs);
6321
6322                        estack.unshift(s);
6323
6324                    } else {
6325
6326                        reportFatal(errorHandler, "Parent of <style> element is not <styling> or <region> at (" + this.line + "," + this.column + ")");
6327
6328                    }
6329
6330                } else if (node.local === 'layout') {
6331
6332                    if (!(estack[0] instanceof Head)) {
6333
6334                        reportFatal(errorHandler, "Parent of <layout> element is not <head> at " + this.line + "," + this.column + ")");
6335
6336                    }
6337
6338                    if (doc.head.layout !== null) {
6339
6340                        reportFatal(errorHandler, "Second <layout> element at " + this.line + "," + this.column + ")");
6341
6342                    }
6343
6344                    doc.head.layout = new Layout();
6345
6346                    estack.unshift(doc.head.layout);
6347
6348                }
vendor: 4,193 bytes, lines 6348-6477
6348 else if (node.local === 'region') {
6349
6350                    if (!(estack[0] instanceof Layout)) {
6351                        reportFatal(errorHandler, "Parent of <region> element is not <layout> at " + this.line + "," + this.column + ")");
6352                    }
6353
6354                    var r = new Region();
6355
6356                    r.initFromNode(doc, node, errorHandler);
6357
6358                    if (!r.id || r.id in doc.head.layout.regions) {
6359
6360                        reportError(errorHandler, "Ignoring <region> with duplicate or missing @id at " + this.line + "," + this.column + ")");
6361
6362                    } else {
6363
6364                        doc.head.layout.regions[r.id] = r;
6365
6366                        doc._registerEvent(r);
6367
6368                    }
6369
6370                    estack.unshift(r);
6371
6372                } else if (node.local === 'body') {
6373
6374                    if (!(estack[0] instanceof TT)) {
6375
6376                        reportFatal(errorHandler, "Parent of <body> element is not <tt> at " + this.line + "," + this.column + ")");
6377
6378                    }
6379
6380                    if (doc.body !== null) {
6381
6382                        reportFatal(errorHandler, "Second <body> element at " + this.line + "," + this.column + ")");
6383
6384                    }
6385
6386                    var b = new Body();
6387
6388                    b.initFromNode(doc, node, errorHandler);
6389
6390                    doc._registerEvent(b);
6391
6392                    doc.body = b;
6393
6394                    estack.unshift(b);
6395
6396                } else if (node.local === 'div') {
6397
6398                    if (!(estack[0] instanceof Div || estack[0] instanceof Body)) {
6399
6400                        reportFatal(errorHandler, "Parent of <div> element is not <body> or <div> at " + this.line + "," + this.column + ")");
6401
6402                    }
6403
6404                    var d = new Div();
6405
6406                    d.initFromNode(doc, estack[0], node, errorHandler);
6407
6408                    doc._registerEvent(d);
6409
6410                    estack[0].contents.push(d);
6411
6412                    estack.unshift(d);
6413
6414                } else if (node.local === 'p') {
6415
6416                    if (!(estack[0] instanceof Div)) {
6417
6418                        reportFatal(errorHandler, "Parent of <p> element is not <div> at " + this.line + "," + this.column + ")");
6419
6420                    }
6421
6422                    var p = new P();
6423
6424                    p.initFromNode(doc, estack[0], node, errorHandler);
6425
6426                    doc._registerEvent(p);
6427
6428                    estack[0].contents.push(p);
6429
6430                    estack.unshift(p);
6431
6432                } else if (node.local === 'span') {
6433
6434                    if (!(estack[0] instanceof Span || estack[0] instanceof P)) {
6435
6436                        reportFatal(errorHandler, "Parent of <span> element is not <span> or <p> at " + this.line + "," + this.column + ")");
6437
6438                    }
6439
6440                    var ns = new Span();
6441
6442                    ns.initFromNode(doc, estack[0], node, xmlspacestack[0], errorHandler);
6443
6444                    doc._registerEvent(ns);
6445
6446                    estack[0].contents.push(ns);
6447
6448                    estack.unshift(ns);
6449
6450                } else if (node.local === 'br') {
6451
6452                    if (!(estack[0] instanceof Span || estack[0] instanceof P)) {
6453
6454                        reportFatal(errorHandler, "Parent of <br> element is not <span> or <p> at " + this.line + "," + this.column + ")");
6455
6456                    }
6457
6458                    var nb = new Br();
6459
6460                    nb.initFromNode(doc, estack[0], node, errorHandler);
6461
6462                    doc._registerEvent(nb);
6463
6464                    estack[0].contents.push(nb);
6465
6466                    estack.unshift(nb);
6467
6468                } else if (node.local === 'set') {
6469
6470                    if (!(estack[0] instanceof Span ||
6471                        estack[0] instanceof P ||
6472                        estack[0] instanceof Div ||
6473                        estack[0] instanceof Body ||
6474                        estack[0] instanceof Region ||
6475                        estack[0] instanceof Br)) {
6476
6477                        reportFatal(errorHandler, "Parent of <set>
vendor: 14,375 bytes, lines 6477-7063
6477 element is not a content element or a region at " + this.line + "," + this.column + ")");
6478
6479                    }
6480
6481                    var st = new Set();
6482
6483                    st.initFromNode(doc, estack[0], node, errorHandler);
6484
6485                    doc._registerEvent(st);
6486
6487                    estack[0].sets.push(st);
6488
6489                    estack.unshift(st);
6490
6491                } else {
6492
6493                    /* element in the TT namespace, but not a content element */
6494
6495                    estack.unshift(new ForeignElement(node));
6496                }
6497
6498            } else {
6499
6500                /* ignore elements not in the TTML namespace unless in metadata element */
6501
6502                estack.unshift(new ForeignElement(node));
6503
6504            }
6505
6506            /* handle metadata callbacks */
6507
6508            if (estack[0] instanceof ForeignElement) {
6509
6510                if (node.uri === imscNames.ns_tt &&
6511                    node.local === 'metadata') {
6512
6513                    /* enter the metadata element */
6514
6515                    metadata_depth++;
6516
6517                } else if (
6518                    metadata_depth > 0 &&
6519                    metadataHandler &&
6520                    'onOpenTag' in metadataHandler
6521                    ) {
6522
6523                    /* start of child of metadata element */
6524
6525                    var attrs = [];
6526
6527                    for (var a in node.attributes) {
6528                        attrs[node.attributes[a].uri + " " + node.attributes[a].local] =
6529                            {
6530                                uri: node.attributes[a].uri,
6531                                local: node.attributes[a].local,
6532                                value: node.attributes[a].value
6533                            };
6534                    }
6535
6536                    metadataHandler.onOpenTag(node.uri, node.local, attrs);
6537
6538                }
6539
6540            }
6541
6542        };
6543
6544        // parse the document
6545
6546        p.write(xmlstring).close();
6547
6548        // all referential styling has been flatten, so delete the styling elements if there is a head
6549        // otherwise create an empty head
6550
6551        if (doc.head !== null) {
6552            delete doc.head.styling;
6553        } else {
6554            doc.head = new Head();
6555        }
6556
6557        // create default region if no regions specified
6558
6559        if (doc.head.layout === null) {
6560
6561            doc.head.layout = new Layout();
6562
6563        }
6564
6565        var hasRegions = false;
6566
6567        /* AFAIK the only way to determine whether an object has members */
6568
6569        for (var i in doc.head.layout.regions) {
6570
6571            hasRegions = true;
6572
6573            break;
6574
6575        }
6576
6577        if (!hasRegions) {
6578
6579            var dr = Region.createDefaultRegion();
6580
6581            doc.head.layout.regions[dr.id] = dr;
6582
6583        }
6584
6585        return doc;
6586    };
6587
6588    function ForeignElement(node) {
6589        this.node = node;
6590    }
6591
6592    function TT() {
6593        this.events = [];
6594        this.head = null;
6595        this.body = null;
6596    }
6597
6598    TT.prototype.initFromNode = function (node, errorHandler) {
6599
6600        /* compute cell resolution */
6601
6602        this.cellResolution = extractCellResolution(node, errorHandler);
6603
6604        /* extract frame rate and tick rate */
6605
6606        var frtr = extractFrameAndTickRate(node, errorHandler);
6607
6608        this.effectiveFrameRate = frtr.effectiveFrameRate;
6609
6610        this.tickRate = frtr.tickRate;
6611
6612        /* extract aspect ratio */
6613
6614        this.aspectRatio = extractAspectRatio(node, errorHandler);
6615
6616        /* check timebase */
6617
6618        var attr = findAttribute(node, imscNames.ns_ttp, "timeBase");
6619
6620        if (attr !== null && attr !== "media") {
6621
6622            reportFatal(errorHandler, "Unsupported time base");
6623
6624        }
6625
6626        /* retrieve extent */
6627
6628        var e = extractExtent(node, errorHandler);
6629
6630        if (e === null) {
6631
6632            /* TODO: remove once unit tests are ready */
6633
6634            this.pxDimensions = {'h': 480, 'w': 640};
6635
6636        } else {
6637
6638            if (e.h.unit !== "px" || e.w.unit !== "px") {
6639                reportFatal(errorHandler, "Extent on TT must be in px or absent");
6640            }
6641
6642            this.pxDimensions = {'h': e.h.value, 'w': e.w.value};
6643        }
6644
6645    };
6646
6647    /* register a temporal events */
6648    TT.prototype._registerEvent = function (elem) {
6649
6650        /* skip if begin is not < then end */
6651
6652        if (elem.end <= elem.begin) return;
6653
6654        /* index the begin time of the event */
6655
6656        var b_i = indexOf(this.events, elem.begin);
6657
6658        if (!b_i.found) {
6659            this.events.splice(b_i.index, 0, elem.begin);
6660        }
6661
6662        /* index the end time of the event */
6663
6664        if (elem.end !== Number.POSITIVE_INFINITY) {
6665
6666            var e_i = indexOf(this.events, elem.end);
6667
6668            if (!e_i.found) {
6669                this.events.splice(e_i.index, 0, elem.end);
6670            }
6671
6672        }
6673
6674    };
6675
6676
6677    /*
6678     * Retrieves the range of ISD times covered by the document
6679     * 
6680     * @returns {Array} Array of two elements: min_begin_time and max_begin_time
6681     * 
6682     */
6683    TT.prototype.getMediaTimeRange = function () {
6684
6685        return [this.events[0], this.events[this.events.length - 1]];
6686    };
6687
6688    /*
6689     * Returns list of ISD begin times  
6690     * 
6691     * @returns {Array}
6692     */
6693    TT.prototype.getMediaTimeEvents = function () {
6694
6695        return this.events;
6696    };
6697
6698    /*
6699     * Represents a TTML Head element
6700     */
6701
6702    function Head() {
6703        this.styling = null;
6704        this.layout = null;
6705    }
6706
6707    /*
6708     * Represents a TTML Styling element
6709     */
6710
6711    function Styling() {
6712        this.styles = {};
6713    }
6714
6715    /*
6716     * Represents a TTML Style element
6717     */
6718
6719    function Style() {
6720        this.id = null;
6721        this.styleAttrs = null;
6722        this.styleRefs = null;
6723    }
6724
6725    Style.prototype.initFromNode = function (node, errorHandler) {
6726        this.id = elementGetXMLID(node);
6727        this.styleAttrs = elementGetStyles(node, errorHandler);
6728        this.styleRefs = elementGetStyleRefs(node);
6729    };
6730
6731    /*
6732     * Represents a TTML Layout element
6733     * 
6734     */
6735
6736    function Layout() {
6737        this.regions = {};
6738    }
6739
6740    /*
6741     * Represents a TTML Content element
6742     * 
6743     */
6744
6745    function ContentElement(kind) {
6746        this.kind = kind;
6747        this.begin = null;
6748        this.end = null;
6749        this.styleAttrs = null;
6750        this.regionID = null;
6751        this.sets = null;
6752        this.timeContainer = null;
6753    }
6754
6755    ContentElement.prototype.initFromNode = function (doc, parent, node, errorHandler) {
6756
6757        var t = processTiming(doc, parent, node, errorHandler);
6758        this.begin = t.begin;
6759        this.end = t.end;
6760
6761        this.styleAttrs = elementGetStyles(node, errorHandler);
6762
6763        if (doc.head !== null && doc.head.styling !== null) {
6764            mergeReferencedStyles(doc.head.styling, elementGetStyleRefs(node), this.styleAttrs, errorHandler);
6765        }
6766
6767        this.regionID = elementGetRegionID(node);
6768
6769        this.sets = [];
6770
6771        this.timeContainer = elementGetTimeContainer(node, errorHandler);
6772
6773    };
6774
6775    /*
6776     * Represents a TTML body element
6777     */
6778
6779    function Body() {
6780        ContentElement.call(this, 'body');
6781    }
6782
6783    Body.prototype.initFromNode = function (doc, node, errorHandler) {
6784        ContentElement.prototype.initFromNode.call(this, doc, null, node, errorHandler);
6785        this.contents = [];
6786    };
6787
6788    /*
6789     * Represents a TTML div element
6790     */
6791
6792    function Div() {
6793        ContentElement.call(this, 'div');
6794    }
6795
6796    Div.prototype.initFromNode = function (doc, parent, node, errorHandler) {
6797        ContentElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
6798        this.contents = [];
6799    };
6800
6801    /*
6802     * Represents a TTML p element
6803     */
6804
6805    function P() {
6806        ContentElement.call(this, 'p');
6807    }
6808
6809    P.prototype.initFromNode = function (doc, parent, node, errorHandler) {
6810        ContentElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
6811        this.contents = [];
6812    };
6813
6814    /*
6815     * Represents a TTML span element
6816     */
6817
6818    function Span() {
6819        ContentElement.call(this, 'span');
6820        this.space = null;
6821    }
6822
6823    Span.prototype.initFromNode = function (doc, parent, node, xmlspace, errorHandler) {
6824        ContentElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
6825        this.space = xmlspace;
6826        this.contents = [];
6827    };
6828    
6829    /*
6830     * Represents a TTML anonymous span element
6831     */
6832    
6833    function AnonymousSpan() {
6834        ContentElement.call(this, 'span');
6835        this.space = null;
6836        this.text = null;
6837    }
6838    
6839    AnonymousSpan.prototype.initFromText = function (doc, parent, text, xmlspace, errorHandler) {
6840        ContentElement.prototype.initFromNode.call(this, doc, parent, null, errorHandler);
6841        this.text = text;
6842        this.space = xmlspace;
6843    };
6844
6845    /*
6846     * Represents a TTML br element
6847     */
6848
6849    function Br() {
6850        ContentElement.call(this, 'br');
6851    }
6852
6853    Br.prototype.initFromNode = function (doc, parent, node, errorHandler) {
6854        ContentElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
6855    };
6856
6857    /*
6858     * Represents a TTML Region element
6859     * 
6860     */
6861
6862    function Region() {
6863        this.id = null;
6864        this.begin = null;
6865        this.end = null;
6866        this.styleAttrs = null;
6867        this.sets = null;
6868    }
6869
6870    Region.createDefaultRegion = function () {
6871        var r = new Region();
6872
6873        r.id = '';
6874        r.begin = 0;
6875        r.end = Number.POSITIVE_INFINITY;
6876        r.styleAttrs = {};
6877        r.sets = [];
6878
6879        return r;
6880    };
6881
6882    Region.prototype.initFromNode = function (doc, node, errorHandler) {
6883
6884        this.id = elementGetXMLID(node);
6885
6886        var t = processTiming(doc, null, node, errorHandler);
6887        this.begin = t.begin;
6888        this.end = t.end;
6889
6890        this.styleAttrs = elementGetStyles(node, errorHandler);
6891
6892        this.sets = [];
6893
6894        /* immediately merge referenced styles */
6895
6896        if (doc.head !== null && doc.head.styling !== null) {
6897            mergeReferencedStyles(doc.head.styling, elementGetStyleRefs(node), this.styleAttrs, errorHandler);
6898        }
6899
6900    };
6901
6902    /*
6903     * Represents a TTML Set element
6904     * 
6905     */
6906
6907    function Set() {
6908        this.begin = null;
6909        this.end = null;
6910        this.qname = null;
6911        this.value = null;
6912    }
6913
6914    Set.prototype.initFromNode = function (doc, parent, node, errorHandler) {
6915
6916        var t = processTiming(doc, parent, node, errorHandler);
6917
6918        this.begin = t.begin;
6919        this.end = t.end;
6920
6921        var styles = elementGetStyles(node, errorHandler);
6922
6923        for (var qname in styles) {
6924
6925            if (this.qname) {
6926
6927                reportError(errorHandler, "More than one style specified on set");
6928                break;
6929
6930            }
6931
6932            this.qname = qname;
6933            this.value = styles[qname];
6934
6935        }
6936
6937    };
6938
6939    /*
6940     * Utility functions
6941     * 
6942     */
6943
6944
6945    function elementGetXMLID(node) {
6946        return node && 'xml:id' in node.attributes ? node.attributes['xml:id'].value || null : null;
6947    }
6948
6949    function elementGetRegionID(node) {
6950        return node && 'region' in node.attributes ? node.attributes.region.value : '';
6951    }
6952
6953    function elementGetTimeContainer(node, errorHandler) {
6954
6955        var tc = node && 'timeContainer' in node.attributes ? node.attributes.timeContainer.value : null;
6956
6957        if ((!tc) || tc === "par") {
6958
6959            return "par";
6960
6961        } else if (tc === "seq") {
6962
6963            return "seq";
6964
6965        } else {
6966
6967            reportError(errorHandler, "Illegal value of timeContainer (assuming 'par')");
6968
6969            return "par";
6970
6971        }
6972
6973    }
6974
6975    function elementGetStyleRefs(node) {
6976
6977        return node && 'style' in node.attributes ? node.attributes.style.value.split(" ") : [];
6978
6979    }
6980
6981    function elementGetStyles(node, errorHandler) {
6982
6983        var s = {};
6984
6985        if (node !== null) {
6986
6987            for (var i in node.attributes) {
6988
6989                var qname = node.attributes[i].uri + " " + node.attributes[i].local;
6990
6991                var sa = imscStyles.byQName[qname];
6992
6993                if (sa !== undefined) {
6994
6995                    var val = sa.parse(node.attributes[i].value);
6996
6997                    if (val !== null) {
6998
6999                        s[qname] = val;
7000
7001                        /* TODO: consider refactoring errorHandler into parse and compute routines */
7002
7003                        if (sa === imscStyles.byName.zIndex) {
7004                            reportWarning(errorHandler, "zIndex attribute present but not used by IMSC1 since regions do not overlap");
7005                        }
7006
7007                    } else {
7008
7009                        reportError(errorHandler, "Cannot parse styling attribute " + qname + " --> " + node.attributes[i].value);
7010
7011                    }
7012
7013                }
7014
7015            }
7016
7017        }
7018
7019        return s;
7020    }
7021
7022    function findAttribute(node, ns, name) {
7023        for (var i in node.attributes) {
7024
7025            if (node.attributes[i].uri === ns &&
7026                node.attributes[i].local === name) {
7027
7028                return node.attributes[i].value;
7029            }
7030        }
7031
7032        return null;
7033    }
7034
7035    function extractAspectRatio(node, errorHandler) {
7036
7037        var ar = findAttribute(node, imscNames.ns_ittp, "aspectRatio");
7038
7039        var rslt = null;
7040
7041        if (ar !== null) {
7042
7043            var ASPECT_RATIO_RE = /(\d+) (\d+)/;
7044
7045            var m = ASPECT_RATIO_RE.exec(ar);
7046
7047            if (m !== null) {
7048
7049                var w = parseInt(m[1]);
7050
7051                var h = parseInt(m[2]);
7052
7053                if (w !== 0 && h !== 0) {
7054
7055                    rslt = w / h;
7056
7057                } else {
7058
7059                    reportError(errorHandler, "Illegal aspectRatio values (ignoring)");
7060                }
7061
7062            } else {
7063
vendor: 3,724 bytes, lines 7064-7235
7064                reportError(errorHandler, "Malformed aspectRatio attribute (ignoring)");
7065            }
7066
7067        }
7068
7069        return rslt;
7070
7071    }
7072
7073    /*
7074     * Returns the cellResolution attribute from a node
7075     * 
7076     */
7077    function extractCellResolution(node, errorHandler) {
7078
7079        var cr = findAttribute(node, imscNames.ns_ttp, "cellResolution");
7080
7081        // initial value
7082
7083        var h = 15;
7084        var w = 32;
7085
7086        if (cr !== null) {
7087
7088            var CELL_RESOLUTION_RE = /(\d+) (\d+)/;
7089
7090            var m = CELL_RESOLUTION_RE.exec(cr);
7091
7092            if (m !== null) {
7093
7094                w = parseInt(m[1]);
7095
7096                h = parseInt(m[2]);
7097
7098            } else {
7099
7100                reportWarning(errorHandler, "Malformed cellResolution value (using initial value instead)");
7101
7102            }
7103
7104        }
7105
7106        return {'w': w, 'h': h};
7107
7108    }
7109
7110
7111    function extractFrameAndTickRate(node, errorHandler) {
7112
7113        // subFrameRate is ignored per IMSC1 specification
7114
7115        // extract frame rate
7116
7117        var fps_attr = findAttribute(node, imscNames.ns_ttp, "frameRate");
7118
7119        // initial value
7120
7121        var fps = 30;
7122
7123        // match variable
7124
7125        var m;
7126
7127        if (fps_attr !== null) {
7128
7129            var FRAME_RATE_RE = /(\d+)/;
7130
7131            m = FRAME_RATE_RE.exec(fps_attr);
7132
7133            if (m !== null) {
7134
7135                fps = parseInt(m[1]);
7136
7137            } else {
7138
7139                reportWarning(errorHandler, "Malformed frame rate attribute (using initial value instead)");
7140            }
7141
7142        }
7143
7144        // extract frame rate multiplier
7145
7146        var frm_attr = findAttribute(node, imscNames.ns_ttp, "frameRateMultiplier");
7147
7148        // initial value
7149
7150        var frm = 1;
7151
7152        if (frm_attr !== null) {
7153
7154            var FRAME_RATE_MULT_RE = /(\d+) (\d+)/;
7155
7156            m = FRAME_RATE_MULT_RE.exec(frm_attr);
7157
7158            if (m !== null) {
7159
7160                frm = parseInt(m[1]) / parseInt(m[2]);
7161
7162            } else {
7163
7164                reportWarning(errorHandler, "Malformed frame rate multiplier attribute (using initial value instead)");
7165            }
7166
7167        }
7168
7169        var efps = frm * fps;
7170
7171        // extract tick rate
7172
7173        var tr = 1;
7174
7175        var trattr = findAttribute(node, imscNames.ns_ttp, "tickRate");
7176
7177        if (trattr === null) {
7178
7179            if (fps_attr !== null) tr = efps;
7180
7181        } else {
7182
7183            var TICK_RATE_RE = /(\d+)/;
7184
7185            m = TICK_RATE_RE.exec(trattr);
7186
7187            if (m !== null) {
7188
7189                tr = parseInt(m[1]);
7190
7191            } else {
7192
7193                reportWarning(errorHandler, "Malformed tick rate attribute (using initial value instead)");
7194            }
7195
7196        }
7197
7198        return {effectiveFrameRate: efps, tickRate: tr};
7199
7200    }
7201
7202    function extractExtent(node, errorHandler) {
7203
7204        var attr = findAttribute(node, imscNames.ns_tts, "extent");
7205
7206        if (attr === null) return null;
7207
7208        var s = attr.split(" ");
7209
7210        if (s.length !== 2) {
7211
7212            reportWarning(errorHandler, "Malformed extent (ignoring)");
7213
7214            return null;
7215        }
7216
7217        var w = imscUtils.parseLength(s[0]);
7218
7219        var h = imscUtils.parseLength(s[1]);
7220
7221        if (!h || !w) {
7222
7223            reportWarning(errorHandler, "Malformed extent values (ignoring)");
7224
7225            return null;
7226        }
7227
7228        return {'h': h, 'w': w};
7229
7230    }
7231
7232    function parseTimeExpression(tickRate, effectiveFrameRate, str) {
7233
7234        var CLOCK_TIME_FRACTION_RE = /^(\d{2,}):(\d\d):(\d\d(?:\.\d+)?)$/;
7235        var CLOCK_TIME_FRAMES_RE = /^(\d{2,}):(\d\d):(\d\d)\:(\d{2,})$/;
7236        var OFFSET_FRAME_RE = /^(\d+(?:\.\d+)?)f$/;
7237        var OFFSET_TICK_RE = /^(\d+(?:\.\d+)?)t$/;
7238        var OFFSET_MS_RE = /^(\d+(?:\.\d+)?)ms$/;
7239        var OFFSET_S_RE = /^(\d+(?:\.\d+)?)s$/;
7240        var OFFSET_H_RE = /^(\d+(?:\.\d+)?)h$/;
7241        var OFFSET_M_RE = /^(\d+(?:\.\d+)?)m$/;
7242        var m;
7243        var r = null;
7244        if ((m = OFFSET_FRAME_RE.exec(str)) !== null) {
7245
7246            if (effectiveFrameRate !== null) {
7247
7248                r = parseFloat(m[1]) / effectiveFrameRate;
7249            }
7250
7251        } else if ((m = OFFSET_TICK_RE.exec(str)) !== null) {
7252
7253            if (tickRate !== null) {
7254
7255                r = parseFloat(m[1]) / tickRate;
7256            }
7257
7258        } else if ((m = OFFSET_MS_RE.exec(str)) !== null) {
7259
7260            r = parseFloat(m[1]) / 1000.0;
7261
7262        } else if ((m = OFFSET_S_RE.exec(str)) !== null) {
7263
7264            r = parseFloat(m[1]);
7265
7266        } else if ((m = OFFSET_H_RE.exec(str)) !== null) {
7267
7268            r = parseFloat(m[1]) * 3600.0;
7269
7270        } else if ((m = OFFSET_M_RE.exec(str)) !== null) {
7271
7272            r = parseFloat(m[1]) * 60.0;
7273
7274        } else if ((m = CLOCK_TIME_FRACTION_RE.exec(str)) !== null) {
7275
7276            r = parseInt(m[1]) * 3600 +
7277                parseInt(m[2]) * 60 +
7278                parseFloat(m[3]);
7279
7280        } else if ((m = CLOCK_TIME_FRAMES_RE.exec(str)) !== null) {
7281
7282            /* this assumes that HH:MM:SS is a clock-time-with-fraction */
7283
7284            if (effectiveFrameRate !== null) {
7285
7286                r = parseInt(m[1]) * 3600 +
7287                    parseInt(m[2]) * 60 +
7288                    parseInt(m[3]) +
7289                    (m[4] === null ? 0 : parseInt(m[4]) / effectiveFrameRate);
7290            }
7291
7292        }
7293
7294        return r;
7295    }
7296
7297    function processTiming(doc, parent, node, errorHandler) {
7298
7299        /* Q: what does this do <div b=1 e=3><p b=1 e=5> ?*/
7300        /* Q: are children clipped by parent time interval? */
7301
7302        var isseq = parent && parent.timeContainer === "seq";
7303
7304        /* retrieve begin value */
7305
7306        var b = 0;
7307
7308        if (node && 'begin' in node.attributes) {
7309
7310            b = parseTimeExpression(doc.tickRate, doc.effectiveFrameRate, node.attributes.begin.value);
7311
7312            if (b === null) {
7313
7314                reportWarning(errorHandler, "Malformed begin value " + node.attributes.begin.value + " (using 0)");
7315
7316                b = 0;
7317
7318            }
7319
7320        }
7321
7322        /* retrieve dur value */
7323
7324        /* NOTE: end is not meaningful on seq container children and dur is equal to 0 if not specified */
7325
7326        var d = isseq ? 0 : null;
7327
7328        if (node && 'dur' in node.attributes) {
7329
7330            d = parseTimeExpression(doc.tickRate, doc.effectiveFrameRate, node.attributes.dur.value);
7331
7332            if (d === null) {
7333
7334                reportWarning(errorHandler, "Malformed dur value " + node.attributes.dur.value + " (ignoring)");
7335
7336            }
7337
7338        }
7339
7340        /* retrieve end value */
7341
7342        var e = null;
7343
7344        if (node && 'end' in node.attributes) {
7345
7346            e = parseTimeExpression(doc.tickRate, doc.effectiveFrameRate, node.attributes.end.value);
7347
7348            if (e === null) {
7349
7350                reportWarning(errorHandler, "Malformed end value (ignoring)");
7351
7352            }
7353
7354        }
7355
7356        /* compute starting offset */
7357
7358        var start_off = 0;
7359
7360        if (parent) {
7361
7362            if (isseq && 'contents' in parent && parent.contents.length > 0) {
7363
7364                /*
7365                 * if seq time container, offset from the previous sibling end
7366                 */
7367
7368                start_off = parent.contents[parent.contents.length - 1].end;
7369
7370
7371            } else {
7372
7373                /* 
7374                 * retrieve parent begin. Assume 0 if no parent.
7375                 * 
7376                 */
7377
7378                start_off = parent.begin || 0;
7379
7380            }
7381
7382        }
7383
7384        /* offset begin per time container semantics */
7385
7386        b += start_off;
7387
7388        /* set end */
7389
7390        if (d !== null) {
7391
7392            // use dur if specified
7393
7394            e = b + d;
7395
7396        } else {
7397
7398            /* retrieve parent end, or +infinity if none */
7399
7400            var parent_e = (parent && 'end' in parent) ? parent.end : Number.POSITIVE_INFINITY;
7401
7402            e = (e !== null) ? e + start_off : parent_e;
7403
7404        }
7405
7406        return {begin: b, end: e};
7407
7408    }
7409
7410
7411
7412    function mergeChainedStyles(styling, style, errorHandler) {
7413
7414        while (style.styleRefs.length > 0) {
7415
7416            var sref = style.styleRefs.pop();
7417
7418            if (!(sref in styling.styles)) {
7419                reportError(errorHandler, "Non-existant style id referenced");
7420                continue;
7421            }
7422
7423            mergeChainedStyles(styling, styling.styles[sref], errorHandler);
7424
7425            mergeStylesIfNotPresent(styling.styles[sref].styleAttrs, style.styleAttrs);
7426
7427        }
7428
7429    }
7430
7431    function mergeReferencedStyles(styling, stylerefs, styleattrs, errorHandler) {
7432
7433        for (var i = stylerefs.length - 1; i >= 0; i--) {
7434
7435            var sref = stylerefs[i];
7436
7437            if (!(sref in styling.styles)) {
7438                reportError(errorHandler, "Non-existant style id referenced");
7439                continue;
7440            }
7441
7442            mergeStylesIfNotPresent(styling.styles[sref].styleAttrs, styleattrs);
7443
7444        }
7445
7446    }
7447
7448    function mergeStylesIfNotPresent(from_styles, into_styles) {
7449
7450        for (var sname in from_styles) {
7451
7452            if (sname in into_styles)
7453                continue;
7454
7455            into_styles[sname] = from_styles[sname];
7456
7457        }
7458
7459    }
7460
7461    /* TODO: validate style format at parsing */
7462
7463
7464    /*
7465     * ERROR HANDLING UTILITY FUNCTIONS
7466     * 
7467     */
7468
7469    function reportInfo(errorHandler, msg) {
7470
7471        if (errorHandler && errorHandler.info && errorHandler.info(msg))
7472            throw msg;
7473
7474    }
7475
7476    function reportWarning(errorHandler, msg) {
7477
7478        if (errorHandler && errorHandler.warn && errorHandler.warn(msg))
7479            throw msg;
7480
7481    }
7482
7483    function reportError(errorHandler, msg) {
7484
7485        if (errorHandler && errorHandler.error && errorHandler.error(msg))
7486            throw msg;
7487
7488    }
7489
7490    function reportFatal(errorHandler, msg) {
7491
7492        if (errorHandler && errorHandler.fatal)
7493            errorHandler.fatal(msg);
7494
7495        throw msg;
7496
7497    }
7498
7499    /*
7500     * Binary search utility function
7501     * 
7502     * @typedef {Object} BinarySearchResult
7503     * @property {boolean} found Was an exact match found?
7504     * @property {number} index Position of the exact match or insert position
7505     * 
7506     * @returns {BinarySearchResult}
7507     */
7508
7509    function indexOf(arr, searchval) {
7510
7511        var min = 0;
7512        var max = arr.length - 1;
7513        var cur;
7514
7515        while (min <= max) {
7516
7517            cur = Math.floor((min + max) / 2);
7518
7519            var curval = arr[cur];
7520
7521            if (curval < searchval) {
7522
7523                min = cur + 1;
7524
7525            } else if (curval > searchval) {
7526
7527                max = cur - 1;
7528
7529            } else {
7530
7531                return {found: true, index: cur};
7532
7533            }
7534
7535        }
7536
7537        return {found: false, index: min};
7538    }
7539
7540
7541})(typeof exports === 'undefined' ? this.imscDoc = {} : exports,
7542    typeof sax === 'undefined' ? _dereq_(45) : sax,
7543    typeof imscNames === 'undefined' ? _dereq_(22) : imscNames,
7544    typeof imscStyles === 'undefined' ? _dereq_(23) : imscStyles,
7545    typeof imscUtils === 'undefined' ? _dereq_(24) : imscUtils);
7546
7547},{"22":22,"23":23,"24":24,"45":45}],19:[function(_dereq_,module,exports){
7548/* 
7549 * Copyright (c) 2016, Pierre-Anthony Lemieux <[email protected]>
7550 * All rights reserved.
7551 *
7552 * Redistribution and use in source and binary forms, with or without
7553 * modification, are permitted provided that the following conditions are met:
7554 *
7555 * * Redistributions of source code must retain the above copyright notice, this
7556 *   list of conditions and the following disclaimer.
7557 * * Redistributions in binary form must reproduce the above copyright notice,
7558 *   this list of conditions and the following disclaimer in the documentation
7559 *   and/or other materials provided with the distribution.
7560 *
7561 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
7562 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
7563 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7564 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
7565 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
7566 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
7567 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
7568 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
7569 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
7570 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
7571 * POSSIBILITY OF SUCH DAMAGE.
7572 */
7573
7574/**
7575 * @module imscHTML
7576 */
7577
7578;
7579(function (imscHTML, imscNames, imscStyles) {
7580
7581    /**
7582     * Function that maps <pre>smpte:background</pre> URIs to URLs resolving to image resource
7583     * @callback IMGResolver
7584     * @param {string} <pre>smpte:background</pre> URI
7585     * @return {string} PNG resource URL
7586     */
7587
7588
7589    /**
7590     * Renders an ISD object (returned by <pre>generateISD()</pre>) into a 
7591     * parent element, that must be attached to the DOM. The ISD will be rendered
7592     * into a child <pre>div</pre>
7593     * with heigh and width equal to the clientHeight and clientWidth of the element,
7594     * unless explicitly specified otherwise by the caller. Images URIs specified 
7595     * by <pre>smpte:background</pre> attributes are mapped to image resource URLs
7596     * by an <pre>imgResolver</pre> function. The latter takes the value of <code>smpte:background</code>
7597     * attribute and an <code>img</code> DOM element as input, and is expected to
7598     * set the <code>src</code> attribute of the <code>img</code> to the absolute URI of the image.
7599     * <pre>displayForcedOnlyMode</pre> sets the (boolean)
7600     * value of the IMSC1 displayForcedOnlyMode parameter.
7601     * 
7602     * @param {Object} isd ISD to be rendered
7603     * @param {Object} element Element into which the ISD is rendered
7604     * @param {?IMGResolver} imgResolver Resolve <pre>smpte:background</pre> URIs into URLs.
7605     * @param {?number} eheight Height (in pixel) of the child <div>div</div> or null 
7606     *                  to use clientHeight of the parent element
7607     * @param {?number} ewidth Width (in pixel) of the child <div>div</div> or null
7608     *                  to use clientWidth of the parent element
7609     * @param {?boolean} displayForcedOnlyMode Value of the IMSC1 displayForcedOnlyMode parameter,
7610     *                   or false if null         
7611     * @param {?module:imscUtils.ErrorHandler} errorHandler Error callback
7612     */
7613
7614    imscHTML.render = function (isd, element, imgResolver, eheight, ewidth, displayForcedOnlyMode, errorHandler) {
7615
7616        /* maintain aspect ratio if specified */
7617
7618        var height = eheight || element.clientHeight;
7619        var width = ewidth || element.clientWidth;
7620
7621        if (isd.aspectRatio !== null) {
7622
7623            var twidth = height * isd.aspectRatio;
7624
7625            if (twidth > width) {
7626
7627                height = Math.round(width / isd.aspectRatio);
7628
7629            } else {
7630
7631                width = twidth;
7632
7633            }
7634
7635        }
7636
7637        var rootcontainer = document.createElement("div");
7638
7639        rootcontainer.style.position = "relative";
7640        rootcontainer.style.width = width + "px";
7641        rootcontainer.style.height = height + "px";
7642        rootcontainer.style.margin = "auto";
7643        rootcontainer.style.top = 0;
7644        rootcontainer.style.bottom = 0;
7645        rootcontainer.style.left = 0;
7646        rootcontainer.style.right = 0;
7647        rootcontainer.style.zIndex = 0;
7648
7649        var context = {
7650            h: height,
7651            w: width,
7652            regionH: null,
7653            regionW: null,
7654            imgResolver: imgResolver,
7655            displayForcedOnlyMode: displayForcedOnlyMode || false,
7656            isd: isd
7657        };
7658
7659        element.appendChild(rootcontainer);
7660
7661        for (var i in isd.contents) {
7662
7663            processElement(context, rootcontainer, isd.contents[i]);
7664
7665        }
7666
7667    };
7668
7669    function processElement(context, dom_parent, isd_element) {
7670
7671        var e;
7672
7673        if (isd_element.kind === 'region') {
7674
7675            e = document.createElement("div");
7676            e.style.position = "absolute";
7677
7678        } else if (isd_element.kind === 'body') {
7679
7680            e = document.createElement("div");
7681
7682        } else if (isd_element.kind === 'div') {
7683
7684            e = document.createElement("div");
7685
7686        } else if (isd_element.kind === 'p') {
7687
7688            e = document.createElement("p");
7689
7690        } else if (isd_element.kind === 'span') {
7691
7692            e = document.createElement("span");
7693
7694            //e.textContent = isd_element.text;
7695
7696        } else if (isd_element.kind === 'br') {
7697
7698            e = document.createElement("br");
7699
7700        }
7701
7702        /* override UA default margin */
7703
7704        e.style.margin = "0";
7705
7706        /* tranform TTML styles to CSS styles */
7707
7708        for (var i in STYLING_MAP_DEFS) {
7709
7710            var sm = STYLING_MAP_DEFS[i];
7711
7712            var attr = isd_element.styleAttrs[sm.qname];
7713
7714            if (attr !== undefined && sm.map !== null) {
7715
7716                sm.map(context, e, isd_element, attr);
7717
7718            }
7719
7720        }
7721
7722        var proc_e = e;
7723
7724
7725        // handle multiRowAlign and linePadding
7726
7727        var mra = isd_element.styleAttrs[imscStyles.byName.multiRowAlign.qname];
7728
7729        if (mra && mra !== "auto") {
7730
7731            var s = document.createElement("span");
7732
7733            s.style.display = "inline-block";
7734
7735            s.style.textAlign = mra;
7736
7737            e.appendChild(s);
7738
7739            proc_e = s;
7740
7741            context.mra = mra;
7742
7743        }
7744
7745        var lp = isd_element.styleAttrs[imscStyles.byName.linePadding.qname];
7746
7747        if (lp && lp > 0) {
7748
7749            context.lp = lp;
7750
7751        }
7752
7753        // wrap characters in spans to find the line wrap locations
7754
7755        if (isd_element.kind === "span" && isd_element.text) {
7756
7757            if (context.lp || context.mra) {
7758
7759                for (var j = 0; j < isd_element.text.length; j++) {
7760
7761                    var span = document.createElement("span");
7762
7763                    span.textContent = isd_element.text.charAt(j);
7764
7765                    e.appendChild(span);
7766
7767                }
7768
7769            } else {
7770                e.textContent = isd_element.text;
7771            }
7772        }
7773
7774
7775        dom_parent.appendChild(e);
7776
7777        for (var k in isd_element.contents) {
7778
7779            processElement(context, proc_e, isd_element.contents[k]);
7780
7781        }
7782
7783        // handle linePadding and multiRowAlign
7784
7785        if ((context.lp || context.mra) && isd_element.kind === "p") {
7786
7787            var elist = [];
7788            
7789            constructElementList(proc_e, elist, "red");
7790
7791            /* TODO: linePadding only supported for horizontal scripts */
7792
7793            processLinePaddingAndMultiRowAlign(elist, context.lp * context.h);
7794
7795            /* TODO: clean-up the spans ? */
7796
7797            if (context.lp)
7798                delete context.lp;
7799            if (context.mra)
7800                delete context.mra;
7801
7802        }
7803
7804    }
7805
7806    function pruneEmptySpans(element) {
7807
7808        var child = element.firstChild;
7809
7810        while (child) {
7811
7812            var nchild = child.nextSibling;
7813
7814            if (child.nodeType === Node.ELEMENT_NODE &&
7815                child.localName === 'span') {
7816
7817                pruneEmptySpans(child);
7818
7819                if (child.childElementCount === 0 &&
7820                    child.textContent.length === 0) {
7821
7822                    element.removeChild(child);
7823
7824                }
7825            }
7826
7827            child = nchild;
7828        }
7829
7830    }
7831
7832    function constructElementList(element, elist, bgcolor) {
7833
7834        if (element.childElementCount === 0) {
7835
7836            elist.push({
7837                "element": element,
7838                "bgcolor": bgcolor}
7839                );
7840
7841        } else {
7842
7843            var newbgcolor = element.style.backgroundColor || bgcolor;
7844
7845            var child = element.firstChild;
7846
7847            while (child) {
7848
7849                if (child.nodeType === Node.ELEMENT_NODE) {
7850
7851                    constructElementList(child, elist, newbgcolor);
7852
7853                }
7854
7855                child = child.nextSibling;
7856            }
7857        }
7858
7859    }
7860
7861    function processLinePaddingAndMultiRowAlign(elist, lp) {
7862
7863        var line_head = null;
7864
7865        var lookingForHead = true;
7866
7867        var foundBR = false;
7868
7869        for (var i = 0; i <= elist.length; i++) {
7870
7871            /* skip <br> since they apparently have a different box top than
7872             * the rest of the line 
7873             */
7874
7875            if (i !== elist.length && elist[i].element.localName === "br") {
7876                foundBR = true;
7877                continue;
7878            }
7879
7880            /* detect new line */
7881
7882            if (line_head === null ||
7883                i === elist.length ||
7884                elist[i].element.getBoundingClientRect().top !== elist[line_head].element.getBoundingClientRect().top) {
7885
7886                /* apply right padding to previous line (if applicable and unless this is the first line) */
7887
7888                if (lp && (!lookingForHead)) {
7889
7890                    for (; --i >= 0; ) {
7891
7892                        if (elist[i].element.getBoundingClientRect().width !== 0) {
7893
7894                            addRightPadding(elist[i].element, elist[i].color, lp);
7895
7896                            if (elist[i].element.getBoundingClientRect().width !== 0 &&
7897                                elist[i].element.getBoundingClientRect().top === elist[line_head].element.getBoundingClientRect().top)
7898                                break;
7899
7900                            removeRightPadding(elist[i].element);
7901
7902                        }
7903
7904                    }
7905
7906                    lookingForHead = true;
7907
7908                    continue;
7909
7910                }
7911
7912                /* explicit <br> unless already present */
7913
7914                if (i !== elist.length && line_head !== null && (!foundBR)) {
7915
7916                    var br = document.createElement("br");
7917
7918                    elist[i].element.parentElement.insertBefore(br, elist[i].element);
7919
7920                    elist.splice(i, 0, {"element": br});
7921
7922                    foundBR = true;
7923
7924                    continue;
7925
7926                }
7927
7928                /* apply left padding to current line (if applicable) */
7929
7930                if (i !== elist.length && lp) {
7931
7932                    /* find first non-zero */
7933
7934                    for (; i < elist.length; i++) {
7935
7936                        if (elist[i].element.getBoundingClientRect().width !== 0) {
7937                            addLeftPadding(elist[i].element, elist[i].color, lp);
7938                            break;
7939                        }
7940
7941                    }
7942
7943                }
7944
7945                lookingForHead = false;
7946
7947                foundBR = false;
7948
7949                line_head = i;
7950
7951            }
7952
7953        }
7954
7955    }
7956
7957    function addLeftPadding(e, c, lp) {
7958        e.style.paddingLeft = lp + "px";
7959        e.style.backgroundColor = c;
7960    }
7961
7962    function addRightPadding(e, c, lp) {
7963        e.style.paddingRight = lp + "px";
7964        e.style.backgroundColor = c;
7965
7966    }
7967
7968    function removeRightPadding(e) {
7969        e.style.paddingRight = null;
7970    }
7971
7972
7973    function HTMLStylingMapDefintion(qName, mapFunc) {
7974        this.qname = qName;
7975        this.map = mapFunc;
7976    }
7977
7978    var STYLING_MAP_DEFS = [
7979
7980        new HTMLStylingMapDefintion(
7981            "http://www.w3.org/ns/ttml#styling backgroundColor",
7982            function (context, dom_element, isd_element, attr) {
7983                dom_element.style.backgroundColor = "rgba(" +
7984                    attr[0].toString() + "," +
7985                    attr[1].toString() + "," +
7986                    attr[2].toString() + "," +
7987                    (attr[3] / 255).toString() +
7988                    ")";
7989            }
7990        ),
7991        new HTMLStylingMapDefintion(
7992            "http://www.w3.org/ns/ttml#styling color",
7993            function (context, dom_element, isd_element, attr) {
7994                dom_element.style.color = "rgba(" +
7995                    attr[0].toString() + "," +
7996                    attr[1].toString() + "," +
7997                    attr[2].toString() + "," +
7998                    (attr[3] / 255).toString() +
7999                    ")";
8000            }
8001        ),
8002        new HTMLStylingMapDefintion(
8003            "http://www.w3.org/ns/ttml#styling direction",
8004            function (context, dom_element, isd_element, attr) {
8005                dom_element.style.direction = attr;
8006            }
8007        ),
8008        new HTMLStylingMapDefintion(
8009            "http://www.w3.org/ns/ttml#styling display",
8010            function (context, dom_element, isd_element, attr) {}
8011        ),
8012        new HTMLStylingMapDefintion(
8013            "http://www.w3.org/ns/ttml#styling displayAlign",
8014            function (context, dom_element, isd_element, attr) {
8015
8016                /* see https://css-tricks.com/snippets/css/a-guide-to-flexbox/ */
8017
8018                /* TODO: is this affected by writing direction? */
8019
8020                dom_element.style.display = "flex";
8021                dom_element.style.flexDirection = "column";
8022
8023
8024                if (attr === "before") {
8025
8026                    dom_element.style.justifyContent = "flex-start";
8027
8028                } else if (attr === "center") {
8029
8030                    dom_element.style.justifyContent = "center";
8031
8032                } else if (attr === "after") {
8033
8034                    dom_element.style.justifyContent = "flex-end";
8035                }
8036
8037            }
8038        ),
8039        new HTMLStylingMapDefintion(
8040            "http://www.w3.org/ns/ttml#styling extent",
8041            function (context, dom_element, isd_element, attr) {
8042                /* TODO: this is super ugly */
8043
8044                context.regionH = (attr.h * context.h);
8045                context.regionW = (attr.w * context.w);
8046
8047                /* 
8048                 * CSS height/width are measured against the content rectangle,
8049                 * whereas TTML height/width include padding
8050                 */
8051
8052                var hdelta = 0;
8053                var wdelta = 0;
8054
8055                var p = isd_element.styleAttrs["http://www.w3.org/ns/ttml#styling padding"];
8056
8057                if (!p) {
8058
8059                    /* error */
8060
8061                }
vendor: 9,386 bytes, lines 8061-8342
8061 else {
8062
8063                    hdelta = (p[0] + p[2]) * context.h;
8064                    wdelta = (p[1] + p[3]) * context.w;
8065
8066                }
8067
8068                dom_element.style.height = (context.regionH - hdelta) + "px";
8069                dom_element.style.width = (context.regionW - wdelta) + "px";
8070
8071            }
8072        ),
8073        new HTMLStylingMapDefintion(
8074            "http://www.w3.org/ns/ttml#styling fontFamily",
8075            function (context, dom_element, isd_element, attr) {
8076
8077                var rslt = [];
8078
8079                /* per IMSC1 */
8080
8081                for (var i in attr) {
8082
8083                    if (attr[i] === "monospaceSerif") {
8084
8085                        rslt.push("Courier New");
8086                        rslt.push('"Liberation Mono"');
8087                        rslt.push("Courier");
8088                        rslt.push("monospace");
8089
8090                    } else if (attr[i] === "proportionalSansSerif") {
8091
8092                        rslt.push("Arial");
8093                        rslt.push("Helvetica");
8094                        rslt.push('"Liberation Sans"');
8095                        rslt.push("sans-serif");
8096
8097                    } else if (attr[i] === "monospace") {
8098
8099                        rslt.push("monospace");
8100
8101                    } else if (attr[i] === "sansSerif") {
8102
8103                        rslt.push("sans-serif");
8104
8105                    } else if (attr[i] === "serif") {
8106
8107                        rslt.push("serif");
8108
8109                    } else if (attr[i] === "monospaceSansSerif") {
8110
8111                        rslt.push("Consolas");
8112                        rslt.push("monospace");
8113
8114                    } else if (attr[i] === "proportionalSerif") {
8115
8116                        rslt.push("serif");
8117
8118                    } else {
8119
8120                        rslt.push(attr[i]);
8121
8122                    }
8123
8124                }
8125
8126                dom_element.style.fontFamily = rslt.join(",");
8127            }
8128        ),
8129
8130        new HTMLStylingMapDefintion(
8131            "http://www.w3.org/ns/ttml#styling fontSize",
8132            function (context, dom_element, isd_element, attr) {
8133                dom_element.style.fontSize = (attr * context.h) + "px";
8134            }
8135        ),
8136
8137        new HTMLStylingMapDefintion(
8138            "http://www.w3.org/ns/ttml#styling fontStyle",
8139            function (context, dom_element, isd_element, attr) {
8140                dom_element.style.fontStyle = attr;
8141            }
8142        ),
8143        new HTMLStylingMapDefintion(
8144            "http://www.w3.org/ns/ttml#styling fontWeight",
8145            function (context, dom_element, isd_element, attr) {
8146                dom_element.style.fontWeight = attr;
8147            }
8148        ),
8149        new HTMLStylingMapDefintion(
8150            "http://www.w3.org/ns/ttml#styling lineHeight",
8151            function (context, dom_element, isd_element, attr) {
8152                if (attr === "normal") {
8153
8154                    dom_element.style.lineHeight = "normal";
8155
8156                } else {
8157
8158                    dom_element.style.lineHeight = (attr * context.h) + "px";
8159                }
8160            }
8161        ),
8162        new HTMLStylingMapDefintion(
8163            "http://www.w3.org/ns/ttml#styling opacity",
8164            function (context, dom_element, isd_element, attr) {
8165                dom_element.style.opacity = attr;
8166            }
8167        ),
8168        new HTMLStylingMapDefintion(
8169            "http://www.w3.org/ns/ttml#styling origin",
8170            function (context, dom_element, isd_element, attr) {
8171                dom_element.style.top = (attr.h * context.h) + "px";
8172                dom_element.style.left = (attr.w * context.w) + "px";
8173            }
8174        ),
8175        new HTMLStylingMapDefintion(
8176            "http://www.w3.org/ns/ttml#styling overflow",
8177            function (context, dom_element, isd_element, attr) {
8178                dom_element.style.overflow = attr;
8179            }
8180        ),
8181        new HTMLStylingMapDefintion(
8182            "http://www.w3.org/ns/ttml#styling padding",
8183            function (context, dom_element, isd_element, attr) {
8184
8185                /* attr: top,left,bottom,right*/
8186
8187                /* style: top right bottom left*/
8188
8189                var rslt = [];
8190
8191                rslt[0] = (attr[0] * context.h) + "px";
8192                rslt[1] = (attr[3] * context.w) + "px";
8193                rslt[2] = (attr[2] * context.h) + "px";
8194                rslt[3] = (attr[1] * context.w) + "px";
8195
8196                dom_element.style.padding = rslt.join(" ");
8197            }
8198        ),
8199        new HTMLStylingMapDefintion(
8200            "http://www.w3.org/ns/ttml#styling showBackground",
8201            null
8202            ),
8203        new HTMLStylingMapDefintion(
8204            "http://www.w3.org/ns/ttml#styling textAlign",
8205            function (context, dom_element, isd_element, attr) {
8206
8207                var ta;
8208                var dir = isd_element.styleAttrs[imscStyles.byName.direction.qname];
8209
8210                /* handle UAs that do not understand start or end */
8211
8212                if (attr === "start") {
8213
8214                    ta = (dir === "rtl") ? "right" : "left";
8215
8216                } else if (attr === "end") {
8217
8218                    ta = (dir === "rtl") ? "left" : "right";
8219
8220                } else {
8221
8222                    ta = attr;
8223
8224                }
8225
8226                dom_element.style.textAlign = ta;
8227
8228            }
8229        ),
8230        new HTMLStylingMapDefintion(
8231            "http://www.w3.org/ns/ttml#styling textDecoration",
8232            function (context, dom_element, isd_element, attr) {
8233                dom_element.style.textDecoration = attr.join(" ").replace("lineThrough", "line-through");
8234            }
8235        ),
8236        new HTMLStylingMapDefintion(
8237            "http://www.w3.org/ns/ttml#styling textOutline",
8238            function (context, dom_element, isd_element, attr) {
8239
8240                if (attr === "none") {
8241
8242                    dom_element.style.textShadow = "";
8243
8244                } else {
8245
8246                    dom_element.style.textShadow = "rgba(" +
8247                        attr.color[0].toString() + "," +
8248                        attr.color[1].toString() + "," +
8249                        attr.color[2].toString() + "," +
8250                        (attr.color[3] / 255).toString() +
8251                        ")" + " 0px 0px " +
8252                        (attr.thickness * context.h) + "px";
8253
8254                }
8255            }
8256        ),
8257        new HTMLStylingMapDefintion(
8258            "http://www.w3.org/ns/ttml#styling unicodeBidi",
8259            function (context, dom_element, isd_element, attr) {
8260
8261                var ub;
8262
8263                if (attr === 'bidiOverride') {
8264                    ub = "bidi-override";
8265                } else {
8266                    ub = attr;
8267                }
8268
8269                dom_element.style.unicodeBidi = ub;
8270            }
8271        ),
8272        new HTMLStylingMapDefintion(
8273            "http://www.w3.org/ns/ttml#styling visibility",
8274            function (context, dom_element, isd_element, attr) {
8275                dom_element.style.visibility = attr;
8276            }
8277        ),
8278        new HTMLStylingMapDefintion(
8279            "http://www.w3.org/ns/ttml#styling wrapOption",
8280            function (context, dom_element, isd_element, attr) {
8281
8282                if (attr === "wrap") {
8283
8284                    if (isd_element.space === "preserve") {
8285                        dom_element.style.whiteSpace = "pre-wrap";
8286                    } else {
8287                        dom_element.style.whiteSpace = "normal";
8288                    }
8289
8290                } else {
8291
8292                    if (isd_element.space === "preserve") {
8293
8294                        dom_element.style.whiteSpace = "pre";
8295
8296                    } else {
8297                        dom_element.style.whiteSpace = "noWrap";
8298                    }
8299
8300                }
8301
8302            }
8303        ),
8304        new HTMLStylingMapDefintion(
8305            "http://www.w3.org/ns/ttml#styling writingMode",
8306            function (context, dom_element, isd_element, attr) {
8307                if (attr === "lrtb" || attr === "lr") {
8308
8309                    dom_element.style.writingMode = "horizontal-tb";
8310
8311                } else if (attr === "rltb" || attr === "rl") {
8312
8313                    dom_element.style.writingMode = "horizontal-tb";
8314
8315                } else if (attr === "tblr") {
8316
8317                    dom_element.style.writingMode = "vertical-lr";
8318
8319                } else if (attr === "tbrl" || attr === "tb") {
8320
8321                    dom_element.style.writingMode = "vertical-rl";
8322
8323                }
8324            }
8325        ),
8326        new HTMLStylingMapDefintion(
8327            "http://www.w3.org/ns/ttml#styling zIndex",
8328            function (context, dom_element, isd_element, attr) {
8329                dom_element.style.zIndex = attr;
8330            }
8331        ),
8332        new HTMLStylingMapDefintion(
8333            "http://www.smpte-ra.org/schemas/2052-1/2010/smpte-tt backgroundImage",
8334            function (context, dom_element, isd_element, attr) {
8335
8336                if (context.imgResolver !== null && attr !== null) {
8337
8338                    var img = document.createElement("img");
8339
8340                    var uri = context.imgResolver(attr, img);
8341
8342                    if (uri)
8342 img.src = uri;
8343
8344                    img.height = context.regionH;
8345                    img.width = context.regionW;
8346
8347                    dom_element.appendChild(img);
8348                }
8349            }
8350        ),
8351        new HTMLStylingMapDefintion(
8352            "http://www.w3.org/ns/ttml/profile/imsc1#styling forcedDisplay",
8353            function (context, dom_element, isd_element, attr) {
8354
8355                if (context.displayForcedOnlyMode && attr === false) {
8356                    dom_element.style.visibility = "hidden";
8357                }
8358
8359            }
8360        )
8361    ];
8362
8363    var STYLMAP_BY_QNAME = {};
8364
8365    for (var i in STYLING_MAP_DEFS) {
8366
8367        STYLMAP_BY_QNAME[STYLING_MAP_DEFS[i].qname] = STYLING_MAP_DEFS[i];
8368    }
8369
8370})(typeof exports === 'undefined' ? this.imscHTML = {} : exports,
8371    typeof imscNames === 'undefined' ? _dereq_(22) : imscNames,
8372    typeof imscStyles === 'undefined' ? _dereq_(23) : imscStyles);
8373},{"22":22,"23":23}],20:[function(_dereq_,module,exports){
8374/* 
8375 * Copyright (c) 2016, Pierre-Anthony Lemieux <[email protected]>
8376 * All rights reserved.
8377 *
8378 * Redistribution and use in source and binary forms, with or without
8379 * modification, are permitted provided that the following conditions are met:
8380 *
8381 * * Redistributions of source code must retain the above copyright notice, this
8382 *   list of conditions and the following disclaimer.
8383 * * Redistributions in binary form must reproduce the above copyright notice,
8384 *   this list of conditions and the following disclaimer in the documentation
8385 *   and/or other materials provided with the distribution.
8386 *
8387 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
8388 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
8389 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
8390 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
8391 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
8392 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
8393 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
8394 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
8395 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
8396 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
8397 * POSSIBILITY OF SUCH DAMAGE.
8398 */
8399
8400/**
8401 * @module imscISD
8402 */
8403
8404
8405;
8406(function (imscISD, imscNames, imscStyles) { // wrapper for non-node envs
8407
8408    /** 
8409     * Creates a canonical representation of an IMSC1 document returned by <pre>imscDoc.fromXML()</pre>
8410     * at a given absolute offset in seconds. This offset does not have to be one of the values returned
8411     * by <pre>getMediaTimeEvents()</pre>.
8412     * 
8413     * @param {Object} tt IMSC1 document
8414     * @param {number} offset Absolute offset (in seconds)
8415     * @param {?module:imscUtils.ErrorHandler} errorHandler Error callback
8416     * @returns {Object} Opaque in-memory representation of an ISD
8417     */
8418
8419    imscISD.generateISD = function (tt, offset, errorHandler) {
8420
8421        /* TODO check for tt and offset validity */
8422
8423        /* create the ISD object from the IMSC1 doc */
8424
8425        var isd = new ISD(tt);
8426
8427        /* process regions */
8428
8429        for (var r in tt.head.layout.regions) {
8430
8431            /* post-order traversal of the body tree per [construct intermediate document] */
8432
8433            var c = isdProcessContentElement(tt, offset, tt.head.layout.regions[r], tt.body, null, '', tt.head.layout.regions[r], errorHandler);
8434
8435            if (c !== null) {
8436
8437                /* add the region to the ISD */
8438
8439                isd.contents.push(c.element);
8440            }
8441
8442
8443        }
8444
8445        return isd;
8446    };
8447
8448    function isdProcessContentElement(doc, offset, region, body, parent, inherited_region_id, elem, errorHandler) {
8449
8450        /* prune if temporally inactive */
8451
8452        if (offset < elem.begin || offset >= elem.end) return null;
8453
8454        /* 
vendor: 15,055 bytes, lines 8455-8993
8455         * set the associated region as specified by the regionID attribute, or the 
8456         * inherited associated region otherwise
8457         */
8458
8459        var associated_region_id = 'regionID' in elem && elem.regionID !== '' ? elem.regionID : inherited_region_id;
8460
8461        /* prune the element if either:
8462         * - the element is not terminal and the associated region is neither the default
8463         *   region nor the parent region (this allows children to be associated with a 
8464         *   region later on)
8465         * - the element is terminal and the associated region is not the parent region
8466         */
8467        
8468        /* TODO: improve detection of terminal elements since <region> has no contents */
8469
8470        if (parent !== null /* are we in the region element */ &&
8471            associated_region_id !== region.id &&
8472                (
8473                    (! ('contents' in elem)) ||
8474                    ('contents' in elem && elem.contents.length === 0) ||
8475                    associated_region_id !== ''
8476                )
8477             )
8478            return null;
8479
8480        /* create an ISD element, including applying specified styles */
8481
8482        var isd_element = new ISDContentElement(elem);
8483
8484        /* apply set (animation) styling */
8485
8486        for (var i in elem.sets) {
8487
8488            if (offset < elem.sets[i].begin || offset >= elem.sets[i].end)
8489                continue;
8490
8491            isd_element.styleAttrs[elem.sets[i].qname] = elem.sets[i].value;
8492
8493        }
8494
8495        /* 
8496         * keep track of specified styling attributes so that we
8497         * can compute them later
8498         */
8499
8500        var spec_attr = {};
8501
8502        for (var qname in isd_element.styleAttrs) {
8503
8504            spec_attr[qname] = true;
8505
8506            /* special rule for tts:writingMode (section 7.29.1 of XSL)
8507             * direction is set consistently with writingMode only
8508             * if writingMode sets inline-direction to LTR or RTL  
8509             */
8510
8511            if (qname === imscStyles.byName.writingMode.qname &&
8512                !(imscStyles.byName.direction.qname in isd_element.styleAttrs)) {
8513
8514                var wm = isd_element.styleAttrs[qname];
8515
8516                if (wm === "lrtb" || wm === "lr") {
8517
8518                    isd_element.styleAttrs[imscStyles.byName.direction.qname] = "ltr";
8519
8520                } else if (wm === "rltb" || wm === "rl") {
8521
8522                    isd_element.styleAttrs[imscStyles.byName.direction.qname] = "rtl";
8523
8524                }
8525
8526            }
8527        }
8528
8529        /* inherited styling */
8530
8531        if (parent !== null) {
8532
8533            for (var j in imscStyles.all) {
8534
8535                var sa = imscStyles.all[j];
8536
8537                /* textDecoration has special inheritance rules */
8538
8539                if (sa.qname === imscStyles.byName.textDecoration.qname) {
8540
8541                    /* handle both textDecoration inheritance and specification */
8542
8543                    var ps = parent.styleAttrs[sa.qname];
8544                    var es = isd_element.styleAttrs[sa.qname];
8545                    var outs = [];
8546
8547                    if (es === undefined) {
8548
8549                        outs = ps;
8550
8551                    } else if (es.indexOf("none") === -1) {
8552
8553                        if ((es.indexOf("noUnderline") === -1 &&
8554                            ps.indexOf("underline") !== -1) ||
8555                            es.indexOf("underline") !== -1) {
8556
8557                            outs.push("underline");
8558
8559                        }
8560
8561                        if ((es.indexOf("noLineThrough") === -1 &&
8562                            ps.indexOf("lineThrough") !== -1) ||
8563                            es.indexOf("lineThrough") !== -1) {
8564
8565                            outs.push("lineThrough");
8566
8567                        }
8568
8569                        if ((es.indexOf("noOverline") === -1 &&
8570                            ps.indexOf("overline") !== -1) ||
8571                            es.indexOf("overline") !== -1) {
8572
8573                            outs.push("overline");
8574
8575                        }
8576
8577                    } else {
8578
8579                        outs.push("none");
8580
8581                    }
8582
8583                    isd_element.styleAttrs[sa.qname] = outs;
8584
8585                } else if (sa.inherit &&
8586                    (sa.qname in parent.styleAttrs) &&
8587                    !(sa.qname in isd_element.styleAttrs)) {
8588
8589                    isd_element.styleAttrs[sa.qname] = parent.styleAttrs[sa.qname];
8590
8591                }
8592
8593            }
8594
8595        }
8596
8597        /* initial value styling */
8598
8599        for (var k in imscStyles.all) {
8600
8601            var ivs = imscStyles.all[k];
8602
8603            /* skip if value is already specified */
8604
8605            if (ivs.qname in isd_element.styleAttrs) continue;
8606
8607            /* apply initial value to elements other than region only if non-inherited */
8608
8609            if (isd_element.kind === 'region' || (ivs.inherit === false && ivs.initial !== null)) {
8610
8611                isd_element.styleAttrs[ivs.qname] = ivs.parse(ivs.initial);
8612
8613                /* keep track of the style as specified */
8614
8615                spec_attr[ivs.qname] = true;
8616
8617            }
8618
8619        }
8620
8621        /* compute styles (only for non-inherited styles) */
8622        /* TODO: get rid of spec_attr */
8623
8624        for (var z in imscStyles.all) {
8625
8626            var cs = imscStyles.all[z];
8627
8628            if (!(cs.qname in spec_attr)) continue;
8629
8630            if (cs.compute !== null) {
8631
8632                var cstyle = cs.compute(
8633                    /*doc, parent, element, attr*/
8634                    doc,
8635                    parent,
8636                    isd_element,
8637                    isd_element.styleAttrs[cs.qname]
8638                    );
8639
8640
8641                isd_element.styleAttrs[cs.qname] = cstyle;
8642
8643
8644                // reportError(errorHandler, "Style '" + sa.qname + "' on element '" + isd_element.kind + "' cannot be computed");
8645
8646            }
8647
8648        }
8649
8650        /* prune if tts:display is none */
8651
8652        if (isd_element.styleAttrs[imscStyles.byName.display.qname] === "none")
8653            return null;
8654
8655        /* process contents of the element */
8656
8657        var contents;
8658
8659        if (parent === null) {
8660
8661            /* we are processing the region */
8662
8663            if (body === null) {
8664
8665                /* if there is no body, still process the region but with empty content */
8666
8667                contents = [];
8668
8669            } else {
8670
8671                /*use the body element as contents */
8672
8673                contents = [body];
8674
8675            }
8676
8677        } else if ('contents' in elem) {
8678
8679            contents = elem.contents;
8680
8681        }
8682
8683        for (var x in contents) {
8684
8685            var c = isdProcessContentElement(doc, offset, region, body, isd_element, associated_region_id, contents[x]);
8686
8687            /* 
8688             * keep child element only if they are non-null and their region match 
8689             * the region of this element
8690             */
8691
8692            if (c !== null) {
8693
8694                isd_element.contents.push(c.element);
8695
8696            }
8697
8698        }
8699
8700        /* compute used value of lineHeight="normal" */
8701
8702        /*        if (isd_element.styleAttrs[imscStyles.byName.lineHeight.qname] === "normal"  ) {
8703         
8704         isd_element.styleAttrs[imscStyles.byName.lineHeight.qname] =
8705         isd_element.styleAttrs[imscStyles.byName.fontSize.qname] * 1.2;
8706         
8707         }
8708         */
8709
8710        /* remove styles that are not applicable */
8711
8712        for (var qnameb in isd_element.styleAttrs) {
8713            var da = imscStyles.byQName[qnameb];
8714
8715            if (da.applies.indexOf(isd_element.kind) === -1) {
8716                delete isd_element.styleAttrs[qnameb];
8717            }
8718        }
8719
8720        /* collapse white space if space is "default" */
8721
8722        if (isd_element.kind === 'span' && isd_element.text && isd_element.space === "default") {
8723
8724            var trimmedspan = isd_element.text.replace(/\s+/g, ' ');
8725
8726            isd_element.text = trimmedspan;
8727
8728        }
8729
8730        /* trim whitespace around explicit line breaks */
8731
8732        if (isd_element.kind === 'p') {
8733
8734            var elist = [];
8735
8736            constructSpanList(isd_element, elist);
8737
8738            var l = 0;
8739
8740            var state = "after_br";
8741            var br_pos = 0;
8742
8743            while (true) {
8744
8745                if (state === "after_br") {
8746
8747                    if (l >= elist.length || elist[l].kind === "br") {
8748
8749                        state = "before_br";
8750                        br_pos = l;
8751                        l--;
8752
8753                    } else {
8754
8755                        if (elist[l].space !== "preserve") {
8756
8757                            elist[l].text = elist[l].text.replace(/^\s+/g, '');
8758
8759                        }
8760
8761                        if (elist[l].text.length > 0) {
8762
8763                            state = "looking_br";
8764                            l++;
8765
8766                        } else {
8767
8768                            elist.splice(l, 1);
8769
8770                        }
8771
8772                    }
8773
8774                } else if (state === "before_br") {
8775
8776                    if (l < 0 || elist[l].kind === "br") {
8777
8778                        state = "after_br";
8779                        l = br_pos + 1;
8780
8781                        if (l >= elist.length) break;
8782
8783                    } else {
8784
8785                        if (elist[l].space !== "preserve") {
8786
8787                            elist[l].text = elist[l].text.replace(/\s+$/g, '');
8788
8789                        }
8790
8791                        if (elist[l].text.length > 0) {
8792
8793                            state = "after_br";
8794                            l = br_pos + 1;
8795
8796                            if (l >= elist.length) break;
8797
8798                        } else {
8799
8800                            elist.splice(l, 1);
8801                            l--;
8802
8803                        }
8804
8805                    }
8806
8807                } else {
8808
8809                    if (l >= elist.length || elist[l].kind === "br") {
8810
8811                        state = "before_br";
8812                        br_pos = l;
8813                        l--;
8814
8815                    } else {
8816
8817                        l++;
8818
8819                    }
8820
8821                }
8822
8823            }
8824            
8825            pruneEmptySpans(isd_element);
8826
8827        }
8828
8829        /* keep element if:
8830         * * contains a background image
8831         * * <br/>
8832         * * if there are children
8833         * * if <span> and has text
8834         * * if region and showBackground = always
8835         */
8836
8837        if ((isd_element.kind === 'div' && imscStyles.byName.backgroundImage.qname in isd_element.styleAttrs) ||
8838            isd_element.kind === 'br' ||
8839            ('contents' in isd_element && isd_element.contents.length > 0) ||
8840            (isd_element.kind === 'span' && isd_element.text !== null) ||
8841            (isd_element.kind === 'region' &&
8842                isd_element.styleAttrs[imscStyles.byName.showBackground.qname] === 'always')) {
8843
8844            return {
8845                region_id: associated_region_id,
8846                element: isd_element
8847            };
8848        }
8849
8850        return null;
8851    }
8852
8853    function constructSpanList(element, elist) {
8854
8855        if ('contents' in element) {
8856
8857            for (var i in element.contents) {
8858                constructSpanList(element.contents[i], elist);
8859            }
8860
8861        } else {
8862
8863            elist.push(element);
8864
8865        }
8866
8867    }
8868
8869    function pruneEmptySpans(element) {
8870
8871        if (element.kind === 'br') {
8872            
8873            return false;
8874            
8875        } else if ('text' in element) {
8876            
8877            return  element.text.length === 0;
8878            
8879        } else if ('contents' in element) {
8880            
8881            var i = element.contents.length;
8882
8883            while (i--) {
8884                
8885                if (pruneEmptySpans(element.contents[i])) {
8886                    element.contents.splice(i, 1);
8887                }
8888                
8889            }
8890            
8891            return element.contents.length === 0;
8892
8893        }
8894    }
8895
8896    function ISD(tt) {
8897        this.contents = [];
8898        this.aspectRatio = tt.aspectRatio;
8899    }
8900
8901    function ISDContentElement(ttelem) {
8902
8903        /* assume the element is a region if it does not have a kind */
8904
8905        this.kind = ttelem.kind || 'region';
8906
8907        /* deep copy of style attributes */
8908        this.styleAttrs = {};
8909
8910        for (var sname in ttelem.styleAttrs) {
8911
8912            this.styleAttrs[sname] =
8913                ttelem.styleAttrs[sname];
8914        }
8915
8916        /* TODO: clean this! */
8917
8918        if ('text' in ttelem) {
8919
8920            this.text = ttelem.text;
8921
8922        } else if (ttelem.kind !== 'br') {
8923            
8924            this.contents = [];
8925        }
8926
8927        if ('space' in ttelem) {
8928
8929            this.space = ttelem.space;
8930        }
8931    }
8932
8933
8934    /*
8935     * ERROR HANDLING UTILITY FUNCTIONS
8936     * 
8937     */
8938
8939    function reportInfo(errorHandler, msg) {
8940
8941        if (errorHandler && errorHandler.info && errorHandler.info(msg))
8942            throw msg;
8943
8944    }
8945
8946    function reportWarning(errorHandler, msg) {
8947
8948        if (errorHandler && errorHandler.warn && errorHandler.warn(msg))
8949            throw msg;
8950
8951    }
8952
8953    function reportError(errorHandler, msg) {
8954
8955        if (errorHandler && errorHandler.error && errorHandler.error(msg))
8956            throw msg;
8957
8958    }
8959
8960    function reportFatal(errorHandler, msg) {
8961
8962        if (errorHandler && errorHandler.fatal)
8963            errorHandler.fatal(msg);
8964
8965        throw msg;
8966
8967    }
8968
8969
8970})(typeof exports === 'undefined' ? this.imscISD = {} : exports,
8971    typeof imscNames === 'undefined' ? _dereq_(22) : imscNames,
8972    typeof imscStyles === 'undefined' ? _dereq_(23) : imscStyles
8973    );
8974
8975},{"22":22,"23":23}],21:[function(_dereq_,module,exports){
8976/* 
8977 * Copyright (c) 2016, Pierre-Anthony Lemieux <[email protected]>
8978 * All rights reserved.
8979 *
8980 * Redistribution and use in source and binary forms, with or without
8981 * modification, are permitted provided that the following conditions are met:
8982 *
8983 * * Redistributions of source code must retain the above copyright notice, this
8984 *   list of conditions and the following disclaimer.
8985 * * Redistributions in binary form must reproduce the above copyright notice,
8986 *   this list of conditions and the following disclaimer in the documentation
8987 *   and/or other materials provided with the distribution.
8988 *
8989 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
8990 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
8991 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
8992 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
8993 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
8994 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
8995 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
8996 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
8997 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
8998 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
8999 * POSSIBILITY OF SUCH DAMAGE.
9000 */
9001
9002exports.generateISD = _dereq_(20).generateISD;
9003exports.fromXML = _dereq_(18).fromXML;
9004exports.renderHTML = _dereq_(19).render;
9005},{"18":18,"19":19,"20":20}],22:[function(_dereq_,module,exports){
9006/* 
9007 * Copyright (c) 2016, Pierre-Anthony Lemieux <[email protected]>
9008 * All rights reserved.
9009 *
9010 * Redistribution and use in source and binary forms, with or without
9011 * modification, are permitted provided that the following conditions are met:
9012 *
9013 * * Redistributions of source code must retain the above copyright notice, this
9014 *   list of conditions and the following disclaimer.
9015 * * Redistributions in binary form must reproduce the above copyright notice,
9016 *   this list of conditions and the following disclaimer in the documentation
9017 *   and/or other materials provided with the distribution.
9018 *
9019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9021 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9022 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
9023 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
9024 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
9025 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
9026 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
9027 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
9028 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
9029 * POSSIBILITY OF SUCH DAMAGE.
9030 */
9031
9032/**
9033 * @module imscNames
9034 */
9035
9036;
9037(function (imscNames) { // wrapper for non-node envs
9038
9039    imscNames.ns_tt = "http://www.w3.org/ns/ttml";
9040    imscNames.ns_tts = "http://www.w3.org/ns/ttml#styling";
9041    imscNames.ns_ttp = "http://www.w3.org/ns/ttml#parameter";
9042    imscNames.ns_xml = "http://www.w3.org/XML/1998/namespace";
9043    imscNames.ns_itts = "http://www.w3.org/ns/ttml/profile/imsc1#styling";
9044    imscNames.ns_ittp = "http://www.w3.org/ns/ttml/profile/imsc1#parameter";
9045    imscNames.ns_smpte = "http://www.smpte-ra.org/schemas/2052-1/2010/smpte-tt";
9046    imscNames.ns_ebutts = "urn:ebu:tt:style";
9047    
9048})(typeof exports === 'undefined' ? this.imscNames = {} : exports);
9049
9050
9051
9052
9053
9054},{}],23:[function(_dereq_,module,exports){
9055/* 
9056 * Copyright (c) 2016, Pierre-Anthony Lemieux <[email protected]>
9057 * All rights reserved.
9058 *
9059 * Redistribution and use in source and binary forms, with or without
9060 * modification, are permitted provided that the following conditions are met:
9061 *
9062 * * Redistributions of source code must retain the above copyright notice, this
9063 *   list of conditions and the following disclaimer.
9064 * * Redistributions in binary form must reproduce the above copyright notice,
9065 *   this list of conditions and the following disclaimer in the documentation
9066 *   and/or other materials provided with the distribution.
9067 *
9068 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9069 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9070 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9071 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
9072 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
9073 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
9074 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
9075 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
9076 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
9077 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
9078 * POSSIBILITY OF SUCH DAMAGE.
9079 */
9080
9081/**
9082 * @module imscStyles
9083 */
9084
9085;
9086(function (imscStyles, imscNames, imscUtils) { // wrapper for non-node envs
9087
9088    function StylingAttributeDefinition(ns, name, initialValue, appliesTo, isInherit, isAnimatable, parseFunc, c
vendor: 24,690 bytes, lines 9088-9936
9088omputeFunc) {
9089        this.name = name;
9090        this.ns = ns;
9091        this.qname = ns + " " + name;
9092        this.inherit = isInherit;
9093        this.animatable = isAnimatable;
9094        this.initial = initialValue;
9095        this.applies = appliesTo;
9096        this.parse = parseFunc;
9097        this.compute = computeFunc;
9098    }
9099
9100    imscStyles.all = [
9101
9102        new StylingAttributeDefinition(
9103                imscNames.ns_tts,
9104                "backgroundColor",
9105                "transparent",
9106                ['body', 'div', 'p', 'region', 'span'],
9107                false,
9108                true,
9109                imscUtils.parseColor,
9110                null
9111                ),
9112        new StylingAttributeDefinition(
9113                imscNames.ns_tts,
9114                "color",
9115                "white",
9116                ['span'],
9117                true,
9118                true,
9119                imscUtils.parseColor,
9120                null
9121                ),
9122        new StylingAttributeDefinition(
9123                imscNames.ns_tts,
9124                "direction",
9125                "ltr",
9126                ['p', 'span'],
9127                true,
9128                true,
9129                function (str) {
9130                    return str;
9131                },
9132                null
9133                ),
9134        new StylingAttributeDefinition(
9135                imscNames.ns_tts,
9136                "display",
9137                "auto",
9138                ['body', 'div', 'p', 'region', 'span'],
9139                false,
9140                true,
9141                function (str) {
9142                    return str;
9143                },
9144                null
9145                ),
9146        new StylingAttributeDefinition(
9147                imscNames.ns_tts,
9148                "displayAlign",
9149                "before",
9150                ['region'],
9151                false,
9152                true,
9153                function (str) {
9154                    return str;
9155                },
9156                null
9157                ),
9158        new StylingAttributeDefinition(
9159                imscNames.ns_tts,
9160                "extent",
9161                "auto",
9162                ['tt', 'region'],
9163                false,
9164                true,
9165                function (str) {
9166
9167                    if (str === "auto") {
9168
9169                        return str;
9170
9171                    } else {
9172
9173                        var s = str.split(" ");
9174                        if (s.length !== 2) return null;
9175                        var w = imscUtils.parseLength(s[0]);
9176                        var h = imscUtils.parseLength(s[1]);
9177                        if (!h || !w) return null;
9178                        return {'h': h, 'w': w};
9179                    }
9180
9181                },
9182                function (doc, parent, element, attr) {
9183
9184                    var h;
9185                    var w;
9186
9187                    if (attr === "auto") {
9188
9189                        h = 1;
9190
9191                    } else if (attr.h.unit === "%") {
9192
9193                        h = attr.h.value / 100;
9194
9195                    } else if (attr.h.unit === "px") {
9196
9197                        h = attr.h.value / doc.pxDimensions.h;
9198
9199                    } else {
9200
9201                        return null;
9202
9203                    }
9204
9205                    if (attr === "auto") {
9206
9207                        w = 1;
9208
9209                    } else if (attr.w.unit === "%") {
9210
9211                        w = attr.w.value / 100;
9212
9213                    } else if (attr.w.unit === "px") {
9214
9215                        w = attr.w.value / doc.pxDimensions.w;
9216
9217                    } else {
9218
9219                        return null;
9220
9221                    }
9222
9223                    return {'h': h, 'w': w};
9224                }
9225        ),
9226        new StylingAttributeDefinition(
9227                imscNames.ns_tts,
9228                "fontFamily",
9229                "default",
9230                ['span'],
9231                true,
9232                true,
9233                function (str) {
9234                    var ffs = str.split(",");
9235                    var rslt = [];
9236
9237                    for (var i in ffs) {
9238
9239                        if (ffs[i].charAt(0) !== "'" && ffs[i].charAt(0) !== '"') {
9240
9241                            if (ffs[i] === "default") {
9242
9243                                /* per IMSC1 */
9244
9245                                rslt.push("monospaceSerif");
9246
9247                            } else {
9248
9249                                rslt.push(ffs[i]);
9250
9251                            }
9252
9253                        } else {
9254
9255                            rslt.push(ffs[i]);
9256
9257                        }
9258
9259                    }
9260
9261                    return rslt;
9262                },
9263                null
9264                ),
9265        new StylingAttributeDefinition(
9266                imscNames.ns_tts,
9267                "fontSize",
9268                "1c",
9269                ['span'],
9270                true,
9271                true,
9272                imscUtils.parseLength,
9273                function (doc, parent, element, attr) {
9274
9275                    var fs;
9276
9277                    if (attr.unit === "%") {
9278
9279                        if (parent !== null) {
9280
9281                            fs = parent.styleAttrs[imscStyles.byName.fontSize.qname] * attr.value / 100;
9282
9283                        } else {
9284
9285                            /* region, so percent of 1c */
9286
9287                            fs = attr.value / 100 / doc.cellResolution.h;
9288
9289                        }
9290
9291                    } else if (attr.unit === "em") {
9292
9293                        if (parent !== null) {
9294
9295                            fs = parent.styleAttrs[imscStyles.byName.fontSize.qname] * attr.value;
9296
9297                        } else {
9298
9299                            /* region, so percent of 1c */
9300
9301                            fs = attr.value / doc.cellResolution.h;
9302
9303                        }
9304
9305                    } else if (attr.unit === "c") {
9306
9307                        fs = attr.value / doc.cellResolution.h;
9308
9309                    } else if (attr.unit === "px") {
9310
9311                        fs = attr.value / doc.pxDimensions.h;
9312
9313                    } else {
9314
9315                        return null;
9316
9317                    }
9318
9319                    return fs;
9320                }
9321        ),
9322        new StylingAttributeDefinition(
9323                imscNames.ns_tts,
9324                "fontStyle",
9325                "normal",
9326                ['span'],
9327                true,
9328                true,
9329                function (str) {
9330                    /* TODO: handle font style */
9331
9332                    return str;
9333                },
9334                null
9335                ),
9336        new StylingAttributeDefinition(
9337                imscNames.ns_tts,
9338                "fontWeight",
9339                "normal",
9340                ['span'],
9341                true,
9342                true,
9343                function (str) {
9344                    /* TODO: handle font weight */
9345
9346                    return str;
9347                },
9348                null
9349                ),
9350        new StylingAttributeDefinition(
9351                imscNames.ns_tts,
9352                "lineHeight",
9353                "normal",
9354                ['p'],
9355                true,
9356                true,
9357                function (str) {
9358                    if (str === "normal") {
9359                        return str;
9360                    } else {
9361                        return imscUtils.parseLength(str);
9362                    }
9363                },
9364                function (doc, parent, element, attr) {
9365
9366                    var lh;
9367
9368                    if (attr === "normal") {
9369
9370                        /* inherit normal per https://github.com/w3c/ttml1/issues/220 */
9371
9372                        lh = attr;
9373
9374                    } else if (attr.unit === "%") {
9375
9376                        lh = element.styleAttrs[imscStyles.byName.fontSize.qname] * attr.value / 100;
9377
9378                    } else if (attr.unit === "em") {
9379
9380                        lh = element.styleAttrs[imscStyles.byName.fontSize.qname] * attr.value;
9381
9382                    } else if (attr.unit === "c") {
9383
9384                        lh = attr.value / doc.cellResolution.h;
9385
9386                    } else if (attr.unit === "px") {
9387
9388                        /* TODO: handle error if no px dimensions are provided */
9389
9390                        lh = attr.value / doc.pxDimensions.h;
9391
9392                    } else {
9393
9394                        return null;
9395
9396                    }
9397
9398                    /* TODO: create a Length constructor */
9399
9400                    return lh;
9401                }
9402        ),
9403        new StylingAttributeDefinition(
9404                imscNames.ns_tts,
9405                "opacity",
9406                1.0,
9407                ['region'],
9408                false,
9409                true,
9410                parseFloat,
9411                null
9412                ),
9413        new StylingAttributeDefinition(
9414                imscNames.ns_tts,
9415                "origin",
9416                "auto",
9417                ['region'],
9418                false,
9419                true,
9420                function (str) {
9421
9422                    if (str === "auto") {
9423
9424                        return str;
9425
9426                    } else {
9427
9428                        var s = str.split(" ");
9429                        if (s.length !== 2) return null;
9430                        var w = imscUtils.parseLength(s[0]);
9431                        var h = imscUtils.parseLength(s[1]);
9432                        if (!h || !w) return null;
9433                        return {'h': h, 'w': w};
9434                    }
9435
9436                },
9437                function (doc, parent, element, attr) {
9438
9439                    var h;
9440                    var w;
9441
9442                    if (attr === "auto") {
9443
9444                        h = 0;
9445
9446                    } else if (attr.h.unit === "%") {
9447
9448                        h = attr.h.value / 100;
9449
9450                    } else if (attr.h.unit === "px") {
9451
9452                        h = attr.h.value / doc.pxDimensions.h;
9453
9454                    } else {
9455
9456                        return null;
9457
9458                    }
9459
9460                    if (attr === "auto") {
9461
9462                        w = 0;
9463
9464                    } else if (attr.w.unit === "%") {
9465
9466                        w = attr.w.value / 100;
9467
9468                    } else if (attr.w.unit === "px") {
9469
9470                        w = attr.w.value / doc.pxDimensions.w;
9471
9472                    } else {
9473
9474                        return null;
9475
9476                    }
9477
9478                    return {'h': h, 'w': w};
9479                }
9480        ),
9481        new StylingAttributeDefinition(
9482                imscNames.ns_tts,
9483                "overflow",
9484                "hidden",
9485                ['region'],
9486                false,
9487                true,
9488                function (str) {
9489                    return str;
9490                },
9491                null
9492                ),
9493        new StylingAttributeDefinition(
9494                imscNames.ns_tts,
9495                "padding",
9496                "0px",
9497                ['region'],
9498                false,
9499                true,
9500                function (str) {
9501
9502                    var s = str.split(" ");
9503                    if (s.length > 4) return null;
9504                    var r = [];
9505                    for (var i in s) {
9506
9507                        var l = imscUtils.parseLength(s[i]);
9508                        if (!l) return null;
9509                        r.push(l);
9510                    }
9511
9512                    return r;
9513                },
9514                function (doc, parent, element, attr) {
9515
9516                    var padding;
9517
9518                    /* TODO: make sure we are in region */
9519
9520                    /*
9521                     * expand padding shortcuts to 
9522                     * [before, end, after, start]
9523                     * 
9524                     */
9525
9526                    if (attr.length === 1) {
9527
9528                        padding = [attr[0], attr[0], attr[0], attr[0]];
9529
9530                    } else if (attr.length === 2) {
9531
9532                        padding = [attr[0], attr[1], attr[0], attr[1]];
9533
9534                    } else if (attr.length === 3) {
9535
9536                        padding = [attr[0], attr[1], attr[2], attr[1]];
9537
9538                    } else if (attr.length === 4) {
9539
9540                        padding = [attr[0], attr[1], attr[2], attr[3]];
9541
9542                    } else {
9543
9544                        return null;
9545
9546                    }
9547
9548                    /* TODO: take into account tts:direction */
9549
9550                    /* 
9551                     * transform [before, end, after, start] according to writingMode to 
9552                     * [top,left,bottom,right]
9553                     * 
9554                     */
9555
9556                    var dir = element.styleAttrs[imscStyles.byName.writingMode.qname];
9557
9558                    if (dir === "lrtb" || dir === "lr") {
9559
9560                        padding = [padding[0], padding[3], padding[2], padding[1]];
9561
9562                    } else if (dir === "rltb" || dir === "rl") {
9563
9564                        padding = [padding[0], padding[1], padding[2], padding[3]];
9565
9566                    } else if (dir === "tblr") {
9567
9568                        padding = [padding[3], padding[0], padding[1], padding[2]];
9569
9570                    } else if (dir === "tbrl" || dir === "tb") {
9571
9572                        padding = [padding[3], padding[2], padding[1], padding[0]];
9573
9574                    } else {
9575
9576                        return null;
9577
9578                    }
9579
9580                    var out = [];
9581
9582                    for (var i in padding) {
9583
9584                        if (padding[i].value === 0) {
9585
9586                            out[i] = 0;
9587
9588                        } else if (padding[i].unit === "%") {
9589
9590                            if (i === "0" || i === "2") {
9591
9592                                out[i] = element.styleAttrs[imscStyles.byName.extent.qname].h * padding[i].value / 100;
9593
9594                            } else {
9595
9596                                out[i] = element.styleAttrs[imscStyles.byName.extent.qname].w * padding[i].value / 100;
9597                            }
9598
9599                        } else if (padding[i].unit === "em") {
9600
9601                            out[i] = element.styleAttrs[imscStyles.byName.fontSize.qname] * padding[i].value;
9602
9603                        } else if (padding[i].unit === "c") {
9604
9605                            out[i] = padding[i].value / doc.cellResolution.h;
9606
9607                        } else if (padding[i].unit === "px") {
9608
9609                            out[i] = padding[i].value / doc.pxDimensions.h;
9610
9611                        } else {
9612
9613                            return null;
9614
9615                        }
9616                    }
9617
9618
9619                    return out;
9620                }
9621        ),
9622        new StylingAttributeDefinition(
9623                imscNames.ns_tts,
9624                "showBackground",
9625                "always",
9626                ['region'],
9627                false,
9628                true,
9629                function (str) {
9630                    return str;
9631                },
9632                null
9633                ),
9634        new StylingAttributeDefinition(
9635                imscNames.ns_tts,
9636                "textAlign",
9637                "start",
9638                ['p'],
9639                true,
9640                true,
9641                function (str) {
9642                    return str;
9643                },
9644                function (doc, parent, element, attr) {
9645                    
9646                    /* Section 7.16.9 of XSL */
9647                    
9648                    if (attr === "left") {
9649                        
9650                        return "start";
9651                        
9652                    } else if (attr === "right") {
9653                        
9654                        return "end";
9655                        
9656                    } else {
9657                        
9658                        return attr;
9659                        
9660                    }
9661                }
9662                ),
9663        new StylingAttributeDefinition(
9664                imscNames.ns_tts,
9665                "textDecoration",
9666                "none",
9667                ['span'],
9668                true,
9669                true,
9670                function (str) {
9671                    return str.split(" ");
9672                },
9673                null
9674                ),
9675        new StylingAttributeDefinition(
9676                imscNames.ns_tts,
9677                "textOutline",
9678                "none",
9679                ['span'],
9680                true,
9681                true,
9682                function (str) {
9683
9684                    /*
9685                     * returns {c: <color>?, thichness: <length>} | "none"
9686                     * 
9687                     */
9688
9689                    if (str === "none") {
9690
9691                        return str;
9692
9693                    } else {
9694
9695                        var r = {};
9696                        var s = str.split(" ");
9697                        if (s.length === 0 || s.length > 2) return null;
9698                        var c = imscUtils.parseColor(s[0]);
9699                       
9700                        r.color = c;
9701                        
9702                        if (c !== null) s.shift();
9703
9704                        if (s.length !== 1) return null;
9705
9706                        var l = imscUtils.parseLength(s[0]);
9707
9708                        if (!l) return null;
9709
9710                        r.thickness = l;
9711
9712                        return r;
9713                    }
9714
9715                },
9716                function (doc, parent, element, attr) {
9717
9718                    /*
9719                     * returns {color: <color>, thickness: <norm length>}
9720                     * 
9721                     */
9722
9723                    if (attr === "none") return attr;
9724
9725                    var rslt = {};
9726
9727                    if (attr.color === null) {
9728                        
9729                        rslt.color = element.styleAttrs[imscStyles.byName.color.qname];
9730                        
9731                    } else {
9732                        
9733                        rslt.color = attr.color;
9734
9735                    }
9736
9737                    if (attr.thickness.unit === "%") {
9738
9739                        rslt.thickness = element.styleAttrs[imscStyles.byName.fontSize.qname] * attr.thickness.value / 100;
9740
9741                    } else if (attr.thickness.unit === "em") {
9742
9743                        rslt.thickness = element.styleAttrs[imscStyles.byName.fontSize.qname] * attr.thickness.value;
9744
9745                    } else if (attr.thickness.unit === "c") {
9746
9747                        rslt.thickness = attr.thickness.value / doc.cellResolution.h;
9748
9749                    } else if (attr.thickness.unit === "px") {
9750
9751                        rslt.thickness = attr.thickness.value / doc.pxDimensions.h;
9752
9753                    } else {
9754
9755                        return null;
9756
9757                    }
9758
9759
9760                    return rslt;
9761                }
9762        ),
9763        new StylingAttributeDefinition(
9764                imscNames.ns_tts,
9765                "unicodeBidi",
9766                "normal",
9767                ['span', 'p'],
9768                false,
9769                true,
9770                function (str) {
9771                    return str;
9772                },
9773                null
9774                ),
9775        new StylingAttributeDefinition(
9776                imscNames.ns_tts,
9777                "visibility",
9778                "visible",
9779                ['body', 'div', 'p', 'region', 'span'],
9780                true,
9781                true,
9782                function (str) {
9783                    return str;
9784                },
9785                null
9786                ),
9787        new StylingAttributeDefinition(
9788                imscNames.ns_tts,
9789                "wrapOption",
9790                "wrap",
9791                ['span'],
9792                true,
9793                true,
9794                function (str) {
9795                    return str;
9796                },
9797                null
9798                ),
9799        new StylingAttributeDefinition(
9800                imscNames.ns_tts,
9801                "writingMode",
9802                "lrtb",
9803                ['region'],
9804                false,
9805                true,
9806                function (str) {
9807                    return str;
9808                },
9809                null
9810                ),
9811        new StylingAttributeDefinition(
9812                imscNames.ns_tts,
9813                "zIndex",
9814                "auto",
9815                ['region'],
9816                false,
9817                true,
9818                function (str) {
9819                    
9820                    var rslt;
9821                    
9822                    if (str === 'auto') {
9823                        
9824                        rslt = str;
9825                        
9826                    } else {
9827                        
9828                        rslt = parseInt(str);
9829                        
9830                        if (isNaN(rslt)) {
9831                            rslt = null;
9832                        }
9833                        
9834                    }
9835                    
9836                    return rslt;
9837                },
9838                null
9839                ),
9840        new StylingAttributeDefinition(
9841                imscNames.ns_ebutts,
9842                "linePadding",
9843                "0c",
9844                ['p'],
9845                true,
9846                false,
9847                imscUtils.parseLength,
9848                function (doc, parent, element, attr) {
9849                    if (attr.unit === "c") {
9850
9851                        return attr.value / doc.cellResolution.h;
9852
9853                    } else {
9854
9855                        return null;
9856
9857                    }
9858                }
9859        ),
9860        new StylingAttributeDefinition(
9861                imscNames.ns_ebutts,
9862                "multiRowAlign",
9863                "auto",
9864                ['p'],
9865                true,
9866                false,
9867                function (str) {
9868                    return str;
9869                },
9870                null
9871                ),
9872
9873        new StylingAttributeDefinition(
9874                imscNames.ns_smpte,
9875                "backgroundImage",
9876                null,
9877                ['div'],
9878                false,
9879                false,
9880                function (str) {
9881                    return str;
9882                },
9883                null
9884                ),
9885
9886        new StylingAttributeDefinition(
9887                imscNames.ns_itts,
9888                "forcedDisplay",
9889                "false",
9890                ['body', 'div', 'p', 'region', 'span'],
9891                true,
9892                true,
9893                function (str) {
9894                    return str === 'true' ? true : false;
9895                },
9896                null
9897                )
9898    ];
9899
9900    /* TODO: allow null parse function */
9901
9902    imscStyles.byQName = {};
9903    for (var i in imscStyles.all) {
9904
9905        imscStyles.byQName[imscStyles.all[i].qname] = imscStyles.all[i];
9906    }
9907
9908    imscStyles.byName = {};
9909    for (var j in imscStyles.all) {
9910
9911        imscStyles.byName[imscStyles.all[j].name] = imscStyles.all[j];
9912    }
9913
9914})(typeof exports === 'undefined' ? this.imscStyles = {} : exports,
9915        typeof imscNames === 'undefined' ? _dereq_(22) : imscNames,
9916        typeof imscUtils === 'undefined' ? _dereq_(24) : imscUtils);
9917
9918},{"22":22,"24":24}],24:[function(_dereq_,module,exports){
9919/* 
9920 * Copyright (c) 2016, Pierre-Anthony Lemieux <[email protected]>
9921 * All rights reserved.
9922 *
9923 * Redistribution and use in source and binary forms, with or without
9924 * modification, are permitted provided that the following conditions are met:
9925 *
9926 * * Redistributions of source code must retain the above copyright notice, this
9927 *   list of conditions and the following disclaimer.
9928 * * Redistributions in binary form must reproduce the above copyright notice,
9929 *   this list of conditions and the following disclaimer in the documentation
9930 *   and/or other materials provided with the distribution.
9931 *
9932 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9933 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9934 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9935 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
9936 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
9937 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
9938 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
9939 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
9940 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
9941 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
9942 * POSSIBILITY OF SUCH DAMAGE.
9943 */
9944
9945/**
9946 * @module imscUtils
9947 */
9948
9949;
9950(function (imscUtils) { // wrapper for non-node envs
9951    
9952    /* Documents the error handler interface */
9953    
9954    /**
9955     * @classdesc Generic interface for handling events. The interface exposes four
9956     * methods:
9957     * * <pre>info</pre>: unusual event that does not result in an inconsistent state
9958     * * <pre>warn</pre>: unexpected event that should not result in an inconsistent state
9959     * * <pre>error</pre>: unexpected event that may result in an inconsistent state
9960     * * <pre>fatal</pre>: unexpected event that results in an inconsistent state
9961     *   and termination of processing
9962     * Each method takes a single <pre>string</pre> describing the event as argument,
9963     * and returns a single <pre>boolean</pre>, which terminates processing if <pre>true</pre>.
9964     *
9965     * @name ErrorHandler
9966     * @class
9967     */
9968
9969
9970    /*
9971     * Parses a TTML color expression
9972     * 
9973     */
9974
9975    var HEX_COLOR_RE = /#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})?/;
9976    var DEC_COLOR_RE = /rgb\((\d+),(\d+),(\d+)\)/;
9977    var DEC_COLORA_RE = /rgba\((\d+),(\d+),(\d+),(\d+)\)/;
9978    var NAMED_COLOR = {
9979        transparent: [0, 0, 0, 0],
9980        black: [0, 0, 0, 255],
9981        silver: [192, 192, 192, 255],
9982        gray: [128, 128, 128, 255],
9983        white: [255, 255, 255, 255],
9984        maroon: [128, 0, 0, 255],
9985        red: [255, 0, 0, 255],
9986        purple: [128, 0, 128, 255],
9987        fuchsia: [255, 0, 255, 255],
9988        magenta: [255, 0, 255, 255],
9989        green: [0, 128, 0, 255],
9990        lime: [0, 255, 0, 255],
9991        olive: [128, 128, 0, 255],
9992        yellow: [255, 255, 0, 255],
9993        navy: [0, 0, 128, 255],
9994        blue: [0, 0, 255, 255],
9995        teal: [0, 128, 128, 255],
9996        aqua: [0, 255, 255, 255],
9997        cyan: [0, 255, 255, 255]
9998    };
9999
10000    imscUtils.parseColor = function (str) {
10001
10002        var m;
10003        var r = null;
10004        if (str in NAMED_COLOR) {
10005
10006            r = NAMED_COLOR[str];
10007
10008        } else if ((m = HEX_COLOR_RE.exec(str)) !== null) {
10009
10010            r = [parseInt(m[1], 16),
10011                parseInt(m[2], 16),
10012                parseInt(m[3], 16),
10013                (m[4] !== undefined ? parseInt(m[4], 16) : 255)];
10014        } else if ((m = DEC_COLOR_RE.exec(str)) !== null) {
10015
10016            r = [parseInt(m[1]),
10017                parseInt(m[2]),
10018                parseInt(m[3]),
10019                255];
10020        } else if ((m = DEC_COLORA_RE.exec(str)) !== null) {
10021
10022            r = [parseInt(m[1]),
10023                parseInt(m[2]),
10024                parseInt(m[3]),
10025                parseInt(m[4])];
10026        }
10027
10028        return r;
10029    };
10030
10031    var LENGTH_RE = /^((?:\+|\-)?\d*(?:\.\d+)?)(px|em|c|%)$/;
10032
10033    imscUtils.parseLength = function (str) {
10034
10035        var m;
10036
10037        var r = null;
10038
10039        if ((m = LENGTH_RE.exec(str)) !== null) {
10040
10041            r = {value: parseFloat(m[1]), unit: m[2]};
10042        }
10043
10044        return r;
10045    };
10046
10047})(typeof exports === 'undefined' ? this.imscUtils = {} : exports);
10048
10049},{}],25:[function(_dereq_,module,exports){
10050if (typeof Object.create === 'function') {
10051  // implementation from standard node.js 'util' module
10052  module.exports = function inherits(ctor, superCtor) {
10053    ctor.super_ = superCtor
10054    ctor.prototype = Object.create(superCtor.prototype, {
10055      constructor: {
10056        value: ctor,
10057        enumerable: false,
10058        writable: true,
10059        configurable: true
10060      }
10061    });
10062  };
10063} else {
10064  // old school shim for old browsers
10065  module.exports = function inherits(ctor, superCtor) {
10066    ctor.super_ = superCtor
10067    var TempCtor = function () {}
10068    TempCtor.prototype = superCtor.prototype
10069    ctor.prototype = new TempCtor()
10070    ctor.prototype.constructor = ctor
10071  }
10072}
10073
10074},{}],26:[function(_dereq_,module,exports){
10075/*!
10076 * Determine if an object is a Buffer
10077 *
10078 * @author   Feross Aboukhadijeh <[email protected]> <http://feross.org>
10079 * @license  MIT
10080 */
10081
10082// The _isBuffer check is for Safari 5-7 support, because it's missing
10083// Object.prototype.constructor. Remove this eventually
10084module.exports = function (obj) {
10085  return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)
10086}
10087
10088function isBuffer (obj) {
10089  return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)
10090}
10091
10092// For Node v0.10 support. Remove this eventually.
10093function isSlowBuffer (obj) {
10094  return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))
10095}
10096
10097},{}],27:[function(_dereq_,module,exports){
10098var toString = {}.toString;
10099
10100module.exports = Array.isArray || function (arr) {
10101  return toString.call(arr) == '[object Array]';
10102};
10103
10104},{}],28:[function(_dereq_,module,exports){
10105(function (process){
10106'use strict';
10107
10108if (!process.version ||
10109    process.version.indexOf('v0.') === 0 ||
10110    process.version.indexOf('v1.') === 0 && process.version.indexOf('v1.8.') !== 0) {
10111  module.exports = nextTick;
10112} else {
10113  module.exports = process.nextTick;
10114}
10115
10116function nextTick(fn, arg1, arg2, arg3) {
10117  if (typeof fn !== 'function') {
10118    throw new TypeError('"callback" argument must be a function');
10119  }
10120  var len = arguments.length;
10121  var args, i;
10122  switch (len) {
10123  case 0:
10124  case 1:
10125    return process.nextTick(fn);
10126  case 2:
10127    return process.nextTick(function afterTickOne() {
10128      fn.call(null, arg1);
10129    });
vendor: 5,156 bytes, lines 10130-10298
10130  case 3:
10131    return process.nextTick(function afterTickTwo() {
10132      fn.call(null, arg1, arg2);
10133    });
10134  case 4:
10135    return process.nextTick(function afterTickThree() {
10136      fn.call(null, arg1, arg2, arg3);
10137    });
10138  default:
10139    args = new Array(len - 1);
10140    i = 0;
10141    while (i < args.length) {
10142      args[i++] = arguments[i];
10143    }
10144    return process.nextTick(function afterTick() {
10145      fn.apply(null, args);
10146    });
10147  }
10148}
10149
10150}).call(this,_dereq_(29))
10151
10152},{"29":29}],29:[function(_dereq_,module,exports){
10153// shim for using process in browser
10154var process = module.exports = {};
10155
10156// cached from whatever global is present so that test runners that stub it
10157// don't break things.  But we need to wrap it in a try catch in case it is
10158// wrapped in strict mode code which doesn't define any globals.  It's inside a
10159// function because try/catches deoptimize in certain engines.
10160
10161var cachedSetTimeout;
10162var cachedClearTimeout;
10163
10164function defaultSetTimout() {
10165    throw new Error('setTimeout has not been defined');
10166}
10167function defaultClearTimeout () {
10168    throw new Error('clearTimeout has not been defined');
10169}
10170(function () {
10171    try {
10172        if (typeof setTimeout === 'function') {
10173            cachedSetTimeout = setTimeout;
10174        } else {
10175            cachedSetTimeout = defaultSetTimout;
10176        }
10177    } catch (e) {
10178        cachedSetTimeout = defaultSetTimout;
10179    }
10180    try {
10181        if (typeof clearTimeout === 'function') {
10182            cachedClearTimeout = clearTimeout;
10183        } else {
10184            cachedClearTimeout = defaultClearTimeout;
10185        }
10186    } catch (e) {
10187        cachedClearTimeout = defaultClearTimeout;
10188    }
10189} ())
10190function runTimeout(fun) {
10191    if (cachedSetTimeout === setTimeout) {
10192        //normal enviroments in sane situations
10193        return setTimeout(fun, 0);
10194    }
10195    // if setTimeout wasn't available but was latter defined
10196    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
10197        cachedSetTimeout = setTimeout;
10198        return setTimeout(fun, 0);
10199    }
10200    try {
10201        // when when somebody has screwed with setTimeout but no I.E. maddness
10202        return cachedSetTimeout(fun, 0);
10203    } catch(e){
10204        try {
10205            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
10206            return cachedSetTimeout.call(null, fun, 0);
10207        } catch(e){
10208            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
10209            return cachedSetTimeout.call(this, fun, 0);
10210        }
10211    }
10212
10213
10214}
10215function runClearTimeout(marker) {
10216    if (cachedClearTimeout === clearTimeout) {
10217        //normal enviroments in sane situations
10218        return clearTimeout(marker);
10219    }
10220    // if clearTimeout wasn't available but was latter defined
10221    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
10222        cachedClearTimeout = clearTimeout;
10223        return clearTimeout(marker);
10224    }
10225    try {
10226        // when when somebody has screwed with setTimeout but no I.E. maddness
10227        return cachedClearTimeout(marker);
10228    } catch (e){
10229        try {
10230            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
10231            return cachedClearTimeout.call(null, marker);
10232        } catch (e){
10233            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
10234            // Some versions of I.E. have different rules for clearTimeout vs setTimeout
10235            return cachedClearTimeout.call(this, marker);
10236        }
10237    }
10238
10239
10240
10241}
10242var queue = [];
10243var draining = false;
10244var currentQueue;
10245var queueIndex = -1;
10246
10247function cleanUpNextTick() {
10248    if (!draining || !currentQueue) {
10249        return;
10250    }
10251    draining = false;
10252    if (currentQueue.length) {
10253        queue = currentQueue.concat(queue);
10254    } else {
10255        queueIndex = -1;
10256    }
10257    if (queue.length) {
10258        drainQueue();
10259    }
10260}
10261
10262function drainQueue() {
10263    if (draining) {
10264        return;
10265    }
10266    var timeout = runTimeout(cleanUpNextTick);
10267    draining = true;
10268
10269    var len = queue.length;
10270    while(len) {
10271        currentQueue = queue;
10272        queue = [];
10273        while (++queueIndex < len) {
10274            if (currentQueue) {
10275                currentQueue[queueIndex].run();
10276            }
10277        }
10278        queueIndex = -1;
10279        len = queue.length;
10280    }
10281    currentQueue = null;
10282    draining = false;
10283    runClearTimeout(timeout);
10284}
10285
10286process.nextTick = function (fun) {
10287    var args = new Array(arguments.length - 1);
10288    if (arguments.length > 1) {
10289        for (var i = 1; i < arguments.length; i++) {
10290            args[i - 1] = arguments[i];
10291        }
10292    }
10293    queue.push(new Item(fun, args));
10294    if (queue.length === 1 && !draining) {
10295        runTimeout(drainQueue);
10296    }
10297};
10298
vendor: 14,736 bytes, lines 10299-10759
10299// v8 likes predictible objects
10300function Item(fun, array) {
10301    this.fun = fun;
10302    this.array = array;
10303}
10304Item.prototype.run = function () {
10305    this.fun.apply(null, this.array);
10306};
10307process.title = 'browser';
10308process.browser = true;
10309process.env = {};
10310process.argv = [];
10311process.version = ''; // empty string to avoid regexp issues
10312process.versions = {};
10313
10314function noop() {}
10315
10316process.on = noop;
10317process.addListener = noop;
10318process.once = noop;
10319process.off = noop;
10320process.removeListener = noop;
10321process.removeAllListeners = noop;
10322process.emit = noop;
10323process.prependListener = noop;
10324process.prependOnceListener = noop;
10325
10326process.listeners = function (name) { return [] }
10327
10328process.binding = function (name) {
10329    throw new Error('process.binding is not supported');
10330};
10331
10332process.cwd = function () { return '/' };
10333process.chdir = function (dir) {
10334    throw new Error('process.chdir is not supported');
10335};
10336process.umask = function() { return 0; };
10337
10338},{}],30:[function(_dereq_,module,exports){
10339module.exports = _dereq_(31);
10340
10341},{"31":31}],31:[function(_dereq_,module,exports){
10342// Copyright Joyent, Inc. and other Node contributors.
10343//
10344// Permission is hereby granted, free of charge, to any person obtaining a
10345// copy of this software and associated documentation files (the
10346// "Software"), to deal in the Software without restriction, including
10347// without limitation the rights to use, copy, modify, merge, publish,
10348// distribute, sublicense, and/or sell copies of the Software, and to permit
10349// persons to whom the Software is furnished to do so, subject to the
10350// following conditions:
10351//
10352// The above copyright notice and this permission notice shall be included
10353// in all copies or substantial portions of the Software.
10354//
10355// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
10356// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
10357// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
10358// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
10359// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
10360// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
10361// USE OR OTHER DEALINGS IN THE SOFTWARE.
10362
10363// a duplex stream is just a stream that is both readable and writable.
10364// Since JS doesn't have multiple prototypal inheritance, this class
10365// prototypally inherits from Readable, and then parasitically from
10366// Writable.
10367
10368'use strict';
10369
10370/*<replacement>*/
10371
10372var processNextTick = _dereq_(28);
10373/*</replacement>*/
10374
10375/*<replacement>*/
10376var objectKeys = Object.keys || function (obj) {
10377  var keys = [];
10378  for (var key in obj) {
10379    keys.push(key);
10380  }return keys;
10381};
10382/*</replacement>*/
10383
10384module.exports = Duplex;
10385
10386/*<replacement>*/
10387var util = _dereq_(12);
10388util.inherits = _dereq_(25);
10389/*</replacement>*/
10390
10391var Readable = _dereq_(33);
10392var Writable = _dereq_(35);
10393
10394util.inherits(Duplex, Readable);
10395
10396var keys = objectKeys(Writable.prototype);
10397for (var v = 0; v < keys.length; v++) {
10398  var method = keys[v];
10399  if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method];
10400}
10401
10402function Duplex(options) {
10403  if (!(this instanceof Duplex)) return new Duplex(options);
10404
10405  Readable.call(this, options);
10406  Writable.call(this, options);
10407
10408  if (options && options.readable === false) this.readable = false;
10409
10410  if (options && options.writable === false) this.writable = false;
10411
10412  this.allowHalfOpen = true;
10413  if (options && options.allowHalfOpen === false) this.allowHalfOpen = false;
10414
10415  this.once('end', onend);
10416}
10417
10418// the no-half-open enforcer
10419function onend() {
10420  // if we allow half-open state, or if the writable side ended,
10421  // then we're ok.
10422  if (this.allowHalfOpen || this._writableState.ended) return;
10423
10424  // no more data can be written.
10425  // But allow more writes to happen in this tick.
10426  processNextTick(onEndNT, this);
10427}
10428
10429function onEndNT(self) {
10430  self.end();
10431}
10432
10433Object.defineProperty(Duplex.prototype, 'destroyed', {
10434  get: function () {
10435    if (this._readableState === undefined || this._writableState === undefined) {
10436      return false;
10437    }
10438    return this._readableState.destroyed && this._writableState.destroyed;
10439  },
10440  set: function (value) {
10441    // we ignore the value if the stream
10442    // has not been initialized yet
10443    if (this._readableState === undefined || this._writableState === undefined) {
10444      return;
10445    }
10446
10447    // backward compatibility, the user is explicitly
10448    // managing destroyed
10449    this._readableState.destroyed = value;
10450    this._writableState.destroyed = value;
10451  }
10452});
10453
10454Duplex.prototype._destroy = function (err, cb) {
10455  this.push(null);
10456  this.end();
10457
10458  processNextTick(cb, err);
10459};
10460
10461function forEach(xs, f) {
10462  for (var i = 0, l = xs.length; i < l; i++) {
10463    f(xs[i], i);
10464  }
10465}
10466},{"12":12,"25":25,"28":28,"33":33,"35":35}],32:[function(_dereq_,module,exports){
10467// Copyright Joyent, Inc. and other Node contributors.
10468//
10469// Permission is hereby granted, free of charge, to any person obtaining a
10470// copy of this software and associated documentation files (the
10471// "Software"), to deal in the Software without restriction, including
10472// without limitation the rights to use, copy, modify, merge, publish,
10473// distribute, sublicense, and/or sell copies of the Software, and to permit
10474// persons to whom the Software is furnished to do so, subject to the
10475// following conditions:
10476//
10477// The above copyright notice and this permission notice shall be included
10478// in all copies or substantial portions of the Software.
10479//
10480// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
10481// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
10482// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
10483// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
10484// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
10485// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
10486// USE OR OTHER DEALINGS IN THE SOFTWARE.
10487
10488// a passthrough stream.
10489// basically just the most minimal sort of Transform stream.
10490// Every written chunk gets output as-is.
10491
10492'use strict';
10493
10494module.exports = PassThrough;
10495
10496var Transform = _dereq_(34);
10497
10498/*<replacement>*/
10499var util = _dereq_(12);
10500util.inherits = _dereq_(25);
10501/*</replacement>*/
10502
10503util.inherits(PassThrough, Transform);
10504
10505function PassThrough(options) {
10506  if (!(this instanceof PassThrough)) return new PassThrough(options);
10507
10508  Transform.call(this, options);
10509}
10510
10511PassThrough.prototype._transform = function (chunk, encoding, cb) {
10512  cb(null, chunk);
10513};
10514},{"12":12,"25":25,"34":34}],33:[function(_dereq_,module,exports){
10515(function (process,global){
10516// Copyright Joyent, Inc. and other Node contributors.
10517//
10518// Permission is hereby granted, free of charge, to any person obtaining a
10519// copy of this software and associated documentation files (the
10520// "Software"), to deal in the Software without restriction, including
10521// without limitation the rights to use, copy, modify, merge, publish,
10522// distribute, sublicense, and/or sell copies of the Software, and to permit
10523// persons to whom the Software is furnished to do so, subject to the
10524// following conditions:
10525//
10526// The above copyright notice and this permission notice shall be included
10527// in all copies or substantial portions of the Software.
10528//
10529// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
10530// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
10531// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
10532// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
10533// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
10534// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
10535// USE OR OTHER DEALINGS IN THE SOFTWARE.
10536
10537'use strict';
10538
10539/*<replacement>*/
10540
10541var processNextTick = _dereq_(28);
10542/*</replacement>*/
10543
10544module.exports = Readable;
10545
10546/*<replacement>*/
10547var isArray = _dereq_(27);
10548/*</replacement>*/
10549
10550/*<replacement>*/
10551var Duplex;
10552/*</replacement>*/
10553
10554Readable.ReadableState = ReadableState;
10555
10556/*<replacement>*/
10557var EE = _dereq_(16).EventEmitter;
10558
10559var EElistenerCount = function (emitter, type) {
10560  return emitter.listeners(type).length;
10561};
10562/*</replacement>*/
10563
10564/*<replacement>*/
10565var Stream = _dereq_(38);
10566/*</replacement>*/
10567
10568// TODO(bmeurer): Change this back to const once hole checks are
10569// properly optimized away early in Ignition+TurboFan.
10570/*<replacement>*/
10571var Buffer = _dereq_(44).Buffer;
10572var OurUint8Array = global.Uint8Array || function () {};
10573function _uint8ArrayToBuffer(chunk) {
10574  return Buffer.from(chunk);
10575}
10576function _isUint8Array(obj) {
10577  return Buffer.isBuffer(obj) || obj instanceof OurUint8Array;
10578}
10579/*</replacement>*/
10580
10581/*<replacement>*/
10582var util = _dereq_(12);
10583util.inherits = _dereq_(25);
10584/*</replacement>*/
10585
10586/*<replacement>*/
10587var debugUtil = _dereq_(8);
10588var debug = void 0;
10589if (debugUtil && debugUtil.debuglog) {
10590  debug = debugUtil.debuglog('stream');
10591} else {
10592  debug = function () {};
10593}
10594/*</replacement>*/
10595
10596var BufferList = _dereq_(36);
10597var destroyImpl = _dereq_(37);
10598var StringDecoder;
10599
10600util.inherits(Readable, Stream);
10601
10602var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume'];
10603
10604function prependListener(emitter, event, fn) {
10605  // Sadly this is not cacheable as some libraries bundle their own
10606  // event emitter implementation with them.
10607  if (typeof emitter.prependListener === 'function') {
10608    return emitter.prependListener(event, fn);
10609  } else {
10610    // This is a hack to make sure that our error handler is attached before any
10611    // userland ones.  NEVER DO THIS. This is here only because this code needs
10612    // to continue to work with older versions of Node.js that do not include
10613    // the prependListener() method. The goal is to eventually remove this hack.
10614    if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]];
10615  }
10616}
10617
10618function ReadableState(options, stream) {
10619  Duplex = Duplex || _dereq_(31);
10620
10621  options = options || {};
10622
10623  // object stream flag. Used to make read(n) ignore n and to
10624  // make all the buffer merging and length checks go away
10625  this.objectMode = !!options.objectMode;
10626
10627  if (stream instanceof Duplex) this.objectMode = this.objectMode || !!options.readableObjectMode;
10628
10629  // the point at which it stops calling _read() to fill the buffer
10630  // Note: 0 is a valid value, means "don't call _read preemptively ever"
10631  var hwm = options.highWaterMark;
10632  var defaultHwm = this.objectMode ? 16 : 16 * 1024;
10633  this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm;
10634
10635  // cast to ints.
10636  this.highWaterMark = Math.floor(this.highWaterMark);
10637
10638  // A linked list is used to store data chunks instead of an array because the
10639  // linked list can remove elements from the beginning faster than
10640  // array.shift()
10641  this.buffer = new BufferList();
10642  this.length = 0;
10643  this.pipes = null;
10644  this.pipesCount = 0;
10645  this.flowing = null;
10646  this.ended = false;
10647  this.endEmitted = false;
10648  this.reading = false;
10649
10650  // a flag to be able to tell if the event 'readable'/'data' is emitted
10651  // immediately, or on a later tick.  We set this to true at first, because
10652  // any actions that shouldn't happen until "later" should generally also
10653  // not happen before the first read call.
10654  this.sync = true;
10655
10656  // whenever we return null, then we set a flag to say
10657  // that we're awaiting a 'readable' event emission.
10658  this.needReadable = false;
10659  this.emittedReadable = false;
10660  this.readableListening = false;
10661  this.resumeScheduled = false;
10662
10663  // has it been destroyed
10664  this.destroyed = false;
10665
10666  // Crypto is kind of old and crusty.  Historically, its default string
10667  // encoding is 'binary' so we have to make this configurable.
10668  // Everything else in the universe uses 'utf8', though.
10669  this.defaultEncoding = options.defaultEncoding || 'utf8';
10670
10671  // the number of writers that are awaiting a drain event in .pipe()s
10672  this.awaitDrain = 0;
10673
10674  // if true, a maybeReadMore has been scheduled
10675  this.readingMore = false;
10676
10677  this.decoder = null;
10678  this.encoding = null;
10679  if (options.encoding) {
10680    if (!StringDecoder) StringDecoder = _dereq_(47).StringDecoder;
10681    this.decoder = new StringDecoder(options.encoding);
10682    this.encoding = options.encoding;
10683  }
10684}
10685
10686function Readable(options) {
10687  Duplex = Duplex || _dereq_(31);
10688
10689  if (!(this instanceof Readable)) return new Readable(options);
10690
10691  this._readableState = new ReadableState(options, this);
10692
10693  // legacy
10694  this.readable = true;
10695
10696  if (options) {
10697    if (typeof options.read === 'function') this._read = options.read;
10698
10699    if (typeof options.destroy === 'function') this._destroy = options.destroy;
10700  }
10701
10702  Stream.call(this);
10703}
10704
10705Object.defineProperty(Readable.prototype, 'destroyed', {
10706  get: function () {
10707    if (this._readableState === undefined) {
10708      return false;
10709    }
10710    return this._readableState.destroyed;
10711  },
10712  set: function (value) {
10713    // we ignore the value if the stream
10714    // has not been initialized yet
10715    if (!this._readableState) {
10716      return;
10717    }
10718
10719    // backward compatibility, the user is explicitly
10720    // managing destroyed
10721    this._readableState.destroyed = value;
10722  }
10723});
10724
10725Readable.prototype.destroy = destroyImpl.destroy;
10726Readable.prototype._undestroy = destroyImpl.undestroy;
10727Readable.prototype._destroy = function (err, cb) {
10728  this.push(null);
10729  cb(err);
10730};
10731
10732// Manually shove something into the read() buffer.
10733// This returns true if the highWaterMark has not been hit yet,
10734// similar to how Writable.write() returns true if you should
10735// write() some more.
10736Readable.prototype.push = function (chunk, encoding) {
10737  var state = this._readableState;
10738  var skipChunkCheck;
10739
10740  if (!state.objectMode) {
10741    if (typeof chunk === 'string') {
10742      encoding = encoding || state.defaultEncoding;
10743      if (encoding !== state.encoding) {
10744        chunk = Buffer.from(chunk, encoding);
10745        encoding = '';
10746      }
10747      skipChunkCheck = true;
10748    }
10749  } else {
10750    skipChunkCheck = true;
10751  }
10752
10753  return readableAddChunk(this, chunk, encoding, false, skipChunkCheck);
10754};
10755
10756// Unshift should *always* be something directly out of read()
10757Readable.prototype.unshift = function (chunk) {
10758  return readableAddChunk(this, chunk, null, true, false);
10759};
vendor: 2,776 bytes, lines 10760-10836
10760
10761function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) {
10762  var state = stream._readableState;
10763  if (chunk === null) {
10764    state.reading = false;
10765    onEofChunk(stream, state);
10766  } else {
10767    var er;
10768    if (!skipChunkCheck) er = chunkInvalid(state, chunk);
10769    if (er) {
10770      stream.emit('error', er);
10771    } else if (state.objectMode || chunk && chunk.length > 0) {
10772      if (typeof chunk !== 'string' && !state.objectMode && Object.getPrototypeOf(chunk) !== Buffer.prototype) {
10773        chunk = _uint8ArrayToBuffer(chunk);
10774      }
10775
10776      if (addToFront) {
10777        if (state.endEmitted) stream.emit('error', new Error('stream.unshift() after end event'));else addChunk(stream, state, chunk, true);
10778      } else if (state.ended) {
10779        stream.emit('error', new Error('stream.push() after EOF'));
10780      } else {
10781        state.reading = false;
10782        if (state.decoder && !encoding) {
10783          chunk = state.decoder.write(chunk);
10784          if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false);else maybeReadMore(stream, state);
10785        } else {
10786          addChunk(stream, state, chunk, false);
10787        }
10788      }
10789    } else if (!addToFront) {
10790      state.reading = false;
10791    }
10792  }
10793
10794  return needMoreData(state);
10795}
10796
10797function addChunk(stream, state, chunk, addToFront) {
10798  if (state.flowing && state.length === 0 && !state.sync) {
10799    stream.emit('data', chunk);
10800    stream.read(0);
10801  } else {
10802    // update the buffer info.
10803    state.length += state.objectMode ? 1 : chunk.length;
10804    if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk);
10805
10806    if (state.needReadable) emitReadable(stream);
10807  }
10808  maybeReadMore(stream, state);
10809}
10810
10811function chunkInvalid(state, chunk) {
10812  var er;
10813  if (!_isUint8Array(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) {
10814    er = new TypeError('Invalid non-string/buffer chunk');
10815  }
10816  return er;
10817}
10818
10819// if it's past the high water mark, we can push in some more.
10820// Also, if we have no data yet, we can stand some
10821// more bytes.  This is to work around cases where hwm=0,
10822// such as the repl.  Also, if the push() triggered a
10823// readable event, and the user called read(largeNumber) such that
10824// needReadable was set, then we ought to push more, so that another
10825// 'readable' event will be triggered.
10826function needMoreData(state) {
10827  return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0);
10828}
10829
10830Readable.prototype.isPaused = function () {
10831  return this._readableState.flowing === false;
10832};
10833
10834// backwards compatibility.
10835Readable.prototype.setEncoding = function (enc) {
10836  if (!StringDecoder) StringDecoder = _dereq_(47
vendor: 20,892 bytes, lines 10836-11522
10836).StringDecoder;
10837  this._readableState.decoder = new StringDecoder(enc);
10838  this._readableState.encoding = enc;
10839  return this;
10840};
10841
10842// Don't raise the hwm > 8MB
10843var MAX_HWM = 0x800000;
10844function computeNewHighWaterMark(n) {
10845  if (n >= MAX_HWM) {
10846    n = MAX_HWM;
10847  } else {
10848    // Get the next highest power of 2 to prevent increasing hwm excessively in
10849    // tiny amounts
10850    n--;
10851    n |= n >>> 1;
10852    n |= n >>> 2;
10853    n |= n >>> 4;
10854    n |= n >>> 8;
10855    n |= n >>> 16;
10856    n++;
10857  }
10858  return n;
10859}
10860
10861// This function is designed to be inlinable, so please take care when making
10862// changes to the function body.
10863function howMuchToRead(n, state) {
10864  if (n <= 0 || state.length === 0 && state.ended) return 0;
10865  if (state.objectMode) return 1;
10866  if (n !== n) {
10867    // Only flow one buffer at a time
10868    if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length;
10869  }
10870  // If we're asking for more than the current hwm, then raise the hwm.
10871  if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n);
10872  if (n <= state.length) return n;
10873  // Don't have enough
10874  if (!state.ended) {
10875    state.needReadable = true;
10876    return 0;
10877  }
10878  return state.length;
10879}
10880
10881// you can override either this method, or the async _read(n) below.
10882Readable.prototype.read = function (n) {
10883  debug('read', n);
10884  n = parseInt(n, 10);
10885  var state = this._readableState;
10886  var nOrig = n;
10887
10888  if (n !== 0) state.emittedReadable = false;
10889
10890  // if we're doing read(0) to trigger a readable event, but we
10891  // already have a bunch of data in the buffer, then just trigger
10892  // the 'readable' event and move on.
10893  if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) {
10894    debug('read: emitReadable', state.length, state.ended);
10895    if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this);
10896    return null;
10897  }
10898
10899  n = howMuchToRead(n, state);
10900
10901  // if we've ended, and we're now clear, then finish it up.
10902  if (n === 0 && state.ended) {
10903    if (state.length === 0) endReadable(this);
10904    return null;
10905  }
10906
10907  // All the actual chunk generation logic needs to be
10908  // *below* the call to _read.  The reason is that in certain
10909  // synthetic stream cases, such as passthrough streams, _read
10910  // may be a completely synchronous operation which may change
10911  // the state of the read buffer, providing enough data when
10912  // before there was *not* enough.
10913  //
10914  // So, the steps are:
10915  // 1. Figure out what the state of things will be after we do
10916  // a read from the buffer.
10917  //
10918  // 2. If that resulting state will trigger a _read, then call _read.
10919  // Note that this may be asynchronous, or synchronous.  Yes, it is
10920  // deeply ugly to write APIs this way, but that still doesn't mean
10921  // that the Readable class should behave improperly, as streams are
10922  // designed to be sync/async agnostic.
10923  // Take note if the _read call is sync or async (ie, if the read call
10924  // has returned yet), so that we know whether or not it's safe to emit
10925  // 'readable' etc.
10926  //
10927  // 3. Actually pull the requested chunks out of the buffer and return.
10928
10929  // if we need a readable event, then we need to do some reading.
10930  var doRead = state.needReadable;
10931  debug('need readable', doRead);
10932
10933  // if we currently have less than the highWaterMark, then also read some
10934  if (state.length === 0 || state.length - n < state.highWaterMark) {
10935    doRead = true;
10936    debug('length less than watermark', doRead);
10937  }
10938
10939  // however, if we've ended, then there's no point, and if we're already
10940  // reading, then it's unnecessary.
10941  if (state.ended || state.reading) {
10942    doRead = false;
10943    debug('reading or ended', doRead);
10944  } else if (doRead) {
10945    debug('do read');
10946    state.reading = true;
10947    state.sync = true;
10948    // if the length is currently zero, then we *need* a readable event.
10949    if (state.length === 0) state.needReadable = true;
10950    // call internal read method
10951    this._read(state.highWaterMark);
10952    state.sync = false;
10953    // If _read pushed data synchronously, then `reading` will be false,
10954    // and we need to re-evaluate how much data we can return to the user.
10955    if (!state.reading) n = howMuchToRead(nOrig, state);
10956  }
10957
10958  var ret;
10959  if (n > 0) ret = fromList(n, state);else ret = null;
10960
10961  if (ret === null) {
10962    state.needReadable = true;
10963    n = 0;
10964  } else {
10965    state.length -= n;
10966  }
10967
10968  if (state.length === 0) {
10969    // If we have nothing in the buffer, then we want to know
10970    // as soon as we *do* get something into the buffer.
10971    if (!state.ended) state.needReadable = true;
10972
10973    // If we tried to read() past the EOF, then emit end on the next tick.
10974    if (nOrig !== n && state.ended) endReadable(this);
10975  }
10976
10977  if (ret !== null) this.emit('data', ret);
10978
10979  return ret;
10980};
10981
10982function onEofChunk(stream, state) {
10983  if (state.ended) return;
10984  if (state.decoder) {
10985    var chunk = state.decoder.end();
10986    if (chunk && chunk.length) {
10987      state.buffer.push(chunk);
10988      state.length += state.objectMode ? 1 : chunk.length;
10989    }
10990  }
10991  state.ended = true;
10992
10993  // emit 'readable' now to make sure it gets picked up.
10994  emitReadable(stream);
10995}
10996
10997// Don't emit readable right away in sync mode, because this can trigger
10998// another read() call => stack overflow.  This way, it might trigger
10999// a nextTick recursion warning, but that's not so bad.
11000function emitReadable(stream) {
11001  var state = stream._readableState;
11002  state.needReadable = false;
11003  if (!state.emittedReadable) {
11004    debug('emitReadable', state.flowing);
11005    state.emittedReadable = true;
11006    if (state.sync) processNextTick(emitReadable_, stream);else emitReadable_(stream);
11007  }
11008}
11009
11010function emitReadable_(stream) {
11011  debug('emit readable');
11012  stream.emit('readable');
11013  flow(stream);
11014}
11015
11016// at this point, the user has presumably seen the 'readable' event,
11017// and called read() to consume some data.  that may have triggered
11018// in turn another _read(n) call, in which case reading = true if
11019// it's in progress.
11020// However, if we're not ended, or reading, and the length < hwm,
11021// then go ahead and try to read some more preemptively.
11022function maybeReadMore(stream, state) {
11023  if (!state.readingMore) {
11024    state.readingMore = true;
11025    processNextTick(maybeReadMore_, stream, state);
11026  }
11027}
11028
11029function maybeReadMore_(stream, state) {
11030  var len = state.length;
11031  while (!state.reading && !state.flowing && !state.ended && state.length < state.highWaterMark) {
11032    debug('maybeReadMore read 0');
11033    stream.read(0);
11034    if (len === state.length)
11035      // didn't get any data, stop spinning.
11036      break;else len = state.length;
11037  }
11038  state.readingMore = false;
11039}
11040
11041// abstract method.  to be overridden in specific implementation classes.
11042// call cb(er, data) where data is <= n in length.
11043// for virtual (non-string, non-buffer) streams, "length" is somewhat
11044// arbitrary, and perhaps not very meaningful.
11045Readable.prototype._read = function (n) {
11046  this.emit('error', new Error('_read() is not implemented'));
11047};
11048
11049Readable.prototype.pipe = function (dest, pipeOpts) {
11050  var src = this;
11051  var state = this._readableState;
11052
11053  switch (state.pipesCount) {
11054    case 0:
11055      state.pipes = dest;
11056      break;
11057    case 1:
11058      state.pipes = [state.pipes, dest];
11059      break;
11060    default:
11061      state.pipes.push(dest);
11062      break;
11063  }
11064  state.pipesCount += 1;
11065  debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts);
11066
11067  var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr;
11068
11069  var endFn = doEnd ? onend : unpipe;
11070  if (state.endEmitted) processNextTick(endFn);else src.once('end', endFn);
11071
11072  dest.on('unpipe', onunpipe);
11073  function onunpipe(readable, unpipeInfo) {
11074    debug('onunpipe');
11075    if (readable === src) {
11076      if (unpipeInfo && unpipeInfo.hasUnpiped === false) {
11077        unpipeInfo.hasUnpiped = true;
11078        cleanup();
11079      }
11080    }
11081  }
11082
11083  function onend() {
11084    debug('onend');
11085    dest.end();
11086  }
11087
11088  // when the dest drains, it reduces the awaitDrain counter
11089  // on the source.  This would be more elegant with a .once()
11090  // handler in flow(), but adding and removing repeatedly is
11091  // too slow.
11092  var ondrain = pipeOnDrain(src);
11093  dest.on('drain', ondrain);
11094
11095  var cleanedUp = false;
11096  function cleanup() {
11097    debug('cleanup');
11098    // cleanup event handlers once the pipe is broken
11099    dest.removeListener('close', onclose);
11100    dest.removeListener('finish', onfinish);
11101    dest.removeListener('drain', ondrain);
11102    dest.removeListener('error', onerror);
11103    dest.removeListener('unpipe', onunpipe);
11104    src.removeListener('end', onend);
11105    src.removeListener('end', unpipe);
11106    src.removeListener('data', ondata);
11107
11108    cleanedUp = true;
11109
11110    // if the reader is waiting for a drain event from this
11111    // specific writer, then it would cause it to never start
11112    // flowing again.
11113    // So, if this is awaiting a drain, then we just call it now.
11114    // If we don't know, then assume that we are waiting for one.
11115    if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain();
11116  }
11117
11118  // If the user pushes more data while we're writing to dest then we'll end up
11119  // in ondata again. However, we only want to increase awaitDrain once because
11120  // dest will only emit one 'drain' event for the multiple writes.
11121  // => Introduce a guard on increasing awaitDrain.
11122  var increasedAwaitDrain = false;
11123  src.on('data', ondata);
11124  function ondata(chunk) {
11125    debug('ondata');
11126    increasedAwaitDrain = false;
11127    var ret = dest.write(chunk);
11128    if (false === ret && !increasedAwaitDrain) {
11129      // If the user unpiped during `dest.write()`, it is possible
11130      // to get stuck in a permanently paused state if that write
11131      // also returned false.
11132      // => Check whether `dest` is still a piping destination.
11133      if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) {
11134        debug('false write response, pause', src._readableState.awaitDrain);
11135        src._readableState.awaitDrain++;
11136        increasedAwaitDrain = true;
11137      }
11138      src.pause();
11139    }
11140  }
11141
11142  // if the dest has an error, then stop piping into it.
11143  // however, don't suppress the throwing behavior for this.
11144  function onerror(er) {
11145    debug('onerror', er);
11146    unpipe();
11147    dest.removeListener('error', onerror);
11148    if (EElistenerCount(dest, 'error') === 0) dest.emit('error', er);
11149  }
11150
11151  // Make sure our error handler is attached before userland ones.
11152  prependListener(dest, 'error', onerror);
11153
11154  // Both close and finish should trigger unpipe, but only once.
11155  function onclose() {
11156    dest.removeListener('finish', onfinish);
11157    unpipe();
11158  }
11159  dest.once('close', onclose);
11160  function onfinish() {
11161    debug('onfinish');
11162    dest.removeListener('close', onclose);
11163    unpipe();
11164  }
11165  dest.once('finish', onfinish);
11166
11167  function unpipe() {
11168    debug('unpipe');
11169    src.unpipe(dest);
11170  }
11171
11172  // tell the dest that it's being piped to
11173  dest.emit('pipe', src);
11174
11175  // start the flow if it hasn't been started already.
11176  if (!state.flowing) {
11177    debug('pipe resume');
11178    src.resume();
11179  }
11180
11181  return dest;
11182};
11183
11184function pipeOnDrain(src) {
11185  return function () {
11186    var state = src._readableState;
11187    debug('pipeOnDrain', state.awaitDrain);
11188    if (state.awaitDrain) state.awaitDrain--;
11189    if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) {
11190      state.flowing = true;
11191      flow(src);
11192    }
11193  };
11194}
11195
11196Readable.prototype.unpipe = function (dest) {
11197  var state = this._readableState;
11198  var unpipeInfo = { hasUnpiped: false };
11199
11200  // if we're not piping anywhere, then do nothing.
11201  if (state.pipesCount === 0) return this;
11202
11203  // just one destination.  most common case.
11204  if (state.pipesCount === 1) {
11205    // passed in one, but it's not the right one.
11206    if (dest && dest !== state.pipes) return this;
11207
11208    if (!dest) dest = state.pipes;
11209
11210    // got a match.
11211    state.pipes = null;
11212    state.pipesCount = 0;
11213    state.flowing = false;
11214    if (dest) dest.emit('unpipe', this, unpipeInfo);
11215    return this;
11216  }
11217
11218  // slow case. multiple pipe destinations.
11219
11220  if (!dest) {
11221    // remove all.
11222    var dests = state.pipes;
11223    var len = state.pipesCount;
11224    state.pipes = null;
11225    state.pipesCount = 0;
11226    state.flowing = false;
11227
11228    for (var i = 0; i < len; i++) {
11229      dests[i].emit('unpipe', this, unpipeInfo);
11230    }return this;
11231  }
11232
11233  // try to find the right one.
11234  var index = indexOf(state.pipes, dest);
11235  if (index === -1) return this;
11236
11237  state.pipes.splice(index, 1);
11238  state.pipesCount -= 1;
11239  if (state.pipesCount === 1) state.pipes = state.pipes[0];
11240
11241  dest.emit('unpipe', this, unpipeInfo);
11242
11243  return this;
11244};
11245
11246// set up data events if they are asked for
11247// Ensure readable listeners eventually get something
11248Readable.prototype.on = function (ev, fn) {
11249  var res = Stream.prototype.on.call(this, ev, fn);
11250
11251  if (ev === 'data') {
11252    // Start flowing on next tick if stream isn't explicitly paused
11253    if (this._readableState.flowing !== false) this.resume();
11254  } else if (ev === 'readable') {
11255    var state = this._readableState;
11256    if (!state.endEmitted && !state.readableListening) {
11257      state.readableListening = state.needReadable = true;
11258      state.emittedReadable = false;
11259      if (!state.reading) {
11260        processNextTick(nReadingNextTick, this);
11261      } else if (state.length) {
11262        emitReadable(this);
11263      }
11264    }
11265  }
11266
11267  return res;
11268};
11269Readable.prototype.addListener = Readable.prototype.on;
11270
11271function nReadingNextTick(self) {
11272  debug('readable nexttick read 0');
11273  self.read(0);
11274}
11275
11276// pause() and resume() are remnants of the legacy readable stream API
11277// If the user uses them, then switch into old mode.
11278Readable.prototype.resume = function () {
11279  var state = this._readableState;
11280  if (!state.flowing) {
11281    debug('resume');
11282    state.flowing = true;
11283    resume(this, state);
11284  }
11285  return this;
11286};
11287
11288function resume(stream, state) {
11289  if (!state.resumeScheduled) {
11290    state.resumeScheduled = true;
11291    processNextTick(resume_, stream, state);
11292  }
11293}
11294
11295function resume_(stream, state) {
11296  if (!state.reading) {
11297    debug('resume read 0');
11298    stream.read(0);
11299  }
11300
11301  state.resumeScheduled = false;
11302  state.awaitDrain = 0;
11303  stream.emit('resume');
11304  flow(stream);
11305  if (state.flowing && !state.reading) stream.read(0);
11306}
11307
11308Readable.prototype.pause = function () {
11309  debug('call pause flowing=%j', this._readableState.flowing);
11310  if (false !== this._readableState.flowing) {
11311    debug('pause');
11312    this._readableState.flowing = false;
11313    this.emit('pause');
11314  }
11315  return this;
11316};
11317
11318function flow(stream) {
11319  var state = stream._readableState;
11320  debug('flow', state.flowing);
11321  while (state.flowing && stream.read() !== null) {}
11322}
11323
11324// wrap an old-style stream as the async data source.
11325// This is *not* part of the readable stream interface.
11326// It is an ugly unfortunate mess of history.
11327Readable.prototype.wrap = function (stream) {
11328  var state = this._readableState;
11329  var paused = false;
11330
11331  var self = this;
11332  stream.on('end', function () {
11333    debug('wrapped end');
11334    if (state.decoder && !state.ended) {
11335      var chunk = state.decoder.end();
11336      if (chunk && chunk.length) self.push(chunk);
11337    }
11338
11339    self.push(null);
11340  });
11341
11342  stream.on('data', function (chunk) {
11343    debug('wrapped data');
11344    if (state.decoder) chunk = state.decoder.write(chunk);
11345
11346    // don't skip over falsy values in objectMode
11347    if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return;
11348
11349    var ret = self.push(chunk);
11350    if (!ret) {
11351      paused = true;
11352      stream.pause();
11353    }
11354  });
11355
11356  // proxy all the other methods.
11357  // important when wrapping filters and duplexes.
11358  for (var i in stream) {
11359    if (this[i] === undefined && typeof stream[i] === 'function') {
11360      this[i] = function (method) {
11361        return function () {
11362          return stream[method].apply(stream, arguments);
11363        };
11364      }(i);
11365    }
11366  }
11367
11368  // proxy certain important events.
11369  for (var n = 0; n < kProxyEvents.length; n++) {
11370    stream.on(kProxyEvents[n], self.emit.bind(self, kProxyEvents[n]));
11371  }
11372
11373  // when we try to consume some more bytes, simply unpause the
11374  // underlying stream.
11375  self._read = function (n) {
11376    debug('wrapped _read', n);
11377    if (paused) {
11378      paused = false;
11379      stream.resume();
11380    }
11381  };
11382
11383  return self;
11384};
11385
11386// exposed for testing purposes only.
11387Readable._fromList = fromList;
11388
11389// Pluck off n bytes from an array of buffers.
11390// Length is the combined lengths of all the buffers in the list.
11391// This function is designed to be inlinable, so please take care when making
11392// changes to the function body.
11393function fromList(n, state) {
11394  // nothing buffered
11395  if (state.length === 0) return null;
11396
11397  var ret;
11398  if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) {
11399    // read it all, truncate the list
11400    if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.head.data;else ret = state.buffer.concat(state.length);
11401    state.buffer.clear();
11402  } else {
11403    // read part of list
11404    ret = fromListPartial(n, state.buffer, state.decoder);
11405  }
11406
11407  return ret;
11408}
11409
11410// Extracts only enough buffered data to satisfy the amount requested.
11411// This function is designed to be inlinable, so please take care when making
11412// changes to the function body.
11413function fromListPartial(n, list, hasStrings) {
11414  var ret;
11415  if (n < list.head.data.length) {
11416    // slice is the same for buffers and strings
11417    ret = list.head.data.slice(0, n);
11418    list.head.data = list.head.data.slice(n);
11419  } else if (n === list.head.data.length) {
11420    // first chunk is a perfect match
11421    ret = list.shift();
11422  } else {
11423    // result spans more than one buffer
11424    ret = hasStrings ? copyFromBufferString(n, list) : copyFromBuffer(n, list);
11425  }
11426  return ret;
11427}
11428
11429// Copies a specified amount of characters from the list of buffered data
11430// chunks.
11431// This function is designed to be inlinable, so please take care when making
11432// changes to the function body.
11433function copyFromBufferString(n, list) {
11434  var p = list.head;
11435  var c = 1;
11436  var ret = p.data;
11437  n -= ret.length;
11438  while (p = p.next) {
11439    var str = p.data;
11440    var nb = n > str.length ? str.length : n;
11441    if (nb === str.length) ret += str;else ret += str.slice(0, n);
11442    n -= nb;
11443    if (n === 0) {
11444      if (nb === str.length) {
11445        ++c;
11446        if (p.next) list.head = p.next;else list.head = list.tail = null;
11447      } else {
11448        list.head = p;
11449        p.data = str.slice(nb);
11450      }
11451      break;
11452    }
11453    ++c;
11454  }
11455  list.length -= c;
11456  return ret;
11457}
11458
11459// Copies a specified amount of bytes from the list of buffered data chunks.
11460// This function is designed to be inlinable, so please take care when making
11461// changes to the function body.
11462function copyFromBuffer(n, list) {
11463  var ret = Buffer.allocUnsafe(n);
11464  var p = list.head;
11465  var c = 1;
11466  p.data.copy(ret);
11467  n -= p.data.length;
11468  while (p = p.next) {
11469    var buf = p.data;
11470    var nb = n > buf.length ? buf.length : n;
11471    buf.copy(ret, ret.length - n, 0, nb);
11472    n -= nb;
11473    if (n === 0) {
11474      if (nb === buf.length) {
11475        ++c;
11476        if (p.next) list.head = p.next;else list.head = list.tail = null;
11477      } else {
11478        list.head = p;
11479        p.data = buf.slice(nb);
11480      }
11481      break;
11482    }
11483    ++c;
11484  }
11485  list.length -= c;
11486  return ret;
11487}
11488
11489function endReadable(stream) {
11490  var state = stream._readableState;
11491
11492  // If we get here before consuming all the bytes, then that is a
11493  // bug in node.  Should never happen.
11494  if (state.length > 0) throw new Error('"endReadable()" called on non-empty stream');
11495
11496  if (!state.endEmitted) {
11497    state.ended = true;
11498    processNextTick(endReadableNT, state, stream);
11499  }
11500}
11501
11502function endReadableNT(state, stream) {
11503  // Check that we didn't get one last unshift.
11504  if (!state.endEmitted && state.length === 0) {
11505    state.endEmitted = true;
11506    stream.readable = false;
11507    stream.emit('end');
11508  }
11509}
11510
11511function forEach(xs, f) {
11512  for (var i = 0, l = xs.length; i < l; i++) {
11513    f(xs[i], i);
11514  }
11515}
11516
11517function indexOf(xs, x) {
11518  for (var i = 0, l = xs.length; i < l; i++) {
11519    if (xs[i] === x) return i;
11520  }
11521  return -1;
11522}
11523}).call(this,_dereq_(29),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
11524
11525},{"12":12,"16":16,"25":25,"27":27,"28":28,"29":29,"31":31,"36":36,"37":37,"38":38,"44":44,"47":47,"8":8}],34:[function(_dereq_,module,exports){
11526// Copyright Joyent, Inc. and other Node contributors.
11527//
11528// Permission is hereby granted, free of charge, to any person obtaining a
11529// copy of this software and associated documentation files (the
11530// "Software"), to deal in the Software without restriction, including
11531// without limitation the rights to use, copy, modify, merge, publish,
11532// distribute, sublicense, and/or sell copies of the Software, and to permit
11533// persons to whom the Software is furnished to do so, subject to the
11534// following conditions:
11535//
11536// The above copyright notice and this permission notice shall be included
11537// in all copies or substantial portions of the Software.
11538//
11539// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
11540// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
11541// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
11542// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
11543// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
11544// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
11545// USE OR OTHER DEALINGS IN THE SOFTWARE.
11546
11547// a transform stream is a readable/writable stream where you do
11548// something with the data.  Sometimes it's called a "filter",
11549// but that's not a great name for it, since that implies a thing where
11550// some bits pass through, and others are simply ignored.  (That would
11551// be a valid example of a transform, of course.)
11552//
11553// While the output is causally related to the input, it's not a
11554// necessarily symmetric or synchronous transformation.  For example,
11555// a zlib stream might take multiple plain-text writes(), and then
11556// emit a single compressed chunk some time in the future.
11557//
11558// Here's how this works:
11559//
11560// The Transform stream has all the aspects of the readable and writable
11561// stream classes.  When you write(chunk), that calls _write(chunk,cb)
11562// internally, and returns false if there's a lot of pending writes
11563// buffered up.  When you call read(), that calls _read(n) until
vendor: 25,962 bytes, lines 11564-12405
11564// there's enough pending readable data buffered up.
11565//
11566// In a transform stream, the written data is placed in a buffer.  When
11567// _read(n) is called, it transforms the queued up data, calling the
11568// buffered _write cb's as it consumes chunks.  If consuming a single
11569// written chunk would result in multiple output chunks, then the first
11570// outputted bit calls the readcb, and subsequent chunks just go into
11571// the read buffer, and will cause it to emit 'readable' if necessary.
11572//
11573// This way, back-pressure is actually determined by the reading side,
11574// since _read has to be called to start processing a new chunk.  However,
11575// a pathological inflate type of transform can cause excessive buffering
11576// here.  For example, imagine a stream where every byte of input is
11577// interpreted as an integer from 0-255, and then results in that many
11578// bytes of output.  Writing the 4 bytes {ff,ff,ff,ff} would result in
11579// 1kb of data being output.  In this case, you could write a very small
11580// amount of input, and end up with a very large amount of output.  In
11581// such a pathological inflating mechanism, there'd be no way to tell
11582// the system to stop doing the transform.  A single 4MB write could
11583// cause the system to run out of memory.
11584//
11585// However, even in such a pathological case, only a single written chunk
11586// would be consumed, and then the rest would wait (un-transformed) until
11587// the results of the previous transformed chunk were consumed.
11588
11589'use strict';
11590
11591module.exports = Transform;
11592
11593var Duplex = _dereq_(31);
11594
11595/*<replacement>*/
11596var util = _dereq_(12);
11597util.inherits = _dereq_(25);
11598/*</replacement>*/
11599
11600util.inherits(Transform, Duplex);
11601
11602function TransformState(stream) {
11603  this.afterTransform = function (er, data) {
11604    return afterTransform(stream, er, data);
11605  };
11606
11607  this.needTransform = false;
11608  this.transforming = false;
11609  this.writecb = null;
11610  this.writechunk = null;
11611  this.writeencoding = null;
11612}
11613
11614function afterTransform(stream, er, data) {
11615  var ts = stream._transformState;
11616  ts.transforming = false;
11617
11618  var cb = ts.writecb;
11619
11620  if (!cb) {
11621    return stream.emit('error', new Error('write callback called multiple times'));
11622  }
11623
11624  ts.writechunk = null;
11625  ts.writecb = null;
11626
11627  if (data !== null && data !== undefined) stream.push(data);
11628
11629  cb(er);
11630
11631  var rs = stream._readableState;
11632  rs.reading = false;
11633  if (rs.needReadable || rs.length < rs.highWaterMark) {
11634    stream._read(rs.highWaterMark);
11635  }
11636}
11637
11638function Transform(options) {
11639  if (!(this instanceof Transform)) return new Transform(options);
11640
11641  Duplex.call(this, options);
11642
11643  this._transformState = new TransformState(this);
11644
11645  var stream = this;
11646
11647  // start out asking for a readable event once data is transformed.
11648  this._readableState.needReadable = true;
11649
11650  // we have implemented the _read method, and done the other things
11651  // that Readable wants before the first _read call, so unset the
11652  // sync guard flag.
11653  this._readableState.sync = false;
11654
11655  if (options) {
11656    if (typeof options.transform === 'function') this._transform = options.transform;
11657
11658    if (typeof options.flush === 'function') this._flush = options.flush;
11659  }
11660
11661  // When the writable side finishes, then flush out anything remaining.
11662  this.once('prefinish', function () {
11663    if (typeof this._flush === 'function') this._flush(function (er, data) {
11664      done(stream, er, data);
11665    });else done(stream);
11666  });
11667}
11668
11669Transform.prototype.push = function (chunk, encoding) {
11670  this._transformState.needTransform = false;
11671  return Duplex.prototype.push.call(this, chunk, encoding);
11672};
11673
11674// This is the part where you do stuff!
11675// override this function in implementation classes.
11676// 'chunk' is an input chunk.
11677//
11678// Call `push(newChunk)` to pass along transformed output
11679// to the readable side.  You may call 'push' zero or more times.
11680//
11681// Call `cb(err)` when you are done with this chunk.  If you pass
11682// an error, then that'll put the hurt on the whole operation.  If you
11683// never call cb(), then you'll never get another chunk.
11684Transform.prototype._transform = function (chunk, encoding, cb) {
11685  throw new Error('_transform() is not implemented');
11686};
11687
11688Transform.prototype._write = function (chunk, encoding, cb) {
11689  var ts = this._transformState;
11690  ts.writecb = cb;
11691  ts.writechunk = chunk;
11692  ts.writeencoding = encoding;
11693  if (!ts.transforming) {
11694    var rs = this._readableState;
11695    if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark);
11696  }
11697};
11698
11699// Doesn't matter what the args are here.
11700// _transform does all the work.
11701// That we got here means that the readable side wants more data.
11702Transform.prototype._read = function (n) {
11703  var ts = this._transformState;
11704
11705  if (ts.writechunk !== null && ts.writecb && !ts.transforming) {
11706    ts.transforming = true;
11707    this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
11708  } else {
11709    // mark that we need a transform, so that any data that comes in
11710    // will get processed, now that we've asked for it.
11711    ts.needTransform = true;
11712  }
11713};
11714
11715Transform.prototype._destroy = function (err, cb) {
11716  var _this = this;
11717
11718  Duplex.prototype._destroy.call(this, err, function (err2) {
11719    cb(err2);
11720    _this.emit('close');
11721  });
11722};
11723
11724function done(stream, er, data) {
11725  if (er) return stream.emit('error', er);
11726
11727  if (data !== null && data !== undefined) stream.push(data);
11728
11729  // if there's nothing in the write buffer, then that means
11730  // that nothing more will ever be provided
11731  var ws = stream._writableState;
11732  var ts = stream._transformState;
11733
11734  if (ws.length) throw new Error('Calling transform done when ws.length != 0');
11735
11736  if (ts.transforming) throw new Error('Calling transform done when still transforming');
11737
11738  return stream.push(null);
11739}
11740},{"12":12,"25":25,"31":31}],35:[function(_dereq_,module,exports){
11741(function (process,global){
11742// Copyright Joyent, Inc. and other Node contributors.
11743//
11744// Permission is hereby granted, free of charge, to any person obtaining a
11745// copy of this software and associated documentation files (the
11746// "Software"), to deal in the Software without restriction, including
11747// without limitation the rights to use, copy, modify, merge, publish,
11748// distribute, sublicense, and/or sell copies of the Software, and to permit
11749// persons to whom the Software is furnished to do so, subject to the
11750// following conditions:
11751//
11752// The above copyright notice and this permission notice shall be included
11753// in all copies or substantial portions of the Software.
11754//
11755// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
11756// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
11757// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
11758// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
11759// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
11760// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
11761// USE OR OTHER DEALINGS IN THE SOFTWARE.
11762
11763// A bit simpler than readable streams.
11764// Implement an async ._write(chunk, encoding, cb), and it'll handle all
11765// the drain event emission and buffering.
11766
11767'use strict';
11768
11769/*<replacement>*/
11770
11771var processNextTick = _dereq_(28);
11772/*</replacement>*/
11773
11774module.exports = Writable;
11775
11776/* <replacement> */
11777function WriteReq(chunk, encoding, cb) {
11778  this.chunk = chunk;
11779  this.encoding = encoding;
11780  this.callback = cb;
11781  this.next = null;
11782}
11783
11784// It seems a linked list but it is not
11785// there will be only 2 of these for each stream
11786function CorkedRequest(state) {
11787  var _this = this;
11788
11789  this.next = null;
11790  this.entry = null;
11791  this.finish = function () {
11792    onCorkedFinish(_this, state);
11793  };
11794}
11795/* </replacement> */
11796
11797/*<replacement>*/
11798var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : processNextTick;
11799/*</replacement>*/
11800
11801/*<replacement>*/
11802var Duplex;
11803/*</replacement>*/
11804
11805Writable.WritableState = WritableState;
11806
11807/*<replacement>*/
11808var util = _dereq_(12);
11809util.inherits = _dereq_(25);
11810/*</replacement>*/
11811
11812/*<replacement>*/
11813var internalUtil = {
11814  deprecate: _dereq_(48)
11815};
11816/*</replacement>*/
11817
11818/*<replacement>*/
11819var Stream = _dereq_(38);
11820/*</replacement>*/
11821
11822/*<replacement>*/
11823var Buffer = _dereq_(44).Buffer;
11824var OurUint8Array = global.Uint8Array || function () {};
11825function _uint8ArrayToBuffer(chunk) {
11826  return Buffer.from(chunk);
11827}
11828function _isUint8Array(obj) {
11829  return Buffer.isBuffer(obj) || obj instanceof OurUint8Array;
11830}
11831/*</replacement>*/
11832
11833var destroyImpl = _dereq_(37);
11834
11835util.inherits(Writable, Stream);
11836
11837function nop() {}
11838
11839function WritableState(options, stream) {
11840  Duplex = Duplex || _dereq_(31);
11841
11842  options = options || {};
11843
11844  // object stream flag to indicate whether or not this stream
11845  // contains buffers or objects.
11846  this.objectMode = !!options.objectMode;
11847
11848  if (stream instanceof Duplex) this.objectMode = this.objectMode || !!options.writableObjectMode;
11849
11850  // the point at which write() starts returning false
11851  // Note: 0 is a valid value, means that we always return false if
11852  // the entire buffer is not flushed immediately on write()
11853  var hwm = options.highWaterMark;
11854  var defaultHwm = this.objectMode ? 16 : 16 * 1024;
11855  this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm;
11856
11857  // cast to ints.
11858  this.highWaterMark = Math.floor(this.highWaterMark);
11859
11860  // if _final has been called
11861  this.finalCalled = false;
11862
11863  // drain event flag.
11864  this.needDrain = false;
11865  // at the start of calling end()
11866  this.ending = false;
11867  // when end() has been called, and returned
11868  this.ended = false;
11869  // when 'finish' is emitted
11870  this.finished = false;
11871
11872  // has it been destroyed
11873  this.destroyed = false;
11874
11875  // should we decode strings into buffers before passing to _write?
11876  // this is here so that some node-core streams can optimize string
11877  // handling at a lower level.
11878  var noDecode = options.decodeStrings === false;
11879  this.decodeStrings = !noDecode;
11880
11881  // Crypto is kind of old and crusty.  Historically, its default string
11882  // encoding is 'binary' so we have to make this configurable.
11883  // Everything else in the universe uses 'utf8', though.
11884  this.defaultEncoding = options.defaultEncoding || 'utf8';
11885
11886  // not an actual buffer we keep track of, but a measurement
11887  // of how much we're waiting to get pushed to some underlying
11888  // socket or file.
11889  this.length = 0;
11890
11891  // a flag to see when we're in the middle of a write.
11892  this.writing = false;
11893
11894  // when true all writes will be buffered until .uncork() call
11895  this.corked = 0;
11896
11897  // a flag to be able to tell if the onwrite cb is called immediately,
11898  // or on a later tick.  We set this to true at first, because any
11899  // actions that shouldn't happen until "later" should generally also
11900  // not happen before the first write call.
11901  this.sync = true;
11902
11903  // a flag to know if we're processing previously buffered items, which
11904  // may call the _write() callback in the same tick, so that we don't
11905  // end up in an overlapped onwrite situation.
11906  this.bufferProcessing = false;
11907
11908  // the callback that's passed to _write(chunk,cb)
11909  this.onwrite = function (er) {
11910    onwrite(stream, er);
11911  };
11912
11913  // the callback that the user supplies to write(chunk,encoding,cb)
11914  this.writecb = null;
11915
11916  // the amount that is being written when _write is called.
11917  this.writelen = 0;
11918
11919  this.bufferedRequest = null;
11920  this.lastBufferedRequest = null;
11921
11922  // number of pending user-supplied write callbacks
11923  // this must be 0 before 'finish' can be emitted
11924  this.pendingcb = 0;
11925
11926  // emit prefinish if the only thing we're waiting for is _write cbs
11927  // This is relevant for synchronous Transform streams
11928  this.prefinished = false;
11929
11930  // True if the error was already emitted and should not be thrown again
11931  this.errorEmitted = false;
11932
11933  // count buffered requests
11934  this.bufferedRequestCount = 0;
11935
11936  // allocate the first CorkedRequest, there is always
11937  // one allocated and free to use, and we maintain at most two
11938  this.corkedRequestsFree = new CorkedRequest(this);
11939}
11940
11941WritableState.prototype.getBuffer = function getBuffer() {
11942  var current = this.bufferedRequest;
11943  var out = [];
11944  while (current) {
11945    out.push(current);
11946    current = current.next;
11947  }
11948  return out;
11949};
11950
11951(function () {
11952  try {
11953    Object.defineProperty(WritableState.prototype, 'buffer', {
11954      get: internalUtil.deprecate(function () {
11955        return this.getBuffer();
11956      }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003')
11957    });
11958  } catch (_) {}
11959})();
11960
11961// Test _writableState for inheritance to account for Duplex streams,
11962// whose prototype chain only points to Readable.
11963var realHasInstance;
11964if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') {
11965  realHasInstance = Function.prototype[Symbol.hasInstance];
11966  Object.defineProperty(Writable, Symbol.hasInstance, {
11967    value: function (object) {
11968      if (realHasInstance.call(this, object)) return true;
11969
11970      return object && object._writableState instanceof WritableState;
11971    }
11972  });
11973} else {
11974  realHasInstance = function (object) {
11975    return object instanceof this;
11976  };
11977}
11978
11979function Writable(options) {
11980  Duplex = Duplex || _dereq_(31);
11981
11982  // Writable ctor is applied to Duplexes, too.
11983  // `realHasInstance` is necessary because using plain `instanceof`
11984  // would return false, as no `_writableState` property is attached.
11985
11986  // Trying to use the custom `instanceof` for Writable here will also break the
11987  // Node.js LazyTransform implementation, which has a non-trivial getter for
11988  // `_writableState` that would lead to infinite recursion.
11989  if (!realHasInstance.call(Writable, this) && !(this instanceof Duplex)) {
11990    return new Writable(options);
11991  }
11992
11993  this._writableState = new WritableState(options, this);
11994
11995  // legacy.
11996  this.writable = true;
11997
11998  if (options) {
11999    if (typeof options.write === 'function') this._write = options.write;
12000
12001    if (typeof options.writev === 'function') this._writev = options.writev;
12002
12003    if (typeof options.destroy === 'function') this._destroy = options.destroy;
12004
12005    if (typeof options.final === 'function') this._final = options.final;
12006  }
12007
12008  Stream.call(this);
12009}
12010
12011// Otherwise people can pipe Writable streams, which is just wrong.
12012Writable.prototype.pipe = function () {
12013  this.emit('error', new Error('Cannot pipe, not readable'));
12014};
12015
12016function writeAfterEnd(stream, cb) {
12017  var er = new Error('write after end');
12018  // TODO: defer error events consistently everywhere, not just the cb
12019  stream.emit('error', er);
12020  processNextTick(cb, er);
12021}
12022
12023// Checks that a user-supplied chunk is valid, especially for the particular
12024// mode the stream is in. Currently this means that `null` is never accepted
12025// and undefined/non-string values are only allowed in object mode.
12026function validChunk(stream, state, chunk, cb) {
12027  var valid = true;
12028  var er = false;
12029
12030  if (chunk === null) {
12031    er = new TypeError('May not write null values to stream');
12032  } else if (typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) {
12033    er = new TypeError('Invalid non-string/buffer chunk');
12034  }
12035  if (er) {
12036    stream.emit('error', er);
12037    processNextTick(cb, er);
12038    valid = false;
12039  }
12040  return valid;
12041}
12042
12043Writable.prototype.write = function (chunk, encoding, cb) {
12044  var state = this._writableState;
12045  var ret = false;
12046  var isBuf = _isUint8Array(chunk) && !state.objectMode;
12047
12048  if (isBuf && !Buffer.isBuffer(chunk)) {
12049    chunk = _uint8ArrayToBuffer(chunk);
12050  }
12051
12052  if (typeof encoding === 'function') {
12053    cb = encoding;
12054    encoding = null;
12055  }
12056
12057  if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding;
12058
12059  if (typeof cb !== 'function') cb = nop;
12060
12061  if (state.ended) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) {
12062    state.pendingcb++;
12063    ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb);
12064  }
12065
12066  return ret;
12067};
12068
12069Writable.prototype.cork = function () {
12070  var state = this._writableState;
12071
12072  state.corked++;
12073};
12074
12075Writable.prototype.uncork = function () {
12076  var state = this._writableState;
12077
12078  if (state.corked) {
12079    state.corked--;
12080
12081    if (!state.writing && !state.corked && !state.finished && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state);
12082  }
12083};
12084
12085Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) {
12086  // node::ParseEncoding() requires lower case.
12087  if (typeof encoding === 'string') encoding = encoding.toLowerCase();
12088  if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new TypeError('Unknown encoding: ' + encoding);
12089  this._writableState.defaultEncoding = encoding;
12090  return this;
12091};
12092
12093function decodeChunk(state, chunk, encoding) {
12094  if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') {
12095    chunk = Buffer.from(chunk, encoding);
12096  }
12097  return chunk;
12098}
12099
12100// if we're already writing something, then just put this
12101// in the queue, and wait our turn.  Otherwise, call _write
12102// If we return false, then we need a drain event, so set that flag.
12103function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) {
12104  if (!isBuf) {
12105    var newChunk = decodeChunk(state, chunk, encoding);
12106    if (chunk !== newChunk) {
12107      isBuf = true;
12108      encoding = 'buffer';
12109      chunk = newChunk;
12110    }
12111  }
12112  var len = state.objectMode ? 1 : chunk.length;
12113
12114  state.length += len;
12115
12116  var ret = state.length < state.highWaterMark;
12117  // we must ensure that previous needDrain will not be reset to false.
12118  if (!ret) state.needDrain = true;
12119
12120  if (state.writing || state.corked) {
12121    var last = state.lastBufferedRequest;
12122    state.lastBufferedRequest = {
12123      chunk: chunk,
12124      encoding: encoding,
12125      isBuf: isBuf,
12126      callback: cb,
12127      next: null
12128    };
12129    if (last) {
12130      last.next = state.lastBufferedRequest;
12131    } else {
12132      state.bufferedRequest = state.lastBufferedRequest;
12133    }
12134    state.bufferedRequestCount += 1;
12135  } else {
12136    doWrite(stream, state, false, len, chunk, encoding, cb);
12137  }
12138
12139  return ret;
12140}
12141
12142function doWrite(stream, state, writev, len, chunk, encoding, cb) {
12143  state.writelen = len;
12144  state.writecb = cb;
12145  state.writing = true;
12146  state.sync = true;
12147  if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite);
12148  state.sync = false;
12149}
12150
12151function onwriteError(stream, state, sync, er, cb) {
12152  --state.pendingcb;
12153
12154  if (sync) {
12155    // defer the callback if we are being called synchronously
12156    // to avoid piling up things on the stack
12157    processNextTick(cb, er);
12158    // this can emit finish, and it will always happen
12159    // after error
12160    processNextTick(finishMaybe, stream, state);
12161    stream._writableState.errorEmitted = true;
12162    stream.emit('error', er);
12163  } else {
12164    // the caller expect this to happen before if
12165    // it is async
12166    cb(er);
12167    stream._writableState.errorEmitted = true;
12168    stream.emit('error', er);
12169    // this can emit finish, but finish must
12170    // always follow error
12171    finishMaybe(stream, state);
12172  }
12173}
12174
12175function onwriteStateUpdate(state) {
12176  state.writing = false;
12177  state.writecb = null;
12178  state.length -= state.writelen;
12179  state.writelen = 0;
12180}
12181
12182function onwrite(stream, er) {
12183  var state = stream._writableState;
12184  var sync = state.sync;
12185  var cb = state.writecb;
12186
12187  onwriteStateUpdate(state);
12188
12189  if (er) onwriteError(stream, state, sync, er, cb);else {
12190    // Check if we're actually ready to finish, but don't emit yet
12191    var finished = needFinish(state);
12192
12193    if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) {
12194      clearBuffer(stream, state);
12195    }
12196
12197    if (sync) {
12198      /*<replacement>*/
12199      asyncWrite(afterWrite, stream, state, finished, cb);
12200      /*</replacement>*/
12201    } else {
12202      afterWrite(stream, state, finished, cb);
12203    }
12204  }
12205}
12206
12207function afterWrite(stream, state, finished, cb) {
12208  if (!finished) onwriteDrain(stream, state);
12209  state.pendingcb--;
12210  cb();
12211  finishMaybe(stream, state);
12212}
12213
12214// Must force callback to be called on nextTick, so that we don't
12215// emit 'drain' before the write() consumer gets the 'false' return
12216// value, and has a chance to attach a 'drain' listener.
12217function onwriteDrain(stream, state) {
12218  if (state.length === 0 && state.needDrain) {
12219    state.needDrain = false;
12220    stream.emit('drain');
12221  }
12222}
12223
12224// if there's something in the buffer waiting, then process it
12225function clearBuffer(stream, state) {
12226  state.bufferProcessing = true;
12227  var entry = state.bufferedRequest;
12228
12229  if (stream._writev && entry && entry.next) {
12230    // Fast case, write everything using _writev()
12231    var l = state.bufferedRequestCount;
12232    var buffer = new Array(l);
12233    var holder = state.corkedRequestsFree;
12234    holder.entry = entry;
12235
12236    var count = 0;
12237    var allBuffers = true;
12238    while (entry) {
12239      buffer[count] = entry;
12240      if (!entry.isBuf) allBuffers = false;
12241      entry = entry.next;
12242      count += 1;
12243    }
12244    buffer.allBuffers = allBuffers;
12245
12246    doWrite(stream, state, true, state.length, buffer, '', holder.finish);
12247
12248    // doWrite is almost always async, defer these to save a bit of time
12249    // as the hot path ends with doWrite
12250    state.pendingcb++;
12251    state.lastBufferedRequest = null;
12252    if (holder.next) {
12253      state.corkedRequestsFree = holder.next;
12254      holder.next = null;
12255    } else {
12256      state.corkedRequestsFree = new CorkedRequest(state);
12257    }
12258  } else {
12259    // Slow case, write chunks one-by-one
12260    while (entry) {
12261      var chunk = entry.chunk;
12262      var encoding = entry.encoding;
12263      var cb = entry.callback;
12264      var len = state.objectMode ? 1 : chunk.length;
12265
12266      doWrite(stream, state, false, len, chunk, encoding, cb);
12267      entry = entry.next;
12268      // if we didn't call the onwrite immediately, then
12269      // it means that we need to wait until it does.
12270      // also, that means that the chunk and cb are currently
12271      // being processed, so move the buffer counter past them.
12272      if (state.writing) {
12273        break;
12274      }
12275    }
12276
12277    if (entry === null) state.lastBufferedRequest = null;
12278  }
12279
12280  state.bufferedRequestCount = 0;
12281  state.bufferedRequest = entry;
12282  state.bufferProcessing = false;
12283}
12284
12285Writable.prototype._write = function (chunk, encoding, cb) {
12286  cb(new Error('_write() is not implemented'));
12287};
12288
12289Writable.prototype._writev = null;
12290
12291Writable.prototype.end = function (chunk, encoding, cb) {
12292  var state = this._writableState;
12293
12294  if (typeof chunk === 'function') {
12295    cb = chunk;
12296    chunk = null;
12297    encoding = null;
12298  } else if (typeof encoding === 'function') {
12299    cb = encoding;
12300    encoding = null;
12301  }
12302
12303  if (chunk !== null && chunk !== undefined) this.write(chunk, encoding);
12304
12305  // .end() fully uncorks
12306  if (state.corked) {
12307    state.corked = 1;
12308    this.uncork();
12309  }
12310
12311  // ignore unnecessary end() calls.
12312  if (!state.ending && !state.finished) endWritable(this, state, cb);
12313};
12314
12315function needFinish(state) {
12316  return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing;
12317}
12318function callFinal(stream, state) {
12319  stream._final(function (err) {
12320    state.pendingcb--;
12321    if (err) {
12322      stream.emit('error', err);
12323    }
12324    state.prefinished = true;
12325    stream.emit('prefinish');
12326    finishMaybe(stream, state);
12327  });
12328}
12329function prefinish(stream, state) {
12330  if (!state.prefinished && !state.finalCalled) {
12331    if (typeof stream._final === 'function') {
12332      state.pendingcb++;
12333      state.finalCalled = true;
12334      processNextTick(callFinal, stream, state);
12335    } else {
12336      state.prefinished = true;
12337      stream.emit('prefinish');
12338    }
12339  }
12340}
12341
12342function finishMaybe(stream, state) {
12343  var need = needFinish(state);
12344  if (need) {
12345    prefinish(stream, state);
12346    if (state.pendingcb === 0) {
12347      state.finished = true;
12348      stream.emit('finish');
12349    }
12350  }
12351  return need;
12352}
12353
12354function endWritable(stream, state, cb) {
12355  state.ending = true;
12356  finishMaybe(stream, state);
12357  if (cb) {
12358    if (state.finished) processNextTick(cb);else stream.once('finish', cb);
12359  }
12360  state.ended = true;
12361  stream.writable = false;
12362}
12363
12364function onCorkedFinish(corkReq, state, err) {
12365  var entry = corkReq.entry;
12366  corkReq.entry = null;
12367  while (entry) {
12368    var cb = entry.callback;
12369    state.pendingcb--;
12370    cb(err);
12371    entry = entry.next;
12372  }
12373  if (state.corkedRequestsFree) {
12374    state.corkedRequestsFree.next = corkReq;
12375  } else {
12376    state.corkedRequestsFree = corkReq;
12377  }
12378}
12379
12380Object.defineProperty(Writable.prototype, 'destroyed', {
12381  get: function () {
12382    if (this._writableState === undefined) {
12383      return false;
12384    }
12385    return this._writableState.destroyed;
12386  },
12387  set: function (value) {
12388    // we ignore the value if the stream
12389    // has not been initialized yet
12390    if (!this._writableState) {
12391      return;
12392    }
12393
12394    // backward compatibility, the user is explicitly
12395    // managing destroyed
12396    this._writableState.destroyed = value;
12397  }
12398});
12399
12400Writable.prototype.destroy = destroyImpl.destroy;
12401Writable.prototype._undestroy = destroyImpl.undestroy;
12402Writable.prototype._destroy = function (err, cb) {
12403  this.end();
12404  cb(err);
12405};
vendor: 2,326 bytes, lines 12406-12490
12406}).call(this,_dereq_(29),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
12407
12408},{"12":12,"25":25,"28":28,"29":29,"31":31,"37":37,"38":38,"44":44,"48":48}],36:[function(_dereq_,module,exports){
12409'use strict';
12410
12411/*<replacement>*/
12412
12413function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
12414
12415var Buffer = _dereq_(44).Buffer;
12416/*</replacement>*/
12417
12418function copyBuffer(src, target, offset) {
12419  src.copy(target, offset);
12420}
12421
12422module.exports = function () {
12423  function BufferList() {
12424    _classCallCheck(this, BufferList);
12425
12426    this.head = null;
12427    this.tail = null;
12428    this.length = 0;
12429  }
12430
12431  BufferList.prototype.push = function push(v) {
12432    var entry = { data: v, next: null };
12433    if (this.length > 0) this.tail.next = entry;else this.head = entry;
12434    this.tail = entry;
12435    ++this.length;
12436  };
12437
12438  BufferList.prototype.unshift = function unshift(v) {
12439    var entry = { data: v, next: this.head };
12440    if (this.length === 0) this.tail = entry;
12441    this.head = entry;
12442    ++this.length;
12443  };
12444
12445  BufferList.prototype.shift = function shift() {
12446    if (this.length === 0) return;
12447    var ret = this.head.data;
12448    if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next;
12449    --this.length;
12450    return ret;
12451  };
12452
12453  BufferList.prototype.clear = function clear() {
12454    this.head = this.tail = null;
12455    this.length = 0;
12456  };
12457
12458  BufferList.prototype.join = function join(s) {
12459    if (this.length === 0) return '';
12460    var p = this.head;
12461    var ret = '' + p.data;
12462    while (p = p.next) {
12463      ret += s + p.data;
12464    }return ret;
12465  };
12466
12467  BufferList.prototype.concat = function concat(n) {
12468    if (this.length === 0) return Buffer.alloc(0);
12469    if (this.length === 1) return this.head.data;
12470    var ret = Buffer.allocUnsafe(n >>> 0);
12471    var p = this.head;
12472    var i = 0;
12473    while (p) {
12474      copyBuffer(p.data, ret, i);
12475      i += p.data.length;
12476      p = p.next;
12477    }
12478    return ret;
12479  };
12480
12481  return BufferList;
12482}();
12483},{"44":44}],37:[function(_dereq_,module,exports){
12484'use strict';
12485
12486/*<replacement>*/
12487
12488var processNextTick = _dereq_(28);
12489/*</replacement>*/
12490
12491// undocumented cb() API, needed for core, not for public API
12492function destroy(err, cb) {
12493  var _this = this;
12494
12495  var readableDestroyed = this._readableState && this._readableState.destroyed;
12496  var writableDestroyed = this._writableState && this._writableState.destroyed;
12497
12498  if (readableDestroyed || writableDestroyed) {
12499    if (cb) {
12500      cb(err);
12501    } else if (err && (!this._writableState || !this._writableState.errorEmitted)) {
12502      processNextTick(emitErrorNT, this, err);
12503    }
12504    return;
12505  }
12506
12507  // we set destroyed to true before firing error callbacks in order
12508  // to make it re-entrance safe in case destroy() is called within callbacks
12509
12510  if (this._readableState) {
12511    this._readableState.destroyed = true;
12512  }
12513
12514  // if this is a duplex stream mark the writable part as destroyed as well
12515  if (this._writableState) {
12516    this._writableState.destroyed = true;
12517  }
12518
12519  this._destroy(err || null, function (err) {
12520    if (!cb && err) {
12521      processNextTick(emitErrorNT, _this, err);
12522      if (_this._writableState) {
12523        _this._writableState.errorEmitted = true;
12524      }
12525    } else if (cb) {
12526      cb(err);
12527    }
12528  });
12529}
12530
12531function undestroy() {
12532  if (this._readableState) {
12533    this._readableState.destroyed = false;
12534    this._readableState.reading = false;
12535    this._readableState.ended = false;
12536    this._readableState.endEmitted = false;
12537  }
12538
12539  if (this._writableState) {
12540    this._writableState.destroyed = false;
12541    this._writableState.ended = false;
12542    this._writableState.ending = false;
12543    this._writableState.finished = false;
12544    this._writableState.errorEmitted = false;
12545  }
12546}
12547
12548function emitErrorNT(self, err) {
12549  self.emit('error', err);
12550}
12551
12552module.exports = {
12553  destroy: destroy,
12554  undestroy: undestroy
12555};
12556},{"28":28}],38:[function(_dereq_,module,exports){
12557module.exports = _dereq_(16).EventEmitter;
12558
12559},{"16":16}],39:[function(_dereq_,module,exports){
12560module.exports = _dereq_(40).PassThrough
12561
12562},{"40":40}],40:[function(_dereq_,module,exports){
12563exports = module.exports = _dereq_(33);
12564exports.Stream = exports;
12565exports.Readable = exports;
12566exports.Writable = _dereq_(35);
12567exports.Duplex = _dereq_(31);
12568exports.Transform = _dereq_(34);
12569exports.PassThrough = _dereq_(32);
12570
12571},{"31":31,"32":32,"33":33,"34":34,"35":35}],41:[function(_dereq_,module,exports){
12572module.exports = _dereq_(40).Transform
12573
12574},{"40":40}],42:[function(_dereq_,module,exports){
12575module.exports = _dereq_(35);
12576
12577},{"35":35}],43:[function(_dereq_,module,exports){
12578/**
12579 * Decimal adjustment of a number.
12580 *
12581 * @param {String}  type  The type of adjustment.
12582 * @param {Number}  value The number.
12583 * @param {Integer} exp   The exponent (the 10 logarithm of the adjustment base).
12584 * @returns {Number} The adjusted value.
12585 */
12586var decimalAdjust = exports.decimalAdjust = function(type, value, exp) {
12587    // If the exp is undefined or zero...
12588    if (typeof exp === 'undefined' || +exp === 0) {
12589        return Math[type](value);
12590    }
12591    value = +value;
12592    exp = +exp;
12593    // If the value is not a number or the exp is not an integer...
12594    if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {
12595        return NaN;
12596    }
12597    // Shift
12598    value = value.toString().split('e');
12599    value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp)));
12600    // Shift back
12601    value = value.toString().split('e');
12602    return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp));
12603}
12604
12605module.exports = {
12606    round10: function(value, exp) {
12607        return decimalAdjust('round', value, exp);
12608    },
12609    floor10: function(value, exp) {
12610        return decimalAdjust('floor', value, exp);
12611    },
12612    ceil10: function(value, exp) {
12613        return decimalAdjust('ceil', value, exp);
12614    },
12615};
12616
12617module.exports.polyfill = function() {
12618    // Decimal round
12619    if (!Math.round10) {
12620        Math.round10 = module.exports.round10;
12621    }
12622    // Decimal floor
12623    if (!Math.floor10) {
12624        Math.floor10 = module.exports.floor10;
12625    }
12626    // Decimal ceil
12627    if (!Math.ceil10) {
12628        Math.ceil10 = module.exports.ceil10;
12629    }
12630};
12631
12632},{}],44:[function(_dereq_,module,exports){
12633/* eslint-disable node/no-deprecated-api */
12634var buffer = _dereq_(10)
12635var Buffer = buffer.Buffer
12636
12637// alternative to using Object.keys for old browsers
12638function copyProps (src, dst) {
12639  for (var key in src) {
12640    dst[key] = src[key]
12641  }
12642}
12643if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) {
12644  module.exports = buffer
12645} else {
12646  // Copy properties from require('buffer')
vendor: 11,261 bytes, lines 12647-13016
12647  copyProps(buffer, exports)
12648  exports.Buffer = SafeBuffer
12649}
12650
12651function SafeBuffer (arg, encodingOrOffset, length) {
12652  return Buffer(arg, encodingOrOffset, length)
12653}
12654
12655// Copy static methods from Buffer
12656copyProps(Buffer, SafeBuffer)
12657
12658SafeBuffer.from = function (arg, encodingOrOffset, length) {
12659  if (typeof arg === 'number') {
12660    throw new TypeError('Argument must not be a number')
12661  }
12662  return Buffer(arg, encodingOrOffset, length)
12663}
12664
12665SafeBuffer.alloc = function (size, fill, encoding) {
12666  if (typeof size !== 'number') {
12667    throw new TypeError('Argument must be a number')
12668  }
12669  var buf = Buffer(size)
12670  if (fill !== undefined) {
12671    if (typeof encoding === 'string') {
12672      buf.fill(fill, encoding)
12673    } else {
12674      buf.fill(fill)
12675    }
12676  } else {
12677    buf.fill(0)
12678  }
12679  return buf
12680}
12681
12682SafeBuffer.allocUnsafe = function (size) {
12683  if (typeof size !== 'number') {
12684    throw new TypeError('Argument must be a number')
12685  }
12686  return Buffer(size)
12687}
12688
12689SafeBuffer.allocUnsafeSlow = function (size) {
12690  if (typeof size !== 'number') {
12691    throw new TypeError('Argument must be a number')
12692  }
12693  return buffer.SlowBuffer(size)
12694}
12695
12696},{"10":10}],45:[function(_dereq_,module,exports){
12697(function (Buffer){
12698;(function (sax) { // wrapper for non-node envs
12699  sax.parser = function (strict, opt) { return new SAXParser(strict, opt) }
12700  sax.SAXParser = SAXParser
12701  sax.SAXStream = SAXStream
12702  sax.createStream = createStream
12703
12704  // When we pass the MAX_BUFFER_LENGTH position, start checking for buffer overruns.
12705  // When we check, schedule the next check for MAX_BUFFER_LENGTH - (max(buffer lengths)),
12706  // since that's the earliest that a buffer overrun could occur.  This way, checks are
12707  // as rare as required, but as often as necessary to ensure never crossing this bound.
12708  // Furthermore, buffers are only tested at most once per write(), so passing a very
12709  // large string into write() might have undesirable effects, but this is manageable by
12710  // the caller, so it is assumed to be safe.  Thus, a call to write() may, in the extreme
12711  // edge case, result in creating at most one complete copy of the string passed in.
12712  // Set to Infinity to have unlimited buffers.
12713  sax.MAX_BUFFER_LENGTH = 64 * 1024
12714
12715  var buffers = [
12716    'comment', 'sgmlDecl', 'textNode', 'tagName', 'doctype',
12717    'procInstName', 'procInstBody', 'entity', 'attribName',
12718    'attribValue', 'cdata', 'script'
12719  ]
12720
12721  sax.EVENTS = [
12722    'text',
12723    'processinginstruction',
12724    'sgmldeclaration',
12725    'doctype',
12726    'comment',
12727    'opentagstart',
12728    'attribute',
12729    'opentag',
12730    'closetag',
12731    'opencdata',
12732    'cdata',
12733    'closecdata',
12734    'error',
12735    'end',
12736    'ready',
12737    'script',
12738    'opennamespace',
12739    'closenamespace'
12740  ]
12741
12742  function SAXParser (strict, opt) {
12743    if (!(this instanceof SAXParser)) {
12744      return new SAXParser(strict, opt)
12745    }
12746
12747    var parser = this
12748    clearBuffers(parser)
12749    parser.q = parser.c = ''
12750    parser.bufferCheckPosition = sax.MAX_BUFFER_LENGTH
12751    parser.opt = opt || {}
12752    parser.opt.lowercase = parser.opt.lowercase || parser.opt.lowercasetags
12753    parser.looseCase = parser.opt.lowercase ? 'toLowerCase' : 'toUpperCase'
12754    parser.tags = []
12755    parser.closed = parser.closedRoot = parser.sawRoot = false
12756    parser.tag = parser.error = null
12757    parser.strict = !!strict
12758    parser.noscript = !!(strict || parser.opt.noscript)
12759    parser.state = S.BEGIN
12760    parser.strictEntities = parser.opt.strictEntities
12761    parser.ENTITIES = parser.strictEntities ? Object.create(sax.XML_ENTITIES) : Object.create(sax.ENTITIES)
12762    parser.attribList = []
12763
12764    // namespaces form a prototype chain.
12765    // it always points at the current tag,
12766    // which protos to its parent tag.
12767    if (parser.opt.xmlns) {
12768      parser.ns = Object.create(rootNS)
12769    }
12770
12771    // mostly just for error reporting
12772    parser.trackPosition = parser.opt.position !== false
12773    if (parser.trackPosition) {
12774      parser.position = parser.line = parser.column = 0
12775    }
12776    emit(parser, 'onready')
12777  }
12778
12779  if (!Object.create) {
12780    Object.create = function (o) {
12781      function F () {}
12782      F.prototype = o
12783      var newf = new F()
12784      return newf
12785    }
12786  }
12787
12788  if (!Object.keys) {
12789    Object.keys = function (o) {
12790      var a = []
12791      for (var i in o) if (o.hasOwnProperty(i)) a.push(i)
12792      return a
12793    }
12794  }
12795
12796  function checkBufferLength (parser) {
12797    var maxAllowed = Math.max(sax.MAX_BUFFER_LENGTH, 10)
12798    var maxActual = 0
12799    for (var i = 0, l = buffers.length; i < l; i++) {
12800      var len = parser[buffers[i]].length
12801      if (len > maxAllowed) {
12802        // Text/cdata nodes can get big, and since they're buffered,
12803        // we can get here under normal conditions.
12804        // Avoid issues by emitting the text node now,
12805        // so at least it won't get any bigger.
12806        switch (buffers[i]) {
12807          case 'textNode':
12808            closeText(parser)
12809            break
12810
12811          case 'cdata':
12812            emitNode(parser, 'oncdata', parser.cdata)
12813            parser.cdata = ''
12814            break
12815
12816          case 'script':
12817            emitNode(parser, 'onscript', parser.script)
12818            parser.script = ''
12819            break
12820
12821          default:
12822            error(parser, 'Max buffer length exceeded: ' + buffers[i])
12823        }
12824      }
12825      maxActual = Math.max(maxActual, len)
12826    }
12827    // schedule the next check for the earliest possible buffer overrun.
12828    var m = sax.MAX_BUFFER_LENGTH - maxActual
12829    parser.bufferCheckPosition = m + parser.position
12830  }
12831
12832  function clearBuffers (parser) {
12833    for (var i = 0, l = buffers.length; i < l; i++) {
12834      parser[buffers[i]] = ''
12835    }
12836  }
12837
12838  function flushBuffers (parser) {
12839    closeText(parser)
12840    if (parser.cdata !== '') {
12841      emitNode(parser, 'oncdata', parser.cdata)
12842      parser.cdata = ''
12843    }
12844    if (parser.script !== '') {
12845      emitNode(parser, 'onscript', parser.script)
12846      parser.script = ''
12847    }
12848  }
12849
12850  SAXParser.prototype = {
12851    end: function () { end(this) },
12852    write: write,
12853    resume: function () { this.error = null; return this },
12854    close: function () { return this.write(null) },
12855    flush: function () { flushBuffers(this) }
12856  }
12857
12858  var Stream
12859  try {
12860    Stream = _dereq_(46).Stream
12861  } catch (ex) {
12862    Stream = function () {}
12863  }
12864
12865  var streamWraps = sax.EVENTS.filter(function (ev) {
12866    return ev !== 'error' && ev !== 'end'
12867  })
12868
12869  function createStream (strict, opt) {
12870    return new SAXStream(strict, opt)
12871  }
12872
12873  function SAXStream (strict, opt) {
12874    if (!(this instanceof SAXStream)) {
12875      return new SAXStream(strict, opt)
12876    }
12877
12878    Stream.apply(this)
12879
12880    this._parser = new SAXParser(strict, opt)
12881    this.writable = true
12882    this.readable = true
12883
12884    var me = this
12885
12886    this._parser.onend = function () {
12887      me.emit('end')
12888    }
12889
12890    this._parser.onerror = function (er) {
12891      me.emit('error', er)
12892
12893      // if didn't throw, then means error was handled.
12894      // go ahead and clear error, so we can write again.
12895      me._parser.error = null
12896    }
12897
12898    this._decoder = null
12899
12900    streamWraps.forEach(function (ev) {
12901      Object.defineProperty(me, 'on' + ev, {
12902        get: function () {
12903          return me._parser['on' + ev]
12904        },
12905        set: function (h) {
12906          if (!h) {
12907            me.removeAllListeners(ev)
12908            me._parser['on' + ev] = h
12909            return h
12910          }
12911          me.on(ev, h)
12912        },
12913        enumerable: true,
12914        configurable: false
12915      })
12916    })
12917  }
12918
12919  SAXStream.prototype = Object.create(Stream.prototype, {
12920    constructor: {
12921      value: SAXStream
12922    }
12923  })
12924
12925  SAXStream.prototype.write = function (data) {
12926    if (typeof Buffer === 'function' &&
12927      typeof Buffer.isBuffer === 'function' &&
12928      Buffer.isBuffer(data)) {
12929      if (!this._decoder) {
12930        var SD = _dereq_(9).StringDecoder
12931        this._decoder = new SD('utf8')
12932      }
12933      data = this._decoder.write(data)
12934    }
12935
12936    this._parser.write(data.toString())
12937    this.emit('data', data)
12938    return true
12939  }
12940
12941  SAXStream.prototype.end = function (chunk) {
12942    if (chunk && chunk.length) {
12943      this.write(chunk)
12944    }
12945    this._parser.end()
12946    return true
12947  }
12948
12949  SAXStream.prototype.on = function (ev, handler) {
12950    var me = this
12951    if (!me._parser['on' + ev] && streamWraps.indexOf(ev) !== -1) {
12952      me._parser['on' + ev] = function () {
12953        var args = arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments)
12954        args.splice(0, 0, ev)
12955        me.emit.apply(me, args)
12956      }
12957    }
12958
12959    return Stream.prototype.on.call(me, ev, handler)
12960  }
12961
12962  // character classes and tokens
12963  var whitespace = '\r\n\t '
12964
12965  // this really needs to be replaced with character classes.
12966  // XML allows all manner of ridiculous numbers and digits.
12967  var number = '0124356789'
12968  var letter = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
12969
12970  // (Letter | "_" | ":")
12971  var quote = '\'"'
12972  var attribEnd = whitespace + '>'
12973  var CDATA = '[CDATA['
12974  var DOCTYPE = 'DOCTYPE'
12975  var XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace'
12976  var XMLNS_NAMESPACE = 'http://www.w3.org/2000/xmlns/'
12977  var rootNS = { xml: XML_NAMESPACE, xmlns: XMLNS_NAMESPACE }
12978
12979  // turn all the string character sets into character class objects.
12980  whitespace = charClass(whitespace)
12981  number = charClass(number)
12982  letter = charClass(letter)
12983
12984  // http://www.w3.org/TR/REC-xml/#NT-NameStartChar
12985  // This implementation works on strings, a single character at a time
12986  // as such, it cannot ever support astral-plane characters (10000-EFFFF)
12987  // without a significant breaking change to either this  parser, or the
12988  // JavaScript language.  Implementation of an emoji-capable xml parser
12989  // is left as an exercise for the reader.
12990  var nameStart = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/
12991
12992  var nameBody = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040\.\d-]/
12993
12994  var entityStart = /[#:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/
12995  var entityBody = /[#:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040\.\d-]/
12996
12997  quote = charClass(quote)
12998  attribEnd = charClass(attribEnd)
12999
13000  function charClass (str) {
13001    return str.split('').reduce(function (s, c) {
13002      s[c] = true
13003      return s
13004    }, {})
13005  }
13006
13007  function isRegExp (c) {
13008    return Object.prototype.toString.call(c) === '[object RegExp]'
13009  }
13010
13011  function is (charclass, c) {
13012    return isRegExp(charclass) ? !!c.match(charclass) : charclass[c]
13013  }
13014
13015  function not (charclass, c) {
13016    return !is(charclass
vendor: 16,337 bytes, lines 13016-13649
13016, c)
13017  }
13018
13019  var S = 0
13020  sax.STATE = {
13021    BEGIN: S++, // leading byte order mark or whitespace
13022    BEGIN_WHITESPACE: S++, // leading whitespace
13023    TEXT: S++, // general stuff
13024    TEXT_ENTITY: S++, // &amp and such.
13025    OPEN_WAKA: S++, // <
13026    SGML_DECL: S++, // <!BLARG
13027    SGML_DECL_QUOTED: S++, // <!BLARG foo "bar
13028    DOCTYPE: S++, // <!DOCTYPE
13029    DOCTYPE_QUOTED: S++, // <!DOCTYPE "//blah
13030    DOCTYPE_DTD: S++, // <!DOCTYPE "//blah" [ ...
13031    DOCTYPE_DTD_QUOTED: S++, // <!DOCTYPE "//blah" [ "foo
13032    COMMENT_STARTING: S++, // <!-
13033    COMMENT: S++, // <!--
13034    COMMENT_ENDING: S++, // <!-- blah -
13035    COMMENT_ENDED: S++, // <!-- blah --
13036    CDATA: S++, // <![CDATA[ something
13037    CDATA_ENDING: S++, // ]
13038    CDATA_ENDING_2: S++, // ]]
13039    PROC_INST: S++, // <?hi
13040    PROC_INST_BODY: S++, // <?hi there
13041    PROC_INST_ENDING: S++, // <?hi "there" ?
13042    OPEN_TAG: S++, // <strong
13043    OPEN_TAG_SLASH: S++, // <strong /
13044    ATTRIB: S++, // <a
13045    ATTRIB_NAME: S++, // <a foo
13046    ATTRIB_NAME_SAW_WHITE: S++, // <a foo _
13047    ATTRIB_VALUE: S++, // <a foo=
13048    ATTRIB_VALUE_QUOTED: S++, // <a foo="bar
13049    ATTRIB_VALUE_CLOSED: S++, // <a foo="bar"
13050    ATTRIB_VALUE_UNQUOTED: S++, // <a foo=bar
13051    ATTRIB_VALUE_ENTITY_Q: S++, // <foo bar="&quot;"
13052    ATTRIB_VALUE_ENTITY_U: S++, // <foo bar=&quot
13053    CLOSE_TAG: S++, // </a
13054    CLOSE_TAG_SAW_WHITE: S++, // </a   >
13055    SCRIPT: S++, // <script> ...
13056    SCRIPT_ENDING: S++ // <script> ... <
13057  }
13058
13059  sax.XML_ENTITIES = {
13060    'amp': '&',
13061    'gt': '>',
13062    'lt': '<',
13063    'quot': '"',
13064    'apos': "'"
13065  }
13066
13067  sax.ENTITIES = {
13068    'amp': '&',
13069    'gt': '>',
13070    'lt': '<',
13071    'quot': '"',
13072    'apos': "'",
13073    'AElig': 198,
13074    'Aacute': 193,
13075    'Acirc': 194,
13076    'Agrave': 192,
13077    'Aring': 197,
13078    'Atilde': 195,
13079    'Auml': 196,
13080    'Ccedil': 199,
13081    'ETH': 208,
13082    'Eacute': 201,
13083    'Ecirc': 202,
13084    'Egrave': 200,
13085    'Euml': 203,
13086    'Iacute': 205,
13087    'Icirc': 206,
13088    'Igrave': 204,
13089    'Iuml': 207,
13090    'Ntilde': 209,
13091    'Oacute': 211,
13092    'Ocirc': 212,
13093    'Ograve': 210,
13094    'Oslash': 216,
13095    'Otilde': 213,
13096    'Ouml': 214,
13097    'THORN': 222,
13098    'Uacute': 218,
13099    'Ucirc': 219,
13100    'Ugrave': 217,
13101    'Uuml': 220,
13102    'Yacute': 221,
13103    'aacute': 225,
13104    'acirc': 226,
13105    'aelig': 230,
13106    'agrave': 224,
13107    'aring': 229,
13108    'atilde': 227,
13109    'auml': 228,
13110    'ccedil': 231,
13111    'eacute': 233,
13112    'ecirc': 234,
13113    'egrave': 232,
13114    'eth': 240,
13115    'euml': 235,
13116    'iacute': 237,
13117    'icirc': 238,
13118    'igrave': 236,
13119    'iuml': 239,
13120    'ntilde': 241,
13121    'oacute': 243,
13122    'ocirc': 244,
13123    'ograve': 242,
13124    'oslash': 248,
13125    'otilde': 245,
13126    'ouml': 246,
13127    'szlig': 223,
13128    'thorn': 254,
13129    'uacute': 250,
13130    'ucirc': 251,
13131    'ugrave': 249,
13132    'uuml': 252,
13133    'yacute': 253,
13134    'yuml': 255,
13135    'copy': 169,
13136    'reg': 174,
13137    'nbsp': 160,
13138    'iexcl': 161,
13139    'cent': 162,
13140    'pound': 163,
13141    'curren': 164,
13142    'yen': 165,
13143    'brvbar': 166,
13144    'sect': 167,
13145    'uml': 168,
13146    'ordf': 170,
13147    'laquo': 171,
13148    'not': 172,
13149    'shy': 173,
13150    'macr': 175,
13151    'deg': 176,
13152    'plusmn': 177,
13153    'sup1': 185,
13154    'sup2': 178,
13155    'sup3': 179,
13156    'acute': 180,
13157    'micro': 181,
13158    'para': 182,
13159    'middot': 183,
13160    'cedil': 184,
13161    'ordm': 186,
13162    'raquo': 187,
13163    'frac14': 188,
13164    'frac12': 189,
13165    'frac34': 190,
13166    'iquest': 191,
13167    'times': 215,
13168    'divide': 247,
13169    'OElig': 338,
13170    'oelig': 339,
13171    'Scaron': 352,
13172    'scaron': 353,
13173    'Yuml': 376,
13174    'fnof': 402,
13175    'circ': 710,
13176    'tilde': 732,
13177    'Alpha': 913,
13178    'Beta': 914,
13179    'Gamma': 915,
13180    'Delta': 916,
13181    'Epsilon': 917,
13182    'Zeta': 918,
13183    'Eta': 919,
13184    'Theta': 920,
13185    'Iota': 921,
13186    'Kappa': 922,
13187    'Lambda': 923,
13188    'Mu': 924,
13189    'Nu': 925,
13190    'Xi': 926,
13191    'Omicron': 927,
13192    'Pi': 928,
13193    'Rho': 929,
13194    'Sigma': 931,
13195    'Tau': 932,
13196    'Upsilon': 933,
13197    'Phi': 934,
13198    'Chi': 935,
13199    'Psi': 936,
13200    'Omega': 937,
13201    'alpha': 945,
13202    'beta': 946,
13203    'gamma': 947,
13204    'delta': 948,
13205    'epsilon': 949,
13206    'zeta': 950,
13207    'eta': 951,
13208    'theta': 952,
13209    'iota': 953,
13210    'kappa': 954,
13211    'lambda': 955,
13212    'mu': 956,
13213    'nu': 957,
13214    'xi': 958,
13215    'omicron': 959,
13216    'pi': 960,
13217    'rho': 961,
13218    'sigmaf': 962,
13219    'sigma': 963,
13220    'tau': 964,
13221    'upsilon': 965,
13222    'phi': 966,
13223    'chi': 967,
13224    'psi': 968,
13225    'omega': 969,
13226    'thetasym': 977,
13227    'upsih': 978,
13228    'piv': 982,
13229    'ensp': 8194,
13230    'emsp': 8195,
13231    'thinsp': 8201,
13232    'zwnj': 8204,
13233    'zwj': 8205,
13234    'lrm': 8206,
13235    'rlm': 8207,
13236    'ndash': 8211,
13237    'mdash': 8212,
13238    'lsquo': 8216,
13239    'rsquo': 8217,
13240    'sbquo': 8218,
13241    'ldquo': 8220,
13242    'rdquo': 8221,
13243    'bdquo': 8222,
13244    'dagger': 8224,
13245    'Dagger': 8225,
13246    'bull': 8226,
13247    'hellip': 8230,
13248    'permil': 8240,
13249    'prime': 8242,
13250    'Prime': 8243,
13251    'lsaquo': 8249,
13252    'rsaquo': 8250,
13253    'oline': 8254,
13254    'frasl': 8260,
13255    'euro': 8364,
13256    'image': 8465,
13257    'weierp': 8472,
13258    'real': 8476,
13259    'trade': 8482,
13260    'alefsym': 8501,
13261    'larr': 8592,
13262    'uarr': 8593,
13263    'rarr': 8594,
13264    'darr': 8595,
13265    'harr': 8596,
13266    'crarr': 8629,
13267    'lArr': 8656,
13268    'uArr': 8657,
13269    'rArr': 8658,
13270    'dArr': 8659,
13271    'hArr': 8660,
13272    'forall': 8704,
13273    'part': 8706,
13274    'exist': 8707,
13275    'empty': 8709,
13276    'nabla': 8711,
13277    'isin': 8712,
13278    'notin': 8713,
13279    'ni': 8715,
13280    'prod': 8719,
13281    'sum': 8721,
13282    'minus': 8722,
13283    'lowast': 8727,
13284    'radic': 8730,
13285    'prop': 8733,
13286    'infin': 8734,
13287    'ang': 8736,
13288    'and': 8743,
13289    'or': 8744,
13290    'cap': 8745,
13291    'cup': 8746,
13292    'int': 8747,
13293    'there4': 8756,
13294    'sim': 8764,
13295    'cong': 8773,
13296    'asymp': 8776,
13297    'ne': 8800,
13298    'equiv': 8801,
13299    'le': 8804,
13300    'ge': 8805,
13301    'sub': 8834,
13302    'sup': 8835,
13303    'nsub': 8836,
13304    'sube': 8838,
13305    'supe': 8839,
13306    'oplus': 8853,
13307    'otimes': 8855,
13308    'perp': 8869,
13309    'sdot': 8901,
13310    'lceil': 8968,
13311    'rceil': 8969,
13312    'lfloor': 8970,
13313    'rfloor': 8971,
13314    'lang': 9001,
13315    'rang': 9002,
13316    'loz': 9674,
13317    'spades': 9824,
13318    'clubs': 9827,
13319    'hearts': 9829,
13320    'diams': 9830
13321  }
13322
13323  Object.keys(sax.ENTITIES).forEach(function (key) {
13324    var e = sax.ENTITIES[key]
13325    var s = typeof e === 'number' ? String.fromCharCode(e) : e
13326    sax.ENTITIES[key] = s
13327  })
13328
13329  for (var s in sax.STATE) {
13330    sax.STATE[sax.STATE[s]] = s
13331  }
13332
13333  // shorthand
13334  S = sax.STATE
13335
13336  function emit (parser, event, data) {
13337    parser[event] && parser[event](data)
13338  }
13339
13340  function emitNode (parser, nodeType, data) {
13341    if (parser.textNode) closeText(parser)
13342    emit(parser, nodeType, data)
13343  }
13344
13345  function closeText (parser) {
13346    parser.textNode = textopts(parser.opt, parser.textNode)
13347    if (parser.textNode) emit(parser, 'ontext', parser.textNode)
13348    parser.textNode = ''
13349  }
13350
13351  function textopts (opt, text) {
13352    if (opt.trim) text = text.trim()
13353    if (opt.normalize) text = text.replace(/\s+/g, ' ')
13354    return text
13355  }
13356
13357  function error (parser, er) {
13358    closeText(parser)
13359    if (parser.trackPosition) {
13360      er += '\nLine: ' + parser.line +
13361        '\nColumn: ' + parser.column +
13362        '\nChar: ' + parser.c
13363    }
13364    er = new Error(er)
13365    parser.error = er
13366    emit(parser, 'onerror', er)
13367    return parser
13368  }
13369
13370  function end (parser) {
13371    if (parser.sawRoot && !parser.closedRoot) strictFail(parser, 'Unclosed root tag')
13372    if ((parser.state !== S.BEGIN) &&
13373      (parser.state !== S.BEGIN_WHITESPACE) &&
13374      (parser.state !== S.TEXT)) {
13375      error(parser, 'Unexpected end')
13376    }
13377    closeText(parser)
13378    parser.c = ''
13379    parser.closed = true
13380    emit(parser, 'onend')
13381    SAXParser.call(parser, parser.strict, parser.opt)
13382    return parser
13383  }
13384
13385  function strictFail (parser, message) {
13386    if (typeof parser !== 'object' || !(parser instanceof SAXParser)) {
13387      throw new Error('bad call to strictFail')
13388    }
13389    if (parser.strict) {
13390      error(parser, message)
13391    }
13392  }
13393
13394  function newTag (parser) {
13395    if (!parser.strict) parser.tagName = parser.tagName[parser.looseCase]()
13396    var parent = parser.tags[parser.tags.length - 1] || parser
13397    var tag = parser.tag = { name: parser.tagName, attributes: {} }
13398
13399    // will be overridden if tag contails an xmlns="foo" or xmlns:foo="bar"
13400    if (parser.opt.xmlns) {
13401      tag.ns = parent.ns
13402    }
13403    parser.attribList.length = 0
13404    emitNode(parser, 'onopentagstart', tag)
13405  }
13406
13407  function qname (name, attribute) {
13408    var i = name.indexOf(':')
13409    var qualName = i < 0 ? [ '', name ] : name.split(':')
13410    var prefix = qualName[0]
13411    var local = qualName[1]
13412
13413    // <x "xmlns"="http://foo">
13414    if (attribute && name === 'xmlns') {
13415      prefix = 'xmlns'
13416      local = ''
13417    }
13418
13419    return { prefix: prefix, local: local }
13420  }
13421
13422  function attrib (parser) {
13423    if (!parser.strict) {
13424      parser.attribName = parser.attribName[parser.looseCase]()
13425    }
13426
13427    if (parser.attribList.indexOf(parser.attribName) !== -1 ||
13428      parser.tag.attributes.hasOwnProperty(parser.attribName)) {
13429      parser.attribName = parser.attribValue = ''
13430      return
13431    }
13432
13433    if (parser.opt.xmlns) {
13434      var qn = qname(parser.attribName, true)
13435      var prefix = qn.prefix
13436      var local = qn.local
13437
13438      if (prefix === 'xmlns') {
13439        // namespace binding attribute. push the binding into scope
13440        if (local === 'xml' && parser.attribValue !== XML_NAMESPACE) {
13441          strictFail(parser,
13442            'xml: prefix must be bound to ' + XML_NAMESPACE + '\n' +
13443            'Actual: ' + parser.attribValue)
13444        } else if (local === 'xmlns' && parser.attribValue !== XMLNS_NAMESPACE) {
13445          strictFail(parser,
13446            'xmlns: prefix must be bound to ' + XMLNS_NAMESPACE + '\n' +
13447            'Actual: ' + parser.attribValue)
13448        } else {
13449          var tag = parser.tag
13450          var parent = parser.tags[parser.tags.length - 1] || parser
13451          if (tag.ns === parent.ns) {
13452            tag.ns = Object.create(parent.ns)
13453          }
13454          tag.ns[local] = parser.attribValue
13455        }
13456      }
13457
13458      // defer onattribute events until all attributes have been seen
13459      // so any new bindings can take effect. preserve attribute order
13460      // so deferred events can be emitted in document order
13461      parser.attribList.push([parser.attribName, parser.attribValue])
13462    } else {
13463      // in non-xmlns mode, we can emit the event right away
13464      parser.tag.attributes[parser.attribName] = parser.attribValue
13465      emitNode(parser, 'onattribute', {
13466        name: parser.attribName,
13467        value: parser.attribValue
13468      })
13469    }
13470
13471    parser.attribName = parser.attribValue = ''
13472  }
13473
13474  function openTag (parser, selfClosing) {
13475    if (parser.opt.xmlns) {
13476      // emit namespace binding events
13477      var tag = parser.tag
13478
13479      // add namespace info to tag
13480      var qn = qname(parser.tagName)
13481      tag.prefix = qn.prefix
13482      tag.local = qn.local
13483      tag.uri = tag.ns[qn.prefix] || ''
13484
13485      if (tag.prefix && !tag.uri) {
13486        strictFail(parser, 'Unbound namespace prefix: ' +
13487          JSON.stringify(parser.tagName))
13488        tag.uri = qn.prefix
13489      }
13490
13491      var parent = parser.tags[parser.tags.length - 1] || parser
13492      if (tag.ns && parent.ns !== tag.ns) {
13493        Object.keys(tag.ns).forEach(function (p) {
13494          emitNode(parser, 'onopennamespace', {
13495            prefix: p,
13496            uri: tag.ns[p]
13497          })
13498        })
13499      }
13500
13501      // handle deferred onattribute events
13502      // Note: do not apply default ns to attributes:
13503      //   http://www.w3.org/TR/REC-xml-names/#defaulting
13504      for (var i = 0, l = parser.attribList.length; i < l; i++) {
13505        var nv = parser.attribList[i]
13506        var name = nv[0]
13507        var value = nv[1]
13508        var qualName = qname(name, true)
13509        var prefix = qualName.prefix
13510        var local = qualName.local
13511        var uri = prefix === '' ? '' : (tag.ns[prefix] || '')
13512        var a = {
13513          name: name,
13514          value: value,
13515          prefix: prefix,
13516          local: local,
13517          uri: uri
13518        }
13519
13520        // if there's any attributes with an undefined namespace,
13521        // then fail on them now.
13522        if (prefix && prefix !== 'xmlns' && !uri) {
13523          strictFail(parser, 'Unbound namespace prefix: ' +
13524            JSON.stringify(prefix))
13525          a.uri = prefix
13526        }
13527        parser.tag.attributes[name] = a
13528        emitNode(parser, 'onattribute', a)
13529      }
13530      parser.attribList.length = 0
13531    }
13532
13533    parser.tag.isSelfClosing = !!selfClosing
13534
13535    // process the tag
13536    parser.sawRoot = true
13537    parser.tags.push(parser.tag)
13538    emitNode(parser, 'onopentag', parser.tag)
13539    if (!selfClosing) {
13540      // special case for <script> in non-strict mode.
13541      if (!parser.noscript && parser.tagName.toLowerCase() === 'script') {
13542        parser.state = S.SCRIPT
13543      } else {
13544        parser.state = S.TEXT
13545      }
13546      parser.tag = null
13547      parser.tagName = ''
13548    }
13549    parser.attribName = parser.attribValue = ''
13550    parser.attribList.length = 0
13551  }
13552
13553  function closeTag (parser) {
13554    if (!parser.tagName) {
13555      strictFail(parser, 'Weird empty close tag.')
13556      parser.textNode += '</>'
13557      parser.state = S.TEXT
13558      return
13559    }
13560
13561    if (parser.script) {
13562      if (parser.tagName !== 'script') {
13563        parser.script += '</' + parser.tagName + '>'
13564        parser.tagName = ''
13565        parser.state = S.SCRIPT
13566        return
13567      }
13568      emitNode(parser, 'onscript', parser.script)
13569      parser.script = ''
13570    }
13571
13572    // first make sure that the closing tag actually exists.
13573    // <a><b></c></b></a> will close everything, otherwise.
13574    var t = parser.tags.length
13575    var tagName = parser.tagName
13576    if (!parser.strict) {
13577      tagName = tagName[parser.looseCase]()
13578    }
13579    var closeTo = tagName
13580    while (t--) {
13581      var close = parser.tags[t]
13582      if (close.name !== closeTo) {
13583        // fail the first time in strict mode
13584        strictFail(parser, 'Unexpected close tag')
13585      } else {
13586        break
13587      }
13588    }
13589
13590    // didn't find it.  we already failed for strict, so just abort.
13591    if (t < 0) {
13592      strictFail(parser, 'Unmatched closing tag: ' + parser.tagName)
13593      parser.textNode += '</' + parser.tagName + '>'
13594      parser.state = S.TEXT
13595      return
13596    }
13597    parser.tagName = tagName
13598    var s = parser.tags.length
13599    while (s-- > t) {
13600      var tag = parser.tag = parser.tags.pop()
13601      parser.tagName = parser.tag.name
13602      emitNode(parser, 'onclosetag', parser.tagName)
13603
13604      var x = {}
13605      for (var i in tag.ns) {
13606        x[i] = tag.ns[i]
13607      }
13608
13609      var parent = parser.tags[parser.tags.length - 1] || parser
13610      if (parser.opt.xmlns && tag.ns !== parent.ns) {
13611        // remove namespace bindings introduced by tag
13612        Object.keys(tag.ns).forEach(function (p) {
13613          var n = tag.ns[p]
13614          emitNode(parser, 'onclosenamespace', { prefix: p, uri: n })
13615        })
13616      }
13617    }
13618    if (t === 0) parser.closedRoot = true
13619    parser.tagName = parser.attribValue = parser.attribName = ''
13620    parser.attribList.length = 0
13621    parser.state = S.TEXT
13622  }
13623
13624  function parseEntity (parser) {
13625    var entity = parser.entity
13626    var entityLC = entity.toLowerCase()
13627    var num
13628    var numStr = ''
13629
13630    if (parser.ENTITIES[entity]) {
13631      return parser.ENTITIES[entity]
13632    }
13633    if (parser.ENTITIES[entityLC]) {
13634      return parser.ENTITIES[entityLC]
13635    }
13636    entity = entityLC
13637    if (entity.charAt(0) === '#') {
13638      if (entity.charAt(1) === 'x') {
13639        entity = entity.slice(2)
13640        num = parseInt(entity, 16)
13641        numStr = num.toString(16)
13642      } else {
13643        entity = entity.slice(1)
13644        num = parseInt(entity, 10)
13645        numStr = num.toString(10)
13646      }
13647    }
13648    entity = entity.replace(/^0+/, '')
13649    if (
vendor: 21,078 bytes, lines 13649-14327
13649numStr.toLowerCase() !== entity) {
13650      strictFail(parser, 'Invalid character entity')
13651      return '&' + parser.entity + ';'
13652    }
13653
13654    return String.fromCodePoint(num)
13655  }
13656
13657  function beginWhiteSpace (parser, c) {
13658    if (c === '<') {
13659      parser.state = S.OPEN_WAKA
13660      parser.startTagPosition = parser.position
13661    } else if (not(whitespace, c)) {
13662      // have to process this as a text node.
13663      // weird, but happens.
13664      strictFail(parser, 'Non-whitespace before first tag.')
13665      parser.textNode = c
13666      parser.state = S.TEXT
13667    }
13668  }
13669
13670  function charAt (chunk, i) {
13671    var result = ''
13672    if (i < chunk.length) {
13673      result = chunk.charAt(i)
13674    }
13675    return result
13676  }
13677
13678  function write (chunk) {
13679    var parser = this
13680    if (this.error) {
13681      throw this.error
13682    }
13683    if (parser.closed) {
13684      return error(parser,
13685        'Cannot write after close. Assign an onready handler.')
13686    }
13687    if (chunk === null) {
13688      return end(parser)
13689    }
13690    if (typeof chunk === 'object') {
13691      chunk = chunk.toString()
13692    }
13693    var i = 0
13694    var c = ''
13695    while (true) {
13696      c = charAt(chunk, i++)
13697      parser.c = c
13698      if (!c) {
13699        break
13700      }
13701      if (parser.trackPosition) {
13702        parser.position++
13703        if (c === '\n') {
13704          parser.line++
13705          parser.column = 0
13706        } else {
13707          parser.column++
13708        }
13709      }
13710      switch (parser.state) {
13711        case S.BEGIN:
13712          parser.state = S.BEGIN_WHITESPACE
13713          if (c === '\uFEFF') {
13714            continue
13715          }
13716          beginWhiteSpace(parser, c)
13717          continue
13718
13719        case S.BEGIN_WHITESPACE:
13720          beginWhiteSpace(parser, c)
13721          continue
13722
13723        case S.TEXT:
13724          if (parser.sawRoot && !parser.closedRoot) {
13725            var starti = i - 1
13726            while (c && c !== '<' && c !== '&') {
13727              c = charAt(chunk, i++)
13728              if (c && parser.trackPosition) {
13729                parser.position++
13730                if (c === '\n') {
13731                  parser.line++
13732                  parser.column = 0
13733                } else {
13734                  parser.column++
13735                }
13736              }
13737            }
13738            parser.textNode += chunk.substring(starti, i - 1)
13739          }
13740          if (c === '<' && !(parser.sawRoot && parser.closedRoot && !parser.strict)) {
13741            parser.state = S.OPEN_WAKA
13742            parser.startTagPosition = parser.position
13743          } else {
13744            if (not(whitespace, c) && (!parser.sawRoot || parser.closedRoot)) {
13745              strictFail(parser, 'Text data outside of root node.')
13746            }
13747            if (c === '&') {
13748              parser.state = S.TEXT_ENTITY
13749            } else {
13750              parser.textNode += c
13751            }
13752          }
13753          continue
13754
13755        case S.SCRIPT:
13756          // only non-strict
13757          if (c === '<') {
13758            parser.state = S.SCRIPT_ENDING
13759          } else {
13760            parser.script += c
13761          }
13762          continue
13763
13764        case S.SCRIPT_ENDING:
13765          if (c === '/') {
13766            parser.state = S.CLOSE_TAG
13767          } else {
13768            parser.script += '<' + c
13769            parser.state = S.SCRIPT
13770          }
13771          continue
13772
13773        case S.OPEN_WAKA:
13774          // either a /, ?, !, or text is coming next.
13775          if (c === '!') {
13776            parser.state = S.SGML_DECL
13777            parser.sgmlDecl = ''
13778          } else if (is(whitespace, c)) {
13779            // wait for it...
13780          } else if (is(nameStart, c)) {
13781            parser.state = S.OPEN_TAG
13782            parser.tagName = c
13783          } else if (c === '/') {
13784            parser.state = S.CLOSE_TAG
13785            parser.tagName = ''
13786          } else if (c === '?') {
13787            parser.state = S.PROC_INST
13788            parser.procInstName = parser.procInstBody = ''
13789          } else {
13790            strictFail(parser, 'Unencoded <')
13791            // if there was some whitespace, then add that in.
13792            if (parser.startTagPosition + 1 < parser.position) {
13793              var pad = parser.position - parser.startTagPosition
13794              c = new Array(pad).join(' ') + c
13795            }
13796            parser.textNode += '<' + c
13797            parser.state = S.TEXT
13798          }
13799          continue
13800
13801        case S.SGML_DECL:
13802          if ((parser.sgmlDecl + c).toUpperCase() === CDATA) {
13803            emitNode(parser, 'onopencdata')
13804            parser.state = S.CDATA
13805            parser.sgmlDecl = ''
13806            parser.cdata = ''
13807          } else if (parser.sgmlDecl + c === '--') {
13808            parser.state = S.COMMENT
13809            parser.comment = ''
13810            parser.sgmlDecl = ''
13811          } else if ((parser.sgmlDecl + c).toUpperCase() === DOCTYPE) {
13812            parser.state = S.DOCTYPE
13813            if (parser.doctype || parser.sawRoot) {
13814              strictFail(parser,
13815                'Inappropriately located doctype declaration')
13816            }
13817            parser.doctype = ''
13818            parser.sgmlDecl = ''
13819          } else if (c === '>') {
13820            emitNode(parser, 'onsgmldeclaration', parser.sgmlDecl)
13821            parser.sgmlDecl = ''
13822            parser.state = S.TEXT
13823          } else if (is(quote, c)) {
13824            parser.state = S.SGML_DECL_QUOTED
13825            parser.sgmlDecl += c
13826          } else {
13827            parser.sgmlDecl += c
13828          }
13829          continue
13830
13831        case S.SGML_DECL_QUOTED:
13832          if (c === parser.q) {
13833            parser.state = S.SGML_DECL
13834            parser.q = ''
13835          }
13836          parser.sgmlDecl += c
13837          continue
13838
13839        case S.DOCTYPE:
13840          if (c === '>') {
13841            parser.state = S.TEXT
13842            emitNode(parser, 'ondoctype', parser.doctype)
13843            parser.doctype = true // just remember that we saw it.
13844          } else {
13845            parser.doctype += c
13846            if (c === '[') {
13847              parser.state = S.DOCTYPE_DTD
13848            } else if (is(quote, c)) {
13849              parser.state = S.DOCTYPE_QUOTED
13850              parser.q = c
13851            }
13852          }
13853          continue
13854
13855        case S.DOCTYPE_QUOTED:
13856          parser.doctype += c
13857          if (c === parser.q) {
13858            parser.q = ''
13859            parser.state = S.DOCTYPE
13860          }
13861          continue
13862
13863        case S.DOCTYPE_DTD:
13864          parser.doctype += c
13865          if (c === ']') {
13866            parser.state = S.DOCTYPE
13867          } else if (is(quote, c)) {
13868            parser.state = S.DOCTYPE_DTD_QUOTED
13869            parser.q = c
13870          }
13871          continue
13872
13873        case S.DOCTYPE_DTD_QUOTED:
13874          parser.doctype += c
13875          if (c === parser.q) {
13876            parser.state = S.DOCTYPE_DTD
13877            parser.q = ''
13878          }
13879          continue
13880
13881        case S.COMMENT:
13882          if (c === '-') {
13883            parser.state = S.COMMENT_ENDING
13884          } else {
13885            parser.comment += c
13886          }
13887          continue
13888
13889        case S.COMMENT_ENDING:
13890          if (c === '-') {
13891            parser.state = S.COMMENT_ENDED
13892            parser.comment = textopts(parser.opt, parser.comment)
13893            if (parser.comment) {
13894              emitNode(parser, 'oncomment', parser.comment)
13895            }
13896            parser.comment = ''
13897          } else {
13898            parser.comment += '-' + c
13899            parser.state = S.COMMENT
13900          }
13901          continue
13902
13903        case S.COMMENT_ENDED:
13904          if (c !== '>') {
13905            strictFail(parser, 'Malformed comment')
13906            // allow <!-- blah -- bloo --> in non-strict mode,
13907            // which is a comment of " blah -- bloo "
13908            parser.comment += '--' + c
13909            parser.state = S.COMMENT
13910          } else {
13911            parser.state = S.TEXT
13912          }
13913          continue
13914
13915        case S.CDATA:
13916          if (c === ']') {
13917            parser.state = S.CDATA_ENDING
13918          } else {
13919            parser.cdata += c
13920          }
13921          continue
13922
13923        case S.CDATA_ENDING:
13924          if (c === ']') {
13925            parser.state = S.CDATA_ENDING_2
13926          } else {
13927            parser.cdata += ']' + c
13928            parser.state = S.CDATA
13929          }
13930          continue
13931
13932        case S.CDATA_ENDING_2:
13933          if (c === '>') {
13934            if (parser.cdata) {
13935              emitNode(parser, 'oncdata', parser.cdata)
13936            }
13937            emitNode(parser, 'onclosecdata')
13938            parser.cdata = ''
13939            parser.state = S.TEXT
13940          } else if (c === ']') {
13941            parser.cdata += ']'
13942          } else {
13943            parser.cdata += ']]' + c
13944            parser.state = S.CDATA
13945          }
13946          continue
13947
13948        case S.PROC_INST:
13949          if (c === '?') {
13950            parser.state = S.PROC_INST_ENDING
13951          } else if (is(whitespace, c)) {
13952            parser.state = S.PROC_INST_BODY
13953          } else {
13954            parser.procInstName += c
13955          }
13956          continue
13957
13958        case S.PROC_INST_BODY:
13959          if (!parser.procInstBody && is(whitespace, c)) {
13960            continue
13961          } else if (c === '?') {
13962            parser.state = S.PROC_INST_ENDING
13963          } else {
13964            parser.procInstBody += c
13965          }
13966          continue
13967
13968        case S.PROC_INST_ENDING:
13969          if (c === '>') {
13970            emitNode(parser, 'onprocessinginstruction', {
13971              name: parser.procInstName,
13972              body: parser.procInstBody
13973            })
13974            parser.procInstName = parser.procInstBody = ''
13975            parser.state = S.TEXT
13976          } else {
13977            parser.procInstBody += '?' + c
13978            parser.state = S.PROC_INST_BODY
13979          }
13980          continue
13981
13982        case S.OPEN_TAG:
13983          if (is(nameBody, c)) {
13984            parser.tagName += c
13985          } else {
13986            newTag(parser)
13987            if (c === '>') {
13988              openTag(parser)
13989            } else if (c === '/') {
13990              parser.state = S.OPEN_TAG_SLASH
13991            } else {
13992              if (not(whitespace, c)) {
13993                strictFail(parser, 'Invalid character in tag name')
13994              }
13995              parser.state = S.ATTRIB
13996            }
13997          }
13998          continue
13999
14000        case S.OPEN_TAG_SLASH:
14001          if (c === '>') {
14002            openTag(parser, true)
14003            closeTag(parser)
14004          } else {
14005            strictFail(parser, 'Forward-slash in opening tag not followed by >')
14006            parser.state = S.ATTRIB
14007          }
14008          continue
14009
14010        case S.ATTRIB:
14011          // haven't read the attribute name yet.
14012          if (is(whitespace, c)) {
14013            continue
14014          } else if (c === '>') {
14015            openTag(parser)
14016          } else if (c === '/') {
14017            parser.state = S.OPEN_TAG_SLASH
14018          } else if (is(nameStart, c)) {
14019            parser.attribName = c
14020            parser.attribValue = ''
14021            parser.state = S.ATTRIB_NAME
14022          } else {
14023            strictFail(parser, 'Invalid attribute name')
14024          }
14025          continue
14026
14027        case S.ATTRIB_NAME:
14028          if (c === '=') {
14029            parser.state = S.ATTRIB_VALUE
14030          } else if (c === '>') {
14031            strictFail(parser, 'Attribute without value')
14032            parser.attribValue = parser.attribName
14033            attrib(parser)
14034            openTag(parser)
14035          } else if (is(whitespace, c)) {
14036            parser.state = S.ATTRIB_NAME_SAW_WHITE
14037          } else if (is(nameBody, c)) {
14038            parser.attribName += c
14039          } else {
14040            strictFail(parser, 'Invalid attribute name')
14041          }
14042          continue
14043
14044        case S.ATTRIB_NAME_SAW_WHITE:
14045          if (c === '=') {
14046            parser.state = S.ATTRIB_VALUE
14047          } else if (is(whitespace, c)) {
14048            continue
14049          } else {
14050            strictFail(parser, 'Attribute without value')
14051            parser.tag.attributes[parser.attribName] = ''
14052            parser.attribValue = ''
14053            emitNode(parser, 'onattribute', {
14054              name: parser.attribName,
14055              value: ''
14056            })
14057            parser.attribName = ''
14058            if (c === '>') {
14059              openTag(parser)
14060            } else if (is(nameStart, c)) {
14061              parser.attribName = c
14062              parser.state = S.ATTRIB_NAME
14063            } else {
14064              strictFail(parser, 'Invalid attribute name')
14065              parser.state = S.ATTRIB
14066            }
14067          }
14068          continue
14069
14070        case S.ATTRIB_VALUE:
14071          if (is(whitespace, c)) {
14072            continue
14073          } else if (is(quote, c)) {
14074            parser.q = c
14075            parser.state = S.ATTRIB_VALUE_QUOTED
14076          } else {
14077            strictFail(parser, 'Unquoted attribute value')
14078            parser.state = S.ATTRIB_VALUE_UNQUOTED
14079            parser.attribValue = c
14080          }
14081          continue
14082
14083        case S.ATTRIB_VALUE_QUOTED:
14084          if (c !== parser.q) {
14085            if (c === '&') {
14086              parser.state = S.ATTRIB_VALUE_ENTITY_Q
14087            } else {
14088              parser.attribValue += c
14089            }
14090            continue
14091          }
14092          attrib(parser)
14093          parser.q = ''
14094          parser.state = S.ATTRIB_VALUE_CLOSED
14095          continue
14096
14097        case S.ATTRIB_VALUE_CLOSED:
14098          if (is(whitespace, c)) {
14099            parser.state = S.ATTRIB
14100          } else if (c === '>') {
14101            openTag(parser)
14102          } else if (c === '/') {
14103            parser.state = S.OPEN_TAG_SLASH
14104          } else if (is(nameStart, c)) {
14105            strictFail(parser, 'No whitespace between attributes')
14106            parser.attribName = c
14107            parser.attribValue = ''
14108            parser.state = S.ATTRIB_NAME
14109          } else {
14110            strictFail(parser, 'Invalid attribute name')
14111          }
14112          continue
14113
14114        case S.ATTRIB_VALUE_UNQUOTED:
14115          if (not(attribEnd, c)) {
14116            if (c === '&') {
14117              parser.state = S.ATTRIB_VALUE_ENTITY_U
14118            } else {
14119              parser.attribValue += c
14120            }
14121            continue
14122          }
14123          attrib(parser)
14124          if (c === '>') {
14125            openTag(parser)
14126          } else {
14127            parser.state = S.ATTRIB
14128          }
14129          continue
14130
14131        case S.CLOSE_TAG:
14132          if (!parser.tagName) {
14133            if (is(whitespace, c)) {
14134              continue
14135            } else if (not(nameStart, c)) {
14136              if (parser.script) {
14137                parser.script += '</' + c
14138                parser.state = S.SCRIPT
14139              } else {
14140                strictFail(parser, 'Invalid tagname in closing tag.')
14141              }
14142            } else {
14143              parser.tagName = c
14144            }
14145          } else if (c === '>') {
14146            closeTag(parser)
14147          } else if (is(nameBody, c)) {
14148            parser.tagName += c
14149          } else if (parser.script) {
14150            parser.script += '</' + parser.tagName
14151            parser.tagName = ''
14152            parser.state = S.SCRIPT
14153          } else {
14154            if (not(whitespace, c)) {
14155              strictFail(parser, 'Invalid tagname in closing tag')
14156            }
14157            parser.state = S.CLOSE_TAG_SAW_WHITE
14158          }
14159          continue
14160
14161        case S.CLOSE_TAG_SAW_WHITE:
14162          if (is(whitespace, c)) {
14163            continue
14164          }
14165          if (c === '>') {
14166            closeTag(parser)
14167          } else {
14168            strictFail(parser, 'Invalid characters in closing tag')
14169          }
14170          continue
14171
14172        case S.TEXT_ENTITY:
14173        case S.ATTRIB_VALUE_ENTITY_Q:
14174        case S.ATTRIB_VALUE_ENTITY_U:
14175          var returnState
14176          var buffer
14177          switch (parser.state) {
14178            case S.TEXT_ENTITY:
14179              returnState = S.TEXT
14180              buffer = 'textNode'
14181              break
14182
14183            case S.ATTRIB_VALUE_ENTITY_Q:
14184              returnState = S.ATTRIB_VALUE_QUOTED
14185              buffer = 'attribValue'
14186              break
14187
14188            case S.ATTRIB_VALUE_ENTITY_U:
14189              returnState = S.ATTRIB_VALUE_UNQUOTED
14190              buffer = 'attribValue'
14191              break
14192          }
14193
14194          if (c === ';') {
14195            parser[buffer] += parseEntity(parser)
14196            parser.entity = ''
14197            parser.state = returnState
14198          } else if (is(parser.entity.length ? entityBody : entityStart, c)) {
14199            parser.entity += c
14200          } else {
14201            strictFail(parser, 'Invalid character in entity name')
14202            parser[buffer] += '&' + parser.entity + c
14203            parser.entity = ''
14204            parser.state = returnState
14205          }
14206
14207          continue
14208
14209        default:
14210          throw new Error(parser, 'Unknown state: ' + parser.state)
14211      }
14212    } // while
14213
14214    if (parser.position >= parser.bufferCheckPosition) {
14215      checkBufferLength(parser)
14216    }
14217    return parser
14218  }
14219
14220  /*! http://mths.be/fromcodepoint v0.1.0 by @mathias */
14221  if (!String.fromCodePoint) {
14222    (function () {
14223      var stringFromCharCode = String.fromCharCode
14224      var floor = Math.floor
14225      var fromCodePoint = function () {
14226        var MAX_SIZE = 0x4000
14227        var codeUnits = []
14228        var highSurrogate
14229        var lowSurrogate
14230        var index = -1
14231        var length = arguments.length
14232        if (!length) {
14233          return ''
14234        }
14235        var result = ''
14236        while (++index < length) {
14237          var codePoint = Number(arguments[index])
14238          if (
14239            !isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity`
14240            codePoint < 0 || // not a valid Unicode code point
14241            codePoint > 0x10FFFF || // not a valid Unicode code point
14242            floor(codePoint) !== codePoint // not an integer
14243          ) {
14244            throw RangeError('Invalid code point: ' + codePoint)
14245          }
14246          if (codePoint <= 0xFFFF) { // BMP code point
14247            codeUnits.push(codePoint)
14248          } else { // Astral code point; split in surrogate halves
14249            // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
14250            codePoint -= 0x10000
14251            highSurrogate = (codePoint >> 10) + 0xD800
14252            lowSurrogate = (codePoint % 0x400) + 0xDC00
14253            codeUnits.push(highSurrogate, lowSurrogate)
14254          }
14255          if (index + 1 === length || codeUnits.length > MAX_SIZE) {
14256            result += stringFromCharCode.apply(null, codeUnits)
14257            codeUnits.length = 0
14258          }
14259        }
14260        return result
14261      }
14262      if (Object.defineProperty) {
14263        Object.defineProperty(String, 'fromCodePoint', {
14264          value: fromCodePoint,
14265          configurable: true,
14266          writable: true
14267        })
14268      } else {
14269        String.fromCodePoint = fromCodePoint
14270      }
14271    }())
14272  }
14273})(typeof exports === 'undefined' ? this.sax = {} : exports)
14274
14275}).call(this,_dereq_(10).Buffer)
14276
14277},{"10":10,"46":46,"9":9}],46:[function(_dereq_,module,exports){
14278// Copyright Joyent, Inc. and other Node contributors.
14279//
14280// Permission is hereby granted, free of charge, to any person obtaining a
14281// copy of this software and associated documentation files (the
14282// "Software"), to deal in the Software without restriction, including
14283// without limitation the rights to use, copy, modify, merge, publish,
14284// distribute, sublicense, and/or sell copies of the Software, and to permit
14285// persons to whom the Software is furnished to do so, subject to the
14286// following conditions:
14287//
14288// The above copyright notice and this permission notice shall be included
14289// in all copies or substantial portions of the Software.
14290//
14291// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14292// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14293// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
14294// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
14295// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
14296// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
14297// USE OR OTHER DEALINGS IN THE SOFTWARE.
14298
14299module.exports = Stream;
14300
14301var EE = _dereq_(16).EventEmitter;
14302var inherits = _dereq_(25);
14303
14304inherits(Stream, EE);
14305Stream.Readable = _dereq_(40);
14306Stream.Writable = _dereq_(42);
14307Stream.Duplex = _dereq_(30);
14308Stream.Transform = _dereq_(41);
14309Stream.PassThrough = _dereq_(39);
14310
14311// Backwards-compat with node 0.4.x
14312Stream.Stream = Stream;
14313
14314
14315
14316// old-style streams.  Note that the pipe method (the only relevant
14317// part of this class) is overridden in the Readable class.
14318
14319function Stream() {
14320  EE.call(this);
14321}
14322
14323Stream.prototype.pipe = function(dest, options) {
14324  var source = this;
14325
14326  function ondata(chunk) {
14327    if (dest.writable) {
vendor: 2,971 bytes, lines 14328-14449
14328      if (false === dest.write(chunk) && source.pause) {
14329        source.pause();
14330      }
14331    }
14332  }
14333
14334  source.on('data', ondata);
14335
14336  function ondrain() {
14337    if (source.readable && source.resume) {
14338      source.resume();
14339    }
14340  }
14341
14342  dest.on('drain', ondrain);
14343
14344  // If the 'end' option is not supplied, dest.end() will be called when
14345  // source gets the 'end' or 'close' events.  Only dest.end() once.
14346  if (!dest._isStdio && (!options || options.end !== false)) {
14347    source.on('end', onend);
14348    source.on('close', onclose);
14349  }
14350
14351  var didOnEnd = false;
14352  function onend() {
14353    if (didOnEnd) return;
14354    didOnEnd = true;
14355
14356    dest.end();
14357  }
14358
14359
14360  function onclose() {
14361    if (didOnEnd) return;
14362    didOnEnd = true;
14363
14364    if (typeof dest.destroy === 'function') dest.destroy();
14365  }
14366
14367  // don't leave dangling pipes when there are errors.
14368  function onerror(er) {
14369    cleanup();
14370    if (EE.listenerCount(this, 'error') === 0) {
14371      throw er; // Unhandled stream error in pipe.
14372    }
14373  }
14374
14375  source.on('error', onerror);
14376  dest.on('error', onerror);
14377
14378  // remove all the event listeners that were added.
14379  function cleanup() {
14380    source.removeListener('data', ondata);
14381    dest.removeListener('drain', ondrain);
14382
14383    source.removeListener('end', onend);
14384    source.removeListener('close', onclose);
14385
14386    source.removeListener('error', onerror);
14387    dest.removeListener('error', onerror);
14388
14389    source.removeListener('end', cleanup);
14390    source.removeListener('close', cleanup);
14391
14392    dest.removeListener('close', cleanup);
14393  }
14394
14395  source.on('end', cleanup);
14396  source.on('close', cleanup);
14397
14398  dest.on('close', cleanup);
14399
14400  dest.emit('pipe', source);
14401
14402  // Allow for unix-like usage: A.pipe(B).pipe(C)
14403  return dest;
14404};
14405
14406},{"16":16,"25":25,"30":30,"39":39,"40":40,"41":41,"42":42}],47:[function(_dereq_,module,exports){
14407'use strict';
14408
14409var Buffer = _dereq_(44).Buffer;
14410
14411var isEncoding = Buffer.isEncoding || function (encoding) {
14412  encoding = '' + encoding;
14413  switch (encoding && encoding.toLowerCase()) {
14414    case 'hex':case 'utf8':case 'utf-8':case 'ascii':case 'binary':case 'base64':case 'ucs2':case 'ucs-2':case 'utf16le':case 'utf-16le':case 'raw':
14415      return true;
14416    default:
14417      return false;
14418  }
14419};
14420
14421function _normalizeEncoding(enc) {
14422  if (!enc) return 'utf8';
14423  var retried;
14424  while (true) {
14425    switch (enc) {
14426      case 'utf8':
14427      case 'utf-8':
14428        return 'utf8';
14429      case 'ucs2':
14430      case 'ucs-2':
14431      case 'utf16le':
14432      case 'utf-16le':
14433        return 'utf16le';
14434      case 'latin1':
14435      case 'binary':
14436        return 'latin1';
14437      case 'base64':
14438      case 'ascii':
14439      case 'hex':
14440        return enc;
14441      default:
14442        if (retried) return; // undefined
14443        enc = ('' + enc).toLowerCase();
14444        retried = true;
14445    }
14446  }
14447};
14448
14449// Do not cache `Buffer.isEncoding` when checking encoding names as some
vendor: 8,934 bytes, lines 14450-14737
14450// modules monkey-patch it to support additional encodings
14451function normalizeEncoding(enc) {
14452  var nenc = _normalizeEncoding(enc);
14453  if (typeof nenc !== 'string' && (Buffer.isEncoding === isEncoding || !isEncoding(enc))) throw new Error('Unknown encoding: ' + enc);
14454  return nenc || enc;
14455}
14456
14457// StringDecoder provides an interface for efficiently splitting a series of
14458// buffers into a series of JS strings without breaking apart multi-byte
14459// characters.
14460exports.StringDecoder = StringDecoder;
14461function StringDecoder(encoding) {
14462  this.encoding = normalizeEncoding(encoding);
14463  var nb;
14464  switch (this.encoding) {
14465    case 'utf16le':
14466      this.text = utf16Text;
14467      this.end = utf16End;
14468      nb = 4;
14469      break;
14470    case 'utf8':
14471      this.fillLast = utf8FillLast;
14472      nb = 4;
14473      break;
14474    case 'base64':
14475      this.text = base64Text;
14476      this.end = base64End;
14477      nb = 3;
14478      break;
14479    default:
14480      this.write = simpleWrite;
14481      this.end = simpleEnd;
14482      return;
14483  }
14484  this.lastNeed = 0;
14485  this.lastTotal = 0;
14486  this.lastChar = Buffer.allocUnsafe(nb);
14487}
14488
14489StringDecoder.prototype.write = function (buf) {
14490  if (buf.length === 0) return '';
14491  var r;
14492  var i;
14493  if (this.lastNeed) {
14494    r = this.fillLast(buf);
14495    if (r === undefined) return '';
14496    i = this.lastNeed;
14497    this.lastNeed = 0;
14498  } else {
14499    i = 0;
14500  }
14501  if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i);
14502  return r || '';
14503};
14504
14505StringDecoder.prototype.end = utf8End;
14506
14507// Returns only complete characters in a Buffer
14508StringDecoder.prototype.text = utf8Text;
14509
14510// Attempts to complete a partial non-UTF-8 character using bytes from a Buffer
14511StringDecoder.prototype.fillLast = function (buf) {
14512  if (this.lastNeed <= buf.length) {
14513    buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed);
14514    return this.lastChar.toString(this.encoding, 0, this.lastTotal);
14515  }
14516  buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length);
14517  this.lastNeed -= buf.length;
14518};
14519
14520// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a
14521// continuation byte.
14522function utf8CheckByte(byte) {
14523  if (byte <= 0x7F) return 0;else if (byte >> 5 === 0x06) return 2;else if (byte >> 4 === 0x0E) return 3;else if (byte >> 3 === 0x1E) return 4;
14524  return -1;
14525}
14526
14527// Checks at most 3 bytes at the end of a Buffer in order to detect an
14528// incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4)
14529// needed to complete the UTF-8 character (if applicable) are returned.
14530function utf8CheckIncomplete(self, buf, i) {
14531  var j = buf.length - 1;
14532  if (j < i) return 0;
14533  var nb = utf8CheckByte(buf[j]);
14534  if (nb >= 0) {
14535    if (nb > 0) self.lastNeed = nb - 1;
14536    return nb;
14537  }
14538  if (--j < i) return 0;
14539  nb = utf8CheckByte(buf[j]);
14540  if (nb >= 0) {
14541    if (nb > 0) self.lastNeed = nb - 2;
14542    return nb;
14543  }
14544  if (--j < i) return 0;
14545  nb = utf8CheckByte(buf[j]);
14546  if (nb >= 0) {
14547    if (nb > 0) {
14548      if (nb === 2) nb = 0;else self.lastNeed = nb - 3;
14549    }
14550    return nb;
14551  }
14552  return 0;
14553}
14554
14555// Validates as many continuation bytes for a multi-byte UTF-8 character as
14556// needed or are available. If we see a non-continuation byte where we expect
14557// one, we "replace" the validated continuation bytes we've seen so far with
14558// UTF-8 replacement characters ('\ufffd'), to match v8's UTF-8 decoding
14559// behavior. The continuation byte check is included three times in the case
14560// where all of the continuation bytes for a character exist in the same buffer.
14561// It is also done this way as a slight performance increase instead of using a
14562// loop.
14563function utf8CheckExtraBytes(self, buf, p) {
14564  if ((buf[0] & 0xC0) !== 0x80) {
14565    self.lastNeed = 0;
14566    return '\ufffd'.repeat(p);
14567  }
14568  if (self.lastNeed > 1 && buf.length > 1) {
14569    if ((buf[1] & 0xC0) !== 0x80) {
14570      self.lastNeed = 1;
14571      return '\ufffd'.repeat(p + 1);
14572    }
14573    if (self.lastNeed > 2 && buf.length > 2) {
14574      if ((buf[2] & 0xC0) !== 0x80) {
14575        self.lastNeed = 2;
14576        return '\ufffd'.repeat(p + 2);
14577      }
14578    }
14579  }
14580}
14581
14582// Attempts to complete a multi-byte UTF-8 character using bytes from a Buffer.
14583function utf8FillLast(buf) {
14584  var p = this.lastTotal - this.lastNeed;
14585  var r = utf8CheckExtraBytes(this, buf, p);
14586  if (r !== undefined) return r;
14587  if (this.lastNeed <= buf.length) {
14588    buf.copy(this.lastChar, p, 0, this.lastNeed);
14589    return this.lastChar.toString(this.encoding, 0, this.lastTotal);
14590  }
14591  buf.copy(this.lastChar, p, 0, buf.length);
14592  this.lastNeed -= buf.length;
14593}
14594
14595// Returns all complete UTF-8 characters in a Buffer. If the Buffer ended on a
14596// partial character, the character's bytes are buffered until the required
14597// number of bytes are available.
14598function utf8Text(buf, i) {
14599  var total = utf8CheckIncomplete(this, buf, i);
14600  if (!this.lastNeed) return buf.toString('utf8', i);
14601  this.lastTotal = total;
14602  var end = buf.length - (total - this.lastNeed);
14603  buf.copy(this.lastChar, 0, end);
14604  return buf.toString('utf8', i, end);
14605}
14606
14607// For UTF-8, a replacement character for each buffered byte of a (partial)
14608// character needs to be added to the output.
14609function utf8End(buf) {
14610  var r = buf && buf.length ? this.write(buf) : '';
14611  if (this.lastNeed) return r + '\ufffd'.repeat(this.lastTotal - this.lastNeed);
14612  return r;
14613}
14614
14615// UTF-16LE typically needs two bytes per character, but even if we have an even
14616// number of bytes available, we need to check if we end on a leading/high
14617// surrogate. In that case, we need to wait for the next two bytes in order to
14618// decode the last character properly.
14619function utf16Text(buf, i) {
14620  if ((buf.length - i) % 2 === 0) {
14621    var r = buf.toString('utf16le', i);
14622    if (r) {
14623      var c = r.charCodeAt(r.length - 1);
14624      if (c >= 0xD800 && c <= 0xDBFF) {
14625        this.lastNeed = 2;
14626        this.lastTotal = 4;
14627        this.lastChar[0] = buf[buf.length - 2];
14628        this.lastChar[1] = buf[buf.length - 1];
14629        return r.slice(0, -1);
14630      }
14631    }
14632    return r;
14633  }
14634  this.lastNeed = 1;
14635  this.lastTotal = 2;
14636  this.lastChar[0] = buf[buf.length - 1];
14637  return buf.toString('utf16le', i, buf.length - 1);
14638}
14639
14640// For UTF-16LE we do not explicitly append special replacement characters if we
14641// end on a partial character, we simply let v8 handle that.
14642function utf16End(buf) {
14643  var r = buf && buf.length ? this.write(buf) : '';
14644  if (this.lastNeed) {
14645    var end = this.lastTotal - this.lastNeed;
14646    return r + this.lastChar.toString('utf16le', 0, end);
14647  }
14648  return r;
14649}
14650
14651function base64Text(buf, i) {
14652  var n = (buf.length - i) % 3;
14653  if (n === 0) return buf.toString('base64', i);
14654  this.lastNeed = 3 - n;
14655  this.lastTotal = 3;
14656  if (n === 1) {
14657    this.lastChar[0] = buf[buf.length - 1];
14658  } else {
14659    this.lastChar[0] = buf[buf.length - 2];
14660    this.lastChar[1] = buf[buf.length - 1];
14661  }
14662  return buf.toString('base64', i, buf.length - n);
14663}
14664
14665function base64End(buf) {
14666  var r = buf && buf.length ? this.write(buf) : '';
14667  if (this.lastNeed) return r + this.lastChar.toString('base64', 0, 3 - this.lastNeed);
14668  return r;
14669}
14670
14671// Pass bytes on through for single-byte encodings (e.g. ascii, latin1, hex)
14672function simpleWrite(buf) {
14673  return buf.toString(this.encoding);
14674}
14675
14676function simpleEnd(buf) {
14677  return buf && buf.length ? this.write(buf) : '';
14678}
14679},{"44":44}],48:[function(_dereq_,module,exports){
14680(function (global){
14681
14682/**
14683 * Module exports.
14684 */
14685
14686module.exports = deprecate;
14687
14688/**
14689 * Mark that a method should not be used.
14690 * Returns a modified function which warns once by default.
14691 *
14692 * If `localStorage.noDeprecation = true` is set, then it is a no-op.
14693 *
14694 * If `localStorage.throwDeprecation = true` is set, then deprecated functions
14695 * will throw an Error when invoked.
14696 *
14697 * If `localStorage.traceDeprecation = true` is set, then deprecated functions
14698 * will invoke `console.trace()` instead of `console.error()`.
14699 *
14700 * @param {Function} fn - the function to deprecate
14701 * @param {String} msg - the string to print to the console when `fn` is invoked
14702 * @returns {Function} a new "deprecated" version of `fn`
14703 * @api public
14704 */
14705
14706function deprecate (fn, msg) {
14707  if (config('noDeprecation')) {
14708    return fn;
14709  }
14710
14711  var warned = false;
14712  function deprecated() {
14713    if (!warned) {
14714      if (config('throwDeprecation')) {
14715        throw new Error(msg);
14716      } else if (config('traceDeprecation')) {
14717        console.trace(msg);
14718      } else {
14719        console.warn(msg);
14720      }
14721      warned = true;
14722    }
14723    return fn.apply(this, arguments);
14724  }
14725
14726  return deprecated;
14727}
14728
14729/**
14730 * Checks `localStorage` for boolean values for the given `name`.
14731 *
14732 * @param {String} name
14733 * @returns {Boolean}
14734 * @api private
14735 */
14736
14737function config (name) {
14738  // accessing global.localStorage can trigger a DOMException in sandboxed iframes
14739  try {
14740    if (!global.localStorage) return false;
14741  } catch (_) {
14742    return false;
14743  }
14744  var val = global.localStorage[name];
14745  if (null == val) return false;
14746  return String(val).toLowerCase() === 'true';
14747}
14748
14749}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
14750
14751},{}],49:[function(_dereq_,module,exports){
14752/**
14753 * The copyright in this software is being made available under the BSD License,
14754 * included below. This software may be subject to other third party and contributor
14755 * rights, including patent rights, and no such rights are granted under this license.
14756 *
14757 * Copyright (c) 2013, Dash Industry Forum.
14758 * All rights reserved.
14759 *
14760 * Redistribution and use in source and binary forms, with or without modification,
14761 * are permitted provided that the following conditions are met:
14762 *  * Redistributions of source code must retain the above copyright notice, this
14763 *  list of conditions and the following disclaimer.
14764 *  * Redistributions in binary form must reproduce the above copyright notice,
14765 *  this list of conditions and the following disclaimer in the documentation and/or
14766 *  other materials provided with the distribution.
14767 *  * Neither the name of Dash Industry Forum nor the names of its
14768 *  contributors may be used to endorse or promote products derived from this software
14769 *  without specific prior written permission.
14770 *
14771 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
14772 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14773 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
14774 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
14775 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
14776 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
14777 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
14778 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
14779 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
14780 *  POSSIBILITY OF SUCH DAMAGE.
14781 */
14782'use strict';
14783
14784Object.defineProperty(exports, '__esModule', {
14785    value: true
14786});
14787
14788function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
14789
14790var _EventBus = _dereq_(50);
14791
14792var _EventBus2 = _interopRequireDefault(_EventBus);
14793
14794var _eventsEvents = _dereq_(54);
14795
14796var _eventsEvents2 = _interopRequireDefault(_eventsEvents);
14797
14798var _FactoryMaker = _dereq_(51);
14799
14800var _FactoryMaker2 = _interopRequireDefault(_FactoryMaker);
14801
14802/**
14803 * @module Debug
14804 */
14805function Debug() {
14806
14807    var context = this.context;
14808    var eventBus = (0, _EventBus2['default'])(context).getInstance();
14809
14810    var instance = undefined,
14811        logToBrowserConsole = undefined,
14812        showLogTimestamp = undefined,
14813        showCalleeName = undefined,
14814        startTime = undefined;
14815
14816    function setup() {
14817        logToBrowserConsole = true;
14818        showLogTimestamp = true;
14819        showCalleeName = false;
14820        startTime = new Date().getTime();
14821    }
14822
14823    /**
14824     * Prepends a timestamp in milliseconds to each log message.
14825     * @param {boolean} value Set to true if you want to see a timestamp in each log message.
14826     * @default false
14827     * @memberof module:Debug
14828     * @instance
14829     */
14830    function setLogTimestampVisible(value) {
14831        showLogTimestamp = value;
14832    }
14833    /**
14834     * Prepends the callee object name, and media type if available, to each log message.
14835     * @param {boolean} value Set to true if you want to see the callee object name and media type in each log message.
14836     * @default false
14837     * @memberof module:Debug
14838     * @instance
14839     */
14840    function setCalleeNameVisible(value) {
14841        showCalleeName = value;
14842    }
14843    /**
14844     * Toggles logging to the browser's javascript console.  If you set to false you will still receive a log event with the same message.
14845     * @param {boolean} value Set to false if you want to turn off logging to the browser's console.
14846     * @default true
14847     * @memberof module:Debug
14848     * @instance
14849     */
14850    function setLogToBrowserConsole(value) {
14851        logToBrowserConsole = value;
14852    }
14853    /**
14854     * Use this method to get the state of logToBrowserConsole.
14855     * @returns {boolean} The current value of logToBrowserConsole
14856     * @memberof module:Debug
14857     * @instance
14858     */
14859    function getLogToBrowserConsole() {
14860        return logToBrowserConsole;
14861    }
14862    /**
14863     * This method will allow you send log messages to either the browser's console and/or dispatch an event to capture at the media player level.
14864     * @param {...*} arguments The message you want to log. The Arguments object is supported for this method so you can send in comma separated logging items.
14865     * @memberof module:Debug
14866     * @instance
14867     */
14868    function log() {
14869
14870        var message = '';
14871        var logTime = null;
14872
14873        if (showLogTimestamp) {
14874            logTime = new Date().getTime();
14875            message += '[' + (logTime - startTime) + ']';
14876        }
14877
14878        if (showCalleeName && this && this.getClassName) {
14879            message += '[' + this.getClassName() + ']';
14880            if (this.getType) {
14881                message += '[' + this.getType() + ']';
14882            }
14883        }
14884
14885        if (message.length > 0) {
14886            message += ' ';
14887        }
14888
14889        Array.apply(null, arguments).forEach(function (item) {
14890            message += item + ' ';
14891        });
14892
14893        if (logToBrowserConsole) {
14894            console.log(message);
14895        }
14896
14897        eventBus.trigger(_eventsEvents2['default'].LOG, { message: message });
14898    }
14899
14900    instance = {
14901        log: log,
14902        setLogTimestampVisible: setLogTimestampVisible,
14903        setCalleeNameVisible: setCalleeNameVisible,
14904        setLogToBrowserConsole: setLogToBrowserConsole,
14905        getLogToBrowserConsole: getLogToBrowserConsole
14906    };
14907
14908    setup();
14909
14910    return instance;
14911}
14912
14913Debug.__dashjs_factory_name = 'Debug';
14914exports['default'] = _FactoryMaker2['default'].getSingletonFactory(Debug);
14915module.exports = exports['default'];
14916
14917},{"50":50,"51":51,"54":54}],50:[function(_dereq_,module,exports){
14918/**
14919 * The copyright in this software is being made available under the BSD License,
14920 * included below. This software may be subject to other third party and contributor
14921 * rights, including patent rights, and no such rights are granted under this license.
14922 *
14923 * Copyright (c) 2013, Dash Industry Forum.
14924 * All rights reserved.
14925 *
14926 * Redistribution and use in source and binary forms, with or without modification,
14927 * are permitted provided that the following conditions are met:
14928 *  * Redistributions of source code must retain the above copyright notice, this
14929 *  list of conditions and the following disclaimer.
14930 *  * Redistributions in binary form must reproduce the above copyright notice,
14931 *  this list of conditions and the following disclaimer in the documentation and/or
14932 *  other materials provided with the distribution.
14933 *  * Neither the name of Dash Industry Forum nor the names of its
14934 *  contributors may be used to endorse or promote products derived from this software
14935 *  without specific prior written permission.
14936 *
14937 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
14938 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14939 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
14940 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
14941 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
14942 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
14943 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
14944 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
14945 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
14946 *  POSSIBILITY OF SUCH DAMAGE.
14947 */
14948'use strict';
14949
14950Object.defineProperty(exports, '__esModule', {
14951    value: true
14952});
14953
14954function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
14955
14956var _FactoryMaker = _dereq_(51);
14957
14958var _FactoryMaker2 = _interopRequireDefault(_FactoryMaker);
14959
14960var EVENT_PRIORITY_LOW = 0;
14961var EVENT_PRIORITY_HIGH = 5000;
14962
14963function EventBus() {
14964
14965    var handlers = {};
14966
14967    function on(type, listener, scope) {
14968        var priority = arguments.length <= 3 || arguments[3] === undefined ? EVENT_PRIORITY_LOW : arguments[3];
14969
14970        if (!type) {
14971            throw new Error('event type cannot be null or undefined');
14972        }
14973        if (!listener || typeof listener !== 'function') {
14974            throw new Error('listener must be a function: ' + listener);
14975        }
14976
14977        if (getHandlerIdx(type, listener, scope) >= 0) return;
14978
14979        handlers[type] = handlers[type] || [];
14980
14981        var handler = {
14982            callback: listener,
14983            scope: scope,
14984            priority: priority
14985        };
14986
14987        var inserted = handlers[type].some(function (item, idx) {
14988            if (item && priority > item.priority) {
14989                handlers[type].splice(idx, 0, handler);
14990                return true;
14991            }
14992        });
14993
14994        if (!inserted) {
14995            handlers[type].push(handler);
14996        }
14997    }
14998
14999    function off(type, listener, scope) {
15000        if (!type || !listener || !handlers[type]) return;
15001        var idx = getHandlerIdx(type, listener, scope);
15002        if (idx < 0) return;
15003        handlers[type][idx] = null;
15004    }
15005
15006    function trigger(type, payload) {
15007        if (!type || !handlers[type]) return;
15008
15009        payload = payload || {};
15010
15011        if (payload.hasOwnProperty('type')) throw new Error('\'type\' is a reserved word for event dispatching');
15012
15013        payload.type = type;
15014
15015        handlers[type] = handlers[type].filter(function (item) {
15016            return item;
15017        });
15018        handlers[type].forEach(function (handler) {
15019            return handler && handler.callback.call(handler.scope, payload);
15020        });
15021    }
15022
15023    function getHandlerIdx(type, listener, scope) {
15024
15025        var idx = -1;
15026
15027        if (!handlers[type]) return idx;
15028
15029        handlers[type].some(function (item, index) {
15030            if (item && item.callback === listener && (!scope || scope === item.scope)) {
15031                idx = index;
15032                return true;
15033            }
15034        });
15035        return idx;
15036    }
15037
15038    function reset() {
15039        handlers = {};
15040    }
15041
15042    var instance = {
15043        on: on,
15044        off: off,
15045        trigger: trigger,
15046        reset: reset
15047    };
15048
15049    return instance;
15050}
15051
15052EventBus.__dashjs_factory_name = 'EventBus';
15053var factory = _FactoryMaker2['default'].getSingletonFactory(EventBus);
15054factory.EVENT_PRIORITY_LOW = EVENT_PRIORITY_LOW;
15055factory.EVENT_PRIORITY_HIGH = EVENT_PRIORITY_HIGH;
15056_FactoryMaker2['default'].updateSingletonFactory(EventBus.__dashjs_factory_name, factory);
15057exports['default'] = factory;
15058module.exports = exports['default'];
15059
15060},{"51":51}],51:[function(_dereq_,module,exports){
15061/**
15062 * The copyright in this software is being made available under the BSD License,
15063 * included below. This software may be subject to other third party and contributor
15064 * rights, including patent rights, and no such rights are granted under this license.
15065 *
15066 * Copyright (c) 2013, Dash Industry Forum.
15067 * All rights reserved.
15068 *
15069 * Redistribution and use in source and binary forms, with or without modification,
15070 * are permitted provided that the following conditions are met:
15071 *  * Redistributions of source code must retain the above copyright notice, this
15072 *  list of conditions and the following disclaimer.
15073 *  * Redistributions in binary form must reproduce the above copyright notice,
15074 *  this list of conditions and the following disclaimer in the documentation and/or
15075 *  other materials provided with the distribution.
15076 *  * Neither the name of Dash Industry Forum nor the names of its
15077 *  contributors may be used to endorse or promote products derived from this software
15078 *  without specific prior written permission.
15079 *
15080 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
15081 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15082 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
15083 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
15084 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
15084INCLUDING, BUT
15085 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
15086 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
15087 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
15088 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
15089 *  POSSIBILITY OF SUCH DAMAGE.
15090 */
15091/**
15092 * @module FactoryMaker
15093 */
15094"use strict";
15095
15096Object.defineProperty(exports, "__esModule", {
15097    value: true
15098});
15099var FactoryMaker = (function () {
15100
15101    var instance = undefined;
15102    var extensions = [];
15103    var singletonContexts = [];
15104    var singletonFactories = [];
15105    var classFactories = [];
15106
15107    function extend(name, childInstance, override, context) {
15108        var extensionContext = getExtensionContext(context);
15109        if (!extensionContext[name] && childInstance) {
15110            extensionContext[name] = {
15111                instance: childInstance,
15112                override: override
15113            };
15114        }
15115    }
15116
15117    /**
15118     * Use this method from your extended object.  this.factory is injected into your object.
15119     * this.factory.getSingletonInstance(this.context, 'VideoModel')
15120     * will return the video model for use in the extended object.
15121     *
15122     * @param {Object} context - injected into extended object as this.context
15123     * @param {string} className - string name found in all dash.js objects
15124     * with name __dashjs_factory_name Will be at the bottom. Will be the same as the object's name.
15125     * @returns {*} Context aware instance of specified singleton name.
15126     * @memberof module:FactoryMaker
15127     * @instance
15128     */
15129    function getSingletonInstance(context, className) {
15130        for (var i in singletonContexts) {
15131            var obj = singletonContexts[i];
15132            if (obj.context === context && obj.name === className) {
15133                return obj.instance;
15134            }
15135        }
15136        return null;
15137    }
15138
15139    /**
15140     * Use this method to add an singleton instance to the system.  Useful for unit testing to mock objects etc.
15141     *
15142     * @param {Object} context
15143     * @param {string} className
15144     * @param {Object} instance
15145     * @memberof module:FactoryMaker
15146     * @instance
15147     */
15148    function setSingletonInstance(context, className, instance) {
15149        for (var i in singletonContexts) {
15150            var obj = singletonContexts[i];
15151            if (obj.context === context && obj.name === className) {
15152                singletonContexts[i].instance = instance;
15153                return;
15154            }
15155        }
15156        singletonContexts.push({
15157            name: className,
15158            context: context,
15159            instance: instance
15160        });
15161    }
15162
15163    /*------------------------------------------------------------------------------------------*/
15164
15165    // Factories storage Management
15166
15167    /*------------------------------------------------------------------------------------------*/
15168
15169    function registerFactory(name, factory, factoriesArray) {
15170        for (var i in factoriesArray) {
15171            var obj = factoriesArray[i];
15172            if (obj.name === name) {
15173                factoriesArray[i].factory = factory;
15174                return;
15175            }
15176        }
15177        factoriesArray.push({
15178            name: name,
15179            factory: factory
15180        });
15181    }
15182
15183    function getFactoryByName(name, factoriesArray) {
15184        for (var i in factoriesArray) {
15185            var obj = factoriesArray[i];
15186            if (obj.name === name) {
15187                return factoriesArray[i].factory;
15188            }
15189        }
15190        return null;
15191    }
15192
15193    function updateFactory(name, factory, factoriesArray) {
15194        for (var i in factoriesArray) {
15195            var obj = factoriesArray[i];
15196            if (obj.name === name) {
15197                factoriesArray[i].factory = factory;
15198                return;
15199            }
15200        }
15201    }
15202
15203    /*------------------------------------------------------------------------------------------*/
15204
15205    // Class Factories Management
15206
15207    /*------------------------------------------------------------------------------------------*/
15208
15209    function updateClassFactory(name, factory) {
15210        updateFactory(name, factory, classFactories);
15211    }
15212
15213    function getClassFactoryByName(name) {
15214        return getFactoryByName(name, classFactories);
15215    }
15216
15217    function getClassFactory(classConstructor) {
15218        var factory = getFactoryByName(classConstructor.__dashjs_factory_name, classFactories);
15219
15220        if (!factory) {
15221            factory = function (context) {
15222                if (context === undefined) {
15223                    context = {};
15224                }
15225                return {
15226                    create: function create() {
15227                        return merge(classConstructor.__dashjs_factory_name, classConstructor.apply({
15228                            context: context
15229                        }, arguments), context, arguments);
15230                    }
15231                };
15232            };
15233
15234            registerFactory(classConstructor.__dashjs_factory_name, factory, classFactories); // store factory
15235        }
15236        return factory;
15237    }
15238
15239    /*------------------------------------------------------------------------------------------*/
15240
15241    // Singleton Factory MAangement
15242
15243    /*------------------------------------------------------------------------------------------*/
15244
15245    function updateSingletonFactory(name, factory) {
15246        updateFactory(name, factory, singletonFactories);
15247    }
15248
15249    function getSingletonFactoryByName(name) {
15250        return getFactoryByName(name, singletonFactories);
15251    }
15252
15253    function getSingletonFactory(classConstructor) {
15254        var factory = getFactoryByName(classConstructor.__dashjs_factory_name, singletonFactories);
15255        if (!factory) {
15256            factory = function (context) {
15257                var instance = undefined;
15258                if (context === undefined) {
15259                    context = {};
15260                }
15261                return {
15262                    getInstance: function getInstance() {
15263                        // If we don't have an instance yet check for one on the context
15264                        if (!instance) {
15265                            instance = getSingletonInstance(context, classConstructor.__dashjs_factory_name);
15266                        }
15267                        // If there's no instance on the context then create one
15268                        if (!instance) {
15269                            instance = merge(classConstructor.__dashjs_factory_name, classConstructor.apply({
15270                                context: context
15271                            }, arguments), context, arguments);
15272                            singletonContexts.push({
15273                                name: classConstructor.__dashjs_factory_name,
15274                                context: context,
15275                                instance: instance
15276                            });
15277                        }
15278                        return instance;
15279                    }
15280                };
15281            };
15282            registerFactory(classConstructor.__dashjs_factory_name, factory, singletonFactories); // store factory
15283        }
15284
15285        return factory;
15286    }
15287
15288    function merge(name, classConstructor, context, args) {
15289        // Add getClassName function to class instance prototype (used by Debug)
15290        classConstructor.getClassName = function () {
15291            return name;
15292        };
15293
15294        var extensionContext = getExtensionContext(context);
15295        var extensionObject = extensionContext[name];
15296        if (extensionObject) {
15297            var extension = extensionObject.instance;
15298            if (extensionObject.override) {
15299                //Override public methods in parent but keep parent.
15300                extension = extension.apply({
15301                    context: context,
15302                    factory: instance,
15303                    parent: classConstructor
15304                }, args);
15305                for (var prop in extension) {
15306                    if (classConstructor.hasOwnProperty(prop)) {
15307                        classConstructor[prop] = extension[prop];
15308                    }
15309                }
15310            } else {
15311                //replace parent object completely with new object. Same as dijon.
15312                return extension.apply({
15313                    context: context,
15314                    factory: instance
15315                }, args);
15316            }
15317        }
15318        return classConstructor;
15319    }
15320
15321    function getExtensionContext(context) {
15322        var extensionContext = undefined;
15323        extensions.forEach(function (obj) {
15324            if (obj === context) {
15325                extensionContext = obj;
15326            }
15327        });
15328        if (!extensionContext) {
15329            extensions.push(context);
15330            extensionContext = context;
15331        }
15332        return extensionContext;
15333    }
15334
15335    instance = {
15336        extend: extend,
15337        getSingletonInstance: getSingletonInstance,
15338        setSingletonInstance: setSingletonInstance,
15339        getSingletonFactory: getSingletonFactory,
15340        getSingletonFactoryByName: getSingletonFactoryByName,
15341        updateSingletonFactory: updateSingletonFactory,
15342        getClassFactory: getClassFactory,
15343        getClassFactoryByName: getClassFactoryByName,
15344        updateClassFactory: updateClassFactory
15345    };
15346
15347    return instance;
15348})();
15349
15350exports["default"] = FactoryMaker;
15351module.exports = exports["default"];
15352
15353},{}],52:[function(_dereq_,module,exports){
15354'use strict';
15355
15356Object.defineProperty(exports, '__esModule', {
15357    value: true
15358});
15359exports.getVersionString = getVersionString;
15360var VERSION = '2.6.2';
15361
15362function getVersionString() {
15363    return VERSION;
15364}
15365
15366},{}],53:[function(_dereq_,module,exports){
15367/**
15368 * The copyright in this software is being made available under the BSD License,
15369 * included below. This software may be subject to other third party and contributor
15370 * rights, including patent rights, and no such rights are granted under this license.
15371 *
15372 * Copyright (c) 2013, Dash Industry Forum.
15373 * All rights reserved.
15374 *
15375 * Redistribution and use in source and binary forms, with or without modification,
15376 * are permitted provided that the following conditions are met:
15377 *  * Redistributions of source code must retain the above copyright notice, this
15378 *  list of conditions and the following disclaimer.
15379 *  * Redistributions in binary form must reproduce the above copyright notice,
15380 *  this list of conditions and the following disclaimer in the documentation and/or
15381 *  other materials provided with the distribution.
15382 *  * Neither the name of Dash Industry Forum nor the names of its
15383 *  contributors may be used to endorse or promote products derived from this software
15384 *  without specific prior written permission.
15385 *
15386 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
15387 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15388 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
15389 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
15390 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
15390INCLUDING, BUT
15391 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
15392 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
15393 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
15394 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
15395 *  POSSIBILITY OF SUCH DAMAGE.
15396 */
15397'use strict';
15398
15399Object.defineProperty(exports, '__esModule', {
15400    value: true
15401});
15402
15403var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
15404
15405function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
15406
15407function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
15408
15409function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
15410
15411var _EventsBase2 = _dereq_(55);
15412
15413var _EventsBase3 = _interopRequireDefault(_EventsBase2);
15414
15415/**
15416 * These are internal events that should not be needed at the player level.
15417 * If you find and event in here that you would like access to from MediaPlayer level
15418 * please add an issue at https://github.com/Dash-Industry-Forum/dash.js/issues/new
15419 * @class
15420 * @ignore
15421 */
15422
15423var CoreEvents = (function (_EventsBase) {
15424    _inherits(CoreEvents, _EventsBase);
15425
15426    function CoreEvents() {
15427        _classCallCheck(this, CoreEvents);
15428
15429        _get(Object.getPrototypeOf(CoreEvents.prototype), 'constructor', this).call(this);
15430        this.BUFFERING_COMPLETED = 'bufferingCompleted';
15431        this.BUFFER_CLEARED = 'bufferCleared';
15432        this.BUFFER_LEVEL_UPDATED = 'bufferLevelUpdated';
15433        this.BYTES_APPENDED = 'bytesAppended';
15434        this.CHECK_FOR_EXISTENCE_COMPLETED = 'checkForExistenceCompleted';
15435        this.CURRENT_TRACK_CHANGED = 'currentTrackChanged';
15436        this.DATA_UPDATE_COMPLETED = 'dataUpdateCompleted';
15437        this.DATA_UPDATE_STARTED = 'dataUpdateStarted';
15438        this.INITIALIZATION_LOADED = 'initializationLoaded';
15439        this.INIT_FRAGMENT_LOADED = 'initFragmentLoaded';
15440        this.INIT_REQUESTED = 'initRequested';
15441        this.INTERNAL_MANIFEST_LOADED = 'internalManifestLoaded';
15442        this.LIVE_EDGE_SEARCH_COMPLETED = 'liveEdgeSearchCompleted';
15443        this.LOADING_COMPLETED = 'loadingCompleted';
15444        this.LOADING_PROGRESS = 'loadingProgress';
15445        this.LOADING_ABANDONED = 'loadingAborted';
15446        this.MANIFEST_UPDATED = 'manifestUpdated';
15447        this.MEDIA_FRAGMENT_LOADED = 'mediaFragmentLoaded';
15448        this.QUOTA_EXCEEDED = 'quotaExceeded';
15449        this.REPRESENTATION_UPDATED = 'representationUpdated';
15450        this.SEGMENTS_LOADED = 'segmentsLoaded';
15451        this.SERVICE_LOCATION_BLACKLIST_ADD = 'serviceLocationBlacklistAdd';
15452        this.SERVICE_LOCATION_BLACKLIST_CHANGED = 'serviceLocationBlacklistChanged';
15453        this.SOURCEBUFFER_APPEND_COMPLETED = 'sourceBufferAppendCompleted';
15454        this.SOURCEBUFFER_REMOVE_COMPLETED = 'sourceBufferRemoveCompleted';
15455        this.STREAMS_COMPOSED = 'streamsComposed';
15456        this.STREAM_BUFFERING_COMPLETED = 'streamBufferingCompleted';
15457        this.STREAM_COMPLETED = 'streamCompleted';
15458        this.TIMED_TEXT_REQUESTED = 'timedTextRequested';
15459        this.TIME_SYNCHRONIZATION_COMPLETED = 'timeSynchronizationComplete';
15460        this.URL_RESOLUTION_FAILED = 'urlResolutionFailed';
15461        this.VIDEO_CHUNK_RECEIVED = 'videoChunkReceived';
15462        this.WALLCLOCK_TIME_UPDATED = 'wallclockTimeUpdated';
15463        this.XLINK_ELEMENT_LOADED = 'xlinkElementLoaded';
15464        this.XLINK_READY = 'xlinkReady';
15465    }
15466
15467    return CoreEvents;
15468})(_EventsBase3['default']);
15469
15470exports['default'] = CoreEvents;
15471module.exports = exports['default'];
15472
15473},{"55":55}],54:[function(_dereq_,module,exports){
15474/**
15475 * The copyright in this software is being made available under the BSD License,
15476 * included below. This software may be subject to other third party and contributor
15477 * rights, including patent rights, and no such rights are granted under this license.
15478 *
15479 * Copyright (c) 2013, Dash Industry Forum.
15480 * All rights reserved.
15481 *
15482 * Redistribution and use in source and binary forms, with or without modification,
15483 * are permitted provided that the following conditions are met:
15484 *  * Redistributions of source code must retain the above copyright notice, this
15485 *  list of conditions and the following disclaimer.
15486 *  * Redistributions in binary form must reproduce the above copyright notice,
15487 *  this list of conditions and the following disclaimer in the documentation and/or
15488 *  other materials provided with the distribution.
15489 *  * Neither the name of Dash Industry Forum nor the names of its
15490 *  contributors may be used to endorse or promote products derived from this software
15491 *  without specific prior written permission.
15492 *
15493 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
15494 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15495 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
15496 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
15497 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
15497INCLUDING, BUT
15498 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
15499 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
15500 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
15501 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
15502 *  POSSIBILITY OF SUCH DAMAGE.
15503 */
15504/**
15505 * @class
15506 * @ignore
15507 */
15508'use strict';
15509
15510Object.defineProperty(exports, '__esModule', {
15511  value: true
15512});
15513
15514var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
15515
15516function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
15517
15518function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
15519
15520function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
15521
15522var _CoreEvents2 = _dereq_(53);
15523
15524var _CoreEvents3 = _interopRequireDefault(_CoreEvents2);
15525
15526var Events = (function (_CoreEvents) {
15527  _inherits(Events, _CoreEvents);
15528
15529  function Events() {
15530    _classCallCheck(this, Events);
15531
15532    _get(Object.getPrototypeOf(Events.prototype), 'constructor', this).apply(this, arguments);
15533  }
15534
15535  return Events;
15536})(_CoreEvents3['default']);
15537
15538var events = new Events();
15539exports['default'] = events;
15540module.exports = exports['default'];
15541
15542},{"53":53}],55:[function(_dereq_,module,exports){
15543/**
15544 * The copyright in this software is being made available under the BSD License,
15545 * included below. This software may be subject to other third party and contributor
15546 * rights, including patent rights, and no such rights are granted under this license.
15547 *
15548 * Copyright (c) 2013, Dash Industry Forum.
15549 * All rights reserved.
15550 *
15551 * Redistribution and use in source and binary forms, with or without modification,
15552 * are permitted provided that the following conditions are met:
15553 *  * Redistributions of source code must retain the above copyright notice, this
15554 *  list of conditions and the following disclaimer.
15555 *  * Redistributions in binary form must reproduce the above copyright notice,
15556 *  this list of conditions and the following disclaimer in the documentation and/or
15557 *  other materials provided with the distribution.
15558 *  * Neither the name of Dash Industry Forum nor the names of its
15559 *  contributors may be used to endorse or promote products derived from this software
15560 *  without specific prior written permission.
15561 *
15562 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
15563 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15564 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
15565 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
15566 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
15567 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
15568 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
15569 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
15570 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
15571 *  POSSIBILITY OF SUCH DAMAGE.
15572 */
15573/**
15574 * @class
15575 * @ignore
15576 */
15577'use strict';
15578
15579Object.defineProperty(exports, '__esModule', {
15580    value: true
15581});
15582
15583var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
15584
15585function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
15586
15587var EventsBase = (function () {
15588    function EventsBase() {
15589        _classCallCheck(this, EventsBase);
15590    }
15591
15592    _createClass(EventsBase, [{
15593        key: 'extend',
15594        value: function extend(events, config) {
15595            if (!events) return;
15596
15597            var override = config ? config.override : false;
15598            var publicOnly = config ? config.publicOnly : false;
15599
15600            for (var evt in events) {
15601                if (!events.hasOwnProperty(evt) || this[evt] && !override) continue;
15602                if (publicOnly && events[evt].indexOf('public_') === -1) continue;
15603                this[evt] = events[evt];
15604            }
15605        }
15606    }]);
15607
15608    return EventsBase;
15609})();
15610
15611exports['default'] = EventsBase;
15612module.exports = exports['default'];
15613
15614},{}],56:[function(_dereq_,module,exports){
15615/**
15616 * The copyright in this software is being made available under the BSD License,
15617 * included below. This software may be subject to other third party and contributor
15618 * rights, including patent rights, and no such rights are granted under this license.
15619 *
15620 * Copyright (c) 2013, Dash Industry Forum.
15621 * All rights reserved.
15622 *
15623 * Redistribution and use in source and binary forms, with or without modification,
15624 * are permitted provided that the following conditions are met:
15625 *  * Redistributions of source code must retain the above copyright notice, this
15626 *  list of conditions and the following disclaimer.
15627 *  * Redistributions in binary form must reproduce the above copyright notice,
15628 *  this list of conditions and the following disclaimer in the documentation and/or
15629 *  other materials provided with the distribution.
15630 *  * Neither the name of Dash Industry Forum nor the names of its
15631 *  contributors may be used to endorse or promote products derived from this software
15632 *  without specific prior written permission.
15633 *
15634 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
15635 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15636 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
15637 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
15638 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
15639 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
15640 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
15641 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
15642 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
15643 *  POSSIBILITY OF SUCH DAMAGE.
15644 */
15645
15646'use strict';
15647
15648Object.defineProperty(exports, '__esModule', {
15649    value: true
15650});
15651
15652function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
15653
15654var _streamingConstantsConstants = _dereq_(100);
15655
15656var _streamingConstantsConstants2 = _interopRequireDefault(_streamingConstantsConstants);
15657
15658var _streamingVoRepresentationInfo = _dereq_(215);
15659
15660var _streamingVoRepresentationInfo2 = _interopRequireDefault(_streamingVoRepresentationInfo);
15661
15662var _streamingVoMediaInfo = _dereq_(213);
15663
15664var _streamingVoMediaInfo2 = _interopRequireDefault(_streamingVoMediaInfo);
15665
15666var _streamingVoStreamInfo = _dereq_(216);
15667
15668var _streamingVoStreamInfo2 = _interopRequireDefault(_streamingVoStreamInfo);
15669
15670var _streamingVoManifestInfo = _dereq_(212);
15671
15672var _streamingVoManifestInfo2 = _interopRequireDefault(_streamingVoManifestInfo);
15673
15674var _voEvent = _dereq_(83);
15675
15676var _voEvent2 = _interopRequireDefault(_voEvent);
15677
15678var _coreFactoryMaker = _dereq_(51);
15679
15680var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
15681
15682var _externalsCea608Parser = _dereq_(2);
15683
15684var _externalsCea608Parser2 = _interopRequireDefault(_externalsCea608Parser);
15685
15686function DashAdapter() {
15687    var instance = undefined,
15688        dashManifestModel = undefined,
15689        voPeriods = undefined,
15690        voAdaptations = undefined;
15691
15692    function setup() {
15693        reset();
15694    }
15695
15696    function setConfig(config) {
15697        if (!config) return;
15698
15699        if (config.dashManifestModel) {
15700            dashManifestModel = config.dashManifestModel;
15701        }
15702    }
15703
15704    function getRepresentationForRepresentationInfo(representationInfo, representationController) {
15705        return representationController && representationInfo ? representationController.getRepresentationForQuality(representationInfo.quality) : null;
15706    }
15707
15708    function getAdaptationForMediaInfo(mediaInfo) {
15709
15710        if (!mediaInfo || !mediaInfo.streamInfo || mediaInfo.streamInfo.id === undefined || !voAdaptations[mediaInfo.streamInfo.id]) return null;
15711        return voAdaptations[mediaInfo.streamInfo.id][mediaInfo.index];
15712    }
15713
15714    function getPeriodForStreamInfo(streamInfo, voPeriodsArray) {
15715        var ln = voPeriodsArray.length;
15716
15717        for (var i = 0; i < ln; i++) {
15718            var voPeriod = voPeriodsArray[i];
15719
15720            if (streamInfo.id === voPeriod.id) return voPeriod;
15721        }
15722
15723        return null;
15724    }
15725
15726    function convertRepresentationToRepresentationInfo(voRepresentation) {
15727        var representationInfo = new _streamingVoRepresentationInfo2['default']();
15728        var realAdaptation = voRepresentation.adaptation.period.mpd.manifest.Period_asArray[voRepresentation.adaptation.period.index].AdaptationSet_asArray[voRepresentation.adaptation.index];
15729        var realRepresentation = dashManifestModel.getRepresentationFor(voRepresentation.index, realAdaptation);
15730
15731        representationInfo.id = voRepresentation.id;
15732        representationInfo.quality = voRepresentation.index;
15733        representationInfo.bandwidth = dashManifestModel.getBandwidth(realRepresentation);
15734        representationInfo.DVRWindow = voRepresentation.segmentAvailabilityRange;
15735        representationInfo.fragmentDuration = voRepresentation.segmentDuration || (voRepresentation.segments && voRepresentation.segments.length > 0 ? voRepresentation.segments[0].duration : NaN);
15736        representationInfo.MSETimeOffset = voRepresentation.MSETimeOffset;
15737        representationInfo.useCalculatedLiveEdgeTime = voRepresentation.useCalculatedLiveEdgeTime;
15738        representationInfo.mediaInfo = convertAdaptationToMediaInfo(voRepresentation.adaptation);
15739
15740        return representationInfo;
15741    }
15742
15743    function convertAdaptationToMediaInfo(adaptation) {
15744        var mediaInfo = new _streamingVoMediaInfo2['default']();
15745        var realAdaptation = adaptation.period.mpd.manifest.Period_asArray[adaptation.period.index].AdaptationSet_asArray[adaptation.index];
15746        var viewpoint = undefined;
15747
15748        mediaInfo.id = adaptation.id;
15749        mediaInfo.index = adaptation.index;
15750        mediaInfo.type = adaptation.type;
15751        mediaInfo.streamInfo = convertPeriodToStreamInfo(adaptation.period);
15752        mediaInfo.representationCount = dashManifestModel.getRepresentationCount(realAdaptation);
15753        mediaInfo.lang = dashManifestModel.getLanguageForAdaptation(realAdaptation);
15754        viewpoint = dashManifestModel.getViewpointForAdaptation(realAdaptation);
15755        mediaInfo.viewpoint = viewpoint ? viewpoint.value : undefined;
15756        mediaInfo.accessibility = dashManifestModel.getAccessibilityForAdaptation(realAdaptation).map(function (accessibility) {
15757            var accessibilityValue = accessibility.value;
15758            var accessibilityData = accessibilityValue;
15759            if (accessibility.schemeIdUri && accessibility.schemeIdUri.search('cea-608') >= 0 && typeof _externalsCea608Parser2['default'] !== 'undefined') {
15760                if (accessibilityValue) {
15761                    accessibilityData = 'cea-608:' + accessibilityValue;
15762                } else {
15763                    accessibilityData = 'cea-608';
15764                }
15765                mediaInfo.embeddedCaptions = true;
15766            }
15767            return accessibilityData;
15768        });
15769
15770        mediaInfo.audioChannelConfiguration = dashManifestModel.getAudioChannelConfigurationForAdaptation(realAdaptation).map(function (audioChannelConfiguration) {
15771            return audioChannelConfiguration.value;
15772        });
15773        mediaInfo.roles = dashManifestModel.getRolesForAdaptation(realAdaptation).map(function (role) {
15774            return role.value;
15775        });
15776        mediaInfo.codec = dashManifestModel.getCodec(realAdaptation);
15777        mediaInfo.mimeType = dashManifestModel.getMimeType(realAdaptation);
15778        mediaInfo.contentProtection = dashManifestModel.getContentProtectionData(realAdaptation);
15779        mediaInfo.bitrateList = dashManifestModel.getBitrateListForAdaptation(realAdaptation);
15780
15781        if (mediaInfo.contentProtection) {
15782            mediaInfo.contentProtection.forEach(function (item) {
15783                item.KID = dashManifestModel.getKID(item);
15784            });
15785        }
15786
15787        mediaInfo.isText = dashManifestModel.getIsTextTrack(mediaInfo.mimeType);
15788
15789        return mediaInfo;
15790    }
15791
15792    function convertVideoInfoToEmbeddedTextInfo(mediaInfo, channel, lang) {
15793        mediaInfo.id = channel; // CC1, CC2, CC3, or CC4
15794        mediaInfo.index = 100 + parseInt(channel.substring(2, 3));
15795        mediaInfo.type = _streamingConstantsConstants2['default'].EMBEDDED_TEXT;
15796        mediaInfo.codec = 'cea-608-in-SEI';
15797        mediaInfo.isText = true;
15798        mediaInfo.isEmbedded = true;
15799        mediaInfo.lang = channel + ' ' + lang;
15800        mediaInfo.roles = ['caption'];
15801    }
15802
15803    function convertPeriodToStreamInfo(period) {
15804        var streamInfo = new _streamingVoStreamInfo2['default']();
15805        var THRESHOLD = 1;
15806
15807        streamInfo.id = period.id;
15808        streamInfo.index = period.index;
15809        streamInfo.start = period.start;
15810        streamInfo.duration = period.duration;
15811        streamInfo.manifestInfo = convertMpdToManifestInfo(period.mpd);
15812        streamInfo.isLast = period.mpd.manifest.Period_asArray.length === 1 || Math.abs(streamInfo.start + streamInfo.duration - streamInfo.manifestInfo.duration) < THRESHOLD;
15813
15814        return streamInfo;
15815    }
15816
15817    function convertMpdToManifestInfo(mpd) {
15818        var manifestInfo = new _streamingVoManifestInfo2['default']();
15819
15820        manifestInfo.DVRWindowSize = mpd.timeShiftBufferDepth;
15821        manifestInfo.loadedTime = mpd.manifest.loadedTime;
15822        manifestInfo.availableFrom = mpd.availabilityStartTime;
15823        manifestInfo.minBufferTime = mpd.manifest.minBufferTime;
15824        manifestInfo.maxFragmentDuration = mpd.maxSegmentDuration;
15825        manifestInfo.duration = dashManifestModel.getDuration(mpd.manifest);
15826        manifestInfo.isDynamic = dashManifestModel.getIsDynamic(mpd.manifest);
15827
15828        return manifestInfo;
15829    }
15830
15831    function getMediaInfoForType(streamInfo, type) {
15832
15833        if (voPeriods.length === 0) {
15834            return null;
15835        }
15836
15837        var manifest = voPeriods[0].mpd.manifest;
15838        var realAdaptation = dashManifestModel.getAdaptationForType(manifest, streamInfo.index, type, streamInfo);
15839        if (!realAdaptation) return null;
15840
15841        var selectedVoPeriod = getPeriodForStreamInfo(streamInfo, voPeriods);
15842        var periodId = selectedVoPeriod.id;
15843        var idx = dashManifestModel.getIndexForAdaptation(realAdaptation, manifest, streamInfo.index);
15844
15845        voAdaptations[periodId] = voAdaptations[periodId] || dashManifestModel.getAdaptationsForPeriod(selectedVoPeriod);
15846
15847        return convertAdaptationToMediaInfo(voAdaptations[periodId][idx]);
15848    }
15849
15850    function getAllMediaInfoForType(streamInfo, type, externalManifest) {
15851        var voLocalPeriods = voPeriods;
15852        var manifest = externalManifest;
15853        var mediaArr = [];
15854        var data = undefined,
15855            media = undefined,
15856            idx = undefined,
15857            i = undefined,
15858            j = undefined,
15859            ln = undefined;
15860
15861        if (manifest) {
15862            checkSetConfigCall();
15863            var mpd = dashManifestModel.getMpd(manifest);
15864
15865            voLocalPeriods = dashManifestModel.getRegularPeriods(mpd);
15866        } else {
15867            if (voPeriods.length > 0) {
15868                manifest = voPeriods[0].mpd.manifest;
15869            } else {
15870                return mediaArr;
15871            }
15872        }
15873
15874        var selectedVoPeriod = getPeriodForStreamInfo(streamInfo, voLocalPeriods);
15875        var periodId = selectedVoPeriod.id;
15876        var adaptationsForType = dashManifestModel.getAdaptationsForType(manifest, streamInfo.index, type !== _streamingConstantsConstants2['default'].EMBEDDED_TEXT ? type : _streamingConstantsConstants2['default'].VIDEO);
15877
15878        if (!adaptationsForType) return mediaArr;
15879
15880        voAdaptations[periodId] = voAdaptations[periodId] || dashManifestModel.getAdaptationsForPeriod(selectedVoPeriod);
15881
15882        for (i = 0, ln = adaptationsForType.length; i < ln; i++) {
15883            data = adaptationsForType[i];
15884            idx = dashManifestModel.getIndexForAdaptation(data, manifest, streamInfo.index);
15885            media = convertAdaptationToMediaInfo(voAdaptations[periodId][idx]);
15886
15887            if (type === _streamingConstantsConstants2['default'].EMBEDDED_TEXT) {
15888                var accessibilityLength = media.accessibility.length;
15889                for (j = 0; j < accessibilityLength; j++) {
15890                    if (!media) {
15891                        continue;
15892                    }
15893                    var accessibility = media.accessibility[j];
15894                    if (accessibility.indexOf('cea-608:') === 0) {
15895                        var value = accessibility.substring(8);
15896                        var parts = value.split(';');
15897                        if (parts[0].substring(0, 2) === 'CC') {
15898                            for (j = 0; j < parts.length; j++) {
15899                                if (!media) {
15900                                    media = convertAdaptationToMediaInfo.call(this, voAdaptations[periodId][idx]);
15901                                }
15902                                convertVideoInfoToEmbeddedTextInfo(media, parts[j].substring(0, 3), parts[j].substring(4));
15903                                mediaArr.push(media);
15904                                media = null;
15905                            }
15906                        } else {
15907                            for (j = 0; j < parts.length; j++) {
15908                                // Only languages for CC1, CC2, ...
15909                                if (!media) {
15910                                    media = convertAdaptationToMediaInfo.call(this, voAdaptations[periodId][idx]);
15911                                }
15912                                convertVideoInfoToEmbeddedTextInfo(media, 'CC' + (j + 1), parts[j]);
15913                                mediaArr.push(media);
15914                                media = null;
15915                            }
15916                        }
15917                    } else if (accessibility.indexOf('cea-608') === 0) {
15918                        // Nothing known. We interpret it as CC1=eng
15919                        convertVideoInfoToEmbeddedTextInfo(media, _streamingConstantsConstants2['default'].CC1, 'eng');
15920                        mediaArr.push(media);
15921                        media = null;
15922                    }
15923                }
15924            }
15925            if (media && type !== _streamingConstantsConstants2['default'].EMBEDDED_TEXT) {
15926                mediaArr.push(media);
15927            }
15928        }
15929
15930        return mediaArr;
15931    }
15932
15933    function checkSetConfigCall() {
15934        if (!dashManifestModel || !dashManifestModel.hasOwnProperty('getMpd') || !dashManifestModel.hasOwnProperty('getRegularPeriods')) {
15935            throw new Error('setConfig function has to be called previously');
15936        }
15937    }
15938
15939    function updatePeriods(newManifest) {
15940        if (!newManifest) return null;
15941
15942        checkSetConfigCall();
15943
15944        var mpd = dashManifestModel.getMpd(newManifest);
15945
15946        voPeriods = dashManifestModel.getRegularPeriods(mpd);
15947        voAdaptations = {};
15948    }
15949
15950    function getStreamsInfo(externalManifest) {
15951        var streams = [];
15952        var voLocalPeriods = voPeriods;
15953
15954        //if manifest is defined, getStreamsInfo is for an outside manifest, not the current one
15955        if (externalManifest) {
15956            checkSetConfigCall();
15957            var mpd = dashManifestModel.getMpd(externalManifest);
15958
15959            voLocalPeriods = dashManifestModel.getRegularPeriods(mpd);
15960        }
15961
15962        for (var i = 0; i < voLocalPeriods.length; i++) {
15963            streams.push(convertPeriodToStreamInfo(voLocalPeriods[i]));
15964        }
15965
15966        return streams;
15967    }
15968
15969    function checkStreamProcessor(streamProcessor) {
15970        if (!streamProcessor || !streamProcessor.hasOwnProperty('getRepresentationController') || !streamProcessor.hasOwnProperty('getIndexHandler') || !streamProcessor.hasOwnProperty('getMediaInfo') || !streamProcessor.hasOwnProperty('getType') || !streamProcessor.hasOwnProperty('getStreamInfo')) {
15971            throw new Error('streamProcessor parameter is missing or malformed!');
15972        }
15973    }
15974
15975    function checkRepresentationController(representationController) {
15976        if (!representationController || !representationController.hasOwnProperty('getRepresentationForQuality') || !representationController.hasOwnProperty('getCurrentRepresentation')) {
15977            throw new Error('representationController parameter is missing or malformed!');
15978        }
15979    }
15980
15981    function checkQuality(quality) {
15982        var isInt = quality !== null && !isNaN(quality) && quality % 1 === 0;
15983
15984        if (!isInt) {
15985            throw new Error('quality argument is not an integer');
15986        }
15987    }
15988
15989    function getInitRequest(streamProcessor, quality) {
15990        var representationController = undefined,
15991            representation = undefined,
15992            indexHandler = undefined;
15993
15994        checkStreamProcessor(streamProcessor);
15995        checkQuality(quality);
15996
15997        representationController = streamProcessor.getRepresentationController();
15998        indexHandler = streamProcessor.getIndexHandler();
15999
16000        representation = representationController ? representationController.getRepresentationForQuality(quality) : null;
16001
16002        return indexHandler ? indexHandler.getInitRequest(representation) : null;
16003    }
16004
16005    function getNextFragmentRequest(streamProcessor, trackInfo) {
16006        var representationController = undefined,
16007            representation = undefined,
16008            indexHandler = undefined;
16009
16010        checkStreamProcessor(streamProcessor);
16011
16012        representationController = streamProcessor.getRepresentationController();
16013        representation = getRepresentationForRepresentationInfo(trackInfo, representationController);
16014        indexHandler = streamProcessor.getIndexHandler();
16015
16016        return indexHandler ? indexHandler.getNextSegmentRequest(representation) : null;
16017    }
16018
16019    function getFragmentRequestForTime(streamProcessor, trackInfo, time, options) {
16020        var representationController = undefined,
16021            representation = undefined,
16022            indexHandler = undefined;
16023
16024        checkStreamProcessor(streamProcessor);
16025
16026        representationController = streamProcessor.getRepresentationController();
16027        representation = getRepresentationForRepresentationInfo(trackInfo, representationController);
16028        indexHandler = streamProcessor.getIndexHandler();
16029
16030        return indexHandler ? indexHandler.getSegmentRequestForTime(representation, time, options) : null;
16031    }
16032
16033    function generateFragmentRequestForTime(streamProcessor, trackInfo, time) {
16034        var representationController = undefined,
16035            representation = undefined,
16036            indexHandler = undefined;
16037
16038        checkStreamProcessor(streamProcessor);
16039
16040        representationController = streamProcessor.getRepresentationController();
16041        representation = getRepresentationForRepresentationInfo(trackInfo, representationController);
16042        indexHandler = streamProcessor.getIndexHandler();
16043
16044        return indexHandler ? indexHandler.generateSegmentRequestForTime(representation, time) : null;
16045    }
16046
16047    function getIndexHandlerTime(streamProcessor) {
16048        checkStreamProcessor(streamProcessor);
16049
16050        var indexHandler = streamProcessor.getIndexHandler();
16051
16052        if (indexHandler) {
16053            return indexHandler.getCurrentTime();
16054        }
16055        return NaN;
16056    }
16057
16058    function setIndexHandlerTime(streamProcessor, value) {
16059        checkStreamProcessor(streamProcessor);
16060
16061        var indexHandler = streamProcessor.getIndexHandler();
16062        if (indexHandler) {
16063            indexHandler.setCurrentTime(value);
16064        }
16065    }
16066
16067    function updateData(streamProcessor) {
16068        checkStreamProcessor(streamProcessor);
16069
16070        var selectedVoPeriod = getPeriodForStreamInfo(streamProcessor.getStreamInfo(), voPeriods);
16071        var mediaInfo = streamProcessor.getMediaInfo();
16072        var voAdaptation = getAdaptationForMediaInfo(mediaInfo);
16073        var type = streamProcessor.getType();
16074
16075        var id = undefined,
16076            realAdaptation = undefined;
16077
16078        id = mediaInfo ? mediaInfo.id : null;
16079        if (voPeriods.length > 0) {
16080            realAdaptation = id ? dashManifestModel.getAdaptationForId(id, voPeriods[0].mpd.manifest, selectedVoPeriod.index) : dashManifestModel.getAdaptationForIndex(mediaInfo.index, voPeriods[0].mpd.manifest, selectedVoPeriod.index);
16081            streamProcessor.getRepresentationController().updateData(realAdaptation, voAdaptation, type);
16082        }
16083    }
16084
16085    function getRepresentationInfoForQuality(representationController, quality) {
16086        checkRepresentationController(representationController);
16087        checkQuality(quality);
16088
16089        var voRepresentation = representationController.getRepresentationForQuality(quality);
16090        return voRepresentation ? convertRepresentationToRepresentationInfo(voRepresentation) : null;
16091    }
16092
16093    function getCurrentRepresentationInfo(representationController) {
16094        checkRepresentationController(representationController);
16095        var voRepresentation = representationController.getCurrentRepresentation();
16096        return voRepresentation ? convertRepresentationToRepresentationInfo(voRepresentation) : null;
16097    }
16098
16099    function getEvent(eventBox, eventStreams, startTime) {
16100        if (!eventBox || !eventStreams) {
16101            return null;
16102        }
16103        var event = new _voEvent2['default']();
16104        var schemeIdUri = eventBox.scheme_id_uri;
16105        var value = eventBox.value;
16106        var timescale = eventBox.timescale;
16107        var presentationTimeDelta = eventBox.presentation_time_delta;
16108        var duration = eventBox.event_duration;
16109        var id = eventBox.id;
16110        var messageData = eventBox.message_data;
16111        var presentationTime = startTime * timescale + presentationTimeDelta;
16112
16113        if (!eventStreams[schemeIdUri]) return null;
16114
16115        event.eventStream = eventStreams[schemeIdUri];
16116        event.eventStream.value = value;
16117        event.eventStream.timescale = timescale;
16118        event.duration = duration;
16119        event.id = id;
16120        event.presentationTime = presentationTime;
16121        event.messageData = messageData;
16122        event.presentationTimeDelta = presentationTimeDelta;
16123
16124        return event;
16125    }
16126
16127    function getEventsFor(info, streamProcessor) {
16128
16129        var events = [];
16130
16131        if (voPeriods.length === 0) {
16132            return events;
16133        }
16134
16135        var manifest = voPeriods[0].mpd.manifest;
16136
16137        if (info instanceof _streamingVoStreamInfo2['default']) {
16138            events = dashManifestModel.getEventsForPeriod(getPeriodForStreamInfo(info, voPeriods));
16139        } else if (info instanceof _streamingVoMediaInfo2['default']) {
16140            events = dashManifestModel.getEventStreamForAdaptationSet(manifest, getAdaptationForMediaInfo(info));
16141        } else if (info instanceof _streamingVoRepresentationInfo2['default']) {
16142            events = dashManifestModel.getEventStreamForRepresentation(manifest, getRepresentationForRepresentationInfo(info, streamProcessor.getRepresentationController()));
16143        }
16144
16145        return events;
16146    }
16147
16148    function reset() {
16149        voPeriods = [];
16150        voAdaptations = {};
16151    }
16152
16153    instance = {
16154        convertDataToRepresentationInfo: convertRepresentationToRepresentationInfo,
16155        getDataForMedia: getAdaptationForMediaInfo,
16156        getStreamsInfo: getStreamsInfo,
16157        getMediaInfoForType: getMediaInfoForType,
16158        getAllMediaInfoForType: getAllMediaInfoForType,
16159        getCurrentRepresentationInfo: getCurrentRepresentationInfo,
16160        getRepresentationInfoForQuality: getRepresentationInfoForQuality,
16161        updateData: updateData,
16162        getInitRequest: getInitRequest,
16163        getNextFragmentRequest: getNextFragmentRequest,
16164        getFragmentRequestForTime: getFragmentRequestForTime,
16165        generateFragmentRequestForTime: generateFragmentRequestForTime,
16166        getIndexHandlerTime: getIndexHandlerTime,
16167        setIndexHandlerTime: setIndexHandlerTime,
16168        getEventsFor: getEventsFor,
16169        getEvent: getEvent,
16170        setConfig: setConfig,
16171        updatePeriods: updatePeriods,
16172        reset: reset
16173    };
16174
16175    setup();
16176    return instance;
16177}
16178
16179DashAdapter.__dashjs_factory_name = 'DashAdapter';
16180exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(DashAdapter);
16181module.exports = exports['default'];
16182
16183},{"100":100,"2":2,"212":212,"213":213,"215":215,"216":216,"51":51,"83":83}],57:[function(_dereq_,module,exports){
16184/**
16185 * The copyright in this software is being made available under the BSD License,
16186 * included below. This software may be subject to other third party and contributor
16187 * rights, including patent rights, and no such rights are granted under this license.
16188 *
16189 * Copyright (c) 2013, Dash Industry Forum.
16190 * All rights reserved.
16191 *
16192 * Redistribution and use in source and binary forms, with or without modification,
16193 * are permitted provided that the following conditions are met:
16194 *  * Redistributions of source code must retain the above copyright notice, this
16195 *  list of conditions and the following disclaimer.
16196 *  * Redistributions in binary form must reproduce the above copyright notice,
16197 *  this list of conditions and the following disclaimer in the documentation and/or
16198 *  other materials provided with the distribution.
16199 *  * Neither the name of Dash Industry Forum nor the names of its
16200 *  contributors may be used to endorse or promote products derived from this software
16201 *  without specific prior written permission.
16202 *
16203 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
16204 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16205 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16206 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
16207 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
16207INCLUDING, BUT
16208 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
16209 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
16210 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
16211 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
16212 *  POSSIBILITY OF SUCH DAMAGE.
16213 */
16214'use strict';
16215
16216Object.defineProperty(exports, '__esModule', {
16217    value: true
16218});
16219
16220function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
16221
16222var _streamingConstantsConstants = _dereq_(100);
16223
16224var _streamingConstantsConstants2 = _interopRequireDefault(_streamingConstantsConstants);
16225
16226var _constantsDashConstants = _dereq_(61);
16227
16228var _constantsDashConstants2 = _interopRequireDefault(_constantsDashConstants);
16229
16230var _streamingVoFragmentRequest = _dereq_(209);
16231
16232var _streamingVoFragmentRequest2 = _interopRequireDefault(_streamingVoFragmentRequest);
16233
16234var _streamingVoDashJSError = _dereq_(207);
16235
16236var _streamingVoDashJSError2 = _interopRequireDefault(_streamingVoDashJSError);
16237
16238var _streamingVoMetricsHTTPRequest = _dereq_(224);
16239
16240var _coreEventsEvents = _dereq_(54);
16241
16242var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
16243
16244var _coreEventBus = _dereq_(50);
16245
16246var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
16247
16248var _coreFactoryMaker = _dereq_(51);
16249
16250var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
16251
16252var _coreDebug = _dereq_(49);
16253
16254var _coreDebug2 = _interopRequireDefault(_coreDebug);
16255
16256var _streamingUtilsURLUtils = _dereq_(202);
16257
16258var _streamingUtilsURLUtils2 = _interopRequireDefault(_streamingUtilsURLUtils);
16259
16260var _voRepresentation = _dereq_(87);
16261
16262var _voRepresentation2 = _interopRequireDefault(_voRepresentation);
16263
16264var _utilsSegmentsUtils = _dereq_(77);
16265
16266var _utilsSegmentsGetter = _dereq_(76);
16267
16268var _utilsSegmentsGetter2 = _interopRequireDefault(_utilsSegmentsGetter);
16269
16270var _SegmentBaseLoader = _dereq_(59);
16271
16272var _SegmentBaseLoader2 = _interopRequireDefault(_SegmentBaseLoader);
16273
16274var _WebmSegmentBaseLoader = _dereq_(60);
16275
16276var _WebmSegmentBaseLoader2 = _interopRequireDefault(_WebmSegmentBaseLoader);
16277
16278var SEGMENTS_UNAVAILABLE_ERROR_CODE = 1;
16279
16280function DashHandler(config) {
16281
16282    var context = this.context;
16283    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
16284    var urlUtils = (0, _streamingUtilsURLUtils2['default'])(context).getInstance();
16285
16286    var segmentBaseLoader = undefined;
16287    var timelineConverter = config.timelineConverter;
16288    var dashMetrics = config.dashMetrics;
16289    var metricsModel = config.metricsModel;
16290    var mediaPlayerModel = config.mediaPlayerModel;
16291    var errHandler = config.errHandler;
16292    var baseURLController = config.baseURLController;
16293
16294    var instance = undefined,
16295        log = undefined,
16296        index = undefined,
16297        requestedTime = undefined,
16298        currentTime = undefined,
16299        earliestTime = undefined,
16300        streamProcessor = undefined,
16301        segmentsGetter = undefined;
16302
16303    function setup() {
16304        log = (0, _coreDebug2['default'])(context).getInstance().log.bind(instance);
16305
16306        resetInitialSettings();
16307
16308        segmentBaseLoader = isWebM(config.mimeType) ? (0, _WebmSegmentBaseLoader2['default'])(context).getInstance() : (0, _SegmentBaseLoader2['default'])(context).getInstance();
16309        segmentBaseLoader.setConfig({
16310            baseURLController: baseURLController,
16311            metricsModel: metricsModel,
16312            mediaPlayerModel: mediaPlayerModel,
16313            errHandler: errHandler
16314        });
16315
16316        eventBus.on(_coreEventsEvents2['default'].INITIALIZATION_LOADED, onInitializationLoaded, instance);
16317        eventBus.on(_coreEventsEvents2['default'].SEGMENTS_LOADED, onSegmentsLoaded, instance);
16318    }
16319
16320    function isWebM(mimeType) {
16321        var type = mimeType.split('/')[1];
16322
16323        return 'webm' === type.toLowerCase();
16324    }
16325
16326    function initialize(StreamProcessor) {
16327        streamProcessor = StreamProcessor;
16328
16329        var isDynamic = streamProcessor ? streamProcessor.getStreamInfo().manifestInfo.isDynamic : null;
16330
16331        segmentBaseLoader.initialize();
16332
16333        segmentsGetter = (0, _utilsSegmentsGetter2['default'])(context).create(config, isDynamic);
16334    }
16335
16336    function getStreamProcessor() {
16337        return streamProcessor;
16338    }
16339
16340    function setCurrentTime(value) {
16341        currentTime = value;
16342    }
16343
16344    function getCurrentTime() {
16345        return currentTime;
16346    }
16347
16348    function getEarliestTime() {
16349        return earliestTime;
16350    }
16351
16352    function resetInitialSettings() {
16353        index = -1;
16354        currentTime = 0;
16355        earliestTime = NaN;
16356        requestedTime = null;
16357        streamProcessor = null;
16358        segmentsGetter = null;
16359    }
16360
16361    function reset() {
16362        resetInitialSettings();
16363
16364        eventBus.off(_coreEventsEvents2['default'].INITIALIZATION_LOADED, onInitializationLoaded, instance);
16365        eventBus.off(_coreEventsEvents2['default'].SEGMENTS_LOADED, onSegmentsLoaded, instance);
16366    }
16367
16368    function unescapeDollarsInTemplate(url) {
16369        return url ? url.split('$$').join('$') : url;
16370    }
16371
16372    function replaceIDForTemplate(url, value) {
16373        if (value === null || url === null || url.indexOf('$RepresentationID$') === -1) {
16374            return url;
16375        }
16376        var v = value.toString();
16377        return url.split('$RepresentationID$').join(v);
16378    }
16379
16380    function setRequestUrl(request, destination, representation) {
16381        var baseURL = baseURLController.resolve(representation.path);
16382        var url = undefined,
16383            serviceLocation = undefined;
16384
16385        if (!baseURL || destination === baseURL.url || !urlUtils.isRelative(destination)) {
16386            url = destination;
16387        } else {
16388            url = baseURL.url;
16389            serviceLocation = baseURL.serviceLocation;
16390
16391            if (destination) {
16392                url = urlUtils.resolve(destination, url);
16393            }
16394        }
16395
16396        if (urlUtils.isRelative(url)) {
16397            return false;
16398        }
16399
16400        request.url = url;
16401        request.serviceLocation = serviceLocation;
16402
16403        return true;
16404    }
16405
16406    function generateInitRequest(representation, mediaType) {
16407
16408        var request = new _streamingVoFragmentRequest2['default']();
16409        var period = representation.adaptation.period;
16410        var presentationStartTime = period.start;
16411        var isDynamic = streamProcessor ? streamProcessor.getStreamInfo().manifestInfo.isDynamic : null;
16412
16413        request.mediaType = mediaType;
16414        request.type = _streamingVoMetricsHTTPRequest.HTTPRequest.INIT_SEGMENT_TYPE;
16415        request.range = representation.range;
16416        request.availabilityStartTime = timelineConverter.calcAvailabilityStartTimeFromPresentationTime(presentationStartTime, period.mpd, isDynamic);
16417        request.availabilityEndTime = timelineConverter.calcAvailabilityEndTimeFromPresentationTime(presentationStartTime + period.duration, period.mpd, isDynamic);
16418        request.quality = representation.index;
16419        request.mediaInfo = streamProcessor ? streamProcessor.getMediaInfo() : null;
16420        request.representationId = representation.id;
16421
16422        if (setRequestUrl(request, representation.initialization, representation)) {
16423            return request;
16424        }
16425    }
16426
16427    function getInitRequest(representation) {
16428        var type = streamProcessor ? streamProcessor.getType() : null;
16429        if (!representation) return null;
16430        var request = generateInitRequest(representation, type);
16431        return request;
16432    }
16433
16434    function isMediaFinished(representation) {
16435
16436        var isFinished = false;
16437        var isDynamic = streamProcessor ? streamProcessor.getStreamInfo().manifestInfo.isDynamic : null;
16438
16439        if (!isDynamic && index === representation.availableSegmentsNumber) {
16440            isFinished = true;
16441        } else {
16442            var seg = (0, _utilsSegmentsUtils.getSegmentByIndex)(index, representation);
16443            if (seg) {
16444                var time = seg.presentationStartTime - representation.adaptation.period.start;
16445                var duration = representation.adaptation.period.duration;
16446                log(representation.segmentInfoType + ': ' + time + ' / ' + duration);
16447                isFinished = representation.segmentInfoType === _constantsDashConstants2['default'].SEGMENT_TIMELINE && isDynamic ? false : time >= duration;
16448            } else {
16449                log('isMediaFinished - no segment found');
16450            }
16451        }
16452
16453        return isFinished;
16454    }
16455
16456    function updateSegments(voRepresentation) {
16457        segmentsGetter.getSegments(voRepresentation, requestedTime, index, onSegmentListUpdated);
16458    }
16459
16460    function onSegmentListUpdated(voRepresentation, segments) {
16461        var isDynamic = streamProcessor ? streamProcessor.getStreamInfo().manifestInfo.isDynamic : null;
16462        voRepresentation.segments = segments;
16463        if (segments && segments.length > 0) {
16464            earliestTime = isNaN(earliestTime) ? segments[0].presentationStartTime : Math.min(segments[0].presentationStartTime, earliestTime);
16465            if (isDynamic && isNaN(timelineConverter.getExpectedLiveEdge())) {
16466                var lastSegment = segments[segments.length - 1];
16467                var liveEdge = lastSegment.presentationStartTime;
16468                var metrics = metricsModel.getMetricsFor(_streamingConstantsConstants2['default'].STREAM);
16469                // the last segment is the Expected, not calculated, live edge.
16470                timelineConverter.setExpectedLiveEdge(liveEdge);
16471                metricsModel.updateManifestUpdateInfo(dashMetrics.getCurrentManifestUpdate(metrics), { presentationStartTime: liveEdge });
16472            }
16473        }
16474    }
16475
16476    function updateSegmentList(voRepresentation) {
16477
16478        if (!voRepresentation) {
16479            throw new Error('no representation');
16480        }
16481
16482        voRepresentation.segments = null;
16483
16484        updateSegments(voRepresentation);
16485    }
16486
16487    function updateRepresentation(voRepresentation, keepIdx) {
16488        var hasInitialization = _voRepresentation2['default'].hasInitialization(voRepresentation);
16489        var hasSegments = _voRepresentation2['default'].hasSegments(voRepresentation);
16490        var type = streamProcessor ? streamProcessor.getType() : null;
16491        var isDynamic = streamProcessor ? streamProcessor.getStreamInfo().manifestInfo.isDynamic : null;
16492        var error = undefined;
16493
16494        if (!voRepresentation.segmentDuration && !voRepresentation.segments) {
16495            updateSegmentList(voRepresentation);
16496        }
16497
16498        voRepresentation.segmentAvailabilityRange = null;
16499        voRepresentation.segmentAvailabilityRange = timelineConverter.calcSegmentAvailabilityRange(voRepresentation, isDynamic);
16500
16501        if (voRepresentation.segmentAvailabilityRange.end < voRepresentation.segmentAvailabilityRange.start && !voRepresentation.useCalculatedLiveEdgeTime) {
16502            error = new _streamingVoDashJSError2['default'](SEGMENTS_UNAVAILABLE_ERROR_CODE, 'no segments are available yet', { availabilityDelay: voRepresentation.segmentAvailabilityRange.start - voRepresentation.segmentAvailabilityRange.end });
16503            eventBus.trigger(_coreEventsEvents2['default'].REPRESENTATION_UPDATED, { sender: this, representation: voRepresentation, error: error });
16504            return;
16505        }
16506
16507        if (!keepIdx) index = -1;
16508
16509        if (voRepresentation.segmentDuration) {
16510            updateSegmentList(voRepresentation);
16511        }
16512
16513        if (!hasInitialization) {
16514            segmentBaseLoader.loadInitialization(voRepresentation);
16515        }
16516
16517        if (!hasSegments) {
16518            segmentBaseLoader.loadSegments(voRepresentation, type, voRepresentation.indexRange);
16519        }
16520
16521        if (hasInitialization && hasSegments) {
16522            eventBus.trigger(_coreEventsEvents2['default'].REPRESENTATION_UPDATED, { sender: this, representation: voRepresentation });
16523        }
16524    }
16525
16526    function getIndexForSegments(time, representation, timeThreshold) {
16527        var segments = representation.segments;
16528        var ln = segments ? segments.length : null;
16529
16530        var idx = -1;
16531        var epsilon = undefined,
16532            frag = undefined,
16533            ft = undefined,
16534            fd = undefined,
16535            i = undefined;
16536
16537        if (segments && ln > 0) {
16538            for (i = 0; i < ln; i++) {
16539                frag = segments[i];
16540                ft = frag.presentationStartTime;
16541                fd = frag.duration;
16542                epsilon = timeThreshold === undefined || timeThreshold === null ? fd / 2 : timeThreshold;
16543                if (time + epsilon >= ft && time - epsilon < ft + fd) {
16544                    idx = frag.availabilityIdx;
16545                    break;
16546                }
16547            }
16548        }
16549
16550        return idx;
16551    }
16552
16553    function getRequestForSegment(segment) {
16554        if (segment === null || segment === undefined) {
16555            return null;
16556        }
16557
16558        var request = new _streamingVoFragmentRequest2['default']();
16559        var representation = segment.representation;
16560        var bandwidth = representation.adaptation.period.mpd.manifest.Period_asArray[representation.adaptation.period.index].AdaptationSet_asArray[representation.adaptation.index].Representation_asArray[representation.index].bandwidth;
16561        var url = segment.media;
16562        var type = streamProcessor ? streamProcessor.getType() : null;
16563
16564        url = (0, _utilsSegmentsUtils.replaceTokenForTemplate)(url, 'Number', segment.replacementNumber);
16565        url = (0, _utilsSegmentsUtils.replaceTokenForTemplate)(url, 'Time', segment.replacementTime);
16566        url = (0, _utilsSegmentsUtils.replaceTokenForTemplate)(url, 'Bandwidth', bandwidth);
16567        url = replaceIDForTemplate(url, representation.id);
16568        url = unescapeDollarsInTemplate(url);
16569
16570        request.mediaType = type;
16571        request.type = _streamingVoMetricsHTTPRequest.HTTPRequest.MEDIA_SEGMENT_TYPE;
16572        request.range = segment.mediaRange;
16573        request.startTime = segment.presentationStartTime;
16574        request.duration = segment.duration;
16575        request.timescale = representation.timescale;
16576        request.availabilityStartTime = segment.availabilityStartTime;
16577        request.availabilityEndTime = segment.availabilityEndTime;
16578        request.wallStartTime = segment.wallStartTime;
16579        request.quality = representation.index;
16580        request.index = segment.availabilityIdx;
16581        request.mediaInfo = streamProcessor.getMediaInfo();
16582        request.adaptationIndex = representation.adaptation.index;
16583
16584        if (setRequestUrl(request, url, representation)) {
16585            return request;
16586        }
16587    }
16588
16589    function getSegmentRequestForTime(representation, time, options) {
16590        var request = undefined,
16591            segment = undefined,
16592            finished = undefined;
16593
16594        var type = streamProcessor ? streamProcessor.getType() : null;
16595        var isDynamic = streamProcessor ? streamProcessor.getStreamInfo().manifestInfo.isDynamic : null;
16596        var idx = index;
16597        var keepIdx = options ? options.keepIdx : false;
16598        var timeThreshold = options ? options.timeThreshold : null;
16599        var ignoreIsFinished = options && options.ignoreIsFinished ? true : false;
16600
16601        if (!representation) {
16602            return null;
16603        }
16604
16605        if (requestedTime !== time) {
16606            // When playing at live edge with 0 delay we may loop back with same time and index until it is available. Reduces verboseness of logs.
16607            requestedTime = time;
16608            log('Getting the request for ' + type + ' time : ' + time);
16609        }
16610
16611        updateSegments(representation);
16612        index = getIndexForSegments(time, representation, timeThreshold);
16613        //Index may be -1 if getSegments needs to update again.  So after getSegments is called and updated then try to get index again.
16614        if (index < 0) {
16615            updateSegments(representation);
16616            index = getIndexForSegments(time, representation, timeThreshold);
16617        }
16618
16619        if (index > 0) {
16620            log('Index for ' + type + ' time ' + time + ' is ' + index);
16621        }
16622
16623        finished = !ignoreIsFinished ? isMediaFinished(representation) : false;
16624        if (finished) {
16625            request = new _streamingVoFragmentRequest2['default']();
16626            request.action = _streamingVoFragmentRequest2['default'].ACTION_COMPLETE;
16627            request.index = index;
16628            request.mediaType = type;
16629            request.mediaInfo = streamProcessor.getMediaInfo();
16630            log('Signal complete.', request);
16631        } else {
16632            segment = (0, _utilsSegmentsUtils.getSegmentByIndex)(index, representation);
16633            request = getRequestForSegment(segment);
16634            // log('[getSegmentRequestForTime]request is ' + JSON.stringify(request));
16635        }
16636
16637        if (keepIdx && idx >= 0) {
16638            index = representation.segmentInfoType === _constantsDashConstants2['default'].SEGMENT_TIMELINE && isDynamic ? index : idx;
16639        }
16640
16641        return request;
16642    }
16643
16644    function generateSegmentRequestForTime(representation, time) {
16645        var step = (representation.segmentAvailabilityRange.end - representation.segmentAvailabilityRange.start) / 2;
16646
16647        representation.segments = null;
16648        representation.segmentAvailabilityRange = { start: time - step, end: time + step };
16649        return getSegmentRequestForTime(representation, time, { keepIdx: false, ignoreIsFinished: true });
16650    }
16651
16652    function getNextSegmentRequest(representation) {
16653        var request = undefined,
16654            segment = undefined,
16655            finished = undefined;
16656
16657        var type = streamProcessor ? streamProcessor.getType() : null;
16658        var isDynamic = streamProcessor ? streamProcessor.getStreamInfo().manifestInfo.isDynamic : null;
16659
16660        if (!representation || index === -1) {
16661            return null;
16662        }
16663
16664        requestedTime = null;
16665        index++;
16666
16667        log('Getting the next request at index: ' + index);
16668
16669        // check that there is a segment in this index. If none, update segments and wait for next time loop is called
16670        var seg = (0, _utilsSegmentsUtils.getSegmentByIndex)(index, representation);
16671        if (!seg && isDynamic) {
16672            log('No segment found at index: ' + index + '. Wait for next loop');
16673            updateSegments(representation);
16674            index--;
16675            return null;
16676        }
16677
16678        finished = isMediaFinished(representation);
16679        if (finished) {
16680            request = new _streamingVoFragmentRequest2['default']();
16681            request.action = _streamingVoFragmentRequest2['default'].ACTION_COMPLETE;
16682            request.index = index;
16683            request.mediaType = type;
16684            request.mediaInfo = streamProcessor.getMediaInfo();
16685            log('Signal complete.');
16686        } else {
16687            updateSegments(representation);
16688            segment = (0, _utilsSegmentsUtils.getSegmentByIndex)(index, representation);
16689            request = getRequestForSegment(segment);
16690            // log('[getSegmentRequestForTime]request is ' + JSON.stringify(request));
16691            if (!segment && isDynamic) {
16692                /*
16693                 Sometimes when playing dynamic streams with 0 fragment delay at live edge we ask for
16694                 an index before it is available so we decrement index back and send null request
16695                 which triggers the validate loop to rerun and the next time the segment should be
16696                 available.
16697                 */
16698                index--;
16699            }
16700        }
16701
16702        return request;
16703    }
16704
16705    function onInitializationLoaded(e) {
16706        var representation = e.representation;
16707        //log("Got an initialization.");
16708        if (!representation.segments) return;
16709
16710        eventBus.trigger(_coreEventsEvents2['default'].REPRESENTATION_UPDATED, { sender: this, representation: representation });
16711    }
16712
16713    function onSegmentsLoaded(e) {
16714        var type = streamProcessor ? streamProcessor.getType() : null;
16715        var isDynamic = streamProcessor ? streamProcessor.getStreamInfo().manifestInfo.isDynamic : null;
16716        if (e.error || type !== e.mediaType) return;
16717
16718        var fragments = e.segments;
16719        var representation = e.representation;
16720        var segments = [];
16721        var count = 0;
16722
16723        var i = undefined,
16724            len = undefined,
16725            s = undefined,
16726            seg = undefined;
16727
16728        for (i = 0, len = fragments.length; i < len; i++) {
16729            s = fragments[i];
16730
16731            seg = (0, _utilsSegmentsUtils.getTimeBasedSegment)(timelineConverter, isDynamic, representation, s.startTime, s.duration, s.timescale, s.media, s.mediaRange, count);
16732
16733            segments.push(seg);
16734            seg = null;
16735            count++;
16736        }
16737
16738        representation.segmentAvailabilityRange = { start: segments[0].presentationStartTime, end: segments[len - 1].presentationStartTime };
16739        representation.availableSegmentsNumber = len;
16740
16741        onSegmentListUpdated(representation, segments);
16742
16743        if (!_voRepresentation2['default'].hasInitialization(representation)) return;
16744
16745        eventBus.trigger(_coreEventsEvents2['default'].REPRESENTATION_UPDATED, { sender: this, representation: representation });
16746    }
16747
16748    instance = {
16749        initialize: initialize,
16750        getStreamProcessor: getStreamProcessor,
16751        getInitRequest: getInitRequest,
16752        getSegmentRequestForTime: getSegmentRequestForTime,
16753        getNextSegmentRequest: getNextSegmentRequest,
16754        generateSegmentRequestForTime: generateSegmentRequestForTime,
16755        updateRepresentation: updateRepresentation,
16756        updateSegmentList: updateSegmentList,
16757        setCurrentTime: setCurrentTime,
16758        getCurrentTime: getCurrentTime,
16759        getEarliestTime: getEarliestTime,
16760        reset: reset
16761    };
16762
16763    setup();
16764
16765    return instance;
16766}
16767
16768DashHandler.__dashjs_factory_name = 'DashHandler';
16769var factory = _coreFactoryMaker2['default'].getClassFactory(DashHandler);
16770factory.SEGMENTS_UNAVAILABLE_ERROR_CODE = SEGMENTS_UNAVAILABLE_ERROR_CODE;
16771_coreFactoryMaker2['default'].updateClassFactory(DashHandler.__dashjs_factory_name, factory);
16772exports['default'] = factory;
16773module.exports = exports['default'];
16774
16775}
16775,{"100":100,"202":202,"207":207,"209":209,"224":224,"49":49,"50":50,"51":51,"54":54,"59":59,"60":60,"61":61,"76":76,"77":77,"87":87}],58:[function(_dereq_,module,exports){
16776/**
16777 * The copyright in this software is being made available under the BSD License,
16778 * included below. This software may be subject to other third party and contributor
16779 * rights, including patent rights, and no such rights are granted under this license.
16780 *
16781 * Copyright (c) 2013, Dash Industry Forum.
16782 * All rights reserved.
16783 *
16784 * Redistribution and use in source and binary forms, with or without modification,
16785 * are permitted provided that the following conditions are met:
16786 *  * Redistributions of source code must retain the above copyright notice, this
16787 *  list of conditions and the following disclaimer.
16788 *  * Redistributions in binary form must reproduce the above copyright notice,
16789 *  this list of conditions and the following disclaimer in the documentation and/or
16790 *  other materials provided with the distribution.
16791 *  * Neither the name of Dash Industry Forum nor the names of its
16792 *  contributors may be used to endorse or promote products derived from this software
16793 *  without specific prior written permission.
16794 *
16795 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
16796 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16797 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16798 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
16799 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
16800 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
16801 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
16802 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
16803 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
16804 *  POSSIBILITY OF SUCH DAMAGE.
16805 */
16806'use strict';
16807
16808Object.defineProperty(exports, '__esModule', {
16809    value: true
16810});
16811
16812function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
16813
16814var _streamingVoMetricsHTTPRequest = _dereq_(224);
16815
16816var _coreFactoryMaker = _dereq_(51);
16817
16818var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
16819
16820var _streamingConstantsMetricsConstants = _dereq_(101);
16821
16822var _streamingConstantsMetricsConstants2 = _interopRequireDefault(_streamingConstantsMetricsConstants);
16823
16824var _round10 = _dereq_(43);
16825
16826/**
16827 * @module DashMetrics
16828 * @param {object} config configuration passed to DashMetrics
16829 */
16830function DashMetrics(config) {
16831
16832    var instance = undefined;
16833    var dashManifestModel = config.dashManifestModel;
16834    var manifestModel = config.manifestModel;
16835
16836    function getBandwidthForRepresentation(representationId, periodId) {
16837        var representation = undefined;
16838        var manifest = manifestModel.getValue();
16839        var period = manifest.Period_asArray[periodId];
16840
16841        representation = findRepresentation(period, representationId);
16842
16843        if (representation === null) {
16844            return null;
16845        }
16846
16847        return representation.bandwidth;
16848    }
16849
16850    /**
16851     *
16852     * @param {string} representationId
16853     * @param {number} periodIdx
16854     * @returns {*}
16855     */
16856    function getIndexForRepresentation(representationId, periodIdx) {
16857        var representationIndex = undefined;
16858        var manifest = manifestModel.getValue();
16859        var period = manifest.Period_asArray[periodIdx];
16860
16861        representationIndex = findRepresentationIndex(period, representationId);
16862        return representationIndex;
16863    }
16864
16865    /**
16866     * This method returns the current max index based on what is defined in the MPD.
16867     *
16868     * @param {string} bufferType - String 'audio' or 'video',
16869     * @param {number} periodIdx - Make sure this is the period index not id
16870     * @return {number}
16871     * @memberof module:DashMetrics
16872     * @instance
16873     */
16874    function getMaxIndexForBufferType(bufferType, periodIdx) {
16875        var maxIndex = undefined;
16876        var manifest = manifestModel.getValue();
16877        var period = manifest.Period_asArray[periodIdx];
16878
16879        maxIndex = findMaxBufferIndex(period, bufferType);
16880        return maxIndex;
16881    }
16882
16883    /**
16884     * @param {MetricsList} metrics
16885     * @returns {*}
16886     * @memberof module:DashMetrics
16887     * @instance
16888     */
16889    function getCurrentRepresentationSwitch(metrics) {
16890        return getCurrent(metrics, _streamingConstantsMetricsConstants2['default'].TRACK_SWITCH);
16891    }
16892
16893    /**
16894     * @param {MetricsList} metrics
16895     * @returns {*}
16896     * @memberof module:DashMetrics
16897     * @instance
16898     */
16899    function getLatestBufferLevelVO(metrics) {
16900        return getCurrent(metrics, _streamingConstantsMetricsConstants2['default'].BUFFER_LEVEL);
16901    }
16902
16903    /**
16904     * @param {MetricsList} metrics
16905     * @returns {number}
16906     * @memberof module:DashMetrics
16907     * @instance
16908     */
16909    function getCurrentBufferLevel(metrics) {
16910        var vo = getLatestBufferLevelVO(metrics);
16911
16912        if (vo) {
16913            return (0, _round10.round10)(vo.level / 1000, -3);
16914        }
16915
16916        return 0;
16917    }
16918
16919    /**
16920     * @param {MetricsList} metrics
16921     * @returns {null|*|vo}
16922     * @memberof module:DashMetrics
16923     * @instance
16924     */
16925    function getRequestsQueue(metrics) {
16926        return metrics ? metrics.RequestsQueue : null;
16927    }
16928
16929    /**
16930     * @param {MetricsList} metrics
16931     * @returns {*}
16932     * @memberof module:DashMetrics
16933     * @instance
16934     */
16935    function getCurrentHttpRequest(metrics) {
16936        if (!metrics) {
16937            return null;
16938        }
16939
16940        var httpList = metrics.HttpList;
16941        var currentHttpList = null;
16942
16943        var httpListLength = undefined,
16944            httpListLastIndex = undefined;
16945
16946        if (!httpList || httpList.length <= 0) {
16947            return null;
16948        }
16949
16950        httpListLength = httpList.length;
16951        httpListLastIndex = httpListLength - 1;
16952
16953        while (httpListLastIndex >= 0) {
16954            if (httpList[httpListLastIndex].responsecode) {
16955                currentHttpList = httpList[httpListLastIndex];
16956                break;
16957            }
16958            httpListLastIndex--;
16959        }
16960        return currentHttpList;
16961    }
16962
16963    /**
16964     * @param {MetricsList} metrics
16965     * @returns {*}
16966     * @memberof module:DashMetrics
16967     * @instance
16968     */
16969    function getHttpRequests(metrics) {
16970        if (!metrics) {
16971            return [];
16972        }
16973
16974        return !!metrics.HttpList ? metrics.HttpList : [];
16975    }
16976
16977    /**
16978     * @param {MetricsList} metrics
16979     * @param {string} metricName
16980     * @returns {*}
16981     * @memberof module:DashMetrics
16982     * @instance
16983     */
16984    function getCurrent(metrics, metricName) {
16985        if (!metrics) {
16986            return null;
16987        }
16988
16989        var list = metrics[metricName];
16990
16991        if (!list) {
16992            return null;
16993        }
16994
16995        var length = list.length;
16996
16997        if (length <= 0) {
16998            return null;
16999        }
17000
17001        return list[length - 1];
17002    }
17003
17004    /**
17005     * @param {MetricsList} metrics
17006     * @returns {*}
17007     * @memberof module:DashMetrics
17008     * @instance
17009     */
17010    function getCurrentDroppedFrames(metrics) {
17011        return getCurrent(metrics, _streamingConstantsMetricsConstants2['default'].DROPPED_FRAMES);
17012    }
17013
17014    /**
17015     * @param {MetricsList} metrics
17016     * @returns {*}
17017     * @memberof module:DashMetrics
17018     * @instance
17019     */
17020    function getCurrentSchedulingInfo(metrics) {
17021        return getCurrent(metrics, _streamingConstantsMetricsConstants2['default'].SCHEDULING_INFO);
17022    }
17023
17024    /**
17025     * @param {MetricsList} metrics
17026     * @returns {*}
17027     * @memberof module:DashMetrics
17028     * @instance
17029     */
17030    function getCurrentManifestUpdate(metrics) {
17031        return getCurrent(metrics, _streamingConstantsMetricsConstants2['default'].MANIFEST_UPDATE);
17032    }
17033
17034    /**
17035     * @param {MetricsList} metrics
17036     * @returns {*}
17037     * @memberof module:DashMetrics
17038     * @instance
17039     */
17040    function getCurrentDVRInfo(metrics) {
17041        return getCurrent(metrics, _streamingConstantsMetricsConstants2['default'].DVR_INFO);
17042    }
17043
17044    /**
17045     * @param {MetricsList} metrics
17046     * @param {string} id
17047     * @returns {*}
17048     * @memberof module:DashMetrics
17049     * @instance
17050     */
17051    function getLatestMPDRequestHeaderValueByID(metrics, id) {
17052        var headers = {};
17053        var httpRequestList = undefined,
17054            httpRequest = undefined,
17055            i = undefined;
17056
17057        httpRequestList = getHttpRequests(metrics);
17058
17059        for (i = httpRequestList.length - 1; i >= 0; i--) {
17060            httpRequest = httpRequestList[i];
17061
17062            if (httpRequest.type === _streamingVoMetricsHTTPRequest.HTTPRequest.MPD_TYPE) {
17063                headers = parseResponseHeaders(httpRequest._responseHeaders);
17064                break;
17065            }
17066        }
17067
17068        return headers[id] === undefined ? null : headers[id];
17069    }
17070
17071    /**
17072     * @param {MetricsList} metrics
17073     * @param {string} id
17074     * @returns {*}
17075     * @memberof module:DashMetrics
17076     * @instance
17077     */
17078    function getLatestFragmentRequestHeaderValueByID(metrics, id) {
17079        var headers = {};
17080        var httpRequest = getCurrentHttpRequest(metrics);
17081        if (httpRequest) {
17082            headers = parseResponseHeaders(httpRequest._responseHeaders);
17083        }
17084        return headers[id] === undefined ? null : headers[id];
17085    }
17086
17087    function parseResponseHeaders(headerStr) {
17088        var headers = {};
17089        if (!headerStr) {
17090            return headers;
17091        }
17092
17093        // Trim headerStr to fix a MS Edge bug with xhr.getAllResponseHeaders method
17094        // which send a string starting with a "\n" character
17095        var headerPairs = headerStr.trim().split('\r\n');
17096        for (var i = 0, ilen = headerPairs.length; i < ilen; i++) {
17097            var headerPair = headerPairs[i];
17098            var index = headerPair.indexOf(': ');
17099            if (index > 0) {
17100                headers[headerPair.substring(0, index)] = headerPair.substring(index + 2);
17101            }
17102        }
17103        return headers;
17104    }
17105
17106    function findRepresentationIndex(period, representationId) {
17107        var index = findRepresentation(period, representationId, true);
17108
17109        if (index !== null) {
17110            return index;
17111        }
17112
17113        return -1;
17114    }
17115
17116    function findRepresentation(period, representationId, returnIndex) {
17117        var adaptationSet = undefined,
17118            adaptationSetArray = undefined,
17119            representation = undefined,
17120            representationArray = undefined,
17121            adaptationSetArrayIndex = undefined,
17122            representationArrayIndex = undefined;
17123
17124        if (period) {
17125            adaptationSetArray = period.AdaptationSet_asArray;
17126            for (adaptationSetArrayIndex = 0; adaptationSetArrayIndex < adaptationSetArray.length; adaptationSetArrayIndex = adaptationSetArrayIndex + 1) {
17127                adaptationSet = adaptationSetArray[adaptationSetArrayIndex];
17128                representationArray = adaptationSet.Representation_asArray;
17129                for (representationArrayIndex = 0; representationArrayIndex < representationArray.length; representationArrayIndex = representationArrayIndex + 1) {
17130                    representation = representationArray[representationArrayIndex];
17131                    if (representationId === representation.id) {
17132                        if (returnIndex) {
17133                            return representationArrayIndex;
17134                        } else {
17135                            return representation;
17136                        }
17137                    }
17138                }
17139            }
17140        }
17141
17142        return null;
17143    }
17144
17145    function adaptationIsType(adaptation, bufferType) {
17146        return dashManifestModel.getIsTypeOf(adaptation, bufferType);
17147    }
17148
17149    function findMaxBufferIndex(period, bufferType) {
17150        var adaptationSet = undefined,
17151            adaptationSetArray = undefined,
17152            representationArray = undefined,
17153            adaptationSetArrayIndex = undefined;
17154
17155        if (!period || !bufferType) return -1;
17156
17157        adaptationSetArray = period.AdaptationSet_asArray;
17158        for (adaptationSetArrayIndex = 0; adaptationSetArrayIndex < adaptationSetArray.length; adaptationSetArrayIndex = adaptationSetArrayIndex + 1) {
17159            adaptationSet = adaptationSetArray[adaptationSetArrayIndex];
17160            representationArray = adaptationSet.Representation_asArray;
17161            if (adaptationIsType(adaptationSet, bufferType)) {
17162                return representationArray.length;
17163            }
17164        }
17165
17166        return -1;
17167    }
17168
17169    instance = {
17170        getBandwidthForRepresentation: getBandwidthForRepresentation,
17171        getIndexForRepresentation: getIndexForRepresentation,
17172        getMaxIndexForBufferType: getMaxIndexForBufferType,
17173        getCurrentRepresentationSwitch: getCurrentRepresentationSwitch,
17174        getLatestBufferLevelVO: getLatestBufferLevelVO,
17175        getCurrentBufferLevel: getCurrentBufferLevel,
17176        getCurrentHttpRequest: getCurrentHttpRequest,
17177        getHttpRequests: getHttpRequests,
17178        getCurrentDroppedFrames: getCurrentDroppedFrames,
17179        getCurrentSchedulingInfo: getCurrentSchedulingInfo,
17180        getCurrentDVRInfo: getCurrentDVRInfo,
17181        getCurrentManifestUpdate: getCurrentManifestUpdate,
17182        getLatestFragmentRequestHeaderValueByID: getLatestFragmentRequestHeaderValueByID,
17183        getLatestMPDRequestHeaderValueByID: getLatestMPDRequestHeaderValueByID,
17184        getRequestsQueue: getRequestsQueue
17185    };
17186
17187    return instance;
17188}
17189
17190DashMetrics.__dashjs_factory_name = 'DashMetrics';
17191exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(DashMetrics);
17192module.exports = exports['default'];
17193
17194},{"101":101,"224":224,"43":43,"51":51}],59:[function(_dereq_,module,exports){
17195/**
17196 * The copyright in this software is being made available under the BSD License,
17197 * included below. This software may be subject to other third party and contributor
17198 * rights, including patent rights, and no such rights are granted under this license.
17199 *
17200 * Copyright (c) 2013, Dash Industry Forum.
17201 * All rights reserved.
17202 *
17203 * Redistribution and use in source and binary forms, with or without modification,
17204 * are permitted provided that the following conditions are met:
17205 *  * Redistributions of source code must retain the above copyright notice, this
17206 *  list of conditions and the following disclaimer.
17207 *  * Redistributions in binary form must reproduce the above copyright notice,
17208 *  this list of conditions and the following disclaimer in the documentation and/or
17209 *  other materials provided with the distribution.
17210 *  * Neither the name of Dash Industry Forum nor the names of its
17211 *  contributors may be used to endorse or promote products derived from this software
17212 *  without specific prior written permission.
17213 *
17214 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
17215 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17216 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17217 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
17218 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
17218INCLUDING, BUT
17219 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
17220 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
17221 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
17222 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
17223 *  POSSIBILITY OF SUCH DAMAGE.
17224 */
17225'use strict';
17226
17227Object.defineProperty(exports, '__esModule', {
17228    value: true
17229});
17230
17231function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
17232
17233var _streamingUtilsRequestModifier = _dereq_(200);
17234
17235var _streamingUtilsRequestModifier2 = _interopRequireDefault(_streamingUtilsRequestModifier);
17236
17237var _voSegment = _dereq_(88);
17238
17239var _voSegment2 = _interopRequireDefault(_voSegment);
17240
17241var _streamingVoDashJSError = _dereq_(207);
17242
17243var _streamingVoDashJSError2 = _interopRequireDefault(_streamingVoDashJSError);
17244
17245var _coreEventsEvents = _dereq_(54);
17246
17247var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
17248
17249var _coreEventBus = _dereq_(50);
17250
17251var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
17252
17253var _streamingUtilsBoxParser = _dereq_(190);
17254
17255var _streamingUtilsBoxParser2 = _interopRequireDefault(_streamingUtilsBoxParser);
17256
17257var _coreFactoryMaker = _dereq_(51);
17258
17259var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
17260
17261var _coreDebug = _dereq_(49);
17262
17263var _coreDebug2 = _interopRequireDefault(_coreDebug);
17264
17265var _streamingVoMetricsHTTPRequest = _dereq_(224);
17266
17267var _streamingVoFragmentRequest = _dereq_(209);
17268
17269var _streamingVoFragmentRequest2 = _interopRequireDefault(_streamingVoFragmentRequest);
17270
17271var _streamingXHRLoader = _dereq_(98);
17272
17273var _streamingXHRLoader2 = _interopRequireDefault(_streamingXHRLoader);
17274
17275function SegmentBaseLoader() {
17276
17277    var context = this.context;
17278    var log = (0, _coreDebug2['default'])(context).getInstance().log;
17279    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
17280
17281    var instance = undefined,
17282        errHandler = undefined,
17283        boxParser = undefined,
17284        requestModifier = undefined,
17285        metricsModel = undefined,
17286        mediaPlayerModel = undefined,
17287        xhrLoader = undefined,
17288        baseURLController = undefined;
17289
17290    function initialize() {
17291        boxParser = (0, _streamingUtilsBoxParser2['default'])(context).getInstance();
17292        requestModifier = (0, _streamingUtilsRequestModifier2['default'])(context).getInstance();
17293        xhrLoader = (0, _streamingXHRLoader2['default'])(context).create({
17294            errHandler: errHandler,
17295            metricsModel: metricsModel,
17296            mediaPlayerModel: mediaPlayerModel,
17297            requestModifier: requestModifier
17298        });
17299    }
17300
17301    function setConfig(config) {
17302        if (config.baseURLController) {
17303            baseURLController = config.baseURLController;
17304        }
17305
17306        if (config.metricsModel) {
17307            metricsModel = config.metricsModel;
17308        }
17309
17310        if (config.mediaPlayerModel) {
17311            mediaPlayerModel = config.mediaPlayerModel;
17312        }
17313
17314        if (config.errHandler) {
17315            errHandler = config.errHandler;
17316        }
17317    }
17318
17319    function checkSetConfigCall() {
17320        if (!baseURLController || !baseURLController.hasOwnProperty('resolve')) {
17321            throw new Error('setConfig function has to be called previously');
17322        }
17323    }
17324
17325    function loadInitialization(representation, loadingInfo) {
17326        checkSetConfigCall();
17327        var initRange = null;
17328        var isoFile = null;
17329        var baseUrl = baseURLController.resolve(representation.path);
17330        var info = loadingInfo || {
17331            init: true,
17332            url: baseUrl ? baseUrl.url : undefined,
17333            range: {
17334                start: 0,
17335                end: 1500
17336            },
17337            searching: false,
17338            bytesLoaded: 0,
17339            bytesToLoad: 1500
17340        };
17341
17342        log('Start searching for initialization.');
17343
17344        var request = getFragmentRequest(info);
17345
17346        var onload = function onload(response) {
17347
17348            info.bytesLoaded = info.range.end;
17349            isoFile = boxParser.parse(response);
17350            initRange = findInitRange(isoFile);
17351
17352            if (initRange) {
17353                representation.range = initRange;
17354                // note that we don't explicitly set rep.initialization as this
17355                // will be computed when all BaseURLs are resolved later
17356                eventBus.trigger(_coreEventsEvents2['default'].INITIALIZATION_LOADED, { representation: representation });
17357            } else {
17358                info.range.end = info.bytesLoaded + info.bytesToLoad;
17359                loadInitialization(representation, info);
17360            }
17361        };
17362
17363        var onerror = function onerror() {
17364            eventBus.trigger(_coreEventsEvents2['default'].INITIALIZATION_LOADED, { representation: representation });
17365        };
17366
17367        xhrLoader.load({ request: request, success: onload, error: onerror });
17368
17369        log('Perform init search: ' + info.url);
17370    }
17371
17372    function loadSegments(representation, type, range, loadingInfo, callback) {
17373        checkSetConfigCall();
17374        if (range && (range.start === undefined || range.end === undefined)) {
17375            var parts = range ? range.toString().split('-') : null;
17376            range = parts ? { start: parseFloat(parts[0]), end: parseFloat(parts[1]) } : null;
17377        }
17378
17379        callback = !callback ? onLoaded : callback;
17380        var isoFile = null;
17381        var sidx = null;
17382        var hasRange = !!range;
17383        var baseUrl = baseURLController.resolve(representation.path);
17384        var info = {
17385            init: false,
17386            url: baseUrl ? baseUrl.url : undefined,
17387            range: hasRange ? range : { start: 0, end: 1500 },
17388            searching: !hasRange,
17389            bytesLoaded: loadingInfo ? loadingInfo.bytesLoaded : 0,
17390            bytesToLoad: 1500
17391        };
17392
17393        var request = getFragmentRequest(info);
17394
17395        var onload = function onload(response) {
17396            var extraBytes = info.bytesToLoad;
17397            var loadedLength = response.byteLength;
17398
17399            info.bytesLoaded = info.range.end - info.range.start;
17400            isoFile = boxParser.parse(response);
17401            sidx = isoFile.getBox('sidx');
17402
17403            if (!sidx || !sidx.isComplete) {
17404                if (sidx) {
17405                    info.range.start = sidx.offset || info.range.start;
17406                    info.range.end = info.range.start + (sidx.size || extraBytes);
17407                } else if (loadedLength < info.bytesLoaded) {
17408                    // if we have reached a search limit or if we have reached the end of the file we have to stop trying to find sidx
17409                    callback(null, representation, type);
17410                    return;
17411                } else {
17412                    var lastBox = isoFile.getLastBox();
17413
17414                    if (lastBox && lastBox.size) {
17415                        info.range.start = lastBox.offset + lastBox.size;
17416                        info.range.end = info.range.start + extraBytes;
17417                    } else {
17418                        info.range.end += extraBytes;
17419                    }
17420                }
17421                loadSegments(representation, type, info.range, info, callback);
17422            } else {
17423                var ref = sidx.references;
17424                var loadMultiSidx = undefined,
17425                    segments = undefined;
17426
17427                if (ref !== null && ref !== undefined && ref.length > 0) {
17428                    loadMultiSidx = ref[0].reference_type === 1;
17429                }
17430
17431                if (loadMultiSidx) {
17432                    (function () {
17433                        log('Initiate multiple SIDX load.');
17434                        info.range.end = info.range.start + sidx.size;
17435
17436                        var j = undefined,
17437                            len = undefined,
17438                            ss = undefined,
17439                            se = undefined,
17440                            r = undefined;
17441                        var segs = [];
17442                        var count = 0;
17443                        var offset = (sidx.offset || info.range.start) + sidx.size;
17444                        var tmpCallback = function tmpCallback(result) {
17445                            if (result) {
17446                                segs = segs.concat(result);
17447                                count++;
17448
17449                                if (count >= len) {
17450                                    callback(segs, representation, type);
17451                                }
17452                            } else {
17453                                callback(null, representation, type);
17454                            }
17455                        };
17456
17457                        for (j = 0, len = ref.length; j < len; j++) {
17458                            ss = offset;
17459                            se = offset + ref[j].referenced_size - 1;
17460                            offset = offset + ref[j].referenced_size;
17461                            r = { start: ss, end: se };
17462                            loadSegments(representation, null, r, info, tmpCallback);
17463                        }
17464                    })();
17465                } else {
17466                    log('Parsing segments from SIDX.');
17467                    segments = getSegmentsForSidx(sidx, info);
17468                    callback(segments, representation, type);
17469                }
17470            }
17471        };
17472
17473        var onerror = function onerror() {
17474            callback(null, representation, type);
17475        };
17476
17477        xhrLoader.load({ request: request, success: onload, error: onerror });
17478        log('Perform SIDX load: ' + info.url);
17479    }
17480
17481    function reset() {
17482        xhrLoader.abort();
17483        xhrLoader = null;
17484        errHandler = null;
17485        boxParser = null;
17486        requestModifier = null;
17487    }
17488
17489    function getSegmentsForSidx(sidx, info) {
17490
17491        var refs = sidx.references;
17492        var len = refs.length;
17493        var timescale = sidx.timescale;
17494        var time = sidx.earliest_presentation_time;
17495        var start = info.range.start + sidx.offset + sidx.first_offset + sidx.size;
17496        var segments = [];
17497        var segment = undefined,
17498            end = undefined,
17499            duration = undefined,
17500            size = undefined;
17501
17502        for (var i = 0; i < len; i++) {
17503            duration = refs[i].subsegment_duration;
17504            size = refs[i].referenced_size;
17505
17506            segment = new _voSegment2['default']();
17507            // note that we don't explicitly set segment.media as this will be
17508            // computed when all BaseURLs are resolved later
17509            segment.duration = duration;
17510            segment.startTime = time;
17511            segment.timescale = timescale;
17512            end = start + size - 1;
17513            segment.mediaRange = start + '-' + end;
17514            segments.push(segment);
17515            time += duration;
17516            start += size;
17517        }
17518
17519        return segments;
17520    }
17521
17522    function findInitRange(isoFile) {
17523        var ftyp = isoFile.getBox('ftyp');
17524        var moov = isoFile.getBox('moov');
17525
17526        var initRange = null;
17527        var start = undefined,
17528            end = undefined;
17529
17530        log('Searching for initialization.');
17531
17532        if (moov && moov.isComplete) {
17533            start = ftyp ? ftyp.offset : moov.offset;
17534            end = moov.offset + moov.size - 1;
17535            initRange = start + '-' + end;
17536
17537            log('Found the initialization.  Range: ' + initRange);
17538        }
17539
17540        return initRange;
17541    }
17542
17543    function getFragmentRequest(info) {
17544        if (!info.url) {
17545            return;
17546        }
17547
17548        var request = new _streamingVoFragmentRequest2['default']();
17549
17550        request.type = info.init ? _streamingVoMetricsHTTPRequest.HTTPRequest.INIT_SEGMENT_TYPE : _streamingVoMetricsHTTPRequest.HTTPRequest.MEDIA_SEGMENT_TYPE;
17551        request.url = info.url;
17552        request.range = info.range.start + '-' + info.range.end;
17553
17554        return request;
17555    }
17556
17557    function onLoaded(segments, representation, type) {
17558        if (segments) {
17559            eventBus.trigger(_coreEventsEvents2['default'].SEGMENTS_LOADED, { segments: segments, representation: representation, mediaType: type });
17560        } else {
17561            eventBus.trigger(_coreEventsEvents2['default'].SEGMENTS_LOADED, { segments: null, representation: representation, mediaType: type, error: new _streamingVoDashJSError2['default'](null, 'error loading segments', null) });
17562        }
17563    }
17564
17565    instance = {
17566        setConfig: setConfig,
17567        initialize: initialize,
17568        loadInitialization: loadInitialization,
17569        loadSegments: loadSegments,
17570        reset: reset
17571    };
17572
17573    return instance;
17574}
17575
17576SegmentBaseLoader.__dashjs_factory_name = 'SegmentBaseLoader';
17577exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(SegmentBaseLoader);
17578module.exports = exports['default'];
17579
17580},{"190":190,"200":200,"207":207,"209":209,"224":224,"49":49,"50":50,"51":51,"54":54,"88":88,"98":98}],60:[function(_dereq_,module,exports){
17581'use strict';
17582
17583Object.defineProperty(exports, '__esModule', {
17584    value: true
17585});
17586
17587function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
17588
17589var _coreEventsEvents = _dereq_(54);
17590
17591var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
17592
17593var _coreEventBus = _dereq_(50);
17594
17595var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
17596
17597var _streamingUtilsEBMLParser = _dereq_(194);
17598
17599var _streamingUtilsEBMLParser2 = _interopRequireDefault(_streamingUtilsEBMLParser);
17600
17601var _coreFactoryMaker = _dereq_(51);
17602
17603var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
17604
17605var _coreDebug = _dereq_(49);
17606
17607var _coreDebug2 = _interopRequireDefault(_coreDebug);
17608
17609var _streamingUtilsRequestModifier = _dereq_(200);
17610
17611var _streamingUtilsRequestModifier2 = _interopRequireDefault(_streamingUtilsRequestModifier);
17612
17613var _voSegment = _dereq_(88);
17614
17615var _voSegment2 = _interopRequireDefault(_voSegment);
17616
17617var _streamingVoMetricsHTTPRequest = _dereq_(224);
17618
17619var _streamingVoFragmentRequest = _dereq_(209);
17620
17621var _streamingVoFragmentRequest2 = _interopRequireDefault(_streamingVoFragmentRequest);
17622
17623var _streamingXHRLoader = _dereq_(98);
17624
17625var _streamingXHRLoader2 = _interopRequireDefault(_streamingXHRLoader);
17626
17627function WebmSegmentBaseLoader() {
17628
17629    var context = this.context;
17630    var log = (0, _coreDebug2['default'])(context).getInstance().log;
17631    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
17632
17633    var instance = undefined,
17634        WebM = undefined,
17635        errHandler = undefined,
17636        requestModifier = undefined,
17637        metricsModel = undefined,
17638        mediaPlayerModel = undefined,
17639        xhrLoader = undefined,
17640        baseURLController = undefined;
17641
17642    function setup() {
17643        WebM = {
17644            EBML: {
17645                tag: 0x1A45DFA3,
17646                required: true
17647            },
17648            Segment: {
17649                tag: 0x18538067,
17650                required: true,
17651                SeekHead: {
17652                    tag: 0x114D9B74,
17653                    required: true
17654                },
17655                Info: {
17656                    tag: 0x1549A966,
17657                    required: true,
17658                    TimecodeScale: {
17659                        tag: 0x2AD7B1,
17660                        required: true,
17661                        parse: 'getMatroskaUint'
17662                    },
17663                    Duration: {
17664                        tag: 0x4489,
17665                        required: true,
17666                        parse: 'getMatroskaFloat'
17667                    }
17668                },
17669                Tracks: {
17670                    tag: 0x1654AE6B,
17671                    required: true
17672                },
17673                Cues: {
17674                    tag: 0x1C53BB6B,
17675                    required: true,
17676                    CuePoint: {
17677                        tag: 0xBB,
17678                        required: true,
17679                        CueTime: {
17680                            tag: 0xB3,
17681                            required: true,
17682                            parse: 'getMatroskaUint'
17683                        },
17684                        CueTrackPositions: {
17685                            tag: 0xB7,
17686                            required: true,
17687                            CueTrack: {
17688                                tag: 0xF7,
17689                                required: true,
17690                                parse: 'getMatroskaUint'
17691                            },
17692                            CueClusterPosition: {
17693                                tag: 0xF1,
17694                                required: true,
17695                                parse: 'getMatroskaUint'
17696                            },
17697                            CueBlockNumber: {
17698                                tag: 0x5378
17699                            }
17700                        }
17701                    }
17702                }
17703            },
17704            Void: {
17705                tag: 0xEC,
17706                required: true
17707            }
17708        };
17709    }
17710
17711    function initialize() {
17712        requestModifier = (0, _streamingUtilsRequestModifier2['default'])(context).getInstance();
17713        xhrLoader = (0, _streamingXHRLoader2['default'])(context).create({
17714            errHandler: errHandler,
17715            metricsModel: metricsModel,
17716            mediaPlayerModel: mediaPlayerModel,
17717            requestModifier: requestModifier
17718        });
17719    }
17720
17721    function setConfig(config) {
17722        if (!config.baseURLController || !config.metricsModel || !config.mediaPlayerModel || !config.errHandler) {
17723            throw new Error('Missing config parameter(s)');
17724        }
17725        baseURLController = config.baseURLController;
17726        metricsModel = config.metricsModel;
17727        mediaPlayerModel = config.mediaPlayerModel;
17728        errHandler = config.errHandler;
17729    }
17730
17731    function parseCues(ab) {
17732        var cues = [];
17733        var cue = undefined;
17734        var cueSize = undefined;
17735        var cueTrack = undefined;
17736        var ebmlParser = (0, _streamingUtilsEBMLParser2['default'])(context).create({
17737            data: ab
17738        });
17739        var numSize = undefined;
17740
17741        ebmlParser.consumeTag(WebM.Segment.Cues);
17742        cueSize = ebmlParser.getMatroskaCodedNum();
17743
17744        while (ebmlParser.moreData() && ebmlParser.consumeTagAndSize(WebM.Segment.Cues.CuePoint, true)) {
17745            cue = {};
17746
17747            cue.CueTime = ebmlParser.parseTag(WebM.Segment.Cues.CuePoint.CueTime);
17748
17749            cue.CueTracks = [];
17750            while (ebmlParser.moreData() && ebmlParser.consumeTagAndSize(WebM.Segment.Cues.CuePoint.CueTrackPositions, true)) {
17751                cueTrack = {};
17752
17753                cueTrack.Track = ebmlParser.parseTag(WebM.Segment.Cues.CuePoint.CueTrackPositions.CueTrack);
17754                if (cueTrack.Track === 0) {
17755                    throw new Error('Cue track cannot be 0');
17756                }
17757
17758                cueTrack.ClusterPosition = ebmlParser.parseTag(WebM.Segment.Cues.CuePoint.CueTrackPositions.CueClusterPosition);
17759
17760                // block number is strictly optional.
17761                // we also have to make sure we don't go beyond the end
17762                // of the cues
17763                if (ebmlParser.getPos() + 4 > cueSize || !ebmlParser.consumeTag(WebM.Segment.Cues.CuePoint.CueTrackPositions.CueBlockNumber, true)) {
17764                    cue.CueTracks.push(cueTrack);
17765                } else {
17766                    // since we have already consumed the tag, get the size of
17767                    // the tag's payload, and manually parse an unsigned int
17768                    // from the bit stream
17769                    numSize = ebmlParser.getMatroskaCodedNum();
17770                    cueTrack.BlockNumber = ebmlParser.getMatroskaUint(numSize);
17771
17772                    cue.CueTracks.push(cueTrack);
17773                }
17774            }
17775
17776            if (cue.CueTracks.length === 0) {
17777                throw new Error('Mandatory cuetrack not found');
17778            }
17779            cues.push(cue);
17780        }
17781
17782        if (cues.length === 0) {
17783            throw new Error('mandatory cuepoint not found');
17784        }
17785        return cues;
17786    }
17787
17788    function parseSegments(data, segmentStart, segmentEnd, segmentDuration) {
17789        var duration = undefined;
17790        var parsed = undefined;
17791        var segments = undefined;
17792        var segment = undefined;
17793        var i = undefined;
17794        var len = undefined;
17795        var start = undefined;
17796        var end = undefined;
17797
17798        parsed = parseCues(data);
17799        segments = [];
17800
17801        // we are assuming one cue track per cue point
17802        // both duration and media range require the i + 1 segment
17803        // the final segment has to use global segment parameters
17804        for (i = 0, len = parsed.length; i < len; i += 1) {
17805            segment = new _voSegment2['default']();
17806            duration = 0;
17807
17808            if (i < parsed.length - 1) {
17809                duration = parsed[i + 1].CueTime - parsed[i].CueTime;
17810            } else {
17811                duration = segmentDuration - parsed[i].CueTime;
17812            }
17813
17814            // note that we don't explicitly set segment.media as this will be
17815            // computed when all BaseURLs are resolved later
17816            segment.duration = duration;
17817            segment.startTime = parsed[i].CueTime;
17818            segment.timescale = 1000; // hardcoded for ms
17819            start = parsed[i].CueTracks[0].ClusterPosition + segmentStart;
17820
17821            if (i < parsed.length - 1) {
17822                end = parsed[i + 1].CueTracks[0].ClusterPosition + segmentStart - 1;
17823            } else {
17824                end = segmentEnd - 1;
17825            }
17826
17827            segment.mediaRange = start + '-' + end;
17828            segments.push(segment);
17829        }
17830
17831        log('Parsed cues: ' + segments.length + ' cues.');
17832
17833        return segments;
17834    }
17835
17836    function parseEbmlHeader(data, media, theRange, callback) {
17837        var ebmlParser = (0, _streamingUtilsEBMLParser2['default'])(context).create({
17838            data: data
17839        });
17840        var duration = undefined;
17841        var segments = undefined;
17842        var parts = theRange.split('-');
17843        var request = null;
17844        var info = {
17845            url: media,
17846            range: {
17847                start: parseFloat(parts[0]),
17848                end: parseFloat(parts[1])
17849            },
17850            request: request
17851        };
17852        var segmentEnd = undefined;
17853        var segmentStart = undefined;
17854
17855        log('Parse EBML header: ' + info.url);
17856
17857        // skip over the header itself
17858        ebmlParser.skipOverElement(WebM.EBML);
17859        ebmlParser.consumeTag(WebM.Segment);
17860
17861        // segments start here
17862        segmentEnd = ebmlParser.getMatroskaCodedNum();
17863        segmentEnd += ebmlParser.getPos();
17864        segmentStart = ebmlParser.getPos();
17865
17866        // skip over any top level elements to get to the segment info
17867        while (ebmlParser.moreData() && !ebmlParser.consumeTagAndSize(WebM.Segment.Info, true)) {
17868            if (!(ebmlParser.skipOverElement(WebM.Segment.SeekHead, true) || ebmlParser.skipOverElement(WebM.Segment.Tracks, true) || ebmlParser.skipOverElement(WebM.Segment.Cues, true) || ebmlParser.skipOverElement(WebM.Void, true))) {
17869                throw new Error('no valid top level element found');
17870            }
17871        }
17872
17873        // we only need one thing in segment info, duration
17874        while (duration === undefined) {
17875            var infoTag = ebmlParser.getMatroskaCodedNum(true);
17876            var infoElementSize = ebmlParser.getMatroskaCodedNum();
17877
17878            switch (infoTag) {
17879                case WebM.Segment.Info.Duration.tag:
17880                    duration = ebmlParser[WebM.Segment.Info.Duration.parse](infoElementSize);
17881                    break;
17882                default:
17883                    ebmlParser.setPos(ebmlParser.getPos() + infoElementSize);
17884                    break;
17885            }
17886        }
17887
17888        // once we have what we need from segment info, we jump right to the
17889        // cues
17890
17891        request = getFragmentRequest(info);
17892
17893        var onload = function onload(response) {
17894            segments = parseSegments(response, segmentStart, segmentEnd, duration);
17895            callback(segments);
17896        };
17897
17898        var onloadend = function onloadend() {
17899            log('Download Error: Cues ' + info.url);
17900            callback(null);
17901        };
17902
17903        xhrLoader.load({
17904            request: request,
17905            success: onload,
17906            error: onloadend
17907        });
17908
17909        log('Perform cues load: ' + info.url + ' bytes=' + info.range.start + '-' + info.range.end);
17910    }
17911
17912    function checkSetConfigCall() {
17913        if (!baseURLController || !baseURLController.hasOwnProperty('resolve')) {
17914            throw new Error('setConfig function has to be called previously');
17915        }
17916    }
17917
17918    function loadInitialization(representation, loadingInfo) {
17919        checkSetConfigCall();
17920        var request = null;
17921        var baseUrl = baseURLController.resolve(representation.path);
17922        var media = baseUrl ? baseUrl.url : undefined;
17923        var initRange = representation.range.split('-');
17924        var info = loadingInfo || {
17925            range: {
17926                start: parseFloat(initRange[0]),
17927                end: parseFloat(initRange[1])
17928            },
17929            request: request,
17930            url: media,
17931            init: true
17932        };
17933
17934        log('Start loading initialization.');
17935
17936        request = getFragmentRequest(info);
17937
17938        var onload = function onload() {
17939            // note that we don't explicitly set rep.initialization as this
17940            // will be computed when all BaseURLs are resolved later
17941            eventBus.trigger(_coreEventsEvents2['default'].INITIALIZATION_LOADED, {
17942                representation: representation
17943            });
17944        };
17945
17946        var onloadend = function onloadend() {
17947            eventBus.trigger(_coreEventsEvents2['default'].INITIALIZATION_LOADED, {
17948                representation: representation
17949            });
17950        };
17951
17952        xhrLoader.load({
17953            request: request,
17954            success: onload,
17955            error: onloadend
17956        });
17957
17958        log('Perform init load: ' + info.url);
17959    }
17960
17961    function loadSegments(representation, type, theRange, callback) {
17962        checkSetConfigCall();
17963        var request = null;
17964        var baseUrl = baseURLController.resolve(representation.path);
17965        var media = baseUrl ? baseUrl.url : undefined;
17966        var bytesToLoad = 8192;
17967        var info = {
17968            bytesLoaded: 0,
17969            bytesToLoad: bytesToLoad,
17970            range: {
17971                start: 0,
17972                end: bytesToLoad
17973            },
17974            request: request,
17975            url: media,
17976            init: false
17977        };
17978
17979        callback = !callback ? onLoaded : callback;
17980        request = getFragmentRequest(info);
17981
17982        // first load the header, but preserve the manifest range so we can
17983        // load the cues after parsing the header
17984        // NOTE: we expect segment info to appear in the first 8192 bytes
17985        log('Parsing ebml header');
17986
17987        var onload = function onload(response) {
17988            parseEbmlHeader(response, media, theRange, function (segments) {
17989                callback(segments, representation, type);
17990            });
17991        };
17992
17993        var onloadend = function onloadend() {
17994            callback(null, representation, type);
17995        };
17996
17997        xhrLoader.load({
17998            request: request,
17999            success: onload,
18000            error: onloadend
18001        });
18002    }
18003
18004    function onLoaded(segments, representation, type) {
18005        if (segments) {
18006            eventBus.trigger(_coreEventsEvents2['default'].SEGMENTS_LOADED, {
18007                segments: segments,
18008                representation: representation,
18009                mediaType: type
18010            });
18011        } else {
18012            eventBus.trigger(_coreEventsEvents2['default'].SEGMENTS_LOADED, {
18013                segments: null,
18014                representation: representation,
18015                mediaType: type,
18016                error: new Error(null, 'error loading segments', null)
18017            });
18018        }
18019    }
18020
18021    function getFragmentRequest(info) {
18022        var request = new _streamingVoFragmentRequest2['default']();
18023
18024        request.type = info.init ? _streamingVoMetricsHTTPRequest.HTTPRequest.INIT_SEGMENT_TYPE : _streamingVoMetricsHTTPRequest.HTTPRequest.MEDIA_SEGMENT_TYPE;
18025        request.url = info.url;
18026        request.range = info.range.start + '-' + info.range.end;
18027
18028        return request;
18029    }
18030
18031    function reset() {
18032        errHandler = null;
18033        requestModifier = null;
18034        log = null;
18035    }
18036
18037    instance = {
18038        setConfig: setConfig,
18039        initialize: initialize,
18040        loadInitialization: loadInitialization,
18041        loadSegments: loadSegments,
18042        reset: reset
18043    };
18044
18045    setup();
18046
18047    return instance;
18048}
18049
18050WebmSegmentBaseLoader.__dashjs_factory_name = 'WebmSegmentBaseLoader';
18051exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(WebmSegmentBaseLoader);
18052module.exports = exports['default'];
18053
18054}
18054,{"194":194,"200":200,"209":209,"224":224,"49":49,"50":50,"51":51,"54":54,"88":88,"98":98}],61:[function(_dereq_,module,exports){
18055/**
18056 * The copyright in this software is being made available under the BSD License,
18057 * included below. This software may be subject to other third party and contributor
18058 * rights, including patent rights, and no such rights are granted under this license.
18059 *
18060 * Copyright (c) 2013, Dash Industry Forum.
18061 * All rights reserved.
18062 *
18063 * Redistribution and use in source and binary forms, with or without modification,
18064 * are permitted provided that the following conditions are met:
18065 *  * Redistributions of source code must retain the above copyright notice, this
18066 *  list of conditions and the following disclaimer.
18067 *  * Redistributions in binary form must reproduce the above copyright notice,
18068 *  this list of conditions and the following disclaimer in the documentation and/or
18069 *  other materials provided with the distribution.
18070 *  * Neither the name of Dash Industry Forum nor the names of its
18071 *  contributors may be used to endorse or promote products derived from this software
18072 *  without specific prior written permission.
18073 *
18074 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
18075 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18076 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18077 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18078 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18079 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
18080 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
18081 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
18082 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
18083 *  POSSIBILITY OF SUCH DAMAGE.
18084 */
18085
18086/**
18087 * Dash constants declaration
18088 * @class
18089 * @ignore
18090 */
18091'use strict';
18092
18093Object.defineProperty(exports, '__esModule', {
18094    value: true
18095});
18096
18097var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
18098
18099function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
18100
18101var DashConstants = (function () {
18102    _createClass(DashConstants, [{
18103        key: 'init',
18104        value: function init() {
18105            this.BASE_URL = 'BaseURL';
18106            this.SEGMENT_BASE = 'SegmentBase';
18107            this.SEGMENT_TEMPLATE = 'SegmentTemplate';
18108            this.SEGMENT_LIST = 'SegmentList';
18109            this.SEGMENT_URL = 'SegmentURL';
18110            this.SEGMENT_TIMELINE = 'SegmentTimeline';
18111            this.SEGMENT_PROFILES = 'segmentProfiles';
18112            this.ADAPTATION_SET = 'AdaptationSet';
18113            this.REPRESENTATION = 'Representation';
18114            this.REPRESENTATION_INDEX = 'RepresentationIndex';
18115            this.SUB_REPRESENTATION = 'SubRepresentation';
18116            this.INITIALIZATION = 'Initialization';
18117            this.INITIALIZATION_MINUS = 'initialization';
18118            this.MPD = 'MPD';
18119            this.PERIOD = 'Period';
18120            this.ASSET_IDENTIFIER = 'AssetIdentifier';
18121            this.EVENT_STREAM = 'EventStream';
18122            this.ID = 'id';
18123            this.PROFILES = 'profiles';
18124            this.SERVICE_LOCATION = 'serviceLocation';
18125            this.RANGE = 'range';
18126            this.INDEX = 'index';
18127            this.MEDIA = 'media';
18128            this.BYTE_RANGE = 'byteRange';
18129            this.INDEX_RANGE = 'indexRange';
18130            this.MEDIA_RANGE = 'mediaRange';
18131            this.VALUE = 'value';
18132            this.CONTENT_TYPE = 'contentType';
18133            this.MIME_TYPE = 'mimeType';
18134            this.BITSTREAM_SWITCHING = 'BitstreamSwitching';
18135            this.BITSTREAM_SWITCHING_MINUS = 'bitstreamSwitching';
18136            this.CODECS = 'codecs';
18137            this.DEPENDENCY_ID = 'dependencyId';
18138            this.MEDIA_STREAM_STRUCTURE_ID = 'mediaStreamStructureId';
18139            this.METRICS = 'Metrics';
18140            this.METRICS_MINUS = 'metrics';
18141            this.REPORTING = 'Reporting';
18142            this.WIDTH = 'width';
18143            this.HEIGHT = 'height';
18144            this.SAR = 'sar';
18145            this.FRAMERATE = 'frameRate';
18146            this.AUDIO_SAMPLING_RATE = 'audioSamplingRate';
18147            this.MAXIMUM_SAP_PERIOD = 'maximumSAPPeriod';
18148            this.START_WITH_SAP = 'startWithSAP';
18149            this.MAX_PLAYOUT_RATE = 'maxPlayoutRate';
18150            this.CODING_DEPENDENCY = 'codingDependency';
18151            this.SCAN_TYPE = 'scanType';
18152            this.FRAME_PACKING = 'FramePacking';
18153            this.AUDIO_CHANNEL_CONFIGURATION = 'AudioChannelConfiguration';
18154            this.CONTENT_PROTECTION = 'ContentProtection';
18155            this.ESSENTIAL_PROPERTY = 'EssentialProperty';
18156            this.SUPPLEMENTAL_PROPERTY = 'SupplementalProperty';
18157            this.INBAND_EVENT_STREAM = 'InbandEventStream';
18158            this.ACCESSIBILITY = 'Accessibility';
18159            this.ROLE = 'Role';
18160            this.RATING = 'Rating';
18161            this.CONTENT_COMPONENT = 'ContentComponent';
18162            this.SUBSET = 'Subset';
18163            this.LANG = 'lang';
18164            this.VIEWPOINT = 'Viewpoint';
18165            this.ROLE_ASARRAY = 'Role_asArray';
18166            this.ACCESSIBILITY_ASARRAY = 'Accessibility_asArray';
18167            this.AUDIOCHANNELCONFIGURATION_ASARRAY = 'AudioChannelConfiguration_asArray';
18168            this.CONTENTPROTECTION_ASARRAY = 'ContentProtection_asArray';
18169            this.MAIN = 'main';
18170            this.DYNAMIC = 'dynamic';
18171            this.MEDIA_PRESENTATION_DURATION = 'mediaPresentationDuration';
18172            this.MINIMUM_UPDATE_PERIOD = 'minimumUpdatePeriod';
18173            this.CODEC_PRIVATE_DATA = 'codecPrivateData';
18174            this.BANDWITH = 'bandwidth';
18175            this.SOURCE_URL = 'sourceURL';
18176            this.TIMESCALE = 'timescale';
18177            this.DURATION = 'duration';
18178            this.START_NUMBER = 'startNumber';
18179            this.PRESENTATION_TIME_OFFSET = 'presentationTimeOffset';
18180            this.AVAILABILITY_START_TIME = 'availabilityStartTime';
18181            this.AVAILABILITY_END_TIME = 'availabilityEndTime';
18182            this.TIMESHIFT_BUFFER_DEPTH = 'timeShiftBufferDepth';
18183            this.MAX_SEGMENT_DURATION = 'maxSegmentDuration';
18184            this.PRESENTATION_TIME = 'presentationTime';
18185            this.MIN_BUFFER_TIME = 'minBufferTime';
18186            this.MAX_SUBSEGMENT_DURATION = 'maxSubsegmentDuration';
18187            this.START = 'start';
18188            this.CENC_DEFAULT_KID = 'cenc:default_KID';
18189            this.DVB_PRIORITY = 'dvb:priority';
18190            this.DVB_WEIGHT = 'dvb:weight';
18191        }
18192    }]);
18193
18194    function DashConstants() {
18195        _classCallCheck(this, DashConstants);
18196
18197        this.init();
18198    }
18199
18200    return DashConstants;
18201})();
18202
18203var constants = new DashConstants();
18204exports['default'] = constants;
18205module.exports = exports['default'];
18206
18207},{}],62:[function(_dereq_,module,exports){
18208/**
18209 * The copyright in this software is being made available under the BSD License,
18210 * included below. This software may be subject to other third party and contributor
18211 * rights, including patent rights, and no such rights are granted under this license.
18212 *
18213 * Copyright (c) 2013, Dash Industry Forum.
18214 * All rights reserved.
18215 *
18216 * Redistribution and use in source and binary forms, with or without modification,
18217 * are permitted provided that the following conditions are met:
18218 *  * Redistributions of source code must retain the above copyright notice, this
18219 *  list of conditions and the following disclaimer.
18220 *  * Redistributions in binary form must reproduce the above copyright notice,
18221 *  this list of conditions and the following disclaimer in the documentation and/or
18222 *  other materials provided with the distribution.
18223 *  * Neither the name of Dash Industry Forum nor the names of its
18224 *  contributors may be used to endorse or promote products derived from this software
18225 *  without specific prior written permission.
18226 *
18227 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
18228 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18229 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18230 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18231 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18232 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
18233 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
18234 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
18235 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
18236 *  POSSIBILITY OF SUCH DAMAGE.
18237 */
18238'use strict';
18239
18240Object.defineProperty(exports, '__esModule', {
18241    value: true
18242});
18243
18244function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
18245
18246var _streamingConstantsConstants = _dereq_(100);
18247
18248var _streamingConstantsConstants2 = _interopRequireDefault(_streamingConstantsConstants);
18249
18250var _constantsDashConstants = _dereq_(61);
18251
18252var _constantsDashConstants2 = _interopRequireDefault(_constantsDashConstants);
18253
18254var _streamingVoDashJSError = _dereq_(207);
18255
18256var _streamingVoDashJSError2 = _interopRequireDefault(_streamingVoDashJSError);
18257
18258var _coreEventBus = _dereq_(50);
18259
18260var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
18261
18262var _coreEventsEvents = _dereq_(54);
18263
18264var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
18265
18266var _streamingMediaPlayerEvents = _dereq_(94);
18267
18268var _streamingMediaPlayerEvents2 = _interopRequireDefault(_streamingMediaPlayerEvents);
18269
18270var _coreFactoryMaker = _dereq_(51);
18271
18272var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
18273
18274var _voRepresentation = _dereq_(87);
18275
18276var _voRepresentation2 = _interopRequireDefault(_voRepresentation);
18277
18278function RepresentationController() {
18279
18280    var SEGMENTS_UPDATE_FAILED_ERROR_CODE = 1;
18281
18282    var context = this.context;
18283    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
18284
18285    var instance = undefined,
18286        realAdaptation = undefined,
18287        realAdaptationIndex = undefined,
18288        updating = undefined,
18289        voAvailableRepresentations = undefined,
18290        currentVoRepresentation = undefined,
18291        abrController = undefined,
18292        indexHandler = undefined,
18293        playbackController = undefined,
18294        metricsModel = undefined,
18295        domStorage = undefined,
18296        timelineConverter = undefined,
18297        dashManifestModel = undefined,
18298        dashMetrics = undefined,
18299        streamProcessor = undefined,
18300        manifestModel = undefined;
18301
18302    function setup() {
18303        resetInitialSettings();
18304
18305        eventBus.on(_coreEventsEvents2['default'].QUALITY_CHANGE_REQUESTED, onQualityChanged, instance);
18306        eventBus.on(_coreEventsEvents2['default'].REPRESENTATION_UPDATED, onRepresentationUpdated, instance);
18307        eventBus.on(_coreEventsEvents2['default'].WALLCLOCK_TIME_UPDATED, onWallclockTimeUpdated, instance);
18308        eventBus.on(_coreEventsEvents2['default'].BUFFER_LEVEL_UPDATED, onBufferLevelUpdated, instance);
18309    }
18310
18311    function setConfig(config) {
18312        // allow the abrController created in setup to be overidden
18313        if (config.abrController) {
18314            abrController = config.abrController;
18315        }
18316        if (config.domStorage) {
18317            domStorage = config.domStorage;
18318        }
18319        if (config.metricsModel) {
18320            metricsModel = config.metricsModel;
18321        }
18322        if (config.dashMetrics) {
18323            dashMetrics = config.dashMetrics;
18324        }
18325        if (config.dashManifestModel) {
18326            dashManifestModel = config.dashManifestModel;
18327        }
18328        if (config.playbackController) {
18329            playbackController = config.playbackController;
18330        }
18331        if (config.timelineConverter) {
18332            timelineConverter = config.timelineConverter;
18333        }
18334        if (config.manifestModel) {
18335            manifestModel = config.manifestModel;
18336        }
18337        if (config.streamProcessor) {
18338            streamProcessor = config.streamProcessor;
18339        }
18340    }
18341
18342    function initialize() {
18343        indexHandler = streamProcessor.getIndexHandler();
18344    }
18345
18346    function getStreamProcessor() {
18347        return streamProcessor;
18348    }
18349
18350    function getData() {
18351        return realAdaptation;
18352    }
18353
18354    function getDataIndex() {
18355        return realAdaptationIndex;
18356    }
18357
18358    function isUpdating() {
18359        return updating;
18360    }
18361
18362    function getCurrentRepresentation() {
18363        return currentVoRepresentation;
18364    }
18365
18366    function resetInitialSettings() {
18367        realAdaptation = null;
18368        realAdaptationIndex = -1;
18369        updating = true;
18370        voAvailableRepresentations = [];
18371        abrController = null;
18372        playbackController = null;
18373        metricsModel = null;
18374        domStorage = null;
18375        timelineConverter = null;
18376        dashManifestModel = null;
18377        dashMetrics = null;
18378    }
18379
18380    function reset() {
18381
18382        eventBus.off(_coreEventsEvents2['default'].QUALITY_CHANGE_REQUESTED, onQualityChanged, instance);
18383        eventBus.off(_coreEventsEvents2['default'].REPRESENTATION_UPDATED, onRepresentationUpdated, instance);
18384        eventBus.off(_coreEventsEvents2['default'].WALLCLOCK_TIME_UPDATED, onWallclockTimeUpdated, instance);
18385        eventBus.off(_coreEventsEvents2['default'].BUFFER_LEVEL_UPDATED, onBufferLevelUpdated, instance);
18386
18387        resetInitialSettings();
18388    }
18389
18390    function updateData(newRealAdaptation, voAdaptation, type) {
18391        var quality = undefined,
18392            averageThroughput = undefined;
18393
18394        var bitrate = null;
18395        var streamInfo = streamProcessor.getStreamInfo();
18396        var maxQuality = abrController.getTopQualityIndexFor(type, streamInfo.id);
18397
18398        updating = true;
18399        eventBus.trigger(_coreEventsEvents2['default'].DATA_UPDATE_STARTED, { sender: this });
18400
18401        voAvailableRepresentations = updateRepresentations(voAdaptation);
18402
18403        if (realAdaptation === null && type !== _streamingConstantsConstants2['default'].FRAGMENTED_TEXT) {
18404            averageThroughput = abrController.getThroughputHistory().getAverageThroughput(type);
18405            bitrate = averageThroughput || abrController.getInitialBitrateFor(type, streamInfo);
18406            quality = abrController.getQualityForBitrate(streamProcessor.getMediaInfo(), bitrate);
18407        } else {
18408            quality = abrController.getQualityFor(type, streamInfo);
18409        }
18410
18411        if (quality > maxQuality) {
18412            quality = maxQuality;
18413        }
18414
18415        currentVoRepresentation = getRepresentationForQuality(quality);
18416        realAdaptation = newRealAdaptation;
18417
18418        if (type !== _streamingConstantsConstants2['default'].VIDEO && type !== _streamingConstantsConstants2['default'].AUDIO && type !== _streamingConstantsConstants2['default'].FRAGMENTED_TEXT) {
18419            updating = false;
18420            eventBus.trigger(_coreEventsEvents2['default'].DATA_UPDATE_COMPLETED, { sender: this, data: realAdaptation, currentRepresentation: currentVoRepresentation });
18421            return;
18422        }
18423
18424        for (var i = 0; i < voAvailableRepresentations.length; i++) {
18425            indexHandler.updateRepresentation(voAvailableRepresentations[i], true);
18426        }
18427    }
18428
18429    function addRepresentationSwitch() {
18430        var now = new Date();
18431        var currentRepresentation = getCurrentRepresentation();
18432        var currentVideoTimeMs = playbackController.getTime() * 1000;
18433
18434        metricsModel.addRepresentationSwitch(currentRepresentation.adaptation.type, now, currentVideoTimeMs, currentRepresentation.id);
18435    }
18436
18437    function addDVRMetric() {
18438        var streamInfo = streamProcessor.getStreamInfo();
18439        var manifestInfo = streamInfo ? streamInfo.manifestInfo : null;
18440        var isDynamic = manifestInfo ? manifestInfo.isDynamic : null;
18441        var range = timelineConverter.calcSegmentAvailabilityRange(currentVoRepresentation, isDynamic);
18442        metricsModel.addDVRInfo(streamProcessor.getType(), playbackController.getTime(), manifestInfo, range);
18443    }
18444
18445    function getRepresentationForQuality(quality) {
18446        return voAvailableRepresentations[quality];
18447    }
18448
18449    function getQualityForRepresentation(voRepresentation) {
18450        return voAvailableRepresentations.indexOf(voRepresentation);
18451    }
18452
18453    function isAllRepresentationsUpdated() {
18454        for (var i = 0, ln = voAvailableRepresentations.length; i < ln; i++) {
18455            var segmentInfoType = voAvailableRepresentations[i].segmentInfoType;
18456            if (voAvailableRepresentations[i].segmentAvailabilityRange === null || !_voRepresentation2['default'].hasInitialization(voAvailableRepresentations[i]) || (segmentInfoType === _constantsDashConstants2['default'].SEGMENT_BASE || segmentInfoType === _constantsDashConstants2['default'].BASE_URL) && !voAvailableRepresentations[i].segments) {
18457                return false;
18458            }
18459        }
18460
18461        return true;
18462    }
18463
18464    function updateRepresentations(voAdaptation) {
18465        var voReps = undefined;
18466
18467        realAdaptationIndex = dashManifestModel.getIndexForAdaptation(realAdaptation, voAdaptation.period.mpd.manifest, voAdaptation.period.index);
18468        voReps = dashManifestModel.getRepresentationsForAdaptation(voAdaptation);
18469
18470        return voReps;
18471    }
18472
18473    function updateAvailabilityWindow(isDynamic) {
18474        var voRepresentation = undefined;
18475
18476        for (var i = 0, ln = voAvailableRepresentations.length; i < ln; i++) {
18477            voRepresentation = voAvailableRepresentations[i];
18478            voRepresentation.segmentAvailabilityRange = timelineConverter.calcSegmentAvailabilityRange(voRepresentation, isDynamic);
18479        }
18480    }
18481
18482    function resetAvailabilityWindow() {
18483        voAvailableRepresentations.forEach(function (rep) {
18484            rep.segmentAvailabilityRange = null;
18485        });
18486    }
18487
18488    function postponeUpdate(postponeTimePeriod) {
18489        var delay = postponeTimePeriod;
18490        var update = function update() {
18491            if (isUpdating()) return;
18492
18493            updating = true;
18494            eventBus.trigger(_coreEventsEvents2['default'].DATA_UPDATE_STARTED, { sender: instance });
18495
18496            // clear the segmentAvailabilityRange for all reps.
18497            // this ensures all are updated before the live edge search starts
18498            resetAvailabilityWindow();
18499
18500            for (var i = 0; i < voAvailableRepresentations.length; i++) {
18501                indexHandler.updateRepresentation(voAvailableRepresentations[i], true);
18502            }
18503        };
18504
18505        updating = false;
18506        eventBus.trigger(_streamingMediaPlayerEvents2['default'].AST_IN_FUTURE, { delay: delay });
18507        setTimeout(update, delay);
18508    }
18509
18510    function onRepresentationUpdated(e) {
18511        if (e.sender.getStreamProcessor() !== streamProcessor || !isUpdating()) return;
18512
18513        var r = e.representation;
18514        var streamMetrics = metricsModel.getMetricsFor(_streamingConstantsConstants2['default'].STREAM);
18515        var metrics = metricsModel.getMetricsFor(getCurrentRepresentation().adaptation.type);
18516        var manifestUpdateInfo = dashMetrics.getCurrentManifestUpdate(streamMetrics);
18517        var alreadyAdded = false;
18518        var postponeTimePeriod = 0;
18519        var repInfo = undefined,
18520            err = undefined,
18521            repSwitch = undefined;
18522
18523        if (r.adaptation.period.mpd.manifest.type === _constantsDashConstants2['default'].DYNAMIC && !r.adaptation.period.mpd.manifest.ignorePostponeTimePeriod) {
18524            var segmentAvailabilityTimePeriod = r.segmentAvailabilityRange.end - r.segmentAvailabilityRange.start;
18525            // We must put things to sleep unless till e.g. the startTime calculation in ScheduleController.onLiveEdgeSearchCompleted fall after the segmentAvailabilityRange.start
18526            var liveDelay = playbackController.computeLiveDelay(currentVoRepresentation.segmentDuration, streamProcessor.getStreamInfo().manifestInfo.DVRWindowSize);
18527            postponeTimePeriod = (liveDelay - segmentAvailabilityTimePeriod) * 1000;
18528        }
18529
18530        if (postponeTimePeriod > 0) {
18531            addDVRMetric();
18532            postponeUpdate(postponeTimePeriod);
18533            err = new _streamingVoDashJSError2['default'](SEGMENTS_UPDATE_FAILED_ERROR_CODE, 'Segments update failed', null);
18534            eventBus.trigger(_coreEventsEvents2['default'].DATA_UPDATE_COMPLETED, { sender: this, data: realAdaptation, currentRepresentation: currentVoRepresentation, error: err });
18535
18536            return;
18537        }
18538
18539        if (manifestUpdateInfo) {
18540            for (var i = 0; i < manifestUpdateInfo.representationInfo.length; i++) {
18541                repInfo = manifestUpdateInfo.representationInfo[i];
18542                if (repInfo.index === r.index && repInfo.mediaType === streamProcessor.getType()) {
18543                    alreadyAdded = true;
18544                    break;
18545                }
18546            }
18547
18548            if (!alreadyAdded) {
18549                metricsModel.addManifestUpdateRepresentationInfo(manifestUpdateInfo, r.id, r.index, r.adaptation.period.index, streamProcessor.getType(), r.presentationTimeOffset, r.startNumber, r.segmentInfoType);
18550            }
18551        }
18552
18553        if (isAllRepresentationsUpdated()) {
18554            updating = false;
18555            abrController.setPlaybackQuality(streamProcessor.getType(), streamProcessor.getStreamInfo(), getQualityForRepresentation(currentVoRepresentation));
18556            metricsModel.updateManifestUpdateInfo(manifestUpdateInfo, { latency: currentVoRepresentation.segmentAvailabilityRange.end - playbackController.getTime() });
18557
18558            repSwitch = dashMetrics.getCurrentRepresentationSwitch(metrics);
18559
18560            if (!repSwitch) {
18561                addRepresentationSwitch();
18562            }
18563
18564            eventBus.trigger(_coreEventsEvents2['default'].DATA_UPDATE_COMPLETED, { sender: this, data: realAdaptation, currentRepresentation: currentVoRepresentation });
18565        }
18566    }
18567
18568    function onWallclockTimeUpdated(e) {
18569        if (e.isDynamic) {
18570            updateAvailabilityWindow(e.isDynamic);
18571        }
18572    }
18573
18574    function onBufferLevelUpdated(e) {
18575        if (e.sender.getStreamProcessor() !== streamProcessor) return;
18576        var manifest = manifestModel.getValue();
18577        if (!manifest.doNotUpdateDVRWindowOnBufferUpdated) {
18578            addDVRMetric();
18579        }
18580    }
18581
18582    function onQualityChanged(e) {
18583        if (e.mediaType !== streamProcessor.getType() || streamProcessor.getStreamInfo().id !== e.streamInfo.id) return;
18584
18585        if (e.oldQuality !== e.newQuality) {
18586            currentVoRepresentation = getRepresentationForQuality(e.newQuality);
18587            var bitrate = abrController.getThroughputHistory().getAverageThroughput(e.mediaType);
18588            if (!isNaN(bitrate)) {
18589                domStorage.setSavedBitrateSettings(e.mediaType, bitrate);
18590            }
18591            addRepresentationSwitch();
18592        }
18593    }
18594
18595    instance = {
18596        initialize: initialize,
18597        setConfig: setConfig,
18598        getData: getData,
18599        getDataIndex: getDataIndex,
18600        isUpdating: isUpdating,
18601        updateData: updateData,
18602        getStreamProcessor: getStreamProcessor,
18603        getCurrentRepresentation: getCurrentRepresentation,
18604        getRepresentationForQuality: getRepresentationForQuality,
18605        reset: reset
18606    };
18607
18608    setup();
18609    return instance;
18610}
18611
18612RepresentationController.__dashjs_factory_name = 'RepresentationController';
18613exports['default'] = _coreFactoryMaker2['default'].getClassFactory(RepresentationController);
18614module.exports = exports['default'];
18615
18616},{"100":100,"207":207,"50":50,"51":51,"54":54,"61":61,"87":87,"94":94}],63:[function(_dereq_,module,exports){
18617/**
18618 * The copyright in this software is being made available under the BSD License,
18619 * included below. This software may be subject to other third party and contributor
18620 * rights, including patent rights, and no such rights are granted under this license.
18621 *
18622 * Copyright (c) 2013, Dash Industry Forum.
18623 * All rights reserved.
18624 *
18625 * Redistribution and use in source and binary forms, with or without modification,
18626 * are permitted provided that the following conditions are met:
18627 *  * Redistributions of source code must retain the above copyright notice, this
18628 *  list of conditions and the following disclaimer.
18629 *  * Redistributions in binary form must reproduce the above copyright notice,
18630 *  this list of conditions and the following disclaimer in the documentation and/or
18631 *  other materials provided with the distribution.
18632 *  * Neither the name of Dash Industry Forum nor the names of its
18633 *  contributors may be used to endorse or promote products derived from this software
18634 *  without specific prior written permission.
18635 *
18636 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
18637 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18638 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18639 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18640 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
18640INCLUDING, BUT
18641 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
18642 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
18643 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
18644 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
18645 *  POSSIBILITY OF SUCH DAMAGE.
18646 */
18647'use strict';
18648
18649Object.defineProperty(exports, '__esModule', {
18650    value: true
18651});
18652
18653function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
18654
18655var _streamingConstantsConstants = _dereq_(100);
18656
18657var _streamingConstantsConstants2 = _interopRequireDefault(_streamingConstantsConstants);
18658
18659var _constantsDashConstants = _dereq_(61);
18660
18661var _constantsDashConstants2 = _interopRequireDefault(_constantsDashConstants);
18662
18663var _voRepresentation = _dereq_(87);
18664
18665var _voRepresentation2 = _interopRequireDefault(_voRepresentation);
18666
18667var _voAdaptationSet = _dereq_(81);
18668
18669var _voAdaptationSet2 = _interopRequireDefault(_voAdaptationSet);
18670
18671var _voPeriod = _dereq_(86);
18672
18673var _voPeriod2 = _interopRequireDefault(_voPeriod);
18674
18675var _voMpd = _dereq_(85);
18676
18677var _voMpd2 = _interopRequireDefault(_voMpd);
18678
18679var _voUTCTiming = _dereq_(89);
18680
18681var _voUTCTiming2 = _interopRequireDefault(_voUTCTiming);
18682
18683var _voEvent = _dereq_(83);
18684
18685var _voEvent2 = _interopRequireDefault(_voEvent);
18686
18687var _voBaseURL = _dereq_(82);
18688
18689var _voBaseURL2 = _interopRequireDefault(_voBaseURL);
18690
18691var _voEventStream = _dereq_(84);
18692
18693var _voEventStream2 = _interopRequireDefault(_voEventStream);
18694
18695var _streamingUtilsObjectUtils = _dereq_(199);
18696
18697var _streamingUtilsObjectUtils2 = _interopRequireDefault(_streamingUtilsObjectUtils);
18698
18699var _streamingUtilsURLUtils = _dereq_(202);
18700
18701var _streamingUtilsURLUtils2 = _interopRequireDefault(_streamingUtilsURLUtils);
18702
18703var _coreFactoryMaker = _dereq_(51);
18704
18705var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
18706
18707function DashManifestModel(config) {
18708
18709    var instance = undefined;
18710    var context = this.context;
18711
18712    var urlUtils = (0, _streamingUtilsURLUtils2['default'])(context).getInstance();
18713    var mediaController = config.mediaController;
18714    var timelineConverter = config.timelineConverter;
18715    var adapter = config.adapter;
18716
18717    var PROFILE_DVB = 'urn:dvb:dash:profile:dvb-dash:2014';
18718    var isInteger = Number.isInteger || function (value) {
18719        return typeof value === 'number' && isFinite(value) && Math.floor(value) === value;
18720    };
18721
18722    function getIsTypeOf(adaptation, type) {
18723
18724        var i = undefined,
18725            len = undefined,
18726            representation = undefined,
18727            col = undefined,
18728            mimeTypeRegEx = undefined,
18729            codecs = undefined;
18730        var result = false;
18731        var found = false;
18732
18733        if (!adaptation) {
18734            throw new Error('adaptation is not defined');
18735        }
18736
18737        if (!type) {
18738            throw new Error('type is not defined');
18739        }
18740
18741        if (adaptation.hasOwnProperty('ContentComponent_asArray')) {
18742            col = adaptation.ContentComponent_asArray;
18743        }
18744
18745        mimeTypeRegEx = type !== _streamingConstantsConstants2['default'].TEXT ? new RegExp(type) : new RegExp('(vtt|ttml)');
18746
18747        if (adaptation.Representation_asArray && adaptation.Representation_asArray.length && adaptation.Representation_asArray.length > 0 && adaptation.Representation_asArray[0].hasOwnProperty(_constantsDashConstants2['default'].CODECS)) {
18748            // Just check the start of the codecs string
18749            codecs = adaptation.Representation_asArray[0].codecs;
18750            if (codecs.search(_streamingConstantsConstants2['default'].STPP) === 0 || codecs.search(_streamingConstantsConstants2['default'].WVTT) === 0) {
18751                return type === _streamingConstantsConstants2['default'].FRAGMENTED_TEXT;
18752            }
18753        }
18754
18755        if (col) {
18756            if (col.length > 1) {
18757                return type === _streamingConstantsConstants2['default'].MUXED;
18758            } else if (col[0] && col[0].contentType === type) {
18759                result = true;
18760                found = true;
18761            }
18762        }
18763
18764        if (adaptation.hasOwnProperty(_constantsDashConstants2['default'].MIME_TYPE)) {
18765            result = mimeTypeRegEx.test(adaptation.mimeType);
18766            found = true;
18767        }
18768
18769        // couldn't find on adaptationset, so check a representation
18770        if (!found) {
18771            i = 0;
18772            len = adaptation.Representation_asArray && adaptation.Representation_asArray.length ? adaptation.Representation_asArray.length : 0;
18773            while (!found && i < len) {
18774                representation = adaptation.Representation_asArray[i];
18775
18776                if (representation.hasOwnProperty(_constantsDashConstants2['default'].MIME_TYPE)) {
18777                    result = mimeTypeRegEx.test(representation.mimeType);
18778                    found = true;
18779                }
18780
18781                i++;
18782            }
18783        }
18784
18785        return result;
18786    }
18787
18788    function getIsAudio(adaptation) {
18789        return getIsTypeOf(adaptation, _streamingConstantsConstants2['default'].AUDIO);
18790    }
18791
18792    function getIsVideo(adaptation) {
18793        return getIsTypeOf(adaptation, _streamingConstantsConstants2['default'].VIDEO);
18794    }
18795
18796    function getIsFragmentedText(adaptation) {
18797        return getIsTypeOf(adaptation, _streamingConstantsConstants2['default'].FRAGMENTED_TEXT);
18798    }
18799
18800    function getIsText(adaptation) {
18801        return getIsTypeOf(adaptation, _streamingConstantsConstants2['default'].TEXT);
18802    }
18803
18804    function getIsMuxed(adaptation) {
18805        return getIsTypeOf(adaptation, _streamingConstantsConstants2['default'].MUXED);
18806    }
18807
18808    function getIsTextTrack(type) {
18809        return type === 'text/vtt' || type === 'application/ttml+xml';
18810    }
18811
18812    function getLanguageForAdaptation(adaptation) {
18813        var lang = '';
18814
18815        if (adaptation && adaptation.hasOwnProperty(_constantsDashConstants2['default'].LANG)) {
18816            //Filter out any other characters not allowed according to RFC5646
18817            lang = adaptation.lang.replace(/[^A-Za-z0-9-]/g, '');
18818        }
18819
18820        return lang;
18821    }
18822
18823    function getViewpointForAdaptation(adaptation) {
18824        return adaptation && adaptation.hasOwnProperty(_constantsDashConstants2['default'].VIEWPOINT) ? adaptation.Viewpoint : null;
18825    }
18826
18827    function getRolesForAdaptation(adaptation) {
18828        return adaptation && adaptation.hasOwnProperty(_constantsDashConstants2['default'].ROLE_ASARRAY) ? adaptation.Role_asArray : [];
18829    }
18830
18831    function getAccessibilityForAdaptation(adaptation) {
18832        return adaptation && adaptation.hasOwnProperty(_constantsDashConstants2['default'].ACCESSIBILITY_ASARRAY) ? adaptation.Accessibility_asArray : [];
18833    }
18834
18835    function getAudioChannelConfigurationForAdaptation(adaptation) {
18836        return adaptation && adaptation.hasOwnProperty(_constantsDashConstants2['default'].AUDIOCHANNELCONFIGURATION_ASARRAY) ? adaptation.AudioChannelConfiguration_asArray : [];
18837    }
18838
18839    function getIsMain(adaptation) {
18840        return getRolesForAdaptation(adaptation).filter(function (role) {
18841            return role.value === _constantsDashConstants2['default'].MAIN;
18842        })[0];
18843    }
18844
18845    function getRepresentationSortFunction() {
18846        return function (a, b) {
18847            return a.bandwidth - b.bandwidth;
18848        };
18849    }
18850
18851    function processAdaptation(realAdaptation) {
18852        if (realAdaptation && realAdaptation.Representation_asArray !== undefined && realAdaptation.Representation_asArray !== null) {
18853            realAdaptation.Representation_asArray.sort(getRepresentationSortFunction());
18854        }
18855
18856        return realAdaptation;
18857    }
18858
18859    function getAdaptationForId(id, manifest, periodIndex) {
18860        var realAdaptations = manifest && manifest.Period_asArray && isInteger(periodIndex) ? manifest.Period_asArray[periodIndex] ? manifest.Period_asArray[periodIndex].AdaptationSet_asArray : [] : [];
18861        var i = undefined,
18862            len = undefined;
18863
18864        for (i = 0, len = realAdaptations.length; i < len; i++) {
18865            if (realAdaptations[i].hasOwnProperty(_constantsDashConstants2['default'].ID) && realAdaptations[i].id === id) {
18866                return realAdaptations[i];
18867            }
18868        }
18869
18870        return null;
18871    }
18872
18873    function getAdaptationForIndex(index, manifest, periodIndex) {
18874        var realAdaptations = manifest && manifest.Period_asArray && isInteger(periodIndex) ? manifest.Period_asArray[periodIndex] ? manifest.Period_asArray[periodIndex].AdaptationSet_asArray : null : null;
18875        if (realAdaptations && isInteger(index)) {
18876            return realAdaptations[index];
18877        } else {
18878            return null;
18879        }
18880    }
18881
18882    function getIndexForAdaptation(realAdaptation, manifest, periodIndex) {
18883        var realAdaptations = manifest && manifest.Period_asArray && isInteger(periodIndex) ? manifest.Period_asArray[periodIndex] ? manifest.Period_asArray[periodIndex].AdaptationSet_asArray : [] : [];
18884        var len = realAdaptations.length;
18885
18886        if (realAdaptation) {
18887            for (var i = 0; i < len; i++) {
18888                var objectUtils = (0, _streamingUtilsObjectUtils2['default'])(context).getInstance();
18889                if (objectUtils.areEqual(realAdaptations[i], realAdaptation)) {
18890                    return i;
18891                }
18892            }
18893        }
18894
18895        return -1;
18896    }
18897
18898    function getAdaptationsForType(manifest, periodIndex, type) {
18899        var realAdaptationSet = manifest && manifest.Period_asArray && isInteger(periodIndex) ? manifest.Period_asArray[periodIndex] ? manifest.Period_asArray[periodIndex].AdaptationSet_asArray : [] : [];
18900        var i = undefined,
18901            len = undefined;
18902        var adaptations = [];
18903
18904        for (i = 0, len = realAdaptationSet.length; i < len; i++) {
18905            if (getIsTypeOf(realAdaptationSet[i], type)) {
18906                adaptations.push(processAdaptation(realAdaptationSet[i]));
18907            }
18908        }
18909
18910        return adaptations;
18911    }
18912
18913    function getAdaptationForType(manifest, periodIndex, type, streamInfo) {
18914        var adaptations = getAdaptationsForType(manifest, periodIndex, type);
18915
18916        if (!adaptations || adaptations.length === 0) return null;
18917
18918        if (adaptations.length > 1 && streamInfo) {
18919            var currentTrack = mediaController.getCurrentTrackFor(type, streamInfo);
18920            var allMediaInfoForType = adapter.getAllMediaInfoForType(streamInfo, type);
18921            for (var i = 0, ln = adaptations.length; i < ln; i++) {
18922                if (currentTrack && mediaController.isTracksEqual(currentTrack, allMediaInfoForType[i])) {
18923                    return adaptations[i];
18924                }
18925            }
18926            for (var i = 0, ln = adaptations.length; i < ln; i++) {
18927                if (getIsMain(adaptations[i])) {
18928                    return adaptations[i];
18929                }
18930            }
18931        }
18932
18933        return adaptations[0];
18934    }
18935
18936    function getCodec(adaptation, representationId) {
18937        if (adaptation && adaptation.Representation_asArray && adaptation.Representation_asArray.length > 0) {
18938            var representation = isInteger(representationId) && representationId >= 0 && representationId < adaptation.Representation_asArray.length ? adaptation.Representation_asArray[representationId] : adaptation.Representation_asArray[0];
18939            return representation.mimeType + ';codecs="' + representation.codecs + '"';
18940        }
18941
18942        return null;
18943    }
18944
18945    function getMimeType(adaptation) {
18946        return adaptation && adaptation.Representation_asArray && adaptation.Representation_asArray.length > 0 ? adaptation.Representation_asArray[0].mimeType : null;
18947    }
18948
18949    function getKID(adaptation) {
18950        if (!adaptation || !adaptation.hasOwnProperty(_constantsDashConstants2['default'].CENC_DEFAULT_KID)) {
18951            return null;
18952        }
18953        return adaptation[_constantsDashConstants2['default'].CENC_DEFAULT_KID];
18954    }
18955
18956    function getContentProtectionData(adaptation) {
18957        if (!adaptation || !adaptation.hasOwnProperty(_constantsDashConstants2['default'].CONTENTPROTECTION_ASARRAY) || adaptation.ContentProtection_asArray.length === 0) {
18958            return null;
18959        }
18960        return adaptation.ContentProtection_asArray;
18961    }
18962
18963    function getIsDynamic(manifest) {
18964        var isDynamic = false;
18965        if (manifest && manifest.hasOwnProperty('type')) {
18966            isDynamic = manifest.type === _constantsDashConstants2['default'].DYNAMIC;
18967        }
18968        return isDynamic;
18969    }
18970
18971    function hasProfile(manifest, profile) {
18972        var has = false;
18973
18974        if (manifest && manifest.profiles && manifest.profiles.length > 0) {
18975            has = manifest.profiles.indexOf(profile) !== -1;
18976        }
18977
18978        return has;
18979    }
18980
18981    function getIsDVB(manifest) {
18982        return hasProfile(manifest, PROFILE_DVB);
18983    }
18984
18985    function getDuration(manifest) {
18986        var mpdDuration = undefined;
18987        //@mediaPresentationDuration specifies the duration of the entire Media Presentation.
18988        //If the attribute is not present, the duration of the Media Presentation is unknown.
18989        if (manifest && manifest.hasOwnProperty(_constantsDashConstants2['default'].MEDIA_PRESENTATION_DURATION)) {
18990            mpdDuration = manifest.mediaPresentationDuration;
18991        } else {
18992            mpdDuration = Number.MAX_SAFE_INTEGER || Number.MAX_VALUE;
18993        }
18994
18995        return mpdDuration;
18996    }
18997
18998    function getBandwidth(representation) {
18999        return representation && representation.bandwidth ? representation.bandwidth : NaN;
19000    }
19001
19002    function getManifestUpdatePeriod(manifest) {
19003        var latencyOfLastUpdate = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];
19004
19005        var delay = NaN;
19006        if (manifest && manifest.hasOwnProperty(_constantsDashConstants2['default'].MINIMUM_UPDATE_PERIOD)) {
19007            delay = manifest.minimumUpdatePeriod;
19008        }
19009        return isNaN(delay) ? delay : Math.max(delay - latencyOfLastUpdate, 1);
19010    }
19011
19012    function getRepresentationCount(adaptation) {
19013        return adaptation && adaptation.Representation_asArray && adaptation.Representation_asArray.length ? adaptation.Representation_asArray.length : 0;
19014    }
19015
19016    function getBitrateListForAdaptation(realAdaptation) {
19017        if (!realAdaptation || !realAdaptation.Representation_asArray || !realAdaptation.Representation_asArray.length) return null;
19018
19019        var processedRealAdaptation = processAdaptation(realAdaptation);
19020        var realRepresentations = processedRealAdaptation.Representation_asArray;
19021        var ln = realRepresentations.length;
19022        var bitrateList = [];
19023        var i = 0;
19024
19025        for (i = 0; i < ln; i++) {
19026            bitrateList.push({
19027                bandwidth: realRepresentations[i].bandwidth,
19028                width: realRepresentations[i].width || 0,
19029                height: realRepresentations[i].height || 0,
19030                scanType: realRepresentations[i].scanType || null
19031            });
19032        }
19033
19034        return bitrateList;
19035    }
19036
19037    function getRepresentationFor(index, adaptation) {
19038        return adaptation && adaptation.Representation_asArray && adaptation.Representation_asArray.length > 0 && isInteger(index) ? adaptation.Representation_asArray[index] : null;
19039    }
19040
19041    function getRepresentationsForAdaptation(voAdaptation) {
19042        var voRepresentations = [];
19043        var voRepresentation = undefined,
19044            initialization = undefined,
19045            segmentInfo = undefined,
19046            processedRealAdaptation = undefined,
19047            realRepresentation = undefined,
19048            i = undefined,
19049            s = undefined;
19050
19051        if (voAdaptation && voAdaptation.period && isInteger(voAdaptation.period.index)) {
19052            var periodArray = voAdaptation.period.mpd.manifest.Period_asArray[voAdaptation.period.index];
19053            if (periodArray && periodArray.AdaptationSet_asArray && isInteger(voAdaptation.index)) {
19054                processedRealAdaptation = processAdaptation(periodArray.AdaptationSet_asArray[voAdaptation.index]);
19055            }
19056        }
19057
19058        for (i = 0; processedRealAdaptation && i < processedRealAdaptation.Representation_asArray.length; i++) {
19059            realRepresentation = processedRealAdaptation.Representation_asArray[i];
19060            voRepresentation = new _voRepresentation2['default']();
19061            voRepresentation.index = i;
19062            voRepresentation.adaptation = voAdaptation;
19063
19064            if (realRepresentation.hasOwnProperty(_constantsDashConstants2['default'].ID)) {
19065                voRepresentation.id = realRepresentation.id;
19066            }
19067            if (realRepresentation.hasOwnProperty(_constantsDashConstants2['default'].CODECS)) {
19068                voRepresentation.codecs = realRepresentation.codecs;
19069            }
19070            if (realRepresentation.hasOwnProperty(_constantsDashConstants2['default'].CODEC_PRIVATE_DATA)) {
19071                voRepresentation.codecPrivateData = realRepresentation.codecPrivateData;
19072            }
19073            if (realRepresentation.hasOwnProperty(_constantsDashConstants2['default'].BANDWITH)) {
19074                voRepresentation.bandwidth = realRepresentation.bandwidth;
19075            }
19076            if (realRepresentation.hasOwnProperty(_constantsDashConstants2['default'].WIDTH)) {
19077                voRepresentation.width = realRepresentation.width;
19078            }
19079            if (realRepresentation.hasOwnProperty(_constantsDashConstants2['default'].HEIGHT)) {
19080                voRepresentation.height = realRepresentation.height;
19081            }
19082            if (realRepresentation.hasOwnProperty(_constantsDashConstants2['default'].SCAN_TYPE)) {
19083                voRepresentation.scanType = realRepresentation.scanType;
19084            }
19085            if (realRepresentation.hasOwnProperty(_constantsDashConstants2['default'].MAX_PLAYOUT_RATE)) {
19086                voRepresentation.maxPlayoutRate = realRepresentation.maxPlayoutRate;
19087            }
19088            if (realRepresentation.hasOwnProperty(_constantsDashConstants2['default'].SEGMENT_BASE)) {
19089                segmentInfo = realRepresentation.SegmentBase;
19090                voRepresentation.segmentInfoType = _constantsDashConstants2['default'].SEGMENT_BASE;
19091            } else if (realRepresentation.hasOwnProperty(_constantsDashConstants2['default'].SEGMENT_LIST)) {
19092                segmentInfo = realRepresentation.SegmentList;
19093
19094                if (segmentInfo.hasOwnProperty(_constantsDashConstants2['default'].SEGMENT_TIMELINE)) {
19095                    voRepresentation.segmentInfoType = _constantsDashConstants2['default'].SEGMENT_TIMELINE;
19096                    s = segmentInfo.SegmentTimeline.S_asArray[segmentInfo.SegmentTimeline.S_asArray.length - 1];
19097                    if (!s.hasOwnProperty('r') || s.r >= 0) {
19098                        voRepresentation.useCalculatedLiveEdgeTime = true;
19099                    }
19100                } else {
19101                    voRepresentation.segmentInfoType = _constantsDashConstants2['default'].SEGMENT_LIST;
19102                    voRepresentation.useCalculatedLiveEdgeTime = true;
19103                }
19104            } else if (realRepresentation.hasOwnProperty(_constantsDashConstants2['default'].SEGMENT_TEMPLATE)) {
19105                segmentInfo = realRepresentation.SegmentTemplate;
19106
19107                if (segmentInfo.hasOwnProperty(_constantsDashConstants2['default'].SEGMENT_TIMELINE)) {
19108                    voRepresentation.segmentInfoType = _constantsDashConstants2['default'].SEGMENT_TIMELINE;
19109                    s = segmentInfo.SegmentTimeline.S_asArray[segmentInfo.SegmentTimeline.S_asArray.length - 1];
19110                    if (!s.hasOwnProperty('r') || s.r >= 0) {
19111                        voRepresentation.useCalculatedLiveEdgeTime = true;
19112                    }
19113                } else {
19114                    voRepresentation.segmentInfoType = _constantsDashConstants2['default'].SEGMENT_TEMPLATE;
19115                }
19116
19117                if (segmentInfo.hasOwnProperty(_constantsDashConstants2['default'].INITIALIZATION_MINUS)) {
19118                    voRepresentation.initialization = segmentInfo.initialization.split('$Bandwidth$').join(realRepresentation.bandwidth).split('$RepresentationID$').join(realRepresentation.id);
19119                }
19120            } else {
19121                voRepresentation.segmentInfoType = _constantsDashConstants2['default'].BASE_URL;
19122            }
19123
19124            if (segmentInfo) {
19125                if (segmentInfo.hasOwnProperty(_constantsDashConstants2['default'].INITIALIZATION)) {
19126                    initialization = segmentInfo.Initialization;
19127
19128                    if (initialization.hasOwnProperty(_constantsDashConstants2['default'].SOURCE_URL)) {
19129                        voRepresentation.initialization = initialization.sourceURL;
19130                    } else if (initialization.hasOwnProperty(_constantsDashConstants2['default'].RANGE)) {
19131                        voRepresentation.range = initialization.range;
19132                        // initialization source url will be determined from
19133                        // BaseURL when resolved at load time.
19134                    }
19135                } else if (realRepresentation.hasOwnProperty(_constantsDashConstants2['default'].MIME_TYPE) && getIsTextTrack(realRepresentation.mimeType)) {
19136                        voRepresentation.range = 0;
19137                    }
19138
19139                if (segmentInfo.hasOwnProperty(_constantsDashConstants2['default'].TIMESCALE)) {
19140                    voRepresentation.timescale = segmentInfo.timescale;
19141                }
19142                if (segmentInfo.hasOwnProperty(_constantsDashConstants2['default'].DURATION)) {
19143                    // TODO according to the spec @maxSegmentDuration specifies the maximum duration of any Segment in any Representation in the Media Presentation
19144                    // It is also said that for a SegmentTimeline any @d value shall not exceed the value of MPD@maxSegmentDuration, but nothing is said about
19145                    // SegmentTemplate @duration attribute. We need to find out if @maxSegmentDuration should be used instead of calculated duration if the the duration
19146                    // exceeds @maxSegmentDuration
19147                    //representation.segmentDuration = Math.min(segmentInfo.duration / representation.timescale, adaptation.period.mpd.maxSegmentDuration);
19148                    voRepresentation.segmentDuration = segmentInfo.duration / voRepresentation.timescale;
19149                }
19150                if (segmentInfo.hasOwnProperty(_constantsDashConstants2['default'].START_NUMBER)) {
19151                    voRepresentation.startNumber = segmentInfo.startNumber;
19152                }
19153                if (segmentInfo.hasOwnProperty(_constantsDashConstants2['default'].INDEX_RANGE)) {
19154                    voRepresentation.indexRange = segmentInfo.indexRange;
19155                }
19156                if (segmentInfo.hasOwnProperty(_constantsDashConstants2['default'].PRESENTATION_TIME_OFFSET)) {
19157                    voRepresentation.presentationTimeOffset = segmentInfo.presentationTimeOffset / voRepresentation.timescale;
19158                }
19159            }
19160
19161            voRepresentation.MSETimeOffset = timelineConverter.calcMSETimeOffset(voRepresentation);
19162            voRepresentation.path = [voAdaptation.period.index, voAdaptation.index, i];
19163            voRepresentations.push(voRepresentation);
19164        }
19165
19166        return voRepresentations;
19167    }
19168
19169    function getAdaptationsForPeriod(voPeriod) {
19170        var realPeriod = voPeriod && isInteger(voPeriod.index) ? voPeriod.mpd.manifest.Period_asArray[voPeriod.index] : null;
19171        var voAdaptations = [];
19172        var voAdaptationSet = undefined,
19173            realAdaptationSet = undefined,
19174            i = undefined;
19175
19176        if (realPeriod && realPeriod.AdaptationSet_asArray) {
19177            for (i = 0; i < realPeriod.AdaptationSet_asArray.length; i++) {
19178                realAdaptationSet = realPeriod.AdaptationSet_asArray[i];
19179                voAdaptationSet = new _voAdaptationSet2['default']();
19180                if (realAdaptationSet.hasOwnProperty(_constantsDashConstants2['default'].ID)) {
19181                    voAdaptationSet.id = realAdaptationSet.id;
19182                }
19183                voAdaptationSet.index = i;
19184                voAdaptationSet.period = voPeriod;
19185
19186                if (getIsMuxed(realAdaptationSet)) {
19187                    voAdaptationSet.type = _streamingConstantsConstants2['default'].MUXED;
19188                } else if (getIsAudio(realAdaptationSet)) {
19189                    voAdaptationSet.type = _streamingConstantsConstants2['default'].AUDIO;
19190                } else if (getIsVideo(realAdaptationSet)) {
19191                    voAdaptationSet.type = _streamingConstantsConstants2['default'].VIDEO;
19192                } else if (getIsFragmentedText(realAdaptationSet)) {
19193                    voAdaptationSet.type = _streamingConstantsConstants2['default'].FRAGMENTED_TEXT;
19194                } else {
19195                    voAdaptationSet.type = _streamingConstantsConstants2['default'].TEXT;
19196                }
19197                voAdaptations.push(voAdaptationSet);
19198            }
19199        }
19200
19201        return voAdaptations;
19202    }
19203
19204    function getRegularPeriods(mpd) {
19205        var isDynamic = mpd ? getIsDynamic(mpd.manifest) : false;
19206        var voPeriods = [];
19207        var realPeriod1 = null;
19208        var realPeriod = null;
19209        var voPeriod1 = null;
19210        var voPeriod = null;
19211        var len = undefined,
19212            i = undefined;
19213
19214        for (i = 0, len = mpd && mpd.manifest && mpd.manifest.Period_asArray ? mpd.manifest.Period_asArray.length : 0; i < len; i++) {
19215            realPeriod = mpd.manifest.Period_asArray[i];
19216
19217            // If the attribute @start is present in the Period, then the
19218            // Period is a regular Period and the PeriodStart is equal
19219            // to the value of this attribute.
19220            if (realPeriod.hasOwnProperty(_constantsDashConstants2['default'].START)) {
19221                voPeriod = new _voPeriod2['default']();
19222                voPeriod.start = realPeriod.start;
19223            }
19224            // If the @start attribute is absent, but the previous Per
19224iod
19225            // element contains a @duration attribute then then this new
19226            // Period is also a regular Period. The start time of the new
19227            // Period PeriodStart is the sum of the start time of the previous
19228            // Period PeriodStart and the value of the attribute @duration
19229            // of the previous Period.
19230            else if (realPeriod1 !== null && realPeriod.hasOwnProperty(_constantsDashConstants2['default'].DURATION) && voPeriod1 !== null) {
19231                    voPeriod = new _voPeriod2['default']();
19232                    voPeriod.start = voPeriod1.start + voPeriod1.duration;
19233                    voPeriod.duration = realPeriod.duration;
19234                }
19235                // If (i) @start attribute is absent, and (ii) the Period element
19236                // is the first in the MPD, and (iii) the MPD@type is 'static',
19237                // then the PeriodStart time shall be set to zero.
19238                else if (i === 0 && !isDynamic) {
19239                        voPeriod = new _voPeriod2['default']();
19240                        voPeriod.start = 0;
19241                    }
19242
19243            // The Period extends until the PeriodStart of the next Period.
19244            // The difference between the PeriodStart time of a Period and
19245            // the PeriodStart time of the following Period.
19246            if (voPeriod1 !== null && isNaN(voPeriod1.duration)) {
19247                voPeriod1.duration = voPeriod.start - voPeriod1.start;
19248            }
19249
19250            if (voPeriod !== null) {
19251                voPeriod.id = getPeriodId(realPeriod, i);
19252            }
19253
19254            if (voPeriod !== null && realPeriod.hasOwnProperty(_constantsDashConstants2['default'].DURATION)) {
19255                voPeriod.duration = realPeriod.duration;
19256            }
19257
19258            if (voPeriod !== null) {
19259                voPeriod.index = i;
19260                voPeriod.mpd = mpd;
19261                voPeriods.push(voPeriod);
19262                realPeriod1 = realPeriod;
19263                voPeriod1 = voPeriod;
19264            }
19265
19266            realPeriod = null;
19267            voPeriod = null;
19268        }
19269
19270        if (voPeriods.length === 0) {
19271            return voPeriods;
19272        }
19273
19274        // The last Period extends until the end of the Media Presentation.
19275        // The difference between the PeriodStart time of the last Period
19276        // and the mpd duration
19277        if (voPeriod1 !== null && isNaN(voPeriod1.duration)) {
19278            voPeriod1.duration = getEndTimeForLastPeriod(voPeriod1) - voPeriod1.start;
19279        }
19280
19281        return voPeriods;
19282    }
19283
19284    function getPeriodId(realPeriod, i) {
19285        if (!realPeriod) {
19286            throw new Error('Period cannot be null or undefined');
19287        }
19288
19289        var id = _voPeriod2['default'].DEFAULT_ID + '_' + i;
19290
19291        if (realPeriod.hasOwnProperty(_constantsDashConstants2['default'].ID) && realPeriod.id.length > 0 && realPeriod.id !== '__proto__') {
19292            id = realPeriod.id;
19293        }
19294
19295        return id;
19296    }
19297
19298    function getMpd(manifest) {
19299        var mpd = new _voMpd2['default']();
19300
19301        if (manifest) {
19302            mpd.manifest = manifest;
19303
19304            if (manifest.hasOwnProperty(_constantsDashConstants2['default'].AVAILABILITY_START_TIME)) {
19305                mpd.availabilityStartTime = new Date(manifest.availabilityStartTime.getTime());
19306            } else {
19307                mpd.availabilityStartTime = new Date(manifest.loadedTime.getTime());
19308            }
19309
19310            if (manifest.hasOwnProperty(_constantsDashConstants2['default'].AVAILABILITY_END_TIME)) {
19311                mpd.availabilityEndTime = new Date(manifest.availabilityEndTime.getTime());
19312            }
19313
19314            if (manifest.hasOwnProperty(_constantsDashConstants2['default'].MINIMUM_UPDATE_PERIOD)) {
19315                mpd.minimumUpdatePeriod = manifest.minimumUpdatePeriod;
19316            }
19317
19318            if (manifest.hasOwnProperty(_constantsDashConstants2['default'].MEDIA_PRESENTATION_DURATION)) {
19319                mpd.mediaPresentationDuration = manifest.mediaPresentationDuration;
19320            }
19321
19322            if (manifest.hasOwnProperty(_streamingConstantsConstants2['default'].SUGGESTED_PRESENTATION_DELAY)) {
19323                mpd.suggestedPresentationDelay = manifest.suggestedPresentationDelay;
19324            }
19325
19326            if (manifest.hasOwnProperty(_constantsDashConstants2['default'].TIMESHIFT_BUFFER_DEPTH)) {
19327                mpd.timeShiftBufferDepth = manifest.timeShiftBufferDepth;
19328            }
19329
19330            if (manifest.hasOwnProperty(_constantsDashConstants2['default'].MAX_SEGMENT_DURATION)) {
19331                mpd.maxSegmentDuration = manifest.maxSegmentDuration;
19332            }
19333        }
19334
19335        return mpd;
19336    }
19337
19338    function getEndTimeForLastPeriod(voPeriod) {
19339        var isDynamic = getIsDynamic(voPeriod.mpd.manifest);
19340
19341        var periodEnd = undefined;
19342        if (voPeriod.mpd.manifest.mediaPresentationDuration) {
19343            periodEnd = voPeriod.mpd.manifest.mediaPresentationDuration;
19344        } else if (voPeriod.duration) {
19345            periodEnd = voPeriod.duration;
19346        } else if (isDynamic) {
19347            periodEnd = Number.POSITIVE_INFINITY;
19348        } else {
19349            throw new Error('Must have @mediaPresentationDuratio on MPD or an explicit @duration on the last period.');
19350        }
19351
19352        return periodEnd;
19353    }
19354
19355    function getEventsForPeriod(period) {
19356        var manifest = period && period.mpd && period.mpd.manifest ? period.mpd.manifest : null;
19357        var periodArray = manifest ? manifest.Period_asArray : null;
19358        var eventStreams = periodArray && period && isInteger(period.index) ? periodArray[period.index].EventStream_asArray : null;
19359        var events = [];
19360        var i = undefined,
19361            j = undefined;
19362
19363        if (eventStreams) {
19364            for (i = 0; i < eventStreams.length; i++) {
19365                var eventStream = new _voEventStream2['default']();
19366                eventStream.period = period;
19367                eventStream.timescale = 1;
19368
19369                if (eventStreams[i].hasOwnProperty(_streamingConstantsConstants2['default'].SCHEME_ID_URI)) {
19370                    eventStream.schemeIdUri = eventStreams[i].schemeIdUri;
19371                } else {
19372                    throw new Error('Invalid EventStream. SchemeIdUri has to be set');
19373                }
19374                if (eventStreams[i].hasOwnProperty(_constantsDashConstants2['default'].TIMESCALE)) {
19375                    eventStream.timescale = eventStreams[i].timescale;
19376                }
19377                if (eventStreams[i].hasOwnProperty(_constantsDashConstants2['default'].VALUE)) {
19378                    eventStream.value = eventStreams[i].value;
19379                }
19380                for (j = 0; j < eventStreams[i].Event_asArray.length; j++) {
19381                    var _event = new _voEvent2['default']();
19382                    _event.presentationTime = 0;
19383                    _event.eventStream = eventStream;
19384
19385                    if (eventStreams[i].Event_asArray[j].hasOwnProperty(_constantsDashConstants2['default'].PRESENTATION_TIME)) {
19386                        _event.presentationTime = eventStreams[i].Event_asArray[j].presentationTime;
19387                    }
19388                    if (eventStreams[i].Event_asArray[j].hasOwnProperty(_constantsDashConstants2['default'].DURATION)) {
19389                        _event.duration = eventStreams[i].Event_asArray[j].duration;
19390                    }
19391                    if (eventStreams[i].Event_asArray[j].hasOwnProperty(_constantsDashConstants2['default'].ID)) {
19392                        _event.id = eventStreams[i].Event_asArray[j].id;
19393                    }
19394                    events.push(_event);
19395                }
19396            }
19397        }
19398
19399        return events;
19400    }
19401
19402    function getEventStreams(inbandStreams, representation) {
19403        var eventStreams = [];
19404        var i = undefined;
19405
19406        if (!inbandStreams) return eventStreams;
19407
19408        for (i = 0; i < inbandStreams.length; i++) {
19409            var eventStream = new _voEventStream2['default']();
19410            eventStream.timescale = 1;
19411            eventStream.representation = representation;
19412
19413            if (inbandStreams[i].hasOwnProperty(_streamingConstantsConstants2['default'].SCHEME_ID_URI)) {
19414                eventStream.schemeIdUri = inbandStreams[i].schemeIdUri;
19415            } else {
19416                throw new Error('Invalid EventStream. SchemeIdUri has to be set');
19417            }
19418            if (inbandStreams[i].hasOwnProperty(_constantsDashConstants2['default'].TIMESCALE)) {
19419                eventStream.timescale = inbandStreams[i].timescale;
19420            }
19421            if (inbandStreams[i].hasOwnProperty(_constantsDashConstants2['default'].VALUE)) {
19422                eventStream.value = inbandStreams[i].value;
19423            }
19424            eventStreams.push(eventStream);
19425        }
19426
19427        return eventStreams;
19428    }
19429
19430    function getEventStreamForAdaptationSet(manifest, adaptation) {
19431        var inbandStreams = undefined,
19432            periodArray = undefined,
19433            adaptationArray = undefined;
19434
19435        if (manifest && manifest.Period_asArray && adaptation && adaptation.period && isInteger(adaptation.period.index)) {
19436            periodArray = manifest.Period_asArray[adaptation.period.index];
19437            if (periodArray && periodArray.AdaptationSet_asArray && isInteger(adaptation.index)) {
19438                adaptationArray = periodArray.AdaptationSet_asArray[adaptation.index];
19439                if (adaptationArray) {
19440                    inbandStreams = adaptationArray.InbandEventStream_asArray;
19441                }
19442            }
19443        }
19444
19445        return getEventStreams(inbandStreams, null);
19446    }
19447
19448    function getEventStreamForRepresentation(manifest, representation) {
19449        var inbandStreams = undefined,
19450            periodArray = undefined,
19451            adaptationArray = undefined,
19452            representationArray = undefined;
19453
19454        if (manifest && manifest.Period_asArray && representation && representation.adaptation && representation.adaptation.period && isInteger(representation.adaptation.period.index)) {
19455            periodArray = manifest.Period_asArray[representation.adaptation.period.index];
19456            if (periodArray && periodArray.AdaptationSet_asArray && isInteger(representation.adaptation.index)) {
19457                adaptationArray = periodArray.AdaptationSet_asArray[representation.adaptation.index];
19458                if (adaptationArray && adaptationArray.Representation_asArray && isInteger(representation.index)) {
19459                    representationArray = adaptationArray.Representation_asArray[representation.index];
19460                    if (representationArray) {
19461                        inbandStreams = representationArray.InbandEventStream_asArray;
19462                    }
19463                }
19464            }
19465        }
19466
19467        return getEventStreams(inbandStreams, representation);
19468    }
19469
19470    function getUTCTimingSources(manifest) {
19471        var isDynamic = getIsDynamic(manifest);
19472        var hasAST = manifest ? manifest.hasOwnProperty(_constantsDashConstants2['default'].AVAILABILITY_START_TIME) : false;
19473        var utcTimingsArray = manifest ? manifest.UTCTiming_asArray : null;
19474        var utcTimingEntries = [];
19475
19476        // do not bother synchronizing the clock unless MPD is live,
19477        // or it is static and has availabilityStartTime attribute
19478        if (isDynamic || hasAST) {
19479            if (utcTimingsArray) {
19480                // the order is important here - 23009-1 states that the order
19481                // in the manifest "indicates relative preference, first having
19482                // the highest, and the last the lowest priority".
19483                utcTimingsArray.forEach(function (utcTiming) {
19484                    var entry = new _voUTCTiming2['default']();
19485
19486                    if (utcTiming.hasOwnProperty(_streamingConstantsConstants2['default'].SCHEME_ID_URI)) {
19487                        entry.schemeIdUri = utcTiming.schemeIdUri;
19488                    } else {
19489                        // entries of type DescriptorType with no schemeIdUri
19490                        // are meaningless. let's just ignore this entry and
19491                        // move on.
19492                        return;
19493                    }
19494
19495                    // this is (incorrectly) interpreted as a number - schema
19496                    // defines it as a string
19497                    if (utcTiming.hasOwnProperty(_constantsDashConstants2['default'].VALUE)) {
19498                        entry.value = utcTiming.value.toString();
19499                    } else {
19500                        // without a value, there's not a lot we can do with
19501                        // this entry. let's just ignore this one and move on
19502                        return;
19503                    }
19504
19505                    // we're not interested in the optional id or any other
19506                    // attributes which might be attached to the entry
19507
19508                    utcTimingEntries.push(entry);
19509                });
19510            }
19511        }
19512
19513        return utcTimingEntries;
19514    }
19515
19516    function getBaseURLsFromElement(node) {
19517        var baseUrls = [];
19518        // if node.BaseURL_asArray and node.baseUri are undefined entries
19519        // will be [undefined] which entries.some will just skip
19520        var entries = node.BaseURL_asArray || [node.baseUri];
19521        var earlyReturn = false;
19522
19523        entries.some(function (entry) {
19524            if (entry) {
19525                var baseUrl = new _voBaseURL2['default']();
19526                var text = entry.__text || entry;
19527
19528                if (urlUtils.isRelative(text)) {
19529                    // it doesn't really make sense to have relative and
19530                    // absolute URLs at the same level, or multiple
19531                    // relative URLs at the same level, so assume we are
19532                    // done from this level of the MPD
19533                    earlyReturn = true;
19534
19535                    // deal with the specific case where the MPD@BaseURL
19536                    // is specified and is relative. when no MPD@BaseURL
19537                    // entries exist, that case is handled by the
19538                    // [node.baseUri] in the entries definition.
19539                    if (node.baseUri) {
19540                        text = urlUtils.resolve(text, node.baseUri);
19541                    }
19542                }
19543
19544                baseUrl.url = text;
19545
19546                // serviceLocation is optional, but we need it in order
19547                // to blacklist correctly. if it's not available, use
19548                // anything unique since there's no relationship to any
19549                // other BaseURL and, in theory, the url should be
19550                // unique so use this instead.
19551                if (entry.hasOwnProperty(_constantsDashConstants2['default'].SERVICE_LOCATION) && entry.serviceLocation.length) {
19552                    baseUrl.serviceLocation = entry.serviceLocation;
19553                } else {
19554                    baseUrl.serviceLocation = text;
19555                }
19556
19557                if (entry.hasOwnProperty(_constantsDashConstants2['default'].DVB_PRIORITY)) {
19558                    baseUrl.dvb_priority = entry[_constantsDashConstants2['default'].DVB_PRIORITY];
19559                }
19560
19561                if (entry.hasOwnProperty(_constantsDashConstants2['default'].DVB_WEIGHT)) {
19562                    baseUrl.dvb_weight = entry[_constantsDashConstants2['default'].DVB_WEIGHT];
19563                }
19564
19565                /* NOTE: byteRange, availabilityTimeOffset,
19566                 * availabilityTimeComplete currently unused
19567                 */
19568
19569                baseUrls.push(baseUrl);
19570
19571                return earlyReturn;
19572            }
19573        });
19574
19575        return baseUrls;
19576    }
19577
19578    function getLocation(manifest) {
19579        if (manifest && manifest.hasOwnProperty(_streamingConstantsConstants2['default'].LOCATION)) {
19580            // for now, do not support multiple Locations -
19581            // just set Location to the first Location.
19582            manifest.Location = manifest.Location_asArray[0];
19583
19584            return manifest.Location;
19585        }
19586
19587        // may well be undefined
19588        return undefined;
19589    }
19590
19591    instance = {
19592        getIsTypeOf: getIsTypeOf,
19593        getIsAudio: getIsAudio,
19594        getIsVideo: getIsVideo,
19595        getIsText: getIsText,
19596        getIsMuxed: getIsMuxed,
19597        getIsTextTrack: getIsTextTrack,
19598        getIsFragmentedText: getIsFragmentedText,
19599        getIsMain: getIsMain,
19600        getLanguageForAdaptation: getLanguageForAdaptation,
19601        getViewpointForAdaptation: getViewpointForAdaptation,
19602        getRolesForAdaptation: getRolesForAdaptation,
19603        getAccessibilityForAdaptation: getAccessibilityForAdaptation,
19604        getAudioChannelConfigurationForAdaptation: getAudioChannelConfigurationForAdaptation,
19605        getAdaptationForIndex: getAdaptationForIndex,
19606        getIndexForAdaptation: getIndexForAdaptation,
19607        getAdaptationForId: getAdaptationForId,
19608        getAdaptationsForType: getAdaptationsForType,
19609        getAdaptationForType: getAdaptationForType,
19610        getCodec: getCodec,
19611        getMimeType: getMimeType,
19612        getKID: getKID,
19613        getContentProtectionData: getContentProtectionData,
19614        getIsDynamic: getIsDynamic,
19615        getIsDVB: getIsDVB,
19616        getDuration: getDuration,
19617        getBandwidth: getBandwidth,
19618        getManifestUpdatePeriod: getManifestUpdatePeriod,
19619        getRepresentationCount: getRepresentationCount,
19620        getBitrateListForAdaptation: getBitrateListForAdaptation,
19621        getRepresentationFor: getRepresentationFor,
19622        getRepresentationsForAdaptation: getRepresentationsForAdaptation,
19623        getAdaptationsForPeriod: getAdaptationsForPeriod,
19624        getRegularPeriods: getRegularPeriods,
19625        getMpd: getMpd,
19626        getEventsForPeriod: getEventsForPeriod,
19627        getEventStreamForAdaptationSet: getEventStreamForAdaptationSet,
19628        getEventStreamForRepresentation: getEventStreamForRepresentation,
19629        getUTCTimingSources: getUTCTimingSources,
19630        getBaseURLsFromElement: getBaseURLsFromElement,
19631        getRepresentationSortFunction: getRepresentationSortFunction,
19632        getLocation: getLocation
19633    };
19634
19635    return instance;
19636}
19637
19638DashManifestModel.__dashjs_factory_name = 'DashManifestModel';
19639exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(DashManifestModel);
19640module.exports = exports['default'];
19641
19642},{"100":100,"199":199,"202":202,"51":51,"61":61,"81":81,"82":82,"83":83,"84":84,"85":85,"86":86,"87":87,"89":89}],64:[function(_dereq_,module,exports){
19643/**
19644 * The copyright in this software is being made available under the BSD License,
19645 * included below. This software may be subject to other third party and contributor
19646 * rights, including patent rights, and no such rights are granted under this license.
19647 *
19648 * Copyright (c) 2013, Dash Industry Forum.
19649 * All rights reserved.
19650 *
19651 * Redistribution and use in source and binary forms, with or without modification,
19652 * are permitted provided that the following conditions are met:
19653 *  * Redistributions of source code must retain the above copyright notice, this
19654 *  list of conditions and the following disclaimer.
19655 *  * Redistributions in binary form must reproduce the above copyright notice,
19656 *  this list of conditions and the following disclaimer in the documentation and/or
19657 *  other materials provided with the distribution.
19658 *  * Neither the name of Dash Industry Forum nor the names of its
19659 *  contributors may be used to endorse or promote products derived from this software
19660 *  without specific prior written permission.
19661 *
19662 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
19663 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19664 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19665 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
19666 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
19666INCLUDING, BUT
19667 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
19668 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
19669 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
19670 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
19671 *  POSSIBILITY OF SUCH DAMAGE.
19672 */
19673'use strict';
19674
19675Object.defineProperty(exports, '__esModule', {
19676    value: true
19677});
19678
19679function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
19680
19681var _coreFactoryMaker = _dereq_(51);
19682
19683var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
19684
19685var _coreDebug = _dereq_(49);
19686
19687var _coreDebug2 = _interopRequireDefault(_coreDebug);
19688
19689var _externalsObjectiron = _dereq_(3);
19690
19691var _externalsObjectiron2 = _interopRequireDefault(_externalsObjectiron);
19692
19693var _externalsXml2json = _dereq_(4);
19694
19695var _externalsXml2json2 = _interopRequireDefault(_externalsXml2json);
19696
19697var _matchersStringMatcher = _dereq_(73);
19698
19699var _matchersStringMatcher2 = _interopRequireDefault(_matchersStringMatcher);
19700
19701var _matchersDurationMatcher = _dereq_(71);
19702
19703var _matchersDurationMatcher2 = _interopRequireDefault(_matchersDurationMatcher);
19704
19705var _matchersDateTimeMatcher = _dereq_(70);
19706
19707var _matchersDateTimeMatcher2 = _interopRequireDefault(_matchersDateTimeMatcher);
19708
19709var _matchersNumericMatcher = _dereq_(72);
19710
19711var _matchersNumericMatcher2 = _interopRequireDefault(_matchersNumericMatcher);
19712
19713var _mapsRepresentationBaseValuesMap = _dereq_(67);
19714
19715var _mapsRepresentationBaseValuesMap2 = _interopRequireDefault(_mapsRepresentationBaseValuesMap);
19716
19717var _mapsSegmentValuesMap = _dereq_(68);
19718
19719var _mapsSegmentValuesMap2 = _interopRequireDefault(_mapsSegmentValuesMap);
19720
19721function DashParser(config) {
19722
19723    var context = this.context;
19724    var log = (0, _coreDebug2['default'])(context).getInstance().log;
19725    var errorHandler = config.errorHandler;
19726
19727    var instance = undefined,
19728        matchers = undefined,
19729        converter = undefined,
19730        objectIron = undefined;
19731
19732    function setup() {
19733        matchers = [new _matchersDurationMatcher2['default'](), new _matchersDateTimeMatcher2['default'](), new _matchersNumericMatcher2['default'](), new _matchersStringMatcher2['default']() // last in list to take precedence over NumericMatcher
19734        ];
19735
19736        converter = new _externalsXml2json2['default']({
19737            escapeMode: false,
19738            attributePrefix: '',
19739            arrayAccessForm: 'property',
19740            emptyNodeForm: 'object',
19741            stripWhitespaces: false,
19742            enableToStringFunc: false,
19743            ignoreRoot: true,
19744            matchers: matchers
19745        });
19746
19747        objectIron = new _externalsObjectiron2['default']([new _mapsRepresentationBaseValuesMap2['default'](), new _mapsSegmentValuesMap2['default']()]);
19748    }
19749
19750    function checkConfig() {
19751        if (!errorHandler || !errorHandler.hasOwnProperty('manifestError')) {
19752            throw new Error('Missing config parameter(s)');
19753        }
19754    }
19755
19756    function getMatchers() {
19757        return matchers;
19758    }
19759
19760    function getIron() {
19761        return objectIron;
19762    }
19763
19764    function parse(data) {
19765        var manifest = undefined;
19766
19767        checkConfig();
19768
19769        try {
19770            var startTime = window.performance.now();
19771
19772            manifest = converter.xml_str2json(data);
19773
19774            if (!manifest) {
19775                throw new Error('parser error');
19776            }
19777
19778            var jsonTime = window.performance.now();
19779
19780            objectIron.run(manifest);
19781
19782            var ironedTime = window.performance.now();
19783
19784            log('Parsing complete: ( xml2json: ' + (jsonTime - startTime).toPrecision(3) + 'ms, objectiron: ' + (ironedTime - jsonTime).toPrecision(3) + 'ms, total: ' + ((ironedTime - startTime) / 1000).toPrecision(3) + 's)');
19785        } catch (err) {
19786            errorHandler.manifestError('parsing the manifest failed', 'parse', data, err);
19787            return null;
19788        }
19789
19790        return manifest;
19791    }
19792
19793    instance = {
19794        parse: parse,
19795        getMatchers: getMatchers,
19796        getIron: getIron
19797    };
19798
19799    setup();
19800
19801    return instance;
19802}
19803
19804DashParser.__dashjs_factory_name = 'DashParser';
19805exports['default'] = _coreFactoryMaker2['default'].getClassFactory(DashParser);
19806module.exports = exports['default'];
19807
19808},{"3":3,"4":4,"49":49,"51":51,"67":67,"68":68,"70":70,"71":71,"72":72,"73":73}],65:[function(_dereq_,module,exports){
19809/**
19810 * The copyright in this software is being made available under the BSD License,
19811 * included below. This software may be subject to other third party and contributor
19812 * rights, including patent rights, and no such rights are granted under this license.
19813 *
19814 * Copyright (c) 2013, Dash Industry Forum.
19815 * All rights reserved.
19816 *
19817 * Redistribution and use in source and binary forms, with or without modification,
19818 * are permitted provided that the following conditions are met:
19819 *  * Redistributions of source code must retain the above copyright notice, this
19820 *  list of conditions and the following disclaimer.
19821 *  * Redistributions in binary form must reproduce the above copyright notice,
19822 *  this list of conditions and the following disclaimer in the documentation and/or
19823 *  other materials provided with the distribution.
19824 *  * Neither the name of Dash Industry Forum nor the names of its
19825 *  contributors may be used to endorse or promote products derived from this software
19826 *  without specific prior written permission.
19827 *
19828 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
19829 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19830 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19831 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
19832 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
19832INCLUDING, BUT
19833 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
19834 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
19835 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
19836 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
19837 *  POSSIBILITY OF SUCH DAMAGE.
19838 */
19839/**
19840 * @classdesc a property belonging to a MapNode
19841 */
19842
19843"use strict";
19844
19845Object.defineProperty(exports, "__esModule", {
19846    value: true
19847});
19848
19849var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
19850
19851function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
19852
19853var CommonProperty = (function () {
19854    function CommonProperty(name, merge) {
19855        _classCallCheck(this, CommonProperty);
19856
19857        var getDefaultMergeForName = function getDefaultMergeForName(n) {
19858            return n && n.length && n.charAt(0) === n.charAt(0).toUpperCase();
19859        };
19860
19861        this._name = name;
19862        this._merge = merge !== undefined ? merge : getDefaultMergeForName(name);
19863    }
19864
19865    _createClass(CommonProperty, [{
19866        key: "name",
19867        get: function get() {
19868            return this._name;
19869        }
19870    }, {
19871        key: "merge",
19872        get: function get() {
19873            return this._merge;
19874        }
19875    }]);
19876
19877    return CommonProperty;
19878})();
19879
19880exports["default"] = CommonProperty;
19881module.exports = exports["default"];
19882
19883},{}],66:[function(_dereq_,module,exports){
19884/**
19885 * The copyright in this software is being made available under the BSD License,
19886 * included below. This software may be subject to other third party and contributor
19887 * rights, including patent rights, and no such rights are granted under this license.
19888 *
19889 * Copyright (c) 2013, Dash Industry Forum.
19890 * All rights reserved.
19891 *
19892 * Redistribution and use in source and binary forms, with or without modification,
19893 * are permitted provided that the following conditions are met:
19894 *  * Redistributions of source code must retain the above copyright notice, this
19895 *  list of conditions and the following disclaimer.
19896 *  * Redistributions in binary form must reproduce the above copyright notice,
19897 *  this list of conditions and the following disclaimer in the documentation and/or
19898 *  other materials provided with the distribution.
19899 *  * Neither the name of Dash Industry Forum nor the names of its
19900 *  contributors may be used to endorse or promote products derived from this software
19901 *  without specific prior written permission.
19902 *
19903 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
19904 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19905 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19906 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
19907 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19908 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
19909 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
19910 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
19911 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
19912 *  POSSIBILITY OF SUCH DAMAGE.
19913 */
19914/**
19915 * @classdesc a node at some level in a ValueMap
19916 */
19917'use strict';
19918
19919Object.defineProperty(exports, '__esModule', {
19920    value: true
19921});
19922
19923var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
19924
19925function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
19926
19927function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
19928
19929var _CommonProperty = _dereq_(65);
19930
19931var _CommonProperty2 = _interopRequireDefault(_CommonProperty);
19932
19933var MapNode = (function () {
19934    function MapNode(name, properties, children, isRoot, isArray) {
19935        var _this = this;
19936
19937        _classCallCheck(this, MapNode);
19938
19939        this._name = name || '';
19940        this._properties = [];
19941        this._children = children || [];
19942        this._isRoot = isRoot || false;
19943        this._isArray = isArray || true;
19944
19945        if (Array.isArray(properties)) {
19946            properties.forEach(function (p) {
19947                _this._properties.push(new _CommonProperty2['default'](p));
19948            });
19949        }
19950    }
19951
19952    _createClass(MapNode, [{
19953        key: 'name',
19954        get: function get() {
19955            return this._name;
19956        }
19957    }, {
19958        key: 'isRoot',
19959        get: function get() {
19960            return this._isRoot;
19961        }
19962    }, {
19963        key: 'isArray',
19964        get: function get() {
19965            return this._isArray;
19966        }
19967    }, {
19968        key: 'children',
19969        get: function get() {
19970            return this._children;
19971        }
19972    }, {
19973        key: 'properties',
19974        get: function get() {
19975            return this._properties;
19976        }
19977    }]);
19978
19979    return MapNode;
19980})();
19981
19982exports['default'] = MapNode;
19983module.exports = exports['default'];
19984
19985},{"65":65}],67:[function(_dereq_,module,exports){
19986/**
19987 * The copyright in this software is being made available under the BSD License,
19988 * included below. This software may be subject to other third party and contributor
19989 * rights, including patent rights, and no such rights are granted under this license.
19990 *
19991 * Copyright (c) 2013, Dash Industry Forum.
19992 * All rights reserved.
19993 *
19994 * Redistribution and use in source and binary forms, with or without modification,
19995 * are permitted provided that the following conditions are met:
19996 *  * Redistributions of source code must retain the above copyright notice, this
19997 *  list of conditions and the following disclaimer.
19998 *  * Redistributions in binary form must reproduce the above copyright notice,
19999 *  this list of conditions and the following disclaimer in the documentation and/or
20000 *  other materials provided with the distribution.
20001 *  * Neither the name of Dash Industry Forum nor the names of its
20002 *  contributors may be used to endorse or promote products derived from this software
20003 *  without specific prior written permission.
20004 *
20005 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
20006 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20007 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20008 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
20009 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20010 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20011 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
20012 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
20013 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
20014 *  POSSIBILITY OF SUCH DAMAGE.
20015 */
20016/**
20017 * @classdesc a RepresentationBaseValuesMap type for input to objectiron
20018 */
20019'use strict';
20020
20021Object.defineProperty(exports, '__esModule', {
20022    value: true
20023});
20024
20025var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
20026
20027function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
20028
20029function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
20030
20031function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { c
20031onstructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
20032
20033var _MapNode2 = _dereq_(66);
20034
20035var _MapNode3 = _interopRequireDefault(_MapNode2);
20036
20037var _constantsDashConstants = _dereq_(61);
20038
20039var _constantsDashConstants2 = _interopRequireDefault(_constantsDashConstants);
20040
20041var RepresentationBaseValuesMap = (function (_MapNode) {
20042    _inherits(RepresentationBaseValuesMap, _MapNode);
20043
20044    function RepresentationBaseValuesMap() {
20045        _classCallCheck(this, RepresentationBaseValuesMap);
20046
20047        var commonProperties = [_constantsDashConstants2['default'].PROFILES, _constantsDashConstants2['default'].WIDTH, _constantsDashConstants2['default'].HEIGHT, _constantsDashConstants2['default'].SAR, _constantsDashConstants2['default'].FRAMERATE, _constantsDashConstants2['default'].AUDIO_SAMPLING_RATE, _constantsDashConstants2['default'].MIME_TYPE, _constantsDashConstants2['default'].SEGMENT_PROFILES, _constantsDashConstants2['default'].CODECS, _constantsDashConstants2['default'].MAXIMUM_SAP_PERIOD, _constantsDashConstants2['default'].START_WITH_SAP, _constantsDashConstants2['default'].MAX_PLAYOUT_RATE, _constantsDashConstants2['default'].CODING_DEPENDENCY, _constantsDashConstants2['default'].SCAN_TYPE, _constantsDashConstants2['default'].FRAME_PACKING, _constantsDashConstants2['default'].AUDIO_CHANNEL_CONFIGURATION, _constantsDashConstants2['default'].CONTENT_PROTECTION, _constantsDashConstants2['default'].ESSENTIAL_PROPERTY, _constantsDashConstants2['default'].SUPPLEMENTAL_PROPERTY, _constantsDashConstants2['default'].INBAND_EVENT_STREAM];
20048
20049        _get(Object.getPrototypeOf(RepresentationBaseValuesMap.prototype), 'constructor', this).call(this, _constantsDashConstants2['default'].ADAPTATION_SET, commonProperties, [new _MapNode3['default'](_constantsDashConstants2['default'].REPRESENTATION, commonProperties, [new _MapNode3['default'](_constantsDashConstants2['default'].SUB_REPRESENTATION, commonProperties)])]);
20050    }
20051
20052    return RepresentationBaseValuesMap;
20053})(_MapNode3['default']);
20054
20055exports['default'] = RepresentationBaseValuesMap;
20056module.exports = exports['default'];
20057
20058},{"61":61,"66":66}],68:[function(_dereq_,module,exports){
20059/**
20060 * The copyright in this software is being made available under the BSD License,
20061 * included below. This software may be subject to other third party and contributor
20062 * rights, including patent rights, and no such rights are granted under this license.
20063 *
20064 * Copyright (c) 2013, Dash Industry Forum.
20065 * All rights reserved.
20066 *
20067 * Redistribution and use in source and binary forms, with or without modification,
20068 * are permitted provided that the following conditions are met:
20069 *  * Redistributions of source code must retain the above copyright notice, this
20070 *  list of conditions and the following disclaimer.
20071 *  * Redistributions in binary form must reproduce the above copyright notice,
20072 *  this list of conditions and the following disclaimer in the documentation and/or
20073 *  other materials provided with the distribution.
20074 *  * Neither the name of Dash Industry Forum nor the names of its
20075 *  contributors may be used to endorse or promote products derived from this software
20076 *  without specific prior written permission.
20077 *
20078 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
20079 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20080 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20081 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
20082 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20083 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20084 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
20085 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
20086 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
20087 *  POSSIBILITY OF SUCH DAMAGE.
20088 */
20089/**
20090 * @classdesc a SegmentValuesMap type for input to objectiron
20091 */
20092'use strict';
20093
20094Object.defineProperty(exports, '__esModule', {
20095    value: true
20096});
20097
20098var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
20099
20100function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
20101
20102function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
20103
20104function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { c
20104onstructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
20105
20106var _MapNode2 = _dereq_(66);
20107
20108var _MapNode3 = _interopRequireDefault(_MapNode2);
20109
20110var _constantsDashConstants = _dereq_(61);
20111
20112var _constantsDashConstants2 = _interopRequireDefault(_constantsDashConstants);
20113
20114var SegmentValuesMap = (function (_MapNode) {
20115    _inherits(SegmentValuesMap, _MapNode);
20116
20117    function SegmentValuesMap() {
20118        _classCallCheck(this, SegmentValuesMap);
20119
20120        var commonProperties = [_constantsDashConstants2['default'].SEGMENT_BASE, _constantsDashConstants2['default'].SEGMENT_TEMPLATE, _constantsDashConstants2['default'].SEGMENT_LIST];
20121
20122        _get(Object.getPrototypeOf(SegmentValuesMap.prototype), 'constructor', this).call(this, _constantsDashConstants2['default'].PERIOD, commonProperties, [new _MapNode3['default'](_constantsDashConstants2['default'].ADAPTATION_SET, commonProperties, [new _MapNode3['default'](_constantsDashConstants2['default'].REPRESENTATION, commonProperties)])]);
20123    }
20124
20125    return SegmentValuesMap;
20126})(_MapNode3['default']);
20127
20128exports['default'] = SegmentValuesMap;
20129module.exports = exports['default'];
20130
20131},{"61":61,"66":66}],69:[function(_dereq_,module,exports){
20132/**
20133 * The copyright in this software is being made available under the BSD License,
20134 * included below. This software may be subject to other third party and contributor
20135 * rights, including patent rights, and no such rights are granted under this license.
20136 *
20137 * Copyright (c) 2013, Dash Industry Forum.
20138 * All rights reserved.
20139 *
20140 * Redistribution and use in source and binary forms, with or without modification,
20141 * are permitted provided that the following conditions are met:
20142 *  * Redistributions of source code must retain the above copyright notice, this
20143 *  list of conditions and the following disclaimer.
20144 *  * Redistributions in binary form must reproduce the above copyright notice,
20145 *  this list of conditions and the following disclaimer in the documentation and/or
20146 *  other materials provided with the distribution.
20147 *  * Neither the name of Dash Industry Forum nor the names of its
20148 *  contributors may be used to endorse or promote products derived from this software
20149 *  without specific prior written permission.
20150 *
20151 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
20152 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20153 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20154 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
20155 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20156 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20157 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
20158 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
20159 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
20160 *  POSSIBILITY OF SUCH DAMAGE.
20161 */
20162/**
20163 * @classdesc a base type for matching and converting types in manifest to
20164 * something more useful
20165 */
20166
20167"use strict";
20168
20169Object.defineProperty(exports, "__esModule", {
20170    value: true
20171});
20172
20173var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
20174
20175function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
20176
20177var BaseMatcher = (function () {
20178    function BaseMatcher(test, converter) {
20179        _classCallCheck(this, BaseMatcher);
20180
20181        this._test = test;
20182        this._converter = converter;
20183    }
20184
20185    _createClass(BaseMatcher, [{
20186        key: "test",
20187        get: function get() {
20188            return this._test;
20189        }
20190    }, {
20191        key: "converter",
20192        get: function get() {
20193            return this._converter;
20194        }
20195    }]);
20196
20197    return BaseMatcher;
20198})();
20199
20200exports["default"] = BaseMatcher;
20201module.exports = exports["default"];
20202
20203},{}],70:[function(_dereq_,module,exports){
20204/**
20205 * The copyright in this software is being made available under the BSD License,
20206 * included below. This software may be subject to other third party and contributor
20207 * rights, including patent rights, and no such rights are granted under this license.
20208 *
20209 * Copyright (c) 2013, Dash Industry Forum.
20210 * All rights reserved.
20211 *
20212 * Redistribution and use in source and binary forms, with or without modification,
20213 * are permitted provided that the following conditions are met:
20214 *  * Redistributions of source code must retain the above copyright notice, this
20215 *  list of conditions and the following disclaimer.
20216 *  * Redistributions in binary form must reproduce the above copyright notice,
20217 *  this list of conditions and the following disclaimer in the documentation and/or
20218 *  other materials provided with the distribution.
20219 *  * Neither the name of Dash Industry Forum nor the names of its
20220 *  contributors may be used to endorse or promote products derived from this software
20221 *  without specific prior written permission.
20222 *
20223 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
20224 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20225 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20226 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
20227 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
20227INCLUDING, BUT
20228 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20229 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
20230 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
20231 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
20232 *  POSSIBILITY OF SUCH DAMAGE.
20233 */
20234/**
20235 * @classdesc matches and converts xs:datetime to Date
20236 */
20237'use strict';
20238
20239Object.defineProperty(exports, '__esModule', {
20240    value: true
20241});
20242
20243var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
20244
20245function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
20246
20247function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
20248
20249function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
20250
20251var _BaseMatcher2 = _dereq_(69);
20252
20253var _BaseMatcher3 = _interopRequireDefault(_BaseMatcher2);
20254
20255var SECONDS_IN_MIN = 60;
20256var MINUTES_IN_HOUR = 60;
20257var MILLISECONDS_IN_SECONDS = 1000;
20258
20259var datetimeRegex = /^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2})(?::([0-9]*)(\.[0-9]*)?)?(?:([+-])([0-9]{2})(?::?)([0-9]{2}))?/;
20260
20261var DateTimeMatcher = (function (_BaseMatcher) {
20262    _inherits(DateTimeMatcher, _BaseMatcher);
20263
20264    function DateTimeMatcher() {
20265        _classCallCheck(this, DateTimeMatcher);
20266
20267        _get(Object.getPrototypeOf(DateTimeMatcher.prototype), 'constructor', this).call(this, function (attr) {
20268            return datetimeRegex.test(attr.value);
20269        }, function (str) {
20270            var match = datetimeRegex.exec(str);
20271            var utcDate = undefined;
20272
20273            // If the string does not contain a timezone offset different browsers can interpret it either
20274            // as UTC or as a local time so we have to parse the string manually to normalize the given date value for
20275            // all browsers
20276            utcDate = Date.UTC(parseInt(match[1], 10), parseInt(match[2], 10) - 1, // months start from zero
20277            parseInt(match[3], 10), parseInt(match[4], 10), parseInt(match[5], 10), match[6] && parseInt(match[6], 10) || 0, match[7] && parseFloat(match[7]) * MILLISECONDS_IN_SECONDS || 0);
20278
20279            // If the date has timezone offset take it into account as well
20280            if (match[9] && match[10]) {
20281                var timezoneOffset = parseInt(match[9], 10) * MINUTES_IN_HOUR + parseInt(match[10], 10);
20282                utcDate += (match[8] === '+' ? -1 : +1) * timezoneOffset * SECONDS_IN_MIN * MILLISECONDS_IN_SECONDS;
20283            }
20284
20285            return new Date(utcDate);
20286        });
20287    }
20288
20289    return DateTimeMatcher;
20290})(_BaseMatcher3['default']);
20291
20292exports['default'] = DateTimeMatcher;
20293module.exports = exports['default'];
20294
20295},{"69":69}],71:[function(_dereq_,module,exports){
20296/**
20297 * The copyright in this software is being made available under the BSD License,
20298 * included below. This software may be subject to other third party and contributor
20299 * rights, including patent rights, and no such rights are granted under this license.
20300 *
20301 * Copyright (c) 2013, Dash Industry Forum.
20302 * All rights reserved.
20303 *
20304 * Redistribution and use in source and binary forms, with or without modification,
20305 * are permitted provided that the following conditions are met:
20306 *  * Redistributions of source code must retain the above copyright notice, this
20307 *  list of conditions and the following disclaimer.
20308 *  * Redistributions in binary form must reproduce the above copyright notice,
20309 *  this list of conditions and the following disclaimer in the documentation and/or
20310 *  other materials provided with the distribution.
20311 *  * Neither the name of Dash Industry Forum nor the names of its
20312 *  contributors may be used to endorse or promote products derived from this software
20313 *  without specific prior written permission.
20314 *
20315 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
20316 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20317 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20318 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
20319 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
20319INCLUDING, BUT
20320 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20321 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
20322 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
20323 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
20324 *  POSSIBILITY OF SUCH DAMAGE.
20325 */
20326/**
20327 * @classdesc matches and converts xs:duration to seconds
20328 */
20329'use strict';
20330
20331Object.defineProperty(exports, '__esModule', {
20332    value: true
20333});
20334
20335var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
20336
20337function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
20338
20339function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
20340
20341function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
20342
20343var _BaseMatcher2 = _dereq_(69);
20344
20345var _BaseMatcher3 = _interopRequireDefault(_BaseMatcher2);
20346
20347var _streamingConstantsConstants = _dereq_(100);
20348
20349var _streamingConstantsConstants2 = _interopRequireDefault(_streamingConstantsConstants);
20350
20351var _constantsDashConstants = _dereq_(61);
20352
20353var _constantsDashConstants2 = _interopRequireDefault(_constantsDashConstants);
20354
20355var durationRegex = /^([-])?P(([\d.]*)Y)?(([\d.]*)M)?(([\d.]*)D)?T?(([\d.]*)H)?(([\d.]*)M)?(([\d.]*)S)?/;
20356
20357var SECONDS_IN_YEAR = 365 * 24 * 60 * 60;
20358var SECONDS_IN_MONTH = 30 * 24 * 60 * 60;
20359var SECONDS_IN_DAY = 24 * 60 * 60;
20360var SECONDS_IN_HOUR = 60 * 60;
20361var SECONDS_IN_MIN = 60;
20362
20363var DurationMatcher = (function (_BaseMatcher) {
20364    _inherits(DurationMatcher, _BaseMatcher);
20365
20366    function DurationMatcher() {
20367        _classCallCheck(this, DurationMatcher);
20368
20369        _get(Object.getPrototypeOf(DurationMatcher.prototype), 'constructor', this).call(this, function (attr) {
20370            var attributeList = [_constantsDashConstants2['default'].MIN_BUFFER_TIME, _constantsDashConstants2['default'].MEDIA_PRESENTATION_DURATION, _constantsDashConstants2['default'].MINIMUM_UPDATE_PERIOD, _constantsDashConstants2['default'].TIMESHIFT_BUFFER_DEPTH, _constantsDashConstants2['default'].MAX_SEGMENT_DURATION, _constantsDashConstants2['default'].MAX_SUBSEGMENT_DURATION, _streamingConstantsConstants2['default'].SUGGESTED_PRESENTATION_DELAY, _constantsDashConstants2['default'].START, _streamingConstantsConstants2['default'].START_TIME, _constantsDashConstants2['default'].DURATION];
20371            var len = attributeList.length;
20372
20373            for (var i = 0; i < len; i++) {
20374                if (attr.nodeName === attributeList[i]) {
20375                    return durationRegex.test(attr.value);
20376                }
20377            }
20378
20379            return false;
20380        }, function (str) {
20381            //str = "P10Y10M10DT10H10M10.1S";
20382            var match = durationRegex.exec(str);
20383            var result = parseFloat(match[2] || 0) * SECONDS_IN_YEAR + parseFloat(match[4] || 0) * SECONDS_IN_MONTH + parseFloat(match[6] || 0) * SECONDS_IN_DAY + parseFloat(match[8] || 0) * SECONDS_IN_HOUR + parseFloat(match[10] || 0) * SECONDS_IN_MIN + parseFloat(match[12] || 0);
20384
20385            if (match[1] !== undefined) {
20386                result = -result;
20387            }
20388
20389            return result;
20390        });
20391    }
20392
20393    return DurationMatcher;
20394})(_BaseMatcher3['default']);
20395
20396exports['default'] = DurationMatcher;
20397module.exports = exports['default'];
20398
20399},{"100":100,"61":61,"69":69}],72:[function(_dereq_,module,exports){
20400/**
20401 * The copyright in this software is being made available under the BSD License,
20402 * included below. This software may be subject to other third party and contributor
20403 * rights, including patent rights, and no such rights are granted under this license.
20404 *
20405 * Copyright (c) 2013, Dash Industry Forum.
20406 * All rights reserved.
20407 *
20408 * Redistribution and use in source and binary forms, with or without modification,
20409 * are permitted provided that the following conditions are met:
20410 *  * Redistributions of source code must retain the above copyright notice, this
20411 *  list of conditions and the following disclaimer.
20412 *  * Redistributions in binary form must reproduce the above copyright notice,
20413 *  this list of conditions and the following disclaimer in the documentation and/or
20414 *  other materials provided with the distribution.
20415 *  * Neither the name of Dash Industry Forum nor the names of its
20416 *  contributors may be used to endorse or promote products derived from this software
20417 *  without specific prior written permission.
20418 *
20419 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
20420 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20421 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20422 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
20423 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
20423INCLUDING, BUT
20424 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20425 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
20426 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
20427 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
20428 *  POSSIBILITY OF SUCH DAMAGE.
20429 */
20430/**
20431 * @classdesc Matches and converts xs:numeric to float
20432 */
20433'use strict';
20434
20435Object.defineProperty(exports, '__esModule', {
20436    value: true
20437});
20438
20439var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
20440
20441function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
20442
20443function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
20444
20445function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
20446
20447var _BaseMatcher2 = _dereq_(69);
20448
20449var _BaseMatcher3 = _interopRequireDefault(_BaseMatcher2);
20450
20451var numericRegex = /^[-+]?[0-9]+[.]?[0-9]*([eE][-+]?[0-9]+)?$/;
20452
20453var NumericMatcher = (function (_BaseMatcher) {
20454    _inherits(NumericMatcher, _BaseMatcher);
20455
20456    function NumericMatcher() {
20457        _classCallCheck(this, NumericMatcher);
20458
20459        _get(Object.getPrototypeOf(NumericMatcher.prototype), 'constructor', this).call(this, function (attr) {
20460            return numericRegex.test(attr.value);
20461        }, function (str) {
20462            return parseFloat(str);
20463        });
20464    }
20465
20466    return NumericMatcher;
20467})(_BaseMatcher3['default']);
20468
20469exports['default'] = NumericMatcher;
20470module.exports = exports['default'];
20471
20472},{"69":69}],73:[function(_dereq_,module,exports){
20473/**
20474 * The copyright in this software is being made available under the BSD License,
20475 * included below. This software may be subject to other third party and contributor
20476 * rights, including patent rights, and no such rights are granted under this license.
20477 *
20478 * Copyright (c) 2013, Dash Industry Forum.
20479 * All rights reserved.
20480 *
20481 * Redistribution and use in source and binary forms, with or without modification,
20482 * are permitted provided that the following conditions are met:
20483 *  * Redistributions of source code must retain the above copyright notice, this
20484 *  list of conditions and the following disclaimer.
20485 *  * Redistributions in binary form must reproduce the above copyright notice,
20486 *  this list of conditions and the following disclaimer in the documentation and/or
20487 *  other materials provided with the distribution.
20488 *  * Neither the name of Dash Industry Forum nor the names of its
20489 *  contributors may be used to endorse or promote products derived from this software
20490 *  without specific prior written permission.
20491 *
20492 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
20493 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20494 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20495 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
20496 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
20496INCLUDING, BUT
20497 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20498 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
20499 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
20500 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
20501 *  POSSIBILITY OF SUCH DAMAGE.
20502 */
20503/**
20504 * @classdesc Matches and converts xs:string to string, but only for specific attributes on specific nodes
20505 */
20506'use strict';
20507
20508Object.defineProperty(exports, '__esModule', {
20509    value: true
20510});
20511
20512var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
20513
20514function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
20515
20516function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
20517
20518function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
20519
20520function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
20521
20522var _BaseMatcher2 = _dereq_(69);
20523
20524var _BaseMatcher3 = _interopRequireDefault(_BaseMatcher2);
20525
20526var _constantsDashConstants = _dereq_(61);
20527
20528var _constantsDashConstants2 = _interopRequireDefault(_constantsDashConstants);
20529
20530var StringMatcher = (function (_BaseMatcher) {
20531    _inherits(StringMatcher, _BaseMatcher);
20532
20533    function StringMatcher() {
20534        _classCallCheck(this, StringMatcher);
20535
20536        _get(Object.getPrototypeOf(StringMatcher.prototype), 'constructor', this).call(this, function (attr, nodeName) {
20537            var _stringAttrsInElements;
20538
20539            var stringAttrsInElements = (_stringAttrsInElements = {}, _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].MPD, [_constantsDashConstants2['default'].ID, _constantsDashConstants2['default'].PROFILES]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].PERIOD, [_constantsDashConstants2['default'].ID]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].BASE_URL, [_constantsDashConstants2['default'].SERVICE_LOCATION, _constantsDashConstants2['default'].BYTE_RANGE]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].SEGMENT_BASE, [_constantsDashConstants2['default'].INDEX_RANGE]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].INITIALIZATION, [_constantsDashConstants2['default'].RANGE]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].REPRESENTATION_INDEX, [_constantsDashConstants2['default'].RANGE]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].SEGMENT_LIST, [_constantsDashConstants2['default'].INDEX_RANGE]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].BITSTREAM_SWITCHING, [_constantsDashConstants2['default'].RANGE]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].SEGMENT_URL, [_constantsDashConstants2['default'].MEDIA_RANGE, _constantsDashConstants2['default'].INDEX_RANGE]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].SEGMENT_TEMPLATE, [_constantsDashConstants2['default'].INDEX_RANGE, _constantsDashConstants2['default'].MEDIA, _constantsDashConstants2['default'].INDEX, _constantsDashConstants2['default'].INITIALIZATION_MINUS, _constantsDashConstants2['default'].BITSTREAM_SWITCHING_MINUS]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].ASSET_IDENTIFIER, [_
20539constantsDashConstants2['default'].VALUE, _constantsDashConstants2['default'].ID]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].EVENT_STREAM, [_constantsDashConstants2['default'].VALUE]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].ADAPTATION_SET, [_constantsDashConstants2['default'].PROFILES, _constantsDashConstants2['default'].MIME_TYPE, _constantsDashConstants2['default'].SEGMENT_PROFILES, _constantsDashConstants2['default'].CODECS, _constantsDashConstants2['default'].CONTENT_TYPE]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].FRAME_PACKING, [_constantsDashConstants2['default'].VALUE, _constantsDashConstants2['default'].ID]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].AUDIO_CHANNEL_CONFIGURATION, [_constantsDashConstants2['default'].VALUE, _constantsDashConstants2['default'].ID]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].CONTENT_PROTECTION, [_constantsDashConstants2['default'].VALUE, _constantsDashConstants2['default'].ID]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].ESSENTIAL_PROPERTY, [_constantsDashConstants2['default'].VALUE, _constantsDashConstants2['default'].ID]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].SUPPLEMENTAL_PROPERTY, [_constantsDashConstants2['default'].VALUE, _constantsDashConstants2['default'].ID]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].INBAND_EVENT_STREAM, [_constantsDashConstants2['default'].VALUE, _constantsDashConstants2['default'].ID]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].ACCESSIBILITY, [_constantsDashConstants2['default'].VALUE, _constantsDashConstants2['default'].ID]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].ROLE, [_constantsDashConstants2['default'].VALUE, _constantsDashConstants2['default'].ID]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].RATING, [_constantsDashConstants2['default'].VALUE, _constantsDashConstants2['default'].ID]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].VIEWPOINT, [_constantsDashConstants2['default'].VALUE, _constantsDashConstants2['default'].ID]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].CONTENT_COMPONENT, [_constantsDashConstants2['default'].CONTENT_TYPE]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].REPRESENTATION, [_constantsDashConstants2['default'].ID, _constantsDashConstants2['default'].DEPENDENCY_ID, _constantsDashConstants2['default'].MEDIA_STREAM_STRUCTURE_ID]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].SUBSET, [_constantsDashConstants2['default'].ID]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].METRICS, [_constantsDashConstants2['default'].METRICS_MINUS]), _defineProperty(_stringAttrsInElements, _constantsDashConstants2['default'].REPORTING, [_constantsDashConstants2['default'].VALUE, _constantsDashConstants2['default'].ID]), _stringAttrsInElements);
20540            if (stringAttrsInElements.hasOwnProperty(nodeName)) {
20541                var attrNames = stringAttrsInElements[nodeName];
20542                if (attrNames !== undefined) {
20543                    return attrNames.indexOf(attr.name) >= 0;
20544                } else {
20545                    return false;
20546                }
20547            }
20548            return false;
20549        }, function (str) {
20550            return String(str);
20551        });
20552    }
20553
20554    return StringMatcher;
20555})(_BaseMatcher3['default']);
20556
20557exports['default'] = StringMatcher;
20558module.exports = exports['default'];
20559
20560},{"61":61,"69":69}],74:[function(_dereq_,module,exports){
20561/**
20562 * The copyright in this software is being made available under the BSD License,
20563 * included below. This software may be subject to other third party and contributor
20564 * rights, including patent rights, and no such rights are granted under this license.
20565 *
20566 * Copyright (c) 2013, Dash Industry Forum.
20567 * All rights reserved.
20568 *
20569 * Redistribution and use in source and binary forms, with or without modification,
20570 * are permitted provided that the following conditions are met:
20571 *  * Redistributions of source code must retain the above copyright notice, this
20572 *  list of conditions and the following disclaimer.
20573 *  * Redistributions in binary form must reproduce the above copyright notice,
20574 *  this list of conditions and the following disclaimer in the documentation and/or
20575 *  other materials provided with the distribution.
20576 *  * Neither the name of Dash Industry Forum nor the names of its
20577 *  contributors may be used to endorse or promote products derived from this software
20578 *  without specific prior written permission.
20579 *
20580 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
20581 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20582 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20583 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
20584 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
20584INCLUDING, BUT
20585 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20586 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
20587 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
20588 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
20589 *  POSSIBILITY OF SUCH DAMAGE.
20590 */
20591
20592'use strict';
20593
20594Object.defineProperty(exports, '__esModule', {
20595    value: true
20596});
20597
20598function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
20599
20600var _coreFactoryMaker = _dereq_(51);
20601
20602var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
20603
20604function FragmentedTextBoxParser() {
20605
20606    var instance = undefined,
20607        boxParser = undefined;
20608
20609    function setConfig(config) {
20610        if (!config) return;
20611
20612        if (config.boxParser) {
20613            boxParser = config.boxParser;
20614        }
20615    }
20616
20617    function getSamplesInfo(ab) {
20618        if (!boxParser) {
20619            throw new Error('boxParser is undefined');
20620        }
20621
20622        if (!ab) {
20623            return { sampleList: [], lastSequenceNumber: NaN, totalDuration: NaN, numSequences: NaN };
20624        }
20625        var isoFile = boxParser.parse(ab);
20626        // zero or more moofs
20627        var moofBoxes = isoFile.getBoxes('moof');
20628        // exactly one mfhd per moof
20629        var mfhdBoxes = isoFile.getBoxes('mfhd');
20630
20631        var sampleDuration = undefined,
20632            sampleCompositionTimeOffset = undefined,
20633            sampleCount = undefined,
20634            sampleSize = undefined,
20635            sampleDts = undefined,
20636            sampleList = undefined,
20637            sample = undefined,
20638            i = undefined,
20639            j = undefined,
20640            k = undefined,
20641            l = undefined,
20642            m = undefined,
20643            n = undefined,
20644            dataOffset = undefined,
20645            lastSequenceNumber = undefined,
20646            numSequences = undefined,
20647            totalDuration = undefined;
20648
20649        numSequences = isoFile.getBoxes('moof').length;
20650        lastSequenceNumber = mfhdBoxes[mfhdBoxes.length - 1].sequence_number;
20651        sampleCount = 0;
20652
20653        sampleList = [];
20654        var subsIndex = -1;
20655        var nextSubsSample = -1;
20656        for (l = 0; l < moofBoxes.length; l++) {
20657            var moofBox = moofBoxes[l];
20658            // zero or more trafs per moof
20659            var trafBoxes = moofBox.getChildBoxes('traf');
20660            for (j = 0; j < trafBoxes.length; j++) {
20661                var trafBox = trafBoxes[j];
20662                // exactly one tfhd per traf
20663                var tfhdBox = trafBox.getChildBox('tfhd');
20664                // zero or one tfdt per traf
20665                var tfdtBox = trafBox.getChildBox('tfdt');
20666                sampleDts = tfdtBox.baseMediaDecodeTime;
20667                // zero or more truns per traf
20668                var trunBoxes = trafBox.getChildBoxes('trun');
20669                // zero or more subs per traf
20670                var subsBoxes = trafBox.getChildBoxes('subs');
20671                for (k = 0; k < trunBoxes.length; k++) {
20672                    var trunBox = trunBoxes[k];
20673                    sampleCount = trunBox.sample_count;
20674                    dataOffset = (tfhdBox.base_data_offset || 0) + (trunBox.data_offset || 0);
20675
20676                    for (i = 0; i < sampleCount; i++) {
20677                        sample = trunBox.samples[i];
20678                        sampleDuration = sample.sample_duration !== undefined ? sample.sample_duration : tfhdBox.default_sample_duration;
20679                        sampleSize = sample.sample_size !== undefined ? sample.sample_size : tfhdBox.default_sample_size;
20680                        sampleCompositionTimeOffset = sample.sample_composition_time_offset !== undefined ? sample.sample_composition_time_offset : 0;
20681                        var sampleData = {
20682                            'dts': sampleDts,
20683                            'cts': sampleDts + sampleCompositionTimeOffset,
20684                            'duration': sampleDuration,
20685                            'offset': moofBox.offset + dataOffset,
20686                            'size': sampleSize,
20687                            'subSizes': [sampleSize]
20688                        };
20689                        if (subsBoxes) {
20690                            for (m = 0; m < subsBoxes.length; m++) {
20691                                var subsBox = subsBoxes[m];
20692                                if (subsIndex < subsBox.entry_count && i > nextSubsSample) {
20693                                    subsIndex++;
20694                                    nextSubsSample += subsBox.entries[subsIndex].sample_delta;
20695                                }
20696                                if (i == nextSubsSample) {
20697                                    sampleData.subSizes = [];
20698                                    var entry = subsBox.entries[subsIndex];
20699                                    for (n = 0; n < entry.subsample_count; n++) {
20700                                        sampleData.subSizes.push(entry.subsamples[n].subsample_size);
20701                                    }
20702                                }
20703                            }
20704                        }
20705                        sampleList.push(sampleData);
20706                        dataOffset += sampleSize;
20707                        sampleDts += sampleDuration;
20708                    }
20709                }
20710                totalDuration = sampleDts - tfdtBox.baseMediaDecodeTime;
20711            }
20712        }
20713        return { sampleList: sampleList, lastSequenceNumber: lastSequenceNumber, totalDuration: totalDuration, numSequences: numSequences };
20714    }
20715
20716    function getMediaTimescaleFromMoov(ab) {
20717        if (!boxParser) {
20718            throw new Error('boxParser is undefined');
20719        }
20720
20721        var isoFile = boxParser.parse(ab);
20722        var mdhdBox = isoFile ? isoFile.getBox('mdhd') : undefined;
20723
20724        return mdhdBox ? mdhdBox.timescale : NaN;
20725    }
20726
20727    instance = {
20728        getSamplesInfo: getSamplesInfo,
20729        getMediaTimescaleFromMoov: getMediaTimescaleFromMoov,
20730        setConfig: setConfig
20731    };
20732
20733    return instance;
20734}
20735
20736FragmentedTextBoxParser.__dashjs_factory_name = 'FragmentedTextBoxParser';
20737exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(FragmentedTextBoxParser);
20738module.exports = exports['default'];
20739
20740},{"51":51}],75:[function(_dereq_,module,exports){
20741/**
20742 * The copyright in this software is being made available under the BSD License,
20743 * included below. This software may be subject to other third party and contributor
20744 * rights, including patent rights, and no such rights are granted under this license.
20745 *
20746 * Copyright (c) 2013, Dash Industry Forum.
20747 * All rights reserved.
20748 *
20749 * Redistribution and use in source and binary forms, with or without modification,
20750 * are permitted provided that the following conditions are met:
20751 *  * Redistributions of source code must retain the above copyright notice, this
20752 *  list of conditions and the following disclaimer.
20753 *  * Redistributions in binary form must reproduce the above copyright notice,
20754 *  this list of conditions and the following disclaimer in the documentation and/or
20755 *  other materials provided with the distribution.
20756 *  * Neither the name of Dash Industry Forum nor the names of its
20757 *  contributors may be used to endorse or promote products derived from this software
20758 *  without specific prior written permission.
20759 *
20760 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
20761 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20762 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20763 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
20764 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20765 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20766 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
20767 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
20768 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
20769 *  POSSIBILITY OF SUCH DAMAGE.
20770 */
20771
20772'use strict';
20773
20774Object.defineProperty(exports, '__esModule', {
20775    value: true
20776});
20777
20778function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
20779
20780var _coreFactoryMaker = _dereq_(51);
20781
20782var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
20783
20784var _SegmentsUtils = _dereq_(77);
20785
20786function ListSegmentsGetter(config, isDynamic) {
20787
20788    var timelineConverter = config.timelineConverter;
20789
20790    var instance = undefined;
20791
20792    function getSegmentsFromList(representation, requestedTime, index) {
20793        var list = representation.adaptation.period.mpd.manifest.Period_asArray[representation.adaptation.period.index].AdaptationSet_asArray[representation.adaptation.index].Representation_asArray[representation.index].SegmentList;
20794        var len = list.SegmentURL_asArray.length;
20795
20796        var segments = [];
20797
20798        var periodSegIdx = undefined,
20799            seg = undefined,
20800            s = undefined,
20801            range = undefined,
20802            startIdx = undefined,
20803            endIdx = undefined,
20804            start = undefined;
20805
20806        start = representation.startNumber;
20807
20808        range = (0, _SegmentsUtils.decideSegmentListRangeForTemplate)(timelineConverter, isDynamic, representation, requestedTime, index);
20809        startIdx = Math.max(range.start, 0);
20810        endIdx = Math.min(range.end, list.SegmentURL_asArray.length - 1);
20811
20812        for (periodSegIdx = startIdx; periodSegIdx <= endIdx; periodSegIdx++) {
20813            s = list.SegmentURL_asArray[periodSegIdx];
20814
20815            seg = (0, _SegmentsUtils.getIndexBasedSegment)(timelineConverter, isDynamic, representation, periodSegIdx);
20816            seg.replacementTime = (start + periodSegIdx - 1) * representation.segmentDuration;
20817            seg.media = s.media ? s.media : '';
20818            seg.mediaRange = s.mediaRange;
20819            seg.index = s.index;
20820            seg.indexRange = s.indexRange;
20821
20822            segments.push(seg);
20823            seg = null;
20824        }
20825
20826        representation.availableSegmentsNumber = len;
20827
20828        return segments;
20829    }
20830
20831    instance = {
20832        getSegments: getSegmentsFromList
20833    };
20834
20835    return instance;
20836}
20837
20838ListSegmentsGetter.__dashjs_factory_name = 'ListSegmentsGetter';
20839var factory = _coreFactoryMaker2['default'].getClassFactory(ListSegmentsGetter);
20840exports['default'] = factory;
20841module.exports = exports['default'];
20842
20843},{"51":51,"77":77}],76:[function(_dereq_,module,exports){
20844/**
20845 * The copyright in this software is being made available under the BSD License,
20846 * included below. This software may be subject to other third party and contributor
20847 * rights, including patent rights, and no such rights are granted under this license.
20848 *
20849 * Copyright (c) 2013, Dash Industry Forum.
20850 * All rights reserved.
20851 *
20852 * Redistribution and use in source and binary forms, with or without modification,
20853 * are permitted provided that the following conditions are met:
20854 *  * Redistributions of source code must retain the above copyright notice, this
20855 *  list of conditions and the following disclaimer.
20856 *  * Redistributions in binary form must reproduce the above copyright notice,
20857 *  this list of conditions and the following disclaimer in the documentation and/or
20858 *  other materials provided with the distribution.
20859 *  * Neither the name of Dash Industry Forum nor the names of its
20860 *  contributors may be used to endorse or promote products derived from this software
20861 *  without specific prior written permission.
20862 *
20863 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
20864 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20865 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20866 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
20867 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
20867INCLUDING, BUT
20868 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20869 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
20870 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
20871 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
20872 *  POSSIBILITY OF SUCH DAMAGE.
20873 */
20874'use strict';
20875
20876Object.defineProperty(exports, '__esModule', {
20877    value: true
20878});
20879
20880function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
20881
20882var _constantsDashConstants = _dereq_(61);
20883
20884var _constantsDashConstants2 = _interopRequireDefault(_constantsDashConstants);
20885
20886var _coreFactoryMaker = _dereq_(51);
20887
20888var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
20889
20890var _TimelineSegmentsGetter = _dereq_(80);
20891
20892var _TimelineSegmentsGetter2 = _interopRequireDefault(_TimelineSegmentsGetter);
20893
20894var _TemplateSegmentsGetter = _dereq_(78);
20895
20896var _TemplateSegmentsGetter2 = _interopRequireDefault(_TemplateSegmentsGetter);
20897
20898var _ListSegmentsGetter = _dereq_(75);
20899
20900var _ListSegmentsGetter2 = _interopRequireDefault(_ListSegmentsGetter);
20901
20902function SegmentsGetter(config, isDynamic) {
20903
20904    var context = this.context;
20905
20906    var instance = undefined,
20907        timelineSegmentsGetter = undefined,
20908        templateSegmentsGetter = undefined,
20909        listSegmentsGetter = undefined;
20910
20911    function setup() {
20912        timelineSegmentsGetter = (0, _TimelineSegmentsGetter2['default'])(context).create(config, isDynamic);
20913        templateSegmentsGetter = (0, _TemplateSegmentsGetter2['default'])(context).create(config, isDynamic);
20914        listSegmentsGetter = (0, _ListSegmentsGetter2['default'])(context).create(config, isDynamic);
20915    }
20916
20917    function getSegments(representation, requestedTime, index, onSegmentListUpdatedCallback) {
20918        var segments = undefined;
20919        var type = representation.segmentInfoType;
20920
20921        // Already figure out the segments.
20922        if (type === _constantsDashConstants2['default'].SEGMENT_BASE || type === _constantsDashConstants2['default'].BASE_URL || !isSegmentListUpdateRequired(representation, index)) {
20923            segments = representation.segments;
20924        } else {
20925            if (type === _constantsDashConstants2['default'].SEGMENT_TIMELINE) {
20926                segments = timelineSegmentsGetter.getSegments(representation, requestedTime, index);
20927            } else if (type === _constantsDashConstants2['default'].SEGMENT_TEMPLATE) {
20928                segments = templateSegmentsGetter.getSegments(representation, requestedTime, index);
20929            } else if (type === _constantsDashConstants2['default'].SEGMENT_LIST) {
20930                segments = listSegmentsGetter.getSegments(representation, requestedTime, index);
20931            }
20932
20933            if (onSegmentListUpdatedCallback) {
20934                onSegmentListUpdatedCallback(representation, segments);
20935            }
20936        }
20937    }
20938
20939    function isSegmentListUpdateRequired(representation, index) {
20940        var segments = representation.segments;
20941        var updateRequired = false;
20942
20943        var upperIdx = undefined,
20944            lowerIdx = undefined;
20945
20946        if (!segments || segments.length === 0) {
20947            updateRequired = true;
20948        } else {
20949            lowerIdx = segments[0].availabilityIdx;
20950            upperIdx = segments[segments.length - 1].availabilityIdx;
20951            updateRequired = index < lowerIdx || index > upperIdx;
20952        }
20953
20954        return updateRequired;
20955    }
20956
20957    instance = {
20958        getSegments: getSegments
20959    };
20960
20961    setup();
20962
20963    return instance;
20964}
20965
20966SegmentsGetter.__dashjs_factory_name = 'SegmentsGetter';
20967var factory = _coreFactoryMaker2['default'].getClassFactory(SegmentsGetter);
20968exports['default'] = factory;
20969module.exports = exports['default'];
20970
20971},{"51":51,"61":61,"75":75,"78":78,"80":80}],77:[function(_dereq_,module,exports){
20972/**
20973 * The copyright in this software is being made available under the BSD License,
20974 * included below. This software may be subject to other third party and contributor
20975 * rights, including patent rights, and no such rights are granted under this license.
20976 *
20977 * Copyright (c) 2013, Dash Industry Forum.
20978 * All rights reserved.
20979 *
20980 * Redistribution and use in source and binary forms, with or without modification,
20981 * are permitted provided that the following conditions are met:
20982 *  * Redistributions of source code must retain the above copyright notice, this
20983 *  list of conditions and the following disclaimer.
20984 *  * Redistributions in binary form must reproduce the above copyright notice,
20985 *  this list of conditions and the following disclaimer in the documentation and/or
20986 *  other materials provided with the distribution.
20987 *  * Neither the name of Dash Industry Forum nor the names of its
20988 *  contributors may be used to endorse or promote products derived from this software
20989 *  without specific prior written permission.
20990 *
20991 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
20992 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20993 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20994 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
20995 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
20995INCLUDING, BUT
20996 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20997 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
20998 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
20999 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
21000 *  POSSIBILITY OF SUCH DAMAGE.
21001 */
21002
21003'use strict';
21004
21005Object.defineProperty(exports, '__esModule', {
21006    value: true
21007});
21008exports.replaceTokenForTemplate = replaceTokenForTemplate;
21009exports.getIndexBasedSegment = getIndexBasedSegment;
21010exports.getTimeBasedSegment = getTimeBasedSegment;
21011exports.getSegmentByIndex = getSegmentByIndex;
21012exports.decideSegmentListRangeForTemplate = decideSegmentListRangeForTemplate;
21013
21014function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
21015
21016var _voSegment = _dereq_(88);
21017
21018var _voSegment2 = _interopRequireDefault(_voSegment);
21019
21020function zeroPadToLength(numStr, minStrLength) {
21021    while (numStr.length < minStrLength) {
21022        numStr = '0' + numStr;
21023    }
21024    return numStr;
21025}
21026
21027function getNumberForSegment(segment, segmentIndex) {
21028    return segment.representation.startNumber + segmentIndex;
21029}
21030
21031function replaceTokenForTemplate(url, token, value) {
21032    var formatTag = '%0';
21033
21034    var startPos = undefined,
21035        endPos = undefined,
21036        formatTagPos = undefined,
21037        specifier = undefined,
21038        width = undefined,
21039        paddedValue = undefined;
21040
21041    var tokenLen = token.length;
21042    var formatTagLen = formatTag.length;
21043
21044    if (!url) {
21045        return url;
21046    }
21047
21048    // keep looping round until all instances of <token> have been
21049    // replaced. once that has happened, startPos below will be -1
21050    // and the completed url will be returned.
21051    while (true) {
21052
21053        // check if there is a valid $<token>...$ identifier
21054        // if not, return the url as is.
21055        startPos = url.indexOf('$' + token);
21056        if (startPos < 0) {
21057            return url;
21058        }
21059
21060        // the next '$' must be the end of the identifier
21061        // if there isn't one, return the url as is.
21062        endPos = url.indexOf('$', startPos + tokenLen);
21063        if (endPos < 0) {
21064            return url;
21065        }
21066
21067        // now see if there is an additional format tag suffixed to
21068        // the identifier within the enclosing '$' characters
21069        formatTagPos = url.indexOf(formatTag, startPos + tokenLen);
21070        if (formatTagPos > startPos && formatTagPos < endPos) {
21071
21072            specifier = url.charAt(endPos - 1);
21073            width = parseInt(url.substring(formatTagPos + formatTagLen, endPos - 1), 10);
21074
21075            // support the minimum specifiers required by IEEE 1003.1
21076            // (d, i , o, u, x, and X) for completeness
21077            switch (specifier) {
21078                // treat all int types as uint,
21079                // hence deliberate fallthrough
21080                case 'd':
21081                case 'i':
21082                case 'u':
21083                    paddedValue = zeroPadToLength(value.toString(), width);
21084                    break;
21085                case 'x':
21086                    paddedValue = zeroPadToLength(value.toString(16), width);
21087                    break;
21088                case 'X':
21089                    paddedValue = zeroPadToLength(value.toString(16), width).toUpperCase();
21090                    break;
21091                case 'o':
21092                    paddedValue = zeroPadToLength(value.toString(8), width);
21093                    break;
21094                default:
21095                    //TODO: commented out logging to supress jshint warning -- `log` is undefined here
21096                    //log('Unsupported/invalid IEEE 1003.1 format identifier string in URL');
21097                    return url;
21098            }
21099        } else {
21100            paddedValue = value;
21101        }
21102
21103        url = url.substring(0, startPos) + paddedValue + url.substring(endPos + 1);
21104    }
21105}
21106
21107function getIndexBasedSegment(timelineConverter, isDynamic, representation, index) {
21108    var seg = undefined,
21109        duration = undefined,
21110        presentationStartTime = undefined,
21111        presentationEndTime = undefined;
21112
21113    duration = representation.segmentDuration;
21114
21115    /*
21116     * From spec - If neither @duration attribute nor SegmentTimeline element is present, then the Representation
21117     * shall contain exactly one Media Segment. The MPD start time is 0 and the MPD duration is obtained
21118     * in the same way as for the last Media Segment in the Representation.
21119     */
21120    if (isNaN(duration)) {
21121        duration = representation.adaptation.period.duration;
21122    }
21123
21124    presentationStartTime = representation.adaptation.period.start + index * duration;
21125    presentationEndTime = presentationStartTime + duration;
21126
21127    seg = new _voSegment2['default']();
21128
21129    seg.representation = representation;
21130    seg.duration = duration;
21131    seg.presentationStartTime = presentationStartTime;
21132
21133    seg.mediaStartTime = timelineConverter.calcMediaTimeFromPresentationTime(seg.presentationStartTime, representation);
21134
21135    seg.availabilityStartTime = timelineConverter.calcAvailabilityStartTimeFromPresentationTime(seg.presentationStartTime, representation.adaptation.period.mpd, isDynamic);
21136    seg.availabilityEndTime = timelineConverter.calcAvailabilityEndTimeFromPresentationTime(presentationEndTime, representation.adaptation.period.mpd, isDynamic);
21137
21138    // at this wall clock time, the video element currentTime should be seg.presentationStartTime
21139    seg.wallStartTime = timelineConverter.calcWallTimeForSegment(seg, isDynamic);
21140
21141    seg.replacementNumber = getNumberForSegment(seg, index);
21142    seg.availabilityIdx = index;
21143
21144    return seg;
21145}
21146
21147function getTimeBasedSegment(timelineConverter, isDynamic, representation, time, duration, fTimescale, url, range, index, tManifest) {
21148    var scaledTime = time / fTimescale;
21149    var scaledDuration = Math.min(duration / fTimescale, representation.adaptation.period.mpd.maxSegmentDuration);
21150
21151    var presentationStartTime = undefined,
21152        presentationEndTime = undefined,
21153        seg = undefined;
21154
21155    presentationStartTime = timelineConverter.calcPresentationTimeFromMediaTime(scaledTime, representation);
21156    presentationEndTime = presentationStartTime + scaledDuration;
21157
21158    seg = new _voSegment2['default']();
21159
21160    seg.representation = representation;
21161    seg.duration = scaledDuration;
21162    seg.mediaStartTime = scaledTime;
21163
21164    seg.presentationStartTime = presentationStartTime;
21165
21166    // For SegmentTimeline every segment is available at loadedTime
21167    seg.availabilityStartTime = representation.adaptation.period.mpd.manifest.loadedTime;
21168    seg.availabilityEndTime = timelineConverter.calcAvailabilityEndTimeFromPresentationTime(presentationEndTime, representation.adaptation.period.mpd, isDynamic);
21169
21170    // at this wall clock time, the video element currentTime should be seg.presentationStartTime
21171    seg.wallStartTime = timelineConverter.calcWallTimeForSegment(seg, isDynamic);
21172
21173    seg.replacementTime = tManifest ? tManifest : time;
21174
21175    seg.replacementNumber = getNumberForSegment(seg, index);
21176
21177    url = replaceTokenForTemplate(url, 'Number', seg.replacementNumber);
21178    url = replaceTokenForTemplate(url, 'Time', seg.replacementTime);
21179    seg.media = url;
21180    seg.mediaRange = range;
21181    seg.availabilityIdx = index;
21182
21183    return seg;
21184}
21185
21186function getSegmentByIndex(index, representation) {
21187    if (!representation || !representation.segments) return null;
21188
21189    var ln = representation.segments.length;
21190    var seg = undefined,
21191        i = undefined;
21192
21193    if (index < ln) {
21194        seg = representation.segments[index];
21195        if (seg && seg.availabilityIdx === index) {
21196            return seg;
21197        }
21198    }
21199
21200    for (i = 0; i < ln; i++) {
21201        seg = representation.segments[i];
21202
21203        if (seg && seg.availabilityIdx === index) {
21204            return seg;
21205        }
21206    }
21207
21208    return null;
21209}
21210
21211function decideSegmentListRangeForTemplate(timelineConverter, isDynamic, representation, requestedTime, index, givenAvailabilityUpperLimit) {
21212    var duration = representation.segmentDuration;
21213    var minBufferTime = representation.adaptation.period.mpd.manifest.minBufferTime;
21214    var availabilityWindow = representation.segmentAvailabilityRange;
21215    var periodRelativeRange = {
21216        start: timelineConverter.calcPeriodRelativeTimeFromMpdRelativeTime(representation, availabilityWindow.start),
21217        end: timelineConverter.calcPeriodRelativeTimeFromMpdRelativeTime(representation, availabilityWindow.end)
21218    };
21219    var currentSegmentList = representation.segments;
21220    var availabilityLowerLimit = 2 * duration;
21221    var availabilityUpperLimit = givenAvailabilityUpperLimit || Math.max(2 * minBufferTime, 10 * duration);
21222
21223    var originAvailabilityTime = NaN;
21224    var originSegment = null;
21225
21226    var start = undefined,
21227        end = undefined,
21228        range = undefined;
21229
21230    periodRelativeRange.start = Math.max(periodRelativeRange.start, 0);
21231
21232    if (isDynamic && !timelineConverter.isTimeSyncCompleted()) {
21233        start = Math.floor(periodRelativeRange.start / duration);
21234        end = Math.floor(periodRelativeRange.end / duration);
21235        range = { start: start, end: end };
21236        return range;
21237    }
21238
21239    // if segments exist we should try to find the latest buffered time, which is the presentation time of the
21240    // segment for the current index
21241    if (currentSegmentList && currentSegmentList.length > 0) {
21242        originSegment = getSegmentByIndex(index, representation);
21243        if (originSegment) {
21244            originAvailabilityTime = timelineConverter.calcPeriodRelativeTimeFromMpdRelativeTime(representation, originSegment.presentationStartTime);
21245        } else {
21246            originAvailabilityTime = index > 0 ? index * duration : timelineConverter.calcPeriodRelativeTimeFromMpdRelativeTime(representation, requestedTime);
21247        }
21248    } else {
21249        // If no segments exist, but index > 0, it means that we switch to the other representation, so
21250        // we should proceed from this time.
21251        // Otherwise we should start from the beginning for static mpds or from the end (live edge) for dynamic mpds
21252        originAvailabilityTime = index > 0 ? index * duration : isDynamic ? periodRelativeRange.end : periodRelativeRange.start;
21253    }
21254
21255    // segment list should not be out of the availability window range
21256    start = Math.floor(Math.max(originAvailabilityTime - availabilityLowerLimit, peri
21256odRelativeRange.start) / duration);
21257    end = Math.floor(Math.min(start + availabilityUpperLimit / duration, periodRelativeRange.end / duration));
21258
21259    range = { start: start, end: end };
21260
21261    return range;
21262}
21263
21264},{"88":88}],78:[function(_dereq_,module,exports){
21265/**
21266 * The copyright in this software is being made available under the BSD License,
21267 * included below. This software may be subject to other third party and contributor
21268 * rights, including patent rights, and no such rights are granted under this license.
21269 *
21270 * Copyright (c) 2013, Dash Industry Forum.
21271 * All rights reserved.
21272 *
21273 * Redistribution and use in source and binary forms, with or without modification,
21274 * are permitted provided that the following conditions are met:
21275 *  * Redistributions of source code must retain the above copyright notice, this
21276 *  list of conditions and the following disclaimer.
21277 *  * Redistributions in binary form must reproduce the above copyright notice,
21278 *  this list of conditions and the following disclaimer in the documentation and/or
21279 *  other materials provided with the distribution.
21280 *  * Neither the name of Dash Industry Forum nor the names of its
21281 *  contributors may be used to endorse or promote products derived from this software
21282 *  without specific prior written permission.
21283 *
21284 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
21285 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21286 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21287 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
21288 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21289 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21290 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21291 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
21292 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
21293 *  POSSIBILITY OF SUCH DAMAGE.
21294 */
21295
21296'use strict';
21297
21298Object.defineProperty(exports, '__esModule', {
21299    value: true
21300});
21301
21302function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
21303
21304var _coreFactoryMaker = _dereq_(51);
21305
21306var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
21307
21308var _SegmentsUtils = _dereq_(77);
21309
21310function TemplateSegmentsGetter(config, isDynamic) {
21311
21312    var timelineConverter = config.timelineConverter;
21313
21314    var instance = undefined;
21315
21316    function getSegmentsFromTemplate(representation, requestedTime, index) {
21317        var template = representation.adaptation.period.mpd.manifest.Period_asArray[representation.adaptation.period.index].AdaptationSet_asArray[representation.adaptation.index].Representation_asArray[representation.index].SegmentTemplate;
21318        var duration = representation.segmentDuration;
21319        var availabilityWindow = representation.segmentAvailabilityRange;
21320
21321        var segments = [];
21322        var url = null;
21323        var seg = null;
21324
21325        var segmentRange = undefined,
21326            periodSegIdx = undefined,
21327            startIdx = undefined,
21328            endIdx = undefined,
21329            start = undefined;
21330
21331        start = representation.startNumber;
21332
21333        if (isNaN(duration) && !isDynamic) {
21334            segmentRange = { start: start, end: start };
21335        } else {
21336            segmentRange = (0, _SegmentsUtils.decideSegmentListRangeForTemplate)(timelineConverter, isDynamic, representation, requestedTime, index);
21337        }
21338
21339        startIdx = segmentRange.start;
21340        endIdx = segmentRange.end;
21341
21342        for (periodSegIdx = startIdx; periodSegIdx <= endIdx; periodSegIdx++) {
21343
21344            seg = (0, _SegmentsUtils.getIndexBasedSegment)(timelineConverter, isDynamic, representation, periodSegIdx);
21345            seg.replacementTime = (start + periodSegIdx - 1) * representation.segmentDuration;
21346            url = template.media;
21347            url = (0, _SegmentsUtils.replaceTokenForTemplate)(url, 'Number', seg.replacementNumber);
21348            url = (0, _SegmentsUtils.replaceTokenForTemplate)(url, 'Time', seg.replacementTime);
21349            seg.media = url;
21350
21351            segments.push(seg);
21352            seg = null;
21353        }
21354
21355        if (isNaN(duration)) {
21356            representation.availableSegmentsNumber = 1;
21357        } else {
21358            representation.availableSegmentsNumber = Math.ceil((availabilityWindow.end - availabilityWindow.start) / duration);
21359        }
21360
21361        return segments;
21362    }
21363
21364    instance = {
21365        getSegments: getSegmentsFromTemplate
21366    };
21367
21368    return instance;
21369}
21370
21371TemplateSegmentsGetter.__dashjs_factory_name = 'TemplateSegmentsGetter';
21372var factory = _coreFactoryMaker2['default'].getClassFactory(TemplateSegmentsGetter);
21373exports['default'] = factory;
21374module.exports = exports['default'];
21375
21376},{"51":51,"77":77}],79:[function(_dereq_,module,exports){
21377/**
21378 * The copyright in this software is being made available under the BSD License,
21379 * included below. This software may be subject to other third party and contributor
21380 * rights, including patent rights, and no such rights are granted under this license.
21381 *
21382 * Copyright (c) 2013, Dash Industry Forum.
21383 * All rights reserved.
21384 *
21385 * Redistribution and use in source and binary forms, with or without modification,
21386 * are permitted provided that the following conditions are met:
21387 *  * Redistributions of source code must retain the above copyright notice, this
21388 *  list of conditions and the following disclaimer.
21389 *  * Redistributions in binary form must reproduce the above copyright notice,
21390 *  this list of conditions and the following disclaimer in the documentation and/or
21391 *  other materials provided with the distribution.
21392 *  * Neither the name of Dash Industry Forum nor the names of its
21393 *  contributors may be used to endorse or promote products derived from this software
21394 *  without specific prior written permission.
21395 *
21396 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
21397 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21398 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21399 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
21400 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21401 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21402 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21403 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
21404 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
21405 *  POSSIBILITY OF SUCH DAMAGE.
21406 */
21407'use strict';
21408
21409Object.defineProperty(exports, '__esModule', {
21410    value: true
21411});
21412
21413function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
21414
21415var _coreEventBus = _dereq_(50);
21416
21417var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
21418
21419var _coreEventsEvents = _dereq_(54);
21420
21421var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
21422
21423var _coreFactoryMaker = _dereq_(51);
21424
21425var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
21426
21427function TimelineConverter() {
21428
21429    var context = this.context;
21430    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
21431
21432    var instance = undefined,
21433        clientServerTimeShift = undefined,
21434        isClientServerTimeSyncCompleted = undefined,
21435        expectedLiveEdge = undefined;
21436
21437    function initialize() {
21438        resetInitialSettings();
21439        eventBus.on(_coreEventsEvents2['default'].TIME_SYNCHRONIZATION_COMPLETED, onTimeSyncComplete, this);
21440    }
21441
21442    function isTimeSyncCompleted() {
21443        return isClientServerTimeSyncCompleted;
21444    }
21445
21446    function setTimeSyncCompleted(value) {
21447        isClientServerTimeSyncCompleted = value;
21448    }
21449
21450    function getClientTimeOffset() {
21451        return clientServerTimeShift;
21452    }
21453
21454    function setClientTimeOffset(value) {
21455        clientServerTimeShift = value;
21456    }
21457
21458    function getExpectedLiveEdge() {
21459        return expectedLiveEdge;
21460    }
21461
21462    function setExpectedLiveEdge(value) {
21463        expectedLiveEdge = value;
21464    }
21465
21466    function calcAvailabilityTimeFromPresentationTime(presentationTime, mpd, isDynamic, calculateEnd) {
21467        var availabilityTime = NaN;
21468
21469        if (calculateEnd) {
21470            //@timeShiftBufferDepth specifies the duration of the time shifting buffer that is guaranteed
21471            // to be available for a Media Presentation with type 'dynamic'.
21472            // When not present, the value is infinite.
21473            if (isDynamic && mpd.timeShiftBufferDepth != Number.POSITIVE_INFINITY) {
21474                availabilityTime = new Date(mpd.availabilityStartTime.getTime() + (presentationTime + mpd.timeShiftBufferDepth) * 1000);
21475            } else {
21476                availabilityTime = mpd.availabilityEndTime;
21477            }
21478        } else {
21479            if (isDynamic) {
21480                availabilityTime = new Date(mpd.availabilityStartTime.getTime() + (presentationTime - clientServerTimeShift) * 1000);
21481            } else {
21482                // in static mpd, all segments are available at the same time
21483                availabilityTime = mpd.availabilityStartTime;
21484            }
21485        }
21486
21487        return availabilityTime;
21488    }
21489
21490    function calcAvailabilityStartTimeFromPresentationTime(presentationTime, mpd, isDynamic) {
21491        return calcAvailabilityTimeFromPresentationTime.call(this, presentationTime, mpd, isDynamic);
21492    }
21493
21494    function calcAvailabilityEndTimeFromPresentationTime(presentationTime, mpd, isDynamic) {
21495        return calcAvailabilityTimeFromPresentationTime.call(this, presentationTime, mpd, isDynamic, true);
21496    }
21497
21498    function calcPresentationTimeFromWallTime(wallTime, period) {
21499        //console.log("XXX", wallTime.getTime() - period.mpd.availabilityStartTime.getTime(), clientServerTimeShift * 1000, clientServerTimeShift, period.mpd.availabilityStartTime.getTime())
21500        return (wallTime.getTime() - period.mpd.availabilityStartTime.getTime() + clientServerTimeShift * 1000) / 1000;
21501    }
21502
21503    function calcPresentationTimeFromMediaTime(mediaTime, representation) {
21504        var periodStart = representation.adaptation.period.start;
21505        var presentationOffset = representation.presentationTimeOffset;
21506
21507        return mediaTime + (periodStart - presentationOffset);
21508    }
21509
21510    function calcMediaTimeFromPresentationTime(presentationTime, representation) {
21511        var periodStart = representation.adaptation.period.start;
21512        var presentationOffset = representation.presentationTimeOffset;
21513
21514        return presentationTime - periodStart + presentationOffset;
21515    }
21516
21517    function calcWallTimeForSegment(segment, isDynamic) {
21518        var suggestedPresentationDelay = undefined,
21519            displayStartTime = undefined,
21520            wallTime = undefined;
21521
21522        if (isDynamic) {
21523            suggestedPresentationDelay = segment.representation.adaptation.period.mpd.suggestedPresentationDelay;
21524            displayStartTime = segment.presentationStartTime + suggestedPresentationDelay;
21525            wallTime = new Date(segment.availabilityStartTime.getTime() + displayStartTime * 1000);
21526        }
21527
21528        return wallTime;
21529    }
21530
21531    function calcSegmentAvailabilityRange(voRepresentation, isDynamic) {
21532
21533        // Static Range Finder
21534        var voPeriod = voRepresentation.adaptation.period;
21535        var range = { start: voPeriod.start, end: voPeriod.start + voPeriod.duration };
21536        if (!isDynamic) return range;
21537
21538        if (!isClientServerTimeSyncCompleted && voRepresentation.segmentAvailabilityRange) {
21539            return voRepresentation.segmentAvailabilityRange;
21540        }
21541
21542        //Dyanmic Range Finder
21543        var d = voRepresentation.segmentDuration || (voRepresentation.segments && voRepresentation.segments.length ? voRepresentation.segments[voRepresentation.segments.length - 1].duration : 0);
21544        var now = calcPresentationTimeFromWallTime(new Date(), voPeriod);
21545        var periodEnd = voPeriod.start + voPeriod.duration;
21546        range.start = Math.max(now - voPeriod.mpd.timeShiftBufferDepth, voPeriod.start);
21547        range.end = now >= periodEnd && now - d < periodEnd ? periodEnd - d : now - d;
21548
21549        return range;
21550    }
21551
21552    function calcPeriodRelativeTimeFromMpdRelativeTime(representation, mpdRelativeTime) {
21553        var periodStartTime = representation.adaptation.period.start;
21554        return mpdRelativeTime - periodStartTime;
21555    }
21556
21557    /*
21558    * We need to figure out if we want to timesync for segmentTimeine where useCalculatedLiveEdge = true
21559    * seems we figure out client offset based on logic in liveEdgeFinder getLiveEdge timelineConverter.setClientTimeOffset(liveEdge - representationInfo.DVRWindow.end);
21560    * FYI StreamController's onManifestUpdated entry point to timeSync
21561    * */
21562    function onTimeSyncComplete(e) {
21563
21564        if (isClientServerTimeSyncCompleted) return;
21565
21566        if (e.offset !== undefined) {
21567
21568            setClientTimeOffset(e.offset / 1000);
21569            isClientServerTimeSyncCompleted = true;
21570        }
21571    }
21572
21573    function calcMSETimeOffset(representation) {
21574        // The MSEOffset is offset from AST for media. It is Period@start - presentationTimeOffset
21575        var presentationOffset = representation.presentationTimeOffset;
21576        var periodStart = representation.adaptation.period.start;
21577        return periodStart - presentationOffset;
21578    }
21579
21580    function resetInitialSettings() {
21581        clientServerTimeShift = 0;
21582        isClientServerTimeSyncCompleted = false;
21583        expectedLiveEdge = NaN;
21584    }
21585
21586    function reset() {
21587        eventBus.off(_coreEventsEvents2['default'].TIME_SYNCHRONIZATION_COMPLETED, onTimeSyncComplete, this);
21588        resetInitialSettings();
21589    }
21590
21591    instance = {
21592        initialize: initialize,
21593        isTimeSyncCompleted: isTimeSyncCompleted,
21594        setTimeSyncCompleted: setTimeSyncCompleted,
21595        getClientTimeOffset: getClientTimeOffset,
21596        setClientTimeOffset: setClientTimeOffset,
21597        getExpectedLiveEdge: getExpectedLiveEdge,
21598        setExpectedLiveEdge: setExpectedLiveEdge,
21599        calcAvailabilityStartTimeFromPresentationTime: calcAvailabilityStartTimeFromPresentationTime,
21600        calcAvailabilityEndTimeFromPresentationTime: calcAvailabilityEndTimeFromPresentationTime,
21601        calcPresentationTimeFromWallTime: calcPresentationTimeFromWallTime,
21602        calcPresentationTimeFromMediaTime: calcPresentationTimeFromMediaTime,
21603        calcPeriodRelativeTimeFromMpdRelativeTime: calcPeriodRelativeTimeFromMpdRelativeTime,
21604        calcMediaTimeFromPresentationTime: calcMediaTimeFromPresentationTime,
21605        calcSegmentAvailabilityRange: calcSegmentAvailabilityRange,
21606        calcWallTimeForSegment: calcWallTimeForSegment,
21607        calcMSETimeOffset: calcMSETimeOffset,
21608        reset: reset
21609    };
21610
21611    return instance;
21612}
21613
21614TimelineConverter.__dashjs_factory_name = 'TimelineConverter';
21615exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(TimelineConverter);
21616module.exports = exports['default'];
21617
21618},{"50":50,"51":51,"54":54}],80:[function(_dereq_,module,exports){
21619/**
21620 * The copyright in this software is being made available under the BSD License,
21621 * included below. This software may be subject to other third party and contributor
21622 * rights, including patent rights, and no such rights are granted under this license.
21623 *
21624 * Copyright (c) 2013, Dash Industry Forum.
21625 * All rights reserved.
21626 *
21627 * Redistribution and use in source and binary forms, with or without modification,
21628 * are permitted provided that the following conditions are met:
21629 *  * Redistributions of source code must retain the above copyright notice, this
21630 *  list of conditions and the following disclaimer.
21631 *  * Redistributions in binary form must reproduce the above copyright notice,
21632 *  this list of conditions and the following disclaimer in the documentation and/or
21633 *  other materials provided with the distribution.
21634 *  * Neither the name of Dash Industry Forum nor the names of its
21635 *  contributors may be used to endorse or promote products derived from this software
21636 *  without specific prior written permission.
21637 *
21638 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
21639 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21640 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21641 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
21642 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21643 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21644 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21645 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
21646 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
21647 *  POSSIBILITY OF SUCH DAMAGE.
21648 */
21649
21650'use strict';
21651
21652Object.defineProperty(exports, '__esModule', {
21653    value: true
21654});
21655
21656function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
21657
21658var _coreFactoryMaker = _dereq_(51);
21659
21660var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
21661
21662var _SegmentsUtils = _dereq_(77);
21663
21664function TimelineSegmentsGetter(config, isDynamic) {
21665
21666    var timelineConverter = config.timelineConverter;
21667
21668    var instance = undefined;
21669
21670    function checkConfig() {
21671        if (!timelineConverter || !timelineConverter.hasOwnProperty('calcMediaTimeFromPresentationTime') || !timelineConverter.hasOwnProperty('calcSegmentAvailabilityRange') || !timelineConverter.hasOwnProperty('calcMediaTimeFromPresentationTime')) {
21672            throw new Error('Missing config parameter(s)');
21673        }
21674    }
21675
21676    function getSegmentsFromTimeline(representation, requestedTime, index) {
21677
21678        checkConfig();
21679
21680        if (!representation) {
21681            throw new Error('no representation');
21682        }
21683
21684        if (requestedTime === undefined) {
21685            requestedTime = null;
21686        }
21687
21688        var base = representation.adaptation.period.mpd.manifest.Period_asArray[representation.adaptation.period.index].AdaptationSet_asArray[representation.adaptation.index].Representation_asArray[representation.index].SegmentTemplate || representation.adaptation.period.mpd.manifest.Period_asArray[representation.adaptation.period.index].AdaptationSet_asArray[representation.adaptation.index].Representation_asArray[representation.index].SegmentList;
21689        var timeline = base.SegmentTimeline;
21690        var list = base.SegmentURL_asArray;
21691        var isAvailableSegmentNumberCalculated = representation.availableSegmentsNumber > 0;
21692
21693        var maxSegmentsAhead = undefined;
21694
21695        maxSegmentsAhead = index > -1 || requestedTime !== null ? 10 : Infinity;
21696
21697        var time = 0;
21698        var scaledTime = 0;
21699        var availabilityIdx = -1;
21700        var segments = [];
21701        var requiredMediaTime = null;
21702
21703        var fragments = undefined,
21704            frag = undefined,
21705            i = undefined,
21706            len = undefined,
21707            j = undefined,
21708            repeat = undefined,
21709            repeatEndTime = undefined,
21710            nextFrag = undefined,
21711            hasEnoughSegments = undefined,
21712            startIdx = undefined,
21713            fTimescale = undefined;
21714
21715        var createSegment = function createSegment(s, i) {
21716            var media = base.media;
21717            var mediaRange = s.mediaRange;
21718
21719            if (list) {
21720                media = list[i].media || '';
21721                mediaRange = list[i].mediaRange;
21722            }
21723
21724            return (0, _SegmentsUtils.getTimeBasedSegment)(timelineConverter, isDynamic, representation, time, s.d, fTimescale, media, mediaRange, availabilityIdx, s.tManifest);
21725        };
21726
21727        fTimescale = representation.timescale;
21728
21729        fragments = timeline.S_asArray;
21730
21731        startIdx = index;
21732
21733        if (requestedTime !== null) {
21734            requiredMediaTime = timelineConverter.calcMediaTimeFromPresentationTime(requestedTime, representation);
21735        }
21736
21737        for (i = 0, len = fragments.length; i < len; i++) {
21738            frag = fragments[i];
21739            repeat = 0;
21740            if (frag.hasOwnProperty('r')) {
21741                repeat = frag.r;
21742            }
21743
21744            //For a repeated S element, t belongs only to the first segment
21745            if (frag.hasOwnProperty('t')) {
21746                time = frag.t;
21747                scaledTime = time / fTimescale;
21748            }
21749
21750            //This is a special case: "A negative value of the @r attribute of the S element indicates that the duration indicated in @d attribute repeats until the start of the next S element, the end of the Period or until the
21751            // next MPD update."
21752            if (repeat < 0) {
21753                nextFrag = fragments[i + 1];
21754
21755                if (nextFrag && nextFrag.hasOwnProperty('t')) {
21756                    repeatEndTime = nextFrag.t / fTimescale;
21757                } else {
21758                    var availabilityEnd = representation.segmentAvailabilityRange ? representation.segmentAvailabilityRange.end : timelineConverter.calcSegmentAvailabilityRange(representation, isDynamic).end;
21759                    repeatEndTime = timelineConverter.calcMediaTimeFromPresentationTime(availabilityEnd, representation);
21760                    representation.segmentDuration = frag.d / fTimescale;
21761                }
21762
21763                repeat = Math.ceil((repeatEndTime - scaledTime) / (frag.d / fTimescale)) - 1;
21764            }
21765
21766            // if we have enough segments in the list, but we have not calculated the total number of the segments yet we
21767            // should continue the loop and calc the number. Once it is calculated, we can break the loop.
21768            if (hasEnoughSegments) {
21769                if (isAvailableSegmentNumberCalculated) break;
21770                availabilityIdx += repeat + 1;
21771                continue;
21772            }
21773
21774            for (j = 0; j <= repeat; j++) {
21775                availabilityIdx++;
21776
21777                if (segments.length > maxSegmentsAhead) {
21778                    hasEnoughSegments = true;
21779                    if (isAvailableSegmentNumberCalculated) break;
21780                    continue;
21781                }
21782
21783                if (requiredMediaTime !== null) {
21784                    // In some cases when requiredMediaTime = actual end time of the last segment
21785                    // it is possible that this time a bit exceeds the declared end time of the last segment.
21786                    // in this case we still need to include the last segment in the segment list. to do this we
21787                    // use a correction factor = 1.5. This number is used because the largest possible deviation is
21788                    // is 50% of segment duration.
21789                    if (scaledTime >= requiredMediaTime - frag.d / fTimescale * 1.5) {
21790                        segments.push(createSegment(frag, availabilityIdx));
21791                    }
21792                } else if (availabilityIdx >= startIdx) {
21793                    segments.push(createSegment(frag, availabilityIdx));
21794                }
21795
21796                time += frag.d;
21797                scaledTime = time / fTimescale;
21798            }
21799        }
21800
21801        if (!isAvailableSegmentNumberCalculated) {
21802            representation.availableSegmentsNumber = availabilityIdx + 1;
21803        }
21804
21805        return segments;
21806    }
21807
21808    instance = {
21809        getSegments: getSegmentsFromTimeline
21810    };
21811
21812    return instance;
21813}
21814
21815TimelineSegmentsGetter.__dashjs_factory_name = 'TimelineSegmentsGetter';
21816var factory = _coreFactoryMaker2['default'].getClassFactory(TimelineSegmentsGetter);
21817exports['default'] = factory;
21818module.exports = exports['default'];
21819
21820},{"51":51,"77":77}],81:[function(_dereq_,module,exports){
21821/**
21822 * The copyright in this software is being made available under the BSD License,
21823 * included below. This software may be subject to other third party and contributor
21824 * rights, including patent rights, and no such rights are granted under this license.
21825 *
21826 * Copyright (c) 2013, Dash Industry Forum.
21827 * All rights reserved.
21828 *
21829 * Redistribution and use in source and binary forms, with or without modification,
21830 * are permitted provided that the following conditions are met:
21831 *  * Redistributions of source code must retain the above copyright notice, this
21832 *  list of conditions and the following disclaimer.
21833 *  * Redistributions in binary form must reproduce the above copyright notice,
21834 *  this list of conditions and the following disclaimer in the documentation and/or
21835 *  other materials provided with the distribution.
21836 *  * Neither the name of Dash Industry Forum nor the names of its
21837 *  contributors may be used to endorse or promote products derived from this software
21838 *  without specific prior written permission.
21839 *
21840 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
21841 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21842 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21843 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
21844 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
21844INCLUDING, BUT
21845 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21846 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21847 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
21848 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
21849 *  POSSIBILITY OF SUCH DAMAGE.
21850 */
21851/**
21852 * @class
21853 * @ignore
21854 */
21855"use strict";
21856
21857Object.defineProperty(exports, "__esModule", {
21858  value: true
21859});
21860
21861function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
21862
21863var AdaptationSet = function AdaptationSet() {
21864  _classCallCheck(this, AdaptationSet);
21865
21866  this.period = null;
21867  this.index = -1;
21868  this.type = null;
21869};
21870
21871exports["default"] = AdaptationSet;
21872module.exports = exports["default"];
21873
21874},{}],82:[function(_dereq_,module,exports){
21875/**
21876 * The copyright in this software is being made available under the BSD License,
21877 * included below. This software may be subject to other third party and contributor
21878 * rights, including patent rights, and no such rights are granted under this license.
21879 *
21880 * Copyright (c) 2013, Dash Industry Forum.
21881 * All rights reserved.
21882 *
21883 * Redistribution and use in source and binary forms, with or without modification,
21884 * are permitted provided that the following conditions are met:
21885 *  * Redistributions of source code must retain the above copyright notice, this
21886 *  list of conditions and the following disclaimer.
21887 *  * Redistributions in binary form must reproduce the above copyright notice,
21888 *  this list of conditions and the following disclaimer in the documentation and/or
21889 *  other materials provided with the distribution.
21890 *  * Neither the name of Dash Industry Forum nor the names of its
21891 *  contributors may be used to endorse or promote products derived from this software
21892 *  without specific prior written permission.
21893 *
21894 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
21895 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21896 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21897 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
21898 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21899 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21900 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21901 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
21902 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
21903 *  POSSIBILITY OF SUCH DAMAGE.
21904 */
21905/**
21906 * @class
21907 * @ignore
21908 */
21909
21910'use strict';
21911
21912Object.defineProperty(exports, '__esModule', {
21913  value: true
21914});
21915
21916function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
21917
21918var DEFAULT_DVB_PRIORITY = 1;
21919var DEFAULT_DVB_WEIGHT = 1;
21920
21921var BaseURL = function BaseURL(url, serviceLocation, priority, weight) {
21922  _classCallCheck(this, BaseURL);
21923
21924  this.url = url || '';
21925  this.serviceLocation = serviceLocation || url || '';
21926
21927  // DVB extensions
21928  this.dvb_priority = priority || DEFAULT_DVB_PRIORITY;
21929  this.dvb_weight = weight || DEFAULT_DVB_WEIGHT;
21930
21931  /* currently unused:
21932   * byteRange,
21933   * availabilityTimeOffset,
21934   * availabilityTimeComplete
21935   */
21936};
21937
21938BaseURL.DEFAULT_DVB_PRIORITY = DEFAULT_DVB_PRIORITY;
21939BaseURL.DEFAULT_DVB_WEIGHT = DEFAULT_DVB_WEIGHT;
21940
21941exports['default'] = BaseURL;
21942module.exports = exports['default'];
21943
21944},{}],83:[function(_dereq_,module,exports){
21945/**
21946 * The copyright in this software is being made available under the BSD License,
21947 * included below. This software may be subject to other third party and contributor
21948 * rights, including patent rights, and no such rights are granted under this license.
21949 *
21950 * Copyright (c) 2013, Dash Industry Forum.
21951 * All rights reserved.
21952 *
21953 * Redistribution and use in source and binary forms, with or without modification,
21954 * are permitted provided that the following conditions are met:
21955 *  * Redistributions of source code must retain the above copyright notice, this
21956 *  list of conditions and the following disclaimer.
21957 *  * Redistributions in binary form must reproduce the above copyright notice,
21958 *  this list of conditions and the following disclaimer in the documentation and/or
21959 *  other materials provided with the distribution.
21960 *  * Neither the name of Dash Industry Forum nor the names of its
21961 *  contributors may be used to endorse or promote products derived from this software
21962 *  without specific prior written permission.
21963 *
21964 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
21965 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21966 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21967 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
21968 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
21968INCLUDING, BUT
21969 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21970 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21971 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
21972 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
21973 *  POSSIBILITY OF SUCH DAMAGE.
21974 */
21975/**
21976 * @class
21977 * @ignore
21978 */
21979'use strict';
21980
21981Object.defineProperty(exports, '__esModule', {
21982  value: true
21983});
21984
21985function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
21986
21987var Event = function Event() {
21988  _classCallCheck(this, Event);
21989
21990  this.duration = NaN;
21991  this.presentationTime = NaN;
21992  this.id = NaN;
21993  this.messageData = '';
21994  this.eventStream = null;
21995  this.presentationTimeDelta = NaN; // Specific EMSG Box parameter
21996};
21997
21998exports['default'] = Event;
21999module.exports = exports['default'];
22000
22001},{}],84:[function(_dereq_,module,exports){
22002/**
22003 * The copyright in this software is being made available under the BSD License,
22004 * included below. This software may be subject to other third party and contributor
22005 * rights, including patent rights, and no such rights are granted under this license.
22006 *
22007 * Copyright (c) 2013, Dash Industry Forum.
22008 * All rights reserved.
22009 *
22010 * Redistribution and use in source and binary forms, with or without modification,
22011 * are permitted provided that the following conditions are met:
22012 *  * Redistributions of source code must retain the above copyright notice, this
22013 *  list of conditions and the following disclaimer.
22014 *  * Redistributions in binary form must reproduce the above copyright notice,
22015 *  this list of conditions and the following disclaimer in the documentation and/or
22016 *  other materials provided with the distribution.
22017 *  * Neither the name of Dash Industry Forum nor the names of its
22018 *  contributors may be used to endorse or promote products derived from this software
22019 *  without specific prior written permission.
22020 *
22021 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
22022 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22023 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22024 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22025 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22026 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22027 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22028 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22029 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
22030 *  POSSIBILITY OF SUCH DAMAGE.
22031 */
22032/**
22033 * @class
22034 * @ignore
22035 */
22036'use strict';
22037
22038Object.defineProperty(exports, '__esModule', {
22039  value: true
22040});
22041
22042function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
22043
22044var EventStream = function EventStream() {
22045  _classCallCheck(this, EventStream);
22046
22047  this.adaptionSet = null;
22048  this.representation = null;
22049  this.period = null;
22050  this.timescale = 1;
22051  this.value = '';
22052  this.schemeIdUri = '';
22053};
22054
22055exports['default'] = EventStream;
22056module.exports = exports['default'];
22057
22058},{}],85:[function(_dereq_,module,exports){
22059/**
22060 * The copyright in this software is being made available under the BSD License,
22061 * included below. This software may be subject to other third party and contributor
22062 * rights, including patent rights, and no such rights are granted under this license.
22063 *
22064 * Copyright (c) 2013, Dash Industry Forum.
22065 * All rights reserved.
22066 *
22067 * Redistribution and use in source and binary forms, with or without modification,
22068 * are permitted provided that the following conditions are met:
22069 *  * Redistributions of source code must retain the above copyright notice, this
22070 *  list of conditions and the following disclaimer.
22071 *  * Redistributions in binary form must reproduce the above copyright notice,
22072 *  this list of conditions and the following disclaimer in the documentation and/or
22073 *  other materials provided with the distribution.
22074 *  * Neither the name of Dash Industry Forum nor the names of its
22075 *  contributors may be used to endorse or promote products derived from this software
22076 *  without specific prior written permission.
22077 *
22078 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
22079 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22080 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22081 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22082 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
22082INCLUDING, BUT
22083 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22084 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22085 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22086 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
22087 *  POSSIBILITY OF SUCH DAMAGE.
22088 */
22089/**
22090 * @class
22091 * @ignore
22092 */
22093"use strict";
22094
22095Object.defineProperty(exports, "__esModule", {
22096  value: true
22097});
22098
22099function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
22100
22101var Mpd = function Mpd() {
22102  _classCallCheck(this, Mpd);
22103
22104  this.manifest = null;
22105  this.suggestedPresentationDelay = 0;
22106  this.availabilityStartTime = null;
22107  this.availabilityEndTime = Number.POSITIVE_INFINITY;
22108  this.timeShiftBufferDepth = Number.POSITIVE_INFINITY;
22109  this.maxSegmentDuration = Number.POSITIVE_INFINITY;
22110  this.minimumUpdatePeriod = NaN;
22111  this.mediaPresentationDuration = NaN;
22112};
22113
22114exports["default"] = Mpd;
22115module.exports = exports["default"];
22116
22117},{}],86:[function(_dereq_,module,exports){
22118/**
22119 * The copyright in this software is being made available under the BSD License,
22120 * included below. This software may be subject to other third party and contributor
22121 * rights, including patent rights, and no such rights are granted under this license.
22122 *
22123 * Copyright (c) 2013, Dash Industry Forum.
22124 * All rights reserved.
22125 *
22126 * Redistribution and use in source and binary forms, with or without modification,
22127 * are permitted provided that the following conditions are met:
22128 *  * Redistributions of source code must retain the above copyright notice, this
22129 *  list of conditions and the following disclaimer.
22130 *  * Redistributions in binary form must reproduce the above copyright notice,
22131 *  this list of conditions and the following disclaimer in the documentation and/or
22132 *  other materials provided with the distribution.
22133 *  * Neither the name of Dash Industry Forum nor the names of its
22134 *  contributors may be used to endorse or promote products derived from this software
22135 *  without specific prior written permission.
22136 *
22137 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
22138 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22139 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22140 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22141 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22142 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22143 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22144 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22145 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
22146 *  POSSIBILITY OF SUCH DAMAGE.
22147 */
22148/**
22149 * @class
22150 * @ignore
22151 */
22152'use strict';
22153
22154Object.defineProperty(exports, '__esModule', {
22155  value: true
22156});
22157
22158function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
22159
22160var Period = function Period() {
22161  _classCallCheck(this, Period);
22162
22163  this.id = null;
22164  this.index = -1;
22165  this.duration = NaN;
22166  this.start = NaN;
22167  this.mpd = null;
22168};
22169
22170Period.DEFAULT_ID = 'defaultId';
22171
22172exports['default'] = Period;
22173module.exports = exports['default'];
22174
22175},{}],87:[function(_dereq_,module,exports){
22176/**
22177 * The copyright in this software is being made available under the BSD License,
22178 * included below. This software may be subject to other third party and contributor
22179 * rights, including patent rights, and no such rights are granted under this license.
22180 *
22181 * Copyright (c) 2013, Dash Industry Forum.
22182 * All rights reserved.
22183 *
22184 * Redistribution and use in source and binary forms, with or without modification,
22185 * are permitted provided that the following conditions are met:
22186 *  * Redistributions of source code must retain the above copyright notice, this
22187 *  list of conditions and the following disclaimer.
22188 *  * Redistributions in binary form must reproduce the above copyright notice,
22189 *  this list of conditions and the following disclaimer in the documentation and/or
22190 *  other materials provided with the distribution.
22191 *  * Neither the name of Dash Industry Forum nor the names of its
22192 *  contributors may be used to endorse or promote products derived from this software
22193 *  without specific prior written permission.
22194 *
22195 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
22196 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22197 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22198 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22199 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
22199INCLUDING, BUT
22200 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22201 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22202 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22203 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
22204 *  POSSIBILITY OF SUCH DAMAGE.
22205 */
22206/**
22207 * @class
22208 * @ignore
22209 */
22210
22211'use strict';
22212
22213Object.defineProperty(exports, '__esModule', {
22214    value: true
22215});
22216
22217var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
22218
22219function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
22220
22221function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
22222
22223var _constantsDashConstants = _dereq_(61);
22224
22225var _constantsDashConstants2 = _interopRequireDefault(_constantsDashConstants);
22226
22227var Representation = (function () {
22228    function Representation() {
22229        _classCallCheck(this, Representation);
22230
22231        this.id = null;
22232        this.index = -1;
22233        this.adaptation = null;
22234        this.segmentInfoType = null;
22235        this.initialization = null;
22236        this.codecs = null;
22237        this.codecPrivateData = null;
22238        this.segmentDuration = NaN;
22239        this.timescale = 1;
22240        this.startNumber = 1;
22241        this.indexRange = null;
22242        this.range = null;
22243        this.presentationTimeOffset = 0;
22244        // Set the source buffer timeOffset to this
22245        this.MSETimeOffset = NaN;
22246        this.segmentAvailabilityRange = null;
22247        this.availableSegmentsNumber = 0;
22248        this.bandwidth = NaN;
22249        this.width = NaN;
22250        this.height = NaN;
22251        this.scanType = null;
22252        this.maxPlayoutRate = NaN;
22253    }
22254
22255    _createClass(Representation, null, [{
22256        key: 'hasInitialization',
22257        value: function hasInitialization(r) {
22258            return r.initialization !== null || (r.segmentInfoType !== _constantsDashConstants2['default'].BASE_URL || r.segmentInfoType !== _constantsDashConstants2['default'].SEGMENT_BASE) && r.range !== null;
22259        }
22260    }, {
22261        key: 'hasSegments',
22262        value: function hasSegments(r) {
22263            return r.segmentInfoType !== _constantsDashConstants2['default'].BASE_URL && r.segmentInfoType !== _constantsDashConstants2['default'].SEGMENT_BASE && !r.indexRange;
22264        }
22265    }]);
22266
22267    return Representation;
22268})();
22269
22270exports['default'] = Representation;
22271module.exports = exports['default'];
22272
22273},{"61":61}],88:[function(_dereq_,module,exports){
22274/**
22275 * The copyright in this software is being made available under the BSD License,
22276 * included below. This software may be subject to other third party and contributor
22277 * rights, including patent rights, and no such rights are granted under this license.
22278 *
22279 * Copyright (c) 2013, Dash Industry Forum.
22280 * All rights reserved.
22281 *
22282 * Redistribution and use in source and binary forms, with or without modification,
22283 * are permitted provided that the following conditions are met:
22284 *  * Redistributions of source code must retain the above copyright notice, this
22285 *  list of conditions and the following disclaimer.
22286 *  * Redistributions in binary form must reproduce the above copyright notice,
22287 *  this list of conditions and the following disclaimer in the documentation and/or
22288 *  other materials provided with the distribution.
22289 *  * Neither the name of Dash Industry Forum nor the names of its
22290 *  contributors may be used to endorse or promote products derived from this software
22291 *  without specific prior written permission.
22292 *
22293 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
22294 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22295 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22296 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22297 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
22297INCLUDING, BUT
22298 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22299 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22300 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22301 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
22302 *  POSSIBILITY OF SUCH DAMAGE.
22303 */
22304/**
22305 * @class
22306 * @ignore
22307 */
22308"use strict";
22309
22310Object.defineProperty(exports, "__esModule", {
22311  value: true
22312});
22313
22314function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
22315
22316var Segment = function Segment() {
22317  _classCallCheck(this, Segment);
22318
22319  this.indexRange = null;
22320  this.index = null;
22321  this.mediaRange = null;
22322  this.media = null;
22323  this.duration = NaN;
22324  // this is the time that should be inserted into the media url
22325  this.replacementTime = null;
22326  // this is the number that should be inserted into the media url
22327  this.replacementNumber = NaN;
22328  // This is supposed to match the time encoded in the media Segment
22329  this.mediaStartTime = NaN;
22330  // When the source buffer timeOffset is set to MSETimeOffset this is the
22331  // time that will match the seekTarget and video.currentTime
22332  this.presentationStartTime = NaN;
22333  // Do not schedule this segment until
22334  this.availabilityStartTime = NaN;
22335  // Ignore and  discard this segment after
22336  this.availabilityEndTime = NaN;
22337  // The index of the segment inside the availability window
22338  this.availabilityIdx = NaN;
22339  // For dynamic mpd's, this is the wall clock time that the video
22340  // element currentTime should be presentationStartTime
22341  this.wallStartTime = NaN;
22342  this.representation = null;
22343};
22344
22345exports["default"] = Segment;
22346module.exports = exports["default"];
22347
22348},{}],89:[function(_dereq_,module,exports){
22349/**
22350 * The copyright in this software is being made available under the BSD License,
22351 * included below. This software may be subject to other third party and contributor
22352 * rights, including patent rights, and no such rights are granted under this license.
22353 *
22354 * Copyright (c) 2013, Dash Industry Forum.
22355 * All rights reserved.
22356 *
22357 * Redistribution and use in source and binary forms, with or without modification,
22358 * are permitted provided that the following conditions are met:
22359 *  * Redistributions of source code must retain the above copyright notice, this
22360 *  list of conditions and the following disclaimer.
22361 *  * Redistributions in binary form must reproduce the above copyright notice,
22362 *  this list of conditions and the following disclaimer in the documentation and/or
22363 *  other materials provided with the distribution.
22364 *  * Neither the name of Dash Industry Forum nor the names of its
22365 *  contributors may be used to endorse or promote products derived from this software
22366 *  without specific prior written permission.
22367 *
22368 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
22369 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22370 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22371 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22372 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22373 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22374 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22375 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22376 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
22377 *  POSSIBILITY OF SUCH DAMAGE.
22378 */
22379/**
22380 * @class
22381 * @ignore
22382 */
22383'use strict';
22384
22385Object.defineProperty(exports, '__esModule', {
22386  value: true
22387});
22388
22389function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
22390
22391var UTCTiming = function UTCTiming() {
22392  _classCallCheck(this, UTCTiming);
22393
22394  // UTCTiming is a DescriptorType and doesn't have any additional fields
22395  this.schemeIdUri = '';
22396  this.value = '';
22397};
22398
22399exports['default'] = UTCTiming;
22400module.exports = exports['default'];
22401
22402},{}],90:[function(_dereq_,module,exports){
22403/**
22404 * The copyright in this software is being made available under the BSD License,
22405 * included below. This software may be subject to other third party and contributor
22406 * rights, including patent rights, and no such rights are granted under this license.
22407 *
22408 * Copyright (c) 2013, Dash Industry Forum.
22409 * All rights reserved.
22410 *
22411 * Redistribution and use in source and binary forms, with or without modification,
22412 * are permitted provided that the following conditions are met:
22413 *  * Redistributions of source code must retain the above copyright notice, this
22414 *  list of conditions and the following disclaimer.
22415 *  * Redistributions in binary form must reproduce the above copyright notice,
22416 *  this list of conditions and the following disclaimer in the documentation and/or
22417 *  other materials provided with the distribution.
22418 *  * Neither the name of Dash Industry Forum nor the names of its
22419 *  contributors may be used to endorse or promote products derived from this software
22420 *  without specific prior written permission.
22421 *
22422 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
22423 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22424 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22425 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22426 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
22426INCLUDING, BUT
22427 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22428 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22429 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22430 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
22431 *  POSSIBILITY OF SUCH DAMAGE.
22432 */
22433'use strict';
22434
22435Object.defineProperty(exports, '__esModule', {
22436    value: true
22437});
22438
22439function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
22440
22441var _XHRLoader = _dereq_(98);
22442
22443var _XHRLoader2 = _interopRequireDefault(_XHRLoader);
22444
22445var _voHeadRequest = _dereq_(210);
22446
22447var _voHeadRequest2 = _interopRequireDefault(_voHeadRequest);
22448
22449var _voDashJSError = _dereq_(207);
22450
22451var _voDashJSError2 = _interopRequireDefault(_voDashJSError);
22452
22453var _coreEventBus = _dereq_(50);
22454
22455var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
22456
22457var _coreEventsEvents = _dereq_(54);
22458
22459var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
22460
22461var _coreFactoryMaker = _dereq_(51);
22462
22463var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
22464
22465var FRAGMENT_LOADER_ERROR_LOADING_FAILURE = 1;
22466var FRAGMENT_LOADER_ERROR_NULL_REQUEST = 2;
22467var FRAGMENT_LOADER_MESSAGE_NULL_REQUEST = 'request is null';
22468
22469function FragmentLoader(config) {
22470
22471    var context = this.context;
22472    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
22473
22474    var instance = undefined,
22475        xhrLoader = undefined;
22476
22477    function setup() {
22478        xhrLoader = (0, _XHRLoader2['default'])(context).create({
22479            errHandler: config.errHandler,
22480            metricsModel: config.metricsModel,
22481            mediaPlayerModel: config.mediaPlayerModel,
22482            requestModifier: config.requestModifier
22483        });
22484    }
22485
22486    function checkForExistence(request) {
22487        var report = function report(success) {
22488            eventBus.trigger(_coreEventsEvents2['default'].CHECK_FOR_EXISTENCE_COMPLETED, {
22489                request: request,
22490                exists: success
22491            });
22492        };
22493
22494        if (request) {
22495            var headRequest = new _voHeadRequest2['default'](request.url);
22496
22497            xhrLoader.load({
22498                request: headRequest,
22499                success: function success() {
22500                    report(true);
22501                },
22502                error: function error() {
22503                    report(false);
22504                }
22505            });
22506        } else {
22507            report(false);
22508        }
22509    }
22510
22511    function load(request) {
22512        var report = function report(data, error) {
22513            eventBus.trigger(_coreEventsEvents2['default'].LOADING_COMPLETED, {
22514                request: request,
22515                response: data || null,
22516                error: error || null,
22517                sender: instance
22518            });
22519        };
22520
22521        if (request) {
22522            xhrLoader.load({
22523                request: request,
22524                progress: function progress() {
22525                    eventBus.trigger(_coreEventsEvents2['default'].LOADING_PROGRESS, {
22526                        request: request
22527                    });
22528                },
22529                success: function success(data) {
22530                    report(data);
22531                },
22532                error: function error(xhr, statusText, errorText) {
22533                    report(undefined, new _voDashJSError2['default'](FRAGMENT_LOADER_ERROR_LOADING_FAILURE, errorText, statusText));
22534                },
22535                abort: function abort(request, status) {
22536                    if (request && status === 0) {
22537                        eventBus.trigger(_coreEventsEvents2['default'].LOADING_ABANDONED, { request: request, mediaType: request.mediaType, sender: instance });
22538                    }
22539                }
22540            });
22541        } else {
22542            report(undefined, new _voDashJSError2['default'](FRAGMENT_LOADER_ERROR_NULL_REQUEST, FRAGMENT_LOADER_MESSAGE_NULL_REQUEST));
22543        }
22544    }
22545
22546    function abort() {
22547        if (xhrLoader) {
22548            xhrLoader.abort();
22549        }
22550    }
22551
22552    function reset() {
22553        if (xhrLoader) {
22554            xhrLoader.abort();
22555            xhrLoader = null;
22556        }
22557    }
22558
22559    instance = {
22560        checkForExistence: checkForExistence,
22561        load: load,
22562        abort: abort,
22563        reset: reset
22564    };
22565
22566    setup();
22567
22568    return instance;
22569}
22570
22571FragmentLoader.__dashjs_factory_name = 'FragmentLoader';
22572
22573var factory = _coreFactoryMaker2['default'].getClassFactory(FragmentLoader);
22574factory.FRAGMENT_LOADER_ERROR_LOADING_FAILURE = FRAGMENT_LOADER_ERROR_LOADING_FAILURE;
22575factory.FRAGMENT_LOADER_ERROR_NULL_REQUEST = FRAGMENT_LOADER_ERROR_NULL_REQUEST;
22576_coreFactoryMaker2['default'].updateClassFactory(FragmentLoader.__dashjs_factory_name, factory);
22577exports['default'] = factory;
22578module.exports = exports['default'];
22579
22580},{"207":207,"210":210,"50":50,"51":51,"54":54,"98":98}],91:[function(_dereq_,module,exports){
22581/**
22582 * The copyright in this software is being made available under the BSD License,
22583 * included below. This software may be subject to other third party and contributor
22584 * rights, including patent rights, and no such rights are granted under this license.
22585 *
22586 * Copyright (c) 2013, Dash Industry Forum.
22587 * All rights reserved.
22588 *
22589 * Redistribution and use in source and binary forms, with or without modification,
22590 * are permitted provided that the following conditions are met:
22591 *  * Redistributions of source code must retain the above copyright notice, this
22592 *  list of conditions and the following disclaimer.
22593 *  * Redistributions in binary form must reproduce the above copyright notice,
22594 *  this list of conditions and the following disclaimer in the documentation and/or
22595 *  other materials provided with the distribution.
22596 *  * Neither the name of Dash Industry Forum nor the names of its
22597 *  contributors may be used to endorse or promote products derived from this software
22598 *  without specific prior written permission.
22599 *
22600 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
22601 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22602 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22603 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22604 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
22604INCLUDING, BUT
22605 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22606 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22607 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22608 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
22609 *  POSSIBILITY OF SUCH DAMAGE.
22610 */
22611'use strict';
22612
22613Object.defineProperty(exports, '__esModule', {
22614    value: true
22615});
22616
22617function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
22618
22619var _constantsConstants = _dereq_(100);
22620
22621var _constantsConstants2 = _interopRequireDefault(_constantsConstants);
22622
22623var _controllersXlinkController = _dereq_(115);
22624
22625var _controllersXlinkController2 = _interopRequireDefault(_controllersXlinkController);
22626
22627var _XHRLoader = _dereq_(98);
22628
22629var _XHRLoader2 = _interopRequireDefault(_XHRLoader);
22630
22631var _utilsURLUtils = _dereq_(202);
22632
22633var _utilsURLUtils2 = _interopRequireDefault(_utilsURLUtils);
22634
22635var _voTextRequest = _dereq_(217);
22636
22637var _voTextRequest2 = _interopRequireDefault(_voTextRequest);
22638
22639var _voDashJSError = _dereq_(207);
22640
22641var _voDashJSError2 = _interopRequireDefault(_voDashJSError);
22642
22643var _voMetricsHTTPRequest = _dereq_(224);
22644
22645var _coreEventBus = _dereq_(50);
22646
22647var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
22648
22649var _coreEventsEvents = _dereq_(54);
22650
22651var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
22652
22653var _coreFactoryMaker = _dereq_(51);
22654
22655var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
22656
22657var _dashParserDashParser = _dereq_(64);
22658
22659var _dashParserDashParser2 = _interopRequireDefault(_dashParserDashParser);
22660
22661var _coreDebug = _dereq_(49);
22662
22663var _coreDebug2 = _interopRequireDefault(_coreDebug);
22664
22665var MANIFEST_LOADER_ERROR_PARSING_FAILURE = 1;
22666var MANIFEST_LOADER_ERROR_LOADING_FAILURE = 2;
22667var MANIFEST_LOADER_MESSAGE_PARSING_FAILURE = 'parsing failed';
22668
22669function ManifestLoader(config) {
22670
22671    var context = this.context;
22672    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
22673    var urlUtils = (0, _utilsURLUtils2['default'])(context).getInstance();
22674    var debug = (0, _coreDebug2['default'])(context).getInstance();
22675    var log = debug.log;
22676
22677    var instance = undefined,
22678        xhrLoader = undefined,
22679        xlinkController = undefined,
22680        parser = undefined;
22681    var mssHandler = config.mssHandler;
22682    var errHandler = config.errHandler;
22683
22684    function setup() {
22685        eventBus.on(_coreEventsEvents2['default'].XLINK_READY, onXlinkReady, instance);
22686
22687        xhrLoader = (0, _XHRLoader2['default'])(context).create({
22688            errHandler: errHandler,
22689            metricsModel: config.metricsModel,
22690            mediaPlayerModel: config.mediaPlayerModel,
22691            requestModifier: config.requestModifier
22692        });
22693
22694        xlinkController = (0, _controllersXlinkController2['default'])(context).create({
22695            errHandler: errHandler,
22696            metricsModel: config.metricsModel,
22697            mediaPlayerModel: config.mediaPlayerModel,
22698            requestModifier: config.requestModifier
22699        });
22700
22701        parser = null;
22702    }
22703
22704    function onXlinkReady(event) {
22705        eventBus.trigger(_coreEventsEvents2['default'].INTERNAL_MANIFEST_LOADED, {
22706            manifest: event.manifest
22707        });
22708    }
22709
22710    function createParser(data) {
22711        var parser = null;
22712        // Analyze manifest content to detect protocol and select appropriate parser
22713        if (data.indexOf('SmoothStreamingMedia') > -1) {
22714            //do some business to transform it into a Dash Manifest
22715            if (mssHandler) {
22716                parser = mssHandler.createMssParser();
22717                mssHandler.registerEvents();
22718            } else {
22719                errHandler.manifestError('manifest type unsupported', 'createParser');
22720            }
22721            return parser;
22722        } else if (data.indexOf('MPD') > -1) {
22723            return (0, _dashParserDashParser2['default'])(context).create({
22724                errorHandler: errHandler
22725            });
22726        } else {
22727            return parser;
22728        }
22729    }
22730
22731    function load(url) {
22732        var request = new _voTextRequest2['default'](url, _voMetricsHTTPRequest.HTTPRequest.MPD_TYPE);
22733
22734        xhrLoader.load({
22735            request: request,
22736            success: function success(data, textStatus, xhr) {
22737                var actualUrl = undefined,
22738                    baseUri = undefined;
22739
22740                // Handle redirects for the MPD - as per RFC3986 Section 5.1.3
22741                // also handily resolves relative MPD URLs to absolute
22742                if (xhr.responseURL && xhr.responseURL !== url) {
22743                    baseUri = urlUtils.parseBaseUrl(xhr.responseURL);
22744                    actualUrl = xhr.responseURL;
22745                } else {
22746                    // usually this case will be caught and resolved by
22747                    // xhr.responseURL above but it is not available for IE11 and Edge/12 and Edge/13
22748                    // baseUri must be absolute for BaseURL resolution later
22749                    if (urlUtils.isRelative(url)) {
22750                        url = urlUtils.resolve(url, window.location.href);
22751                    }
22752
22753                    baseUri = urlUtils.parseBaseUrl(url);
22754                }
22755
22756                // Create parser according to manifest type
22757                if (parser === null) {
22758                    parser = createParser(data);
22759                }
22760
22761                if (parser === null) {
22762                    eventBus.trigger(_coreEventsEvents2['default'].INT
22762ERNAL_MANIFEST_LOADED, {
22763                        manifest: null,
22764                        error: new _voDashJSError2['default'](MANIFEST_LOADER_ERROR_PARSING_FAILURE, 'Failed detecting manifest type: ' + url)
22765                    });
22766                    return;
22767                }
22768
22769                // init xlinkcontroller with matchers and iron object from created parser
22770                xlinkController.setMatchers(parser.getMatchers());
22771                xlinkController.setIron(parser.getIron());
22772
22773                var manifest = parser.parse(data);
22774
22775                if (manifest) {
22776                    manifest.url = actualUrl || url;
22777
22778                    // URL from which the MPD was originally retrieved (MPD updates will not change this value)
22779                    if (!manifest.originalUrl) {
22780                        manifest.originalUrl = manifest.url;
22781                    }
22782
22783                    // In the following, we only use the first Location entry even if many are available
22784                    // Compare with ManifestUpdater/DashManifestModel
22785                    if (manifest.hasOwnProperty(_constantsConstants2['default'].LOCATION)) {
22786                        baseUri = urlUtils.parseBaseUrl(manifest.Location_asArray[0]);
22787                        log('BaseURI set by Location to: ' + baseUri);
22788                    }
22789
22790                    manifest.baseUri = baseUri;
22791                    manifest.loadedTime = new Date();
22792                    xlinkController.resolveManifestOnLoad(manifest);
22793                } else {
22794                    eventBus.trigger(_coreEventsEvents2['default'].INTERNAL_MANIFEST_LOADED, {
22795                        manifest: null,
22796                        error: new _voDashJSError2['default'](MANIFEST_LOADER_ERROR_PARSING_FAILURE, MANIFEST_LOADER_MESSAGE_PARSING_FAILURE)
22797                    });
22798                }
22799            },
22800            error: function error(xhr, statusText, errorText) {
22801                eventBus.trigger(_coreEventsEvents2['default'].INTERNAL_MANIFEST_LOADED, {
22802                    manifest: null,
22803                    error: new _voDashJSError2['default'](MANIFEST_LOADER_ERROR_LOADING_FAILURE, 'Failed loading manifest: ' + url + ', ' + errorText)
22804                });
22805            }
22806        });
22807    }
22808
22809    function reset() {
22810        eventBus.off(_coreEventsEvents2['default'].XLINK_READY, onXlinkReady, instance);
22811
22812        if (xlinkController) {
22813            xlinkController.reset();
22814            xlinkController = null;
22815        }
22816
22817        if (xhrLoader) {
22818            xhrLoader.abort();
22819            xhrLoader = null;
22820        }
22821
22822        if (mssHandler) {
22823            mssHandler.reset();
22824        }
22825    }
22826
22827    instance = {
22828        load: load,
22829        reset: reset
22830    };
22831
22832    setup();
22833
22834    return instance;
22835}
22836
22837ManifestLoader.__dashjs_factory_name = 'ManifestLoader';
22838
22839var factory = _coreFactoryMaker2['default'].getClassFactory(ManifestLoader);
22840factory.MANIFEST_LOADER_ERROR_PARSING_FAILURE = MANIFEST_LOADER_ERROR_PARSING_FAILURE;
22841factory.MANIFEST_LOADER_ERROR_LOADING_FAILURE = MANIFEST_LOADER_ERROR_LOADING_FAILURE;
22842_coreFactoryMaker2['default'].updateClassFactory(ManifestLoader.__dashjs_factory_name, factory);
22843exports['default'] = factory;
22844module.exports = exports['default'];
22845
22846},{"100":100,"115":115,"202":202,"207":207,"217":217,"224":224,"49":49,"50":50,"51":51,"54":54,"64":64,"98":98}],92:[function(_dereq_,module,exports){
22847/**
22848 * The copyright in this software is being made available under the BSD License,
22849 * included below. This software may be subject to other third party and contributor
22850 * rights, including patent rights, and no such rights are granted under this license.
22851 *
22852 * Copyright (c) 2013, Dash Industry Forum.
22853 * All rights reserved.
22854 *
22855 * Redistribution and use in source and binary forms, with or without modification,
22856 * are permitted provided that the following conditions are met:
22857 *  * Redistributions of source code must retain the above copyright notice, this
22858 *  list of conditions and the following disclaimer.
22859 *  * Redistributions in binary form must reproduce the above copyright notice,
22860 *  this list of conditions and the following disclaimer in the documentation and/or
22861 *  other materials provided with the distribution.
22862 *  * Neither the name of Dash Industry Forum nor the names of its
22863 *  contributors may be used to endorse or promote products derived from this software
22864 *  without specific prior written permission.
22865 *
22866 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
22867 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22868 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22869 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22870 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
22870INCLUDING, BUT
22871 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22872 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22873 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22874 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
22875 *  POSSIBILITY OF SUCH DAMAGE.
22876 */
22877'use strict';
22878
22879Object.defineProperty(exports, '__esModule', {
22880    value: true
22881});
22882
22883function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
22884
22885var _coreEventBus = _dereq_(50);
22886
22887var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
22888
22889var _coreEventsEvents = _dereq_(54);
22890
22891var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
22892
22893var _coreFactoryMaker = _dereq_(51);
22894
22895var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
22896
22897var _coreDebug = _dereq_(49);
22898
22899var _coreDebug2 = _interopRequireDefault(_coreDebug);
22900
22901function ManifestUpdater() {
22902
22903    var context = this.context;
22904    var log = (0, _coreDebug2['default'])(context).getInstance().log;
22905    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
22906
22907    var instance = undefined,
22908        refreshDelay = undefined,
22909        refreshTimer = undefined,
22910        isPaused = undefined,
22911        isUpdating = undefined,
22912        manifestLoader = undefined,
22913        manifestModel = undefined,
22914        dashManifestModel = undefined,
22915        mediaPlayerModel = undefined;
22916
22917    function setConfig(config) {
22918        if (!config) return;
22919
22920        if (config.manifestModel) {
22921            manifestModel = config.manifestModel;
22922        }
22923        if (config.dashManifestModel) {
22924            dashManifestModel = config.dashManifestModel;
22925        }
22926        if (config.mediaPlayerModel) {
22927            mediaPlayerModel = config.mediaPlayerModel;
22928        }
22929        if (config.manifestLoader) {
22930            manifestLoader = config.manifestLoader;
22931        }
22932    }
22933
22934    function initialize() {
22935        resetInitialSettings();
22936
22937        eventBus.on(_coreEventsEvents2['default'].STREAMS_COMPOSED, onStreamsComposed, this);
22938        eventBus.on(_coreEventsEvents2['default'].PLAYBACK_STARTED, onPlaybackStarted, this);
22939        eventBus.on(_coreEventsEvents2['default'].PLAYBACK_PAUSED, onPlaybackPaused, this);
22940        eventBus.on(_coreEventsEvents2['default'].INTERNAL_MANIFEST_LOADED, onManifestLoaded, this);
22941    }
22942
22943    function setManifest(manifest) {
22944        update(manifest);
22945    }
22946
22947    function resetInitialSettings() {
22948        refreshDelay = NaN;
22949        isUpdating = false;
22950        isPaused = true;
22951        stopManifestRefreshTimer();
22952    }
22953
22954    function reset() {
22955
22956        eventBus.off(_coreEventsEvents2['default'].PLAYBACK_STARTED, onPlaybackStarted, this);
22957        eventBus.off(_coreEventsEvents2['default'].PLAYBACK_PAUSED, onPlaybackPaused, this);
22958        eventBus.off(_coreEventsEvents2['default'].STREAMS_COMPOSED, onStreamsComposed, this);
22959        eventBus.off(_coreEventsEvents2['default'].INTERNAL_MANIFEST_LOADED, onManifestLoaded, this);
22960
22961        resetInitialSettings();
22962    }
22963
22964    function stopManifestRefreshTimer() {
22965        if (refreshTimer !== null) {
22966            clearInterval(refreshTimer);
22967            refreshTimer = null;
22968        }
22969    }
22970
22971    function startManifestRefreshTimer() {
22972        stopManifestRefreshTimer();
22973        if (!isNaN(refreshDelay)) {
22974            log('Refresh manifest in ' + refreshDelay + ' seconds.');
22975            refreshTimer = setTimeout(onRefreshTimer, refreshDelay * 1000);
22976        }
22977    }
22978
22979    function refreshManifest() {
22980        isUpdating = true;
22981        var manifest = manifestModel.getValue();
22982        var url = manifest.url;
22983        var location = dashManifestModel.getLocation(manifest);
22984        if (location) {
22985            url = location;
22986        }
22987        manifestLoader.load(url);
22988    }
22989
22990    function update(manifest) {
22991
22992        manifestModel.setValue(manifest);
22993
22994        var date = new Date();
22995        var latencyOfLastUpdate = (date.getTime() - manifest.loadedTime.getTime()) / 1000;
22996        refreshDelay = dashManifestModel.getManifestUpdatePeriod(manifest, latencyOfLastUpdate);
22997
22998        eventBus.trigger(_coreEventsEvents2['default'].MANIFEST_UPDATED, { manifest: manifest });
22999        log('Manifest has been refreshed at ' + date + '[' + date.getTime() / 1000 + '] ');
23000
23001        if (!isPaused) {
23002            startManifestRefreshTimer();
23003        }
23004    }
23005
23006    function onRefreshTimer() {
23007        if (isPaused && !mediaPlayerModel.getScheduleWhilePaused() || isUpdating) return;
23008        refreshManifest();
23009    }
23010
23011    function onManifestLoaded(e) {
23012        if (!e.error) {
23013            update(e.manifest);
23014        }
23015    }
23016
23017    function onPlaybackStarted() /*e*/{
23018        isPaused = false;
23019        startManifestRefreshTimer();
23020    }
23021
23022    function onPlaybackPaused() /*e*/{
23023        isPaused = true;
23024        stopManifestRefreshTimer();
23025    }
23026
23027    function onStreamsComposed() /*e*/{
23028        // When streams are ready we can consider manifest update completed. Resolve the update promise.
23029        isUpdating = false;
23030    }
23031
23032    instance = {
23033        initialize: initialize,
23034        setManifest: setManifest,
23035        refreshManifest: refreshManifest,
23036        setConfig: setConfig,
23037        reset: reset
23038    };
23039
23040    return instance;
23041}
23042ManifestUpdater.__dashjs_factory_name = 'ManifestUpdater';
23043exports['default'] = _coreFactoryMaker2['default'].getClassFactory(ManifestUpdater);
23044module.exports = exports['default'];
23045
23046},{"49":49,"50":50,"51":51,"54":54}],93:[function(_dereq_,module,exports){
23047/**
23048 * The copyright in this software is being made available under the BSD License,
23049 * included below. This software may be subject to other third party and contributor
23050 * rights, including patent rights, and no such rights are granted under this license.
23051 *
23052 * Copyright (c) 2013, Dash Industry Forum.
23053 * All rights reserved.
23054 *
23055 * Redistribution and use in source and binary forms, with or without modification,
23056 * are permitted provided that the following conditions are met:
23057 *  * Redistributions of source code must retain the above copyright notice, this
23058 *  list of conditions and the following disclaimer.
23059 *  * Redistributions in binary form must reproduce the above copyright notice,
23060 *  this list of conditions and the following disclaimer in the documentation and/or
23061 *  other materials provided with the distribution.
23062 *  * Neither the name of Dash Industry Forum nor the names of its
23063 *  contributors may be used to endorse or promote products derived from this software
23064 *  without specific prior written permission.
23065 *
23066 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
23067 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23068 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23069 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23070 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
23070INCLUDING, BUT
23071 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23072 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23073 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23074 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
23075 *  POSSIBILITY OF SUCH DAMAGE.
23076 */
23077'use strict';
23078
23079Object.defineProperty(exports, '__esModule', {
23080    value: true
23081});
23082
23083function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
23084
23085var _constantsConstants = _dereq_(100);
23086
23087var _constantsConstants2 = _interopRequireDefault(_constantsConstants);
23088
23089var _constantsMetricsConstants = _dereq_(101);
23090
23091var _constantsMetricsConstants2 = _interopRequireDefault(_constantsMetricsConstants);
23092
23093var _dashVoUTCTiming = _dereq_(89);
23094
23095var _dashVoUTCTiming2 = _interopRequireDefault(_dashVoUTCTiming);
23096
23097var _controllersPlaybackController = _dereq_(110);
23098
23099var _controllersPlaybackController2 = _interopRequireDefault(_controllersPlaybackController);
23100
23101var _controllersStreamController = _dereq_(113);
23102
23103var _controllersStreamController2 = _interopRequireDefault(_controllersStreamController);
23104
23105var _controllersMediaController = _dereq_(108);
23106
23107var _controllersMediaController2 = _interopRequireDefault(_controllersMediaController);
23108
23109var _ManifestLoader = _dereq_(91);
23110
23111var _ManifestLoader2 = _interopRequireDefault(_ManifestLoader);
23112
23113var _utilsErrorHandler = _dereq_(195);
23114
23115var _utilsErrorHandler2 = _interopRequireDefault(_utilsErrorHandler);
23116
23117var _utilsCapabilities = _dereq_(191);
23118
23119var _utilsCapabilities2 = _interopRequireDefault(_utilsCapabilities);
23120
23121var _textTextTracks = _dereq_(188);
23122
23123var _textTextTracks2 = _interopRequireDefault(_textTextTracks);
23124
23125var _utilsRequestModifier = _dereq_(200);
23126
23127var _utilsRequestModifier2 = _interopRequireDefault(_utilsRequestModifier);
23128
23129var _textTextController = _dereq_(186);
23130
23131var _textTextController2 = _interopRequireDefault(_textTextController);
23132
23133var _modelsURIQueryAndFragmentModel = _dereq_(144);
23134
23135var _modelsURIQueryAndFragmentModel2 = _interopRequireDefault(_modelsURIQueryAndFragmentModel);
23136
23137var _modelsManifestModel = _dereq_(141);
23138
23139var _modelsManifestModel2 = _interopRequireDefault(_modelsManifestModel);
23140
23141var _modelsMediaPlayerModel = _dereq_(142);
23142
23143var _modelsMediaPlayerModel2 = _interopRequireDefault(_modelsMediaPlayerModel);
23144
23145var _modelsMetricsModel = _dereq_(143);
23146
23147var _modelsMetricsModel2 = _interopRequireDefault(_modelsMetricsModel);
23148
23149var _controllersAbrController = _dereq_(102);
23150
23151var _controllersAbrController2 = _interopRequireDefault(_controllersAbrController);
23152
23153var _controllersSourceBufferController = _dereq_(112);
23154
23155var _controllersSourceBufferController2 = _interopRequireDefault(_controllersSourceBufferController);
23156
23157var _modelsVideoModel = _dereq_(145);
23158
23159var _modelsVideoModel2 = _interopRequireDefault(_modelsVideoModel);
23160
23161var _utilsDOMStorage = _dereq_(193);
23162
23163var _utilsDOMStorage2 = _interopRequireDefault(_utilsDOMStorage);
23164
23165var _coreDebug = _dereq_(49);
23166
23167var _coreDebug2 = _interopRequireDefault(_coreDebug);
23168
23169var _coreEventBus = _dereq_(50);
23170
23171var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
23172
23173var _coreEventsEvents = _dereq_(54);
23174
23175var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
23176
23177var _MediaPlayerEvents = _dereq_(94);
23178
23179var _MediaPlayerEvents2 = _interopRequireDefault(_MediaPlayerEvents);
23180
23181var _coreFactoryMaker = _dereq_(51);
23182
23183var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
23184
23185var _coreVersion = _dereq_(52);
23186
23187//Dash
23188
23189var _dashDashAdapter = _dereq_(56);
23190
23191var _dashDashAdapter2 = _interopRequireDefault(_dashDashAdapter);
23192
23193var _dashModelsDashManifestModel = _dereq_(63);
23194
23195var _dashModelsDashManifestModel2 = _interopRequireDefault(_dashModelsDashManifestModel);
23196
23197var _dashDashMetrics = _dereq_(58);
23198
23199var _dashDashMetrics2 = _interopRequireDefault(_dashDashMetrics);
23200
23201var _dashUtilsTimelineConverter = _dereq_(79);
23202
23203var _dashUtilsTimelineConverter2 = _interopRequireDefault(_dashUtilsTimelineConverter);
23204
23205var _voMetricsHTTPRequest = _dereq_(224);
23206
23207var _externalsBase64 = _dereq_(1);
23208
23209var _externalsBase642 = _interopRequireDefault(_externalsBase64);
23210
23211var _codemIsoboxer = _dereq_(11);
23212
23213var _codemIsoboxer2 = _interopRequireDefault(_codemIsoboxer);
23214
23215/**
23216 * @module MediaPlayer
23217 * @description The MediaPlayer is the primary dash.js Module and a Facade to build your player around.
23218 * It will allow you access to all the important dash.js properties/methods via the public API and all the
23219 * events to build a robust DASH media player.
23220 */
23221function MediaPlayer() {
23222
23223    var PLAYBACK_NOT_INITIALIZED_ERROR = 'You must first call initialize() to init playback before calling this method';
23224    var ELEMENT_NOT_ATTACHED_ERROR = 'You must first call attachView() to set the video element before calling this method';
23225    var SOURCE_NOT_ATTACHED_ERROR = 'You must first call attachSource() with a valid source before calling this method';
23226    var MEDIA_PLAYER_NOT_INITIALIZED_ERROR = 'MediaPlayer not initialized!';
23227
23228    var context = this.context;
23229    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
23230    var debug = (0, _coreDebug2['default'])(context).getInstance();
23231    var log = debug.log;
23232
23233    var instance = undefined,
23234        source = undefined,
23235        protectionData = undefined,
23236        mediaPlayerInitialized = undefined,
23237        playbackInitialized = undefined,
23238        autoPlay = undefined,
23239        abrController = undefined,
23240        timelineConverter = undefined,
23241        mediaController = undefined,
23242        protectionController = undefined,
23243        metricsReportingController = undefined,
23244        mssHandler = undefined,
23245        adapter = undefined,
23246        metricsModel = undefined,
23247        mediaPlayerModel = undefined,
23248        errHandler = undefined,
23249        capabilities = undefined,
23250        streamController = undefined,
23251        playbackController = undefined,
23252        dashMetrics = undefined,
23253        dashManifestModel = undefined,
23254        manifestModel = undefined,
23255        videoModel = undefined,
23256        textController = undefined,
23257        domStorage = undefined;
23258
23259    /*
23260    ---------------------------------------------------------------------------
23261         INIT FUNCTIONS
23262     ---------------------------------------------------------------------------
23263    */
23264    function setup() {
23265        mediaPlayerInitialized = false;
23266        playbackInitialized = false;
23267        autoPlay = true;
23268        protectionController = null;
23269        protectionData = null;
23270        adapter = null;
23271        _coreEventsEvents2['default'].extend(_MediaPlayerEvents2['default']);
23272        mediaPlayerModel = (0, _modelsMediaPlayerModel2['default'])(context).getInstance();
23273    }
23274
23275    /**
23276     * Configure media plyer with customs controllers. Helpful for tests
23277     *
23278     * @param {object=} config controllers configuration
23279     * @memberof module:MediaPlayer
23280     * @instance
23281     */
23282    function setConfig(config) {
23283        if (!config) {
23284            return;
23285        }
23286        if (config.capabilities) {
23287            capabilities = config.capabilities;
23288        }
23289        if (config.streamController) {
23290            streamController = config.streamController;
23291        }
23292        if (config.playbackController) {
23293            playbackController = config.playbackController;
23294        }
23295        if (config.mediaPlayerModel) {
23296            mediaPlayerModel = config.mediaPlayerModel;
23297        }
23298        if (config.abrController) {
23299            abrController = config.abrController;
23300        }
23301        if (config.mediaController) {
23302            mediaController = config.mediaController;
23303        }
23304    }
23305
23306    /**
23307     * Upon creating the MediaPlayer you must call initialize before you call anything else.
23308     * There is one exception to this rule. It is crucial to call {@link module:MediaPlayer#extend extend()}
23309     * with all your extensions prior to calling initialize.
23310     *
23311     * ALL arguments are optional and there are individual methods to set each argument later on.
23312     * The args in this method are just for convenience and should only be used for a simple player setup.
23313     *
23314     * @param {HTML5MediaElement=} view - Optional arg to set the video element. {@link module:MediaPlayer#attachView attachView()}
23315     * @param {string=} source - Optional arg to set the media source. {@link module:MediaPlayer#attachSource attachSource()}
23316     * @param {boolean=} AutoPlay - Optional arg to set auto play. {@link module:MediaPlayer#setAutoPlay setAutoPlay()}
23317     * @see {@link module:MediaPlayer#attachView attachView()}
23318     * @see {@link module:MediaPlayer#attachSource attachSource()}
23319     * @see {@link module:MediaPlayer#setAutoPlay setAutoPlay()}
23320     * @memberof module:MediaPlayer
23321     * @instance
23322     */
23323    function initialize(view, source, AutoPlay) {
23324
23325        if (!capabilities) {
23326            capabilities = (0, _utilsCapabilities2['default'])(context).getInstance();
23327        }
23328        errHandler = (0, _utilsErrorHandler2['default'])(context).getInstance();
23329
23330        if (!capabilities.supportsMediaSource()) {
23331            errHandler.capabilityError('mediasource');
23332            return;
23333        }
23334
23335        if (mediaPlayerInitialized) return;
23336        mediaPlayerInitialized = true;
23337
23338        // init some controllers and models
23339        timelineConverter = (0, _dashUtilsTimelineConverter2['default'])(context).getInstance();
23340        if (!abrController) {
23341            abrController = (0, _controllersAbrController2['default'])(context).getInstance();
23342        }
23343
23344        if (!playbackController) {
23345            playbackController = (0, _controllersPlaybackController2['default'])(context).getInstance();
23346        }
23347
23348        if (!mediaController) {
23349            mediaController = (0, _controllersMediaController2['default'])(context).getInstance();
23350        }
23351
23352        adapter = (0, _dashDashAdapter2['default'])(context).getInstance();
23353        dashManifestModel = (0, _dashModelsDashManifestModel2['default'])(context).getInstance({
23354            mediaController: mediaController,
23355            timelineConverter: timelineConverter,
23356            adapter: adapter
23357        });
23358        manifestModel = (0, _modelsManifestModel2['default'])(context).getInstance();
23359        dashMetrics = (0, _dashDashMetrics2['default'])(context).getInstance({
23360            manifestModel: manifestModel,
23361            dashManifestModel: dashManifestModel
23362        });
23363        metricsModel = (0, _modelsMetricsModel2['default'])(context).getInstance();
23364
23365        textController = (0, _textTextController2['default'])(context).getInstance();
23366        domStorage = (0, _utilsDOMStorage2['default'])(context).getInstance({
23367            mediaPlayerModel: mediaPlayerModel
23368        });
23369
23370        adapter.setConfig({
23371            dashManifestModel: dashManifestModel
23372        });
23373        metricsModel.setConfig({
23374            adapter: adapter
23375        });
23376
23377        restoreDefaultUTCTimingSources();
23378        setAutoPlay(AutoPlay !== undefined ? AutoPlay : true);
23379
23380        if (view) {
23381            attachView(view);
23382        }
23383
23384        if (source) {
23385            attachSource(source);
23386        }
23387
23388        log('[dash.js ' + getVersion() + '] ' + 'MediaPlayer has been initialized');
23389    }
23390
23391    /**
23392     * Sets the MPD source and the video element to null. You can also reset the MediaPlayer by
23393     * calling attachSource with a new source file.
23394     *
23395     * Calling this method is all that is necessary to destroy a MediaPlayer instance.
23396     *
23397     * @memberof module:MediaPlayer
23398     * @instance
23399     */
23400    function reset() {
23401        attachSource(null);
23402        attachView(null);
23403        protectionData = null;
23404        if (protectionController) {
23405            protectionController.reset();
23406            protectionController = null;
23407        }
23408        if (metricsReportingController) {
23409            metricsReportingController.reset();
23410            metricsReportingController = null;
23411        }
23412    }
23413
23414    /**
23415     * The ready state of the MediaPlayer based on both the video element and MPD source being defined.
23416     *
23417     * @returns {boolean} The current ready state of the MediaPlayer
23418     * @see {@link module:MediaPlayer#attachView attachView()}
23419     * @see {@link module:MediaPlayer#attachSource attachSource()}
23420     * @memberof module:MediaPlayer
23421     * @instance
23422     */
23423    function isReady() {
23424        return !!videoModel && !!source;
23425    }
23426
23427    /**
23428     * Use the on method to listen for public events found in MediaPlayer.events. {@link MediaPlayerEvents}
23429     *
23430     * @param {string} type - {@link MediaPlayerEvents}
23431     * @param {Function} listener - callback method when the event fires.
23432     * @param {Object} scope - context of the listener so it can be removed properly.
23433     * @memberof module:MediaPlayer
23434     * @instance
23435     */
23436    function on(type, listener, scope) {
23437        eventBus.on(type, listener, scope);
23438    }
23439
23440    /**
23441     * Use the off method to remove listeners for public events found in MediaPlayer.events. {@link MediaPlayerEvents}
23442     *
23443     * @param {string} type - {@link MediaPlayerEvents}
23444     * @param {Function} listener - callback method when the event fires.
23445     * @param {Object} scope - context of the listener so it can be removed properly.
23446     * @memberof module:MediaPlayer
23447     * @instance
23448     */
23449    function off(type, listener, scope) {
23450        eventBus.off(type, listener, scope);
23451    }
23452
23453    /**
23454     * Current version of Dash.js
23455     * @returns {string}
23455 the current dash.js version string.
23456     * @memberof module:MediaPlayer
23457     * @instance
23458     */
23459    function getVersion() {
23460        return (0, _coreVersion.getVersionString)();
23461    }
23462
23463    /**
23464     * Use this method to access the dash.js logging class.
23465     *
23466     * @returns {Debug}
23467     * @memberof module:MediaPlayer
23468     * @instance
23469     */
23470    function getDebug() {
23471        return debug;
23472    }
23473
23474    /*
23475    ---------------------------------------------------------------------------
23476         PLAYBACK FUNCTIONS
23477     ---------------------------------------------------------------------------
23478    */
23479    /**
23480     * The play method initiates playback of the media defined by the {@link module:MediaPlayer#attachSource attachSource()} method.
23481     * This method will call play on the native Video Element.
23482     *
23483     * @see {@link module:MediaPlayer#attachSource attachSource()}
23484     * @memberof module:MediaPlayer
23485     * @instance
23486     */
23487    function play() {
23488        if (!playbackInitialized) {
23489            throw PLAYBACK_NOT_INITIALIZED_ERROR;
23490        }
23491        if (!autoPlay || isPaused() && playbackInitialized) {
23492            playbackController.play();
23493        }
23494    }
23495
23496    /**
23497     * This method will call pause on the native Video Element.
23498     *
23499     * @memberof module:MediaPlayer
23500     * @instance
23501     */
23502    function pause() {
23503        if (!playbackInitialized) {
23504            throw PLAYBACK_NOT_INITIALIZED_ERROR;
23505        }
23506        playbackController.pause();
23507    }
23508
23509    /**
23510     * Returns a Boolean that indicates whether the Video Element is paused.
23511     * @return {boolean}
23512     * @memberof module:MediaPlayer
23513     * @instance
23514     */
23515    function isPaused() {
23516        if (!playbackInitialized) {
23517            throw PLAYBACK_NOT_INITIALIZED_ERROR;
23518        }
23519        return playbackController.isPaused();
23520    }
23521
23522    /**
23523     * Sets the currentTime property of the attached video element.  If it is a live stream with a
23524     * timeShiftBufferLength, then the DVR window offset will be automatically calculated.
23525     *
23526     * @param {number} value - A relative time, in seconds, based on the return value of the {@link module:MediaPlayer#duration duration()} method is expected
23527     * @see {@link module:MediaPlayer#getDVRSeekOffset getDVRSeekOffset()}
23528     * @memberof module:MediaPlayer
23529     * @instance
23530     */
23531    function seek(value) {
23532        if (!playbackInitialized) {
23533            throw PLAYBACK_NOT_INITIALIZED_ERROR;
23534        }
23535        var s = playbackController.getIsDynamic() ? getDVRSeekOffset(value) : value;
23536        playbackController.seek(s);
23537    }
23538
23539    /**
23540     * Returns a Boolean that indicates whether the media is in the process of seeking to a new position.
23541     * @return {boolean}
23542     * @memberof module:MediaPlayer
23543     * @instance
23544     */
23545    function isSeeking() {
23546        if (!playbackInitialized) {
23547            throw PLAYBACK_NOT_INITIALIZED_ERROR;
23548        }
23549        return playbackController.isSeeking();
23550    }
23551
23552    /**
23553     * Returns a Boolean that indicates whether the media is in the process of dynamic.
23554     * @return {boolean}
23555     * @memberof module:MediaPlayer
23556     * @instance
23557     */
23558    function isDynamic() {
23559        if (!playbackInitialized) {
23560            throw PLAYBACK_NOT_INITIALIZED_ERROR;
23561        }
23562        return playbackController.getIsDynamic();
23563    }
23564
23565    /**
23566     * Use this method to set the native Video Element's playback rate.
23567     * @param {number} value
23568     * @memberof module:MediaPlayer
23569     * @instance
23570     */
23571    function setPlaybackRate(value) {
23572        if (!videoModel) {
23573            throw ELEMENT_NOT_ATTACHED_ERROR;
23574        }
23575        getVideoElement().playbackRate = value;
23576    }
23577
23578    /**
23579     * Returns the current playback rate.
23580     * @returns {number}
23581     * @memberof module:MediaPlayer
23582     * @instance
23583     */
23584    function getPlaybackRate() {
23585        if (!videoModel) {
23586            throw ELEMENT_NOT_ATTACHED_ERROR;
23587        }
23588        return getVideoElement().playbackRate;
23589    }
23590
23591    /**
23592     * Use this method to set the native Video Element's muted state. Takes a Boolean that determines whether audio is muted. true if the audio is muted and false otherwise.
23593     * @param {boolean} value
23594     * @memberof module:MediaPlayer
23595     * @instance
23596     */
23597    function setMute(value) {
23598        if (!videoModel) {
23599            throw ELEMENT_NOT_ATTACHED_ERROR;
23600        }
23601        getVideoElement().muted = value;
23602    }
23603
23604    /**
23605     * A Boolean that determines whether audio is muted.
23606     * @returns {boolean}
23607     * @memberof module:MediaPlayer
23608     * @instance
23609     */
23610    function isMuted() {
23611        if (!videoModel) {
23612            throw ELEMENT_NOT_ATTACHED_ERROR;
23613        }
23614        return getVideoElement().muted;
23615    }
23616
23617    /**
23618     * A double indicating the audio volume, from 0.0 (silent) to 1.0 (loudest).
23619     * @param {number} value
23620     * @memberof module:MediaPlayer
23621     * @instance
23622     */
23623    function setVolume(value) {
23624        if (!videoModel) {
23625            throw ELEMENT_NOT_ATTACHED_ERROR;
23626        }
23627        getVideoElement().volume = value;
23628    }
23629
23630    /**
23631     * Returns the current audio volume, from 0.0 (silent) to 1.0 (loudest).
23632     * @returns {number}
23633     * @memberof module:MediaPlayer
23634     * @instance
23635     */
23636    function getVolume() {
23637        if (!videoModel) {
23638            throw ELEMENT_NOT_ATTACHED_ERROR;
23639        }
23640        return getVideoElement().volume;
23641    }
23642
23643    /**
23644     * The length of the buffer for a given media type, in seconds. Valid media
23645     * types are "video", "audio" and "fragmentedText". If no type is passed
23646     * in, then the minimum of video, audio and fragmentedText buffer length is
23647     * returned. NaN is returned if an invalid type is requested, the
23648     * presentation does not contain that type, or if no arguments are passed
23649     * and the presentation does not include any adaption sets of valid media
23650     * type.
23651     *
23652     * @param {string} type - the media type of the buffer
23653     * @returns {number} The length of the buffer for the given media type, in
23654     *  seconds, or NaN
23655     * @memberof module:MediaPlayer
23656     * @instance
23657     */
23658    function getBufferLength(type) {
23659        var types = [_constantsConstants2['default'].VIDEO, _constantsConstants2['default'].AUDIO, _constantsConstants2['default'].FRAGMENTED_TEXT];
23660        if (!type) {
23661            var buffer = types.map(function (t) {
23662                return getTracksFor(t).length > 0 ? getDashMetrics().getCurrentBufferLevel(getMetricsFor(t)) : Number.MAX_VALUE;
23663            }).reduce(function (p, c) {
23664                return Math.min(p, c);
23665            });
23666            return buffer === Number.MAX_VALUE ? NaN : buffer;
23667        } else {
23668            if (types.indexOf(type) !== -1) {
23669                var buffer = getDashMetrics().getCurrentBufferLevel(getMetricsFor(type));
23670                return buffer ? buffer : NaN;
23671            } else {
23672                log('Warning  - getBufferLength requested for invalid type');
23673                return NaN;
23674            }
23675        }
23676    }
23677
23678    /**
23679     * The timeShiftBufferLength (DVR Window), in seconds.
23680     *
23681     * @returns {number} The window of allowable play time behind the live point of a live stream.
23682     * @memberof module:MediaPlayer
23683     * @instance
23684     */
23685    function getDVRWindowSize() {
23686        var metric = getDVRInfoMetric();
23687        if (!metric) {
23688            return 0;
23689        }
23690        return metric.manifestInfo.DVRWindowSize;
23691    }
23692
23693    /**
23694     * This method should only be used with a live stream that has a valid timeShiftBufferLength (DVR Window).
23695     * NOTE - If you do not need the raw offset value (i.e. media analytics, tracking, etc) consider using the {@link module:MediaPlayer#seek seek()} method
23696     * which will calculate this value for you and set the video element's currentTime property all in one simple call.
23697     *
23698     * @param {number} value - A relative time, in seconds, based on the return value of the {@link module:MediaPlayer#duration duration()} method is expected.
23699     * @returns {number} A value that is relative the available range within the timeShiftBufferLength (DVR Window).
23700     * @see {@link module:MediaPlayer#seek seek()}
23701     * @memberof module:MediaPlayer
23702     * @instance
23703     */
23704    function getDVRSeekOffset(value) {
23705        var metric = getDVRInfoMetric();
23706
23707        if (!metric) {
23708            return 0;
23709        }
23710
23711        var val = metric.range.start + value;
23712
23713        if (val > metric.range.end) {
23714            val = metric.range.end;
23715        }
23716
23717        return val;
23718    }
23719
23720    /**
23721     * Current time of the playhead, in seconds.
23722     *
23723     * If called with no arguments then the returned time value is time elapsed since the start point of the first stream, or if it is a live stream, then the time will be based on the return value of the {@link module:MediaPlayer#duration duration()} method.
23724     * However if a stream ID is supplied then time is relative to the start of that stream, or is null if there is no such stream id in the manifest.
23725     *
23726     * @param {string} streamId - The ID of a stream that the returned playhead time must be relative to the start of. If undefined, then playhead time is relative to the first stream.
23727     * @returns {number} The current playhead time of the media, or null.
23728     * @memberof module:MediaPlayer
23729     * @instance
23730     */
23731    function time(streamId) {
23732        if (!playbackInitialized) {
23733            throw PLAYBACK_NOT_INITIALIZED_ERROR;
23734        }
23735        var t = getVideoElement().currentTime;
23736
23737        if (streamId !== undefined) {
23738            t = streamController.getTimeRelativeToStreamId(t, streamId);
23739        } else if (playbackController.getIsDynamic()) {
23740            var metric = getDVRInfoMetric();
23741            t = metric === null ? 0 : duration() - (metric.range.end - metric.time);
23742        }
23743
23744        return t;
23745    }
23746
23747    /**
23748     * Duration of the media's playback, in seconds.
23749     *
23750     * @returns {number} The current duration of the media.
23751     * @memberof module:MediaPlayer
23752     * @instance
23753     */
23754    function duration() {
23755        if (!playbackInitialized) {
23756            throw PLAYBACK_NOT_INITIALIZED_ERROR;
23757        }
23758        var d = getVideoElement().duration;
23759
23760        if (playbackController.getIsDynamic()) {
23761
23762            var metric = getDVRInfoMetric();
23763            var range = undefined;
23764
23765            if (!metric) {
23766                return 0;
23767            }
23768
23769            range = metric.range.end - metric.range.start;
23770            d = range < metric.manifestInfo.DVRWindowSize ? range : metric.manifestInfo.DVRWindowSize;
23771        }
23772        return d;
23773    }
23774
23775    /**
23776     * Use this method to get the current playhead time as an absolute value, the time in seconds since midnight UTC, Jan 1 1970.
23777     * Note - this property only has meaning for live streams. If called before play() has begun, it will return a value of NaN.
23778     *
23779     * @returns {number} The current playhead time as UTC timestamp.
23780     * @memberof module:MediaPlayer
23781     * @instance
23782     */
23783    function timeAsUTC() {
23784        if (!playbackInitialized) {
23785            throw PLAYBACK_NOT_INITIALIZED_ERROR;
23786        }
23787        if (time() < 0) {
23788            return NaN;
23789        }
23790        return getAsUTC(time());
23791    }
23792
23793    /**
23794     * Use this method to get the current duration as an absolute value, the time in seconds since midnight UTC, Jan 1 1970.
23795     * Note - this property only has meaning for live streams.
23796     *
23797     * @returns {number} The current duration as UTC timestamp.
23798     * @memberof module:MediaPlayer
23799     * @instance
23800     */
23801    function durationAsUTC() {
23802        if (!playbackInitialized) {
23803            throw PLAYBACK_NOT_INITIALIZED_ERROR;
23804        }
23805        return getAsUTC(duration());
23806    }
23807
23808    /*
23809    ---------------------------------------------------------------------------
23810         AUTO BITRATE
23811     ---------------------------------------------------------------------------
23812    */
23813    /**
23814     * When switching multi-bitrate content (auto or manual mode) this property specifies the maximum bitrate allowed.
23815     * If you set this property to a value lower than that currently playing, the switching engine will switch down to
23816     * satisfy this requirement. If you set it to a value that is lower than the lowest bitrate, it will still play
23817     * that lowest bitrate.
23818     *
23819     * You can set or remove this bitrate cap at anytime before or during playback.  To clear this setting you must use the API
23820     * and set the value param to NaN.
23821     *
23822     * This feature is typically used to reserve higher bitrates for playback only when the player is in large or full-screen format.
23823     *
23824     * @param {string} type - 'video' or 'audio' are the type options.
23825     * @param {number} value - Value in kbps representing the maximum bitrate allowed.
23826     * @memberof module:MediaPlayer
23827     * @instance
23828     */
23829    function setMaxAllowedBitrateFor(type, value) {
23830        abrController.setMaxAllowedBitrateFor(type, value);
23831    }
23832
23833    /**
23834     * When switching multi-bitrate content (auto or manual mode) this property specifies the minimum bitrate allowed.
23835     * If you set this property to a value higher than that currently playing, the switching engine will switch up to
23836     * satisfy this requirement. If you set it to a value that is lower than the lowest bitrate, it will still play
23837     * that lowest bitrate.
23838     *
23839     * You can set or remove this bitrate limit at anytime before or during playback. To clear this setting you must use the API
23840     * and set the value param to NaN.
23841     *
23842     * This feature is used to force higher quality playback.
23843     *
23844     * @param {string} type - 'video' or 'audio' are the type options.
23845     * @param {number} value - Value in kbps representing the minimum bitrate allowed.
23846     * @memberof module:MediaPlayer
23847     * @instance
23848     */
23849    function setMinAllowedBitrateFor(type, value) {
23850        abrController.setMinAllowedBitrateFor(type, value);
23851    }
23852
23853    /**
23854     * @param {string} type - 'video' or 'audio' are the type options.
23855     * @memberof module:MediaPlayer
23856     * @see {@link module:MediaPlayer#setMaxAllowedBitrateFor setMaxAllowedBitrateFor()}
23857     * @instance
23858     */
23859    function getMaxAllowedBitrateFor(type) {
23860        return abrController.getMaxAllowedBitrateFor(type);
23861    }
23862
23863    /**
23864     * @param {string} type - 'video' or 'audio' are the type options.
23865     * @memberof module:MediaPlayer
23866     * @see {@link module:MediaPlayer#setMinAllowedBitrateFor setMinAllowedBitrateFor()}
23867     * @instance
23868     */
23869    function getMinAllowedBitrateFor(type) {
23870        return abrController.getMinAllowedBitrateFor(type);
23871    }
23872
23873    /**
23874     * When switching multi-bitrate content (auto or manual mode) this property specifies the maximum representation allowed,
23875     * as a proportion of the size of the representation set.
23876     *
23877     * You can set or remove this cap at anytime before or during playback. To clear this setting you must use the API
23878     * and set the value param to NaN.
23879     *
23880     * If both this and maxAllowedBitrate are defined, maxAllowedBitrate is evaluated first, then maxAllowedRepresentation,
23881     * i.e. the lowest value from executing these rules is used.
23882     *
23883     * This feature is typically used to reserve higher representations for playback only when connected over a fast connection.
23884     *
23885     * @param {string} type - 'video' or 'audio' are the type options.
23886     * @param {number} value - number between 0 and 1, where 1 is allow all representations, and 0 is allow only the lowest.
23887     * @memberof module:MediaPlayer
23888     * @instance
23889     */
23890    function setMaxAllowedRepresentationRatioFor(type, value) {
23891        abrController.setMaxAllowedRepresentationRatioFor(type, value);
23892    }
23893
23894    /**
23895     * @param {string} type - 'video' or 'audio' are the type options.
23896     * @returns {number} The current representation ratio cap.
23897     * @memberof module:MediaPlayer
23898     * @see {@link module:MediaPlayer#setMaxAllowedRepresentationRatioFor setMaxAllowedRepresentationRatioFor()}
23899     * @instance
23900     */
23901    function getMaxAllowedRepresentationRatioFor(type) {
23902        return abrController.getMaxAllowedRepresentationRatioFor(type);
23903    }
23904
23905    /**
23906     * Gets the current download quality for media type. The ABR rules update this value before every new download
23907     * unless setAutoSwitchQualityFor(type, false) is called.
23908     *
23909     * @param {string} type - 'video' or 'audio'
23910     * @returns {number} the quality index, 0 corresponding to the lowest bitrate
23911     * @memberof module:MediaPlayer
23912     * @see {@link module:MediaPlayer#setAutoSwitchQualityFor setAutoSwitchQualityFor()}
23913     * @see {@link module:MediaPlayer#setQualityFor setQualityFor()}
23914     * @instance
23915     */
23916    function getQualityFor(type) {
23917        if (!playbackInitialized) {
23918            throw PLAYBACK_NOT_INITIALIZED_ERROR;
23919        }
23920        return abrController.getQualityFor(type, streamController.getActiveStreamInfo());
23921    }
23922
23923    /**
23924     * Sets the current quality for media type instead of letting the ABR Heuristics automatically selecting it.
23925     * This value will be overwritten by the ABR rules unless setAutoSwitchQualityFor(type, false) is called.
23926     *
23927     * @param {string} type - 'video' or 'audio'
23928     * @param {number} value - the quality index, 0 corresponding to the lowest bitrate
23929     * @memberof module:MediaPlayer
23930     * @see {@link module:MediaPlayer#setAutoSwitchQualityFor setAutoSwitchQualityFor()}
23931     * @see {@link module:MediaPlayer#getQualityFor getQualityFor()}
23932     * @instance
23933     */
23934    function setQualityFor(type, value) {
23935        if (!playbackInitialized) {
23936            throw PLAYBACK_NOT_INITIALIZED_ERROR;
23937        }
23938        abrController.setPlaybackQuality(type, streamController.getActiveStreamInfo(), value);
23939    }
23940
23941    /**
23942     * Update the video element size variables
23943     * Should be called on window resize (or any other time player is resized). Fullscreen does trigger a window resize event.
23944     *
23945     * Once windowResizeEventCalled = true, abrController.checkPortalSize() will use element size variables rather than querying clientWidth every time.
23946     *
23947     * @memberof module:MediaPlayer
23948     * @instance
23949     */
23950    function updatePortalSize() {
23951        abrController.setElementSize();
23952        abrController.setWindowResizeEventCalled(true);
23953    }
23954
23955    /**
23956     * @memberof module:MediaPlayer
23957     * @instance
23958     */
23959    function getLimitBitrateByPortal() {
23960        return abrController.getLimitBitrateByPortal();
23961    }
23962
23963    /**
23964     * Sets whether to limit the representation used based on the size of the playback area
23965     *
23966     * @param {boolean} value
23967     * @memberof module:MediaPlayer
23968     * @instance
23969     */
23970    function setLimitBitrateByPortal(value) {
23971        abrController.setLimitBitrateByPortal(value);
23972    }
23973
23974    /**
23975     * @memberof module:MediaPlayer
23976     * @instance
23977     */
23978    function getUsePixelRatioInLimitBitrateByPortal() {
23979        return abrController.getUsePixelRatioInLimitBitrateByPortal();
23980    }
23981
23982    /**
23983     * Sets whether to take into account the device's pixel ratio when defining the portal dimensions.
23984     * Useful on, for example, retina displays.
23985     *
23986     * @param {boolean} value
23987     * @memberof module:MediaPlayer
23988     * @instance
23989     * @default {boolean} false
23990     */
23991    function setUsePixelRatioInLimitBitrateByPortal(value) {
23992        abrController.setUsePixelRatioInLimitBitrateByPortal(value);
23993    }
23994
23995    /**
23996     * Use this method to explicitly set the starting bitrate for audio | video
23997     *
23998     * @param {string} type
23999     * @param {number} value - A value of the initial bitrate, kbps
24000     * @memberof module:MediaPlayer
24001     * @instance
24002     */
24003    function setInitialBitrateFor(type, value) {
24004        abrController.setInitialBitrateFor(type, value);
24005    }
24006
24007    /**
24008     * @param {string} type
24009     * @returns {number} A value of the initial bitrate, kbps
24010     * @memberof module:MediaPlayer
24011     * @instance
24012     */
24013    function getInitialBitrateFor(type) {
24014        if (!playbackInitialized) {
24015            throw PLAYBACK_NOT_INITIALIZED_ERROR; //abrController.getInitialBitrateFor is overloaded with ratioDict logic that needs manifest force it to not be callable pre play.
24016        }
24017        return abrController.getInitialBitrateFor(type);
24018    }
24019
24020    /**
24021     * @param {string} type
24022     * @param {number} value - A value of the initial Representation Ratio
24023     * @memberof module:MediaPlayer
24024     * @instance
24025     */
24026    function setInitialRepresentationRatioFor(type, value) {
24027        abrController.setInitialRepresentationRatioFor(type, value);
24028    }
24029
24030    /**
24031     * @param {string} type
24032     * @returns {number} A value of the initial Representation Ratio
24033     * @memberof module:MediaPlayer
24034     * @instance
24035     */
24036    function getInitialRepresentationRatioFor(type) {
24037        return abrController.getInitialRepresentationRatioFor(type);
24038    }
24039
24040    /**
24041     * @param {string} type - 'audio' | 'video'
24042     * @returns {boolean} Current state of adaptive bitrate switching
24043     * @memberof module:MediaPlayer
24044     * @instance
24045     */
24046    function getAutoSwitchQualityFor(type) {
24047        return abrController.getAutoSwitchBitrateFor(type);
24048    }
24049
24050    /**
24051     * Set to false to switch off adaptive bitrate switching.
24052     *
24053     * @param {string} type - 'audio' | 'video'
24054     * @param {boolean} value
24055     * @default true
24056     * @memberof module:MediaPlayer
24057     * @instance
24058     */
24059    function setAutoSwitchQualityFor(type, value) {
24060        abrController.setAutoSwitchBitrateFor(type, value);
24061    }
24062
24063    /**
24064     * Get the value of useDeadTimeLatency in AbrController. @see setUseDeadTimeLatencyForAbr
24065     *
24066     * @returns {boolean}
24067     *
24068     * @memberof module:MediaPlayer
24069     * @instance
24070     */
24071    function getUseDeadTimeLatencyForAbr() {
24072        return abrController.getUseDeadTimeLatency();
24073    }
24074
24075    /**
24076     * Set the value of useDeadTimeLatency in AbrController. If true, only the download
24077     * portion will be considered part of the download bitrate and latency will be
24078     * regarded as static. If false, the reciprocal of the whole transfer time will be used.
24079     * Defaults to true.
24080     *
24081     * @param {boolean=} useDeadTimeLatency - True or false flag.
24082     *
24083     * @memberof module:MediaPlayer
24084     * @instance
24085     */
24086    function setUseDeadTimeLatencyForAbr(useDeadTimeLatency) {
24087        abrController.setUseDeadTimeLatency(useDeadTimeLatency);
24088    }
24089
24090    /*
24091    ---------------------------------------------------------------------------
24092         MEDIA PLAYER CONFIGURATION
24093     ---------------------------------------------------------------------------
24094    */
24095    /**
24096     * <p>Set to false to prevent stream from auto-playing when the view is attached.</p>
24097     *
24098     * @param {boolean} value
24099     * @default true
24100     * @memberof module:MediaPlayer
24101     * @see {@link module:MediaPlayer#attachView attachView()}
24102     * @instance
24103     *
24104     */
24105    function setAutoPlay(value) {
24106        autoPlay = value;
24107    }
24108
24109    /**
24110     * @returns {boolean} The current autoPlay state.
24111     * @memberof module:MediaPlayer
24112     * @instance
24113     */
24114    function getAutoPlay() {
24115        return autoPlay;
24116    }
24117
24118    /**
24119     * <p>Changing this value will lower or increase live stream latency.  The detected segment duration will be multiplied by this value
24120     * to define a time in seconds to delay a live stream from the live edge.</p>
24121     * <p>Lowering this value will lower latency but may decrease the player's ability to build a stable buffer.</p>
24122     *
24123     * @param {number} value - Represents how many segment durations to delay the live stream.
24124     * @default 4
24125     * @memberof module:MediaPlayer
24126     * @see {@link module:MediaPlayer#useSuggestedPresentationDelay useSuggestedPresentationDelay()}
24127     * @instance
24128     */
24129    function setLiveDelayFragmentCount(value) {
24130        mediaPlayerModel.setLiveDelayFragmentCount(value);
24131    }
24132
24133    /**
24134     * <p>Equivalent in seconds of setLiveDelayFragmentCount</p>
24135     * <p>Lowering this value will lower latency but may decrease the player's ability to build a stable buffer.</p>
24136     * <p>This value should be less than the manifest duration by a couple of segment durations to avoid playback issues</p>
24137     * <p>If set, this parameter will take precedence over setLiveDelayFragmentCount and manifest info</p>
24138     *
24139     * @param {number} value - Represents how many seconds to delay the live stream.
24140     * @default undefined
24141     * @memberof module:MediaPlayer
24142     * @see {@link module:MediaPlayer#useSuggestedPresentationDelay useSuggestedPresentationDelay()}
24143     * @instance
24144     */
24145    function setLiveDelay(value) {
24146        mediaPlayerModel.setLiveDelay(value);
24147    }
24148
24149    /**
24150     * @memberof module:MediaPlayer
24151     * @see {@link module:MediaPlayer#setLiveDelay setLiveDelay()}
24152     * @instance
24153     * @returns {number|undefined} Current live stream delay in seconds when previously set, or `undefined`
24154     */
24155    function getLiveDelay() {
24156        return mediaPlayerModel.getLiveDelay();
24157    }
24158
24159    /**
24160     * <p>Set to true if you would like to override the default live delay and honor the SuggestedPresentationDelay attribute in by the manifest.</p>
24161     * @param {boolean} value
24162     * @default false
24163     * @memberof module:MediaPlayer
24164     * @see {@link module:MediaPlayer#setLiveDelayFragmentCount setLiveDelayFragmentCount()}
24165     * @instance
24166     */
24167    function useSuggestedPresentationDelay(value) {
24168        mediaPlayerModel.setUseSuggestedPresentationDelay(value);
24169    }
24170
24171    /**
24172     * Set to false if you would like to disable the last known bit rate from being stored during playback and used
24173     * to set the initial bit rate for subsequent playback within the expiration window.
24174     *
24175     * The default expiration is one hour, defined in milliseconds. If expired, the default initial bit rate (closest to 1000 kbps) will be used
24176     * for that session and a new bit rate will be stored during that session.
24177     *
24178     * @param {boolean} enable - Will toggle if feature is enabled. True to enable, False to disable.
24179     * @param {number=} ttl - (Optional) A value defined in milliseconds representing how long to cache the bit rate for. Time to live.
24180     * @default enable = True, ttl = 360000 (1 hour)
24181     * @memberof module:MediaPlayer
24182     * @instance
24183     *
24184     */
24185    function enableLastBitrateCaching(enable, ttl) {
24186        mediaPlayerModel.setLastBitrateCachingInfo(enable, ttl);
24187    }
24188
24189    /**
24190     * Set to false if you would like to disable the last known lang for audio (or camera angle for video) from being stored during playback and used
24191     * to set the initial settings for subsequent playback within the expiration window.
24192     *
24193     * The default expiration is one hour, defined in milliseconds. If expired, the default settings will be used
24194     * for that session and a new settings will be stored during that session.
24195     *
24196     * @param {boolean} enable - Will toggle if feature is enabled. True to enable, False to disable.
24197     * @param {number=} [ttl] - (Optional) A value defined in milliseconds representing how long to cache the settings for. Time to live.
24198     * @default enable = True, ttl = 360000 (1 hour)
24199     * @memberof module:MediaPlayer
24200     * @instance
24201     *
24202     */
24203    function enableLastMediaSettingsCaching(enable, ttl) {
24204        mediaPlayerModel.setLastMediaSettingsCachingInfo(enable, ttl);
24205    }
24206
24207    /**
24208     * Set to true if you would like dash.js to keep downloading fragments in the background
24209     * when the video element is paused.
24210     *
24211     * @default true
24212     * @param {boolean} value
24213     * @memberof module:MediaPlayer
24214     * @instance
24215     */
24216    function setScheduleWhilePaused(value) {
24217        mediaPlayerModel.setScheduleWhilePaused(value);
24218    }
24219
24220    /**
24221     * Returns a boolean of the current state of ScheduleWhilePaused.
24222     * @returns {boolean}
24223     * @see {@link module:MediaPlayer#setScheduleWhilePaused setScheduleWhilePaused()}
24224     * @memberof module:MediaPlayer
24225     * @instance
24226     */
24227    function getScheduleWhilePaused() {
24228        return mediaPlayerModel.getScheduleWhilePaused();
24229    }
24230
24231    /**
24232     * When enabled, after an ABR up-switch in quality, instead of requesting and appending the next fragment
24233     * at the end of the current buffer range it is requested and appended closer to the current time
24234     * When enabled, The maximum time to render a higher quality is current time + (1.5 * fragment duration).
24235     *
24236     * Note, When ABR down-switch is detected, we appended the lower quality at the end of the buffer range to preserve the
24237     * higher quality media for as long as possible.
24238     *
24239     * If enabled, it should be noted there are a few cases when the client will not replace inside buffer range but rather
24240     * just append at the end.  1. When the buffer level is less than one fragment duration 2.  The client
24241     * is in an Abandonment State due to recent fragment abandonment event.
24242     *
24243     * Known issues:
24244     * 1. In IE11 with auto switching off, if a user switches to a quality they can not download in time the
24245     * fragment may be appended in the same range as the playhead or even in the past, in IE11 it may cause a stutter
24246     * or stall in playback.
24247     *
24248     *
24249     * @param {boolean} value
24250     * @default {boolean} false
24251     * @memberof module:MediaPlayer
24252     * @instance
24253     */
24254    function setFastSwitchEnabled(value) {
24255        //TODO we need to look at track switches for adaptation sets.  If always replace it works much like this but clears buffer. Maybe too many ways to do same thing.
24256        mediaPlayerModel.setFastSwitchEnabled(value);
24257    }
24258
24259    /**
24260     * Enabled by default. Will return the current state of Fast Switch.
24261     * @return {boolean} Returns true if FastSwitch ABR is enabled.
24262     * @see {@link module:MediaPlayer#setFastSwitchEnabled setFastSwitchEnabled()}
24263     * @memberof module:MediaPlayer
24264     * @instance
24265     */
24266    function getFastSwitchEnabled() {
24267        return mediaPlayerModel.getFastSwitchEnabled();
24268    }
24269
24270    /**
24271     * Obsolete since version 2.6.0.
24272     * Buffer-occupancy ABR is now switched on and off dynamically.
24273     * @see {@link module:MediaPlayer#setABRStrategy setABRStrategy()}
24274     *
24275     * @param {boolean} value
24276     * @memberof module:MediaPlayer
24277     * @instance
24278     */
24279    function enableBufferOccupancyABR(value) {
24280        throw new Error('Calling obsolete function - enabledBufferOccupancyABR(' + value + ') has no effect.');
24281    }
24282
24283    /**
24284     * Sets the ABR strategy. Valid strategies are "abrDynamic", "abrBola" and "abrThroughput".
24285     * The ABR strategy can also be changed during a streaming session.
24286     * The call has no effect if an invalid method is passed.
24287     *
24288     * The BOLA strategy chooses bitrate based on current buffer level, with higher bitrates for higher buffer levels.
24289     * The Throughput strategy chooses bitrate based on the recent throughput history.
24290     * The Dynamic strategy switches smoothly between BOLA and Throughput in real time, playing to the strengths of both.
24291     *
24292     * @param {string} value
24293     * @default "abrDynamic"
24294     * @memberof module:MediaPlayer
24295     * @instance
24296     */
24297    function setABRStrategy(value) {
24298        if (value === _constantsConstants2['default'].ABR_STRATEGY_DYNAMIC || value === _constantsConstants2['default'].ABR_STRATEGY_BOLA || value === _constantsConstants2['default'].ABR_STRATEGY_THROUGHPUT) {
24299            mediaPlayerModel.setABRStrategy(value);
24300        } else {
24301            log('Warning: Ignoring setABRStrategy(' + value + ') - unknown value.');
24302        }
24303    }
24304
24305    /**
24306     * Returns the current ABR strategy being used.
24307     * @return {string} "abrDynamic", "abrBola" or "abrThroughput"
24308     * @see {@link module:MediaPlayer#setABRStrategy setABRStrategy()}
24309     * @memberof module:MediaPlayer
24310     * @instance
24311     */
24312    function getABRStrategy() {
24313        return mediaPlayerModel.getABRStrategy();
24314    }
24315
24316    /**
24317     * Enable/disable builtin dashjs ABR rules
24318     * @param {boolean} value
24319     * @default true
24320     * @memberof module:MediaPlayer
24321     * @instance
24322     */
24323    function useDefaultABRRules(value) {
24324        mediaPlayerModel.setUseDefaultABRRules(value);
24325    }
24326
24327    /**
24328     * Add a custom ABR Rule
24329     * Rule will be apply on next stream if a stream is being played
24330     *
24331     * @param {string} type - rule type (one of ['qualitySwitchRules','abandonFragmentRules'])
24332     * @param {string} rulename - name of rule (used to identify custom rule). If one rule of same name has been added, then existing rule will be updated
24333     * @param {object} rule - the rule object instance
24334     * @memberof module:MediaPlayer
24335     * @instance
24336     */
24337    function addABRCustomRule(type, rulename, rule) {
24338        mediaPlayerModel.addABRCustomRule(type, rulename, rule);
24339    }
24340
24341    /**
24342     * Remove a custom ABR Rule
24343     *
24344     * @param {string} rulename - name of the rule to be removed
24345     * @memberof module:MediaPlayer
24346     * @instance
24347     */
24348    function removeABRCustomRule(rulename) {
24349        mediaPlayerModel.removeABRCustomRule(rulename);
24350    }
24351
24352    /**
24353     * Remove all custom rules
24354     * @memberof module:MediaPlayer
24355     * @instance
24356     */
24357    function removeAllABRCustomRule() {
24358        mediaPlayerModel.removeAllABRCustomRule();
24359    }
24360
24361    /**
24362     * Sets the moving average method used for smoothing throughput estimates. Valid methods are
24363     * "slidingWindow" and "ewma". The call has no effect if an invalid method is passed.
24364     *
24365     * The sliding window moving average method computes the average throughput using the last four segments downloaded.
24366     * If the stream is live (as opposed to VOD), then only the last three segments are used.
24367     * If wide variations in throughput are detected, the number of segments can be dynamically increased to avoid oscillations.
24368     *
24369     * The exponentially weighted moving average (EWMA) method computes the average using exponential smoothing.
24370     * Two separate estimates are maintained, a fast one with a three-second half life and a slow one with an eight-second half life.
24371     * The throughput estimate at any time is the minimum of the fast and slow estimates.
24372     * This allows a fast reaction to a bandwidth drop and prevents oscillations on bandwidth spikes.
24373     *
24374     * @param {string} value
24375     * @default {string} 'slidingWindow'
24376     * @memberof module:MediaPlayer
24377     * @instance
24378     */
24379    function setMovingAverageMethod(value) {
24380        if (value === _constantsConstants2['default'].MOVING_AVERAGE_SLIDING_WINDOW || value === _constantsConstants2['default'].MOVING_AVERAGE_EWMA) {
24381            mediaPlayerModel.setMovingAverageMethod(value);
24382        } else {
24383            log('Warning: Ignoring setMovingAverageMethod(' + value + ') - unknown value.');
24384        }
24385    }
24386
24387    /**
24388     * Return the current moving average method used for smoothing throughput estimates.
24389     * @return {string} Returns "slidingWindow" or "ewma".
24390     * @see {@link module:MediaPlayer#setMovingAverageMethod setMovingAverageMethod()}
24391     * @memberof module:MediaPlayer
24392     * @instance
24393     */
24394    function getMovingAverageMethod() {
24395        return mediaPlayerModel.getMovingAverageMethod();
24396    }
24397
24398    /**
24399     * <p>Allows you to set a scheme and server source for UTC live edge detection for dynamic streams.
24400     * If UTCTiming is defined in the manifest, it will take precedence over any time source manually added.</p>
24401     * <p>If you have exposed the Date header, use the method {@link module:MediaPlayer#clearDefaultUTCTimingSources clearDefaultUTCTimingSources()}.
24402     * This will allow the date header on the manifest to be used instead of a time server</p>
24403     * @param {string} schemeIdUri - <ul>
24404     * <li>urn:mpeg:dash:utc:http-head:2014</li>
24405     * <li>urn:mpeg:dash:utc:http-xsdate:2014</li>
24406     * <li>urn:mpeg:dash:utc:http-iso:2014</li>
24407     * <li>
24407urn:mpeg:dash:utc:direct:2014</li>
24408     * </ul>
24409     * <p>Some specs referencing early ISO23009-1 drafts incorrectly use
24410     * 2012 in the URI, rather than 2014. support these for now.</p>
24411     * <ul>
24412     * <li>urn:mpeg:dash:utc:http-head:2012</li>
24413     * <li>urn:mpeg:dash:utc:http-xsdate:2012</li>
24414     * <li>urn:mpeg:dash:utc:http-iso:2012</li>
24415     * <li>urn:mpeg:dash:utc:direct:2012</li>
24416     * </ul>
24417     * @param {string} value - Path to a time source.
24418     * @default
24419     * <ul>
24420     *     <li>schemeIdUri:urn:mpeg:dash:utc:http-xsdate:2014</li>
24421     *     <li>value:http://time.akamai.com</li>
24422     * </ul>
24423     * @memberof module:MediaPlayer
24424     * @see {@link module:MediaPlayer#removeUTCTimingSource removeUTCTimingSource()}
24425     * @instance
24426     */
24427    function addUTCTimingSource(schemeIdUri, value) {
24428        removeUTCTimingSource(schemeIdUri, value); //check if it already exists and remove if so.
24429        var vo = new _dashVoUTCTiming2['default']();
24430        vo.schemeIdUri = schemeIdUri;
24431        vo.value = value;
24432        mediaPlayerModel.getUTCTimingSources().push(vo);
24433    }
24434
24435    /**
24436     * <p>Allows you to remove a UTC time source. Both schemeIdUri and value need to match the Dash.vo.UTCTiming properties in order for the
24437     * entry to be removed from the array</p>
24438     * @param {string} schemeIdUri - see {@link module:MediaPlayer#addUTCTimingSource addUTCTimingSource()}
24439     * @param {string} value - see {@link module:MediaPlayer#addUTCTimingSource addUTCTimingSource()}
24440     * @memberof module:MediaPlayer
24441     * @see {@link module:MediaPlayer#clearDefaultUTCTimingSources clearDefaultUTCTimingSources()}
24442     * @instance
24443     */
24444    function removeUTCTimingSource(schemeIdUri, value) {
24445        var UTCTimingSources = mediaPlayerModel.getUTCTimingSources();
24446        UTCTimingSources.forEach(function (obj, idx) {
24447            if (obj.schemeIdUri === schemeIdUri && obj.value === value) {
24448                UTCTimingSources.splice(idx, 1);
24449            }
24450        });
24451    }
24452
24453    /**
24454     * <p>Allows you to clear the stored array of time sources.</p>
24455     * <p>Example use: If you have exposed the Date header, calling this method
24456     * will allow the date header on the manifest to be used instead of the time server.</p>
24457     * <p>Example use: Calling this method, assuming there is not an exposed date header on the manifest,  will default back
24458     * to using a binary search to discover the live edge</p>
24459     *
24460     * @memberof module:MediaPlayer
24461     * @see {@link module:MediaPlayer#restoreDefaultUTCTimingSources restoreDefaultUTCTimingSources()}
24462     * @instance
24463     */
24464    function clearDefaultUTCTimingSources() {
24465        mediaPlayerModel.setUTCTimingSources([]);
24466    }
24467
24468    /**
24469     * <p>Allows you to restore the default time sources after calling {@link module:MediaPlayer#clearDefaultUTCTimingSources clearDefaultUTCTimingSources()}</p>
24470     *
24471     * @default
24472     * <ul>
24473     *     <li>schemeIdUri:urn:mpeg:dash:utc:http-xsdate:2014</li>
24474     *     <li>value:http://time.akamai.com</li>
24475     * </ul>
24476     *
24477     * @memberof module:MediaPlayer
24478     * @see {@link module:MediaPlayer#addUTCTimingSource addUTCTimingSource()}
24479     * @instance
24480     */
24481    function restoreDefaultUTCTimingSources() {
24482        addUTCTimingSource(_modelsMediaPlayerModel2['default'].DEFAULT_UTC_TIMING_SOURCE.scheme, _modelsMediaPlayerModel2['default'].DEFAULT_UTC_TIMING_SOURCE.value);
24483    }
24484
24485    /**
24486     * <p>Allows you to enable the use of the Date Header, if exposed with CORS, as a timing source for live edge detection. The
24487     * use of the date header will happen only after the other timing source that take precedence fail or are omitted as described.
24488     * {@link module:MediaPlayer#clearDefaultUTCTimingSources clearDefaultUTCTimingSources()} </p>
24489     *
24490     * @param {boolean} value - true to enable
24491     * @default {boolean} True
24492     * @memberof module:MediaPlayer
24493     * @see {@link module:MediaPlayer#addUTCTimingSource addUTCTimingSource()}
24494     * @instance
24495     */
24496    function enableManifestDateHeaderTimeSource(value) {
24497        mediaPlayerModel.setUseManifestDateHeaderTimeSource(value);
24498    }
24499
24500    /**
24501     * This value influences the buffer pruning logic.
24502     * Allows you to modify the buffer that is kept in source buffer in seconds.
24503     *  0|-----------bufferToPrune-----------|-----bufferToKeep-----|currentTime|
24504     *
24505     * @default 30 seconds
24506     * @param {int} value
24507     * @memberof module:MediaPlayer
24508     * @instance
24509     */
24510    function setBufferToKeep(value) {
24511        mediaPlayerModel.setBufferToKeep(value);
24512    }
24513
24514    /**
24515     * This value influences the buffer pruning logic.
24516     * Allows you to modify the interval of pruning buffer in seconds.
24517     *
24518     * @default 30 seconds
24519     * @param {int} value
24520     * @memberof module:MediaPlayer
24521     * @instance
24522     */
24523    function setBufferPruningInterval(value) {
24524        mediaPlayerModel.setBufferPruningInterval(value);
24525    }
24526
24527    /**
24528     * The time that the internal buffer target will be set to post startup/seeks (NOT top quality).
24529     *
24530     * When the time is set higher than the default you will have to wait longer
24531     * to see automatic bitrate switches but will have a larger buffer which
24532     * will increase stability.
24533     *
24534     * @default 12 seconds.
24535     * @param {int} value
24536     * @memberof module:MediaPlayer
24537     * @instance
24538     */
24539    function setStableBufferTime(value) {
24540        mediaPlayerModel.setStableBufferTime(value);
24541    }
24542
24543    /**
24544     * The time that the internal buffer target will be set to post startup/seeks (NOT top quality).
24545     *
24546     * When the time is set higher than the default you will have to wait longer
24547     * to see automatic bitrate switches but will have a larger buffer which
24548     * will increase stability.
24549     *
24550     * @default 12 seconds.
24551     * @memberof module:MediaPlayer
24552     * @instance
24553     */
24554    function getStableBufferTime() {
24555        return mediaPlayerModel.getStableBufferTime();
24556    }
24557
24558    /**
24559     * The time that the internal buffer target will be set to once playing the top quality.
24560     * If there are multiple bitrates in your adaptation, and the media is playing at the highest
24561     * bitrate, then we try to build a larger buffer at the top quality to increase stability
24562     * and to maintain media quality.
24563     *
24564     * @default 30 seconds.
24565     * @param {int} value
24566    /**
24567     * The time that the internal buffer target will be set to once playing the top quality.
24568     * If there are multiple bitrates in your adaptation, and the media is playing at the highest
24569     * bitrate, then we try to build a larger buffer at the top quality to increase stability
24570     * and to maintain media quality.
24571     *
24572     * @default 30 seconds.
24573     * @param {int} value
24574     * @memberof module:MediaPlayer
24575     * @instance
24576     */
24577    function setBufferTimeAtTopQuality(value) {
24578        mediaPlayerModel.setBufferTimeAtTopQuality(value);
24579    }
24580
24581    /**
24582     * The time that the internal buffer target will be set to once playing the top quality.
24583     * If there are multiple bitrates in your adaptation, and the media is playing at the highest
24584     * bitrate, then we try to build a larger buffer at the top quality to increase stability
24585     * and to maintain media quality.
24586     *
24587     * @default 30 seconds.
24588     * @memberof module:MediaPlayer
24589     * @instance
24590     */
24591    function getBufferTimeAtTopQuality() {
24592        return mediaPlayerModel.getBufferTimeAtTopQuality();
24593    }
24594
24595    /**
24596     * The time that the internal buffer target will be set to once playing the top quality for long form content.
24597     *
24598     * @default 60 seconds.
24599     * @see {@link module:MediaPlayer#setLongFormContentDurationThreshold setLongFormContentDurationThreshold()}
24600     * @see {@link module:MediaPlayer#setBufferTimeAtTopQuality setBufferTimeAtTopQuality()}
24601     * @param {int} value
24602     * @memberof module:MediaPlayer
24603     * @instance
24604     */
24605    function setBufferTimeAtTopQualityLongForm(value) {
24606        mediaPlayerModel.setBufferTimeAtTopQualityLongForm(value);
24607    }
24608
24609    /**
24610     * The time that the internal buffer target will be set to once playing the top quality for long form content.
24611     *
24612     * @default 60 seconds.
24613     * @see {@link module:MediaPlayer#setLongFormContentDurationThreshold setLongFormContentDurationThreshold()}
24614     * @see {@link module:MediaPlayer#setBufferTimeAtTopQuality setBufferTimeAtTopQuality()}
24615     * @memberof module:MediaPlayer
24616     * @instance
24617     */
24618    function getBufferTimeAtTopQualityLongForm() {
24619        return mediaPlayerModel.getBufferTimeAtTopQualityLongForm();
24620    }
24621
24622    /**
24623     * The threshold which defines if the media is considered long form content.
24624     * This will directly affect the buffer targets when playing back at the top quality.
24625     *
24626     * @see {@link module:MediaPlayer#setBufferTimeAtTopQualityLongForm setBufferTimeAtTopQualityLongForm()}
24627     * @default 600 seconds (10 minutes).
24628     * @param {number} value
24629     * @memberof module:MediaPlayer
24630     * @instance
24631     */
24632    function setLongFormContentDurationThreshold(value) {
24633        mediaPlayerModel.setLongFormContentDurationThreshold(value);
24634    }
24635
24636    /**
24637     * Obsolete since version 2.6.0.
24638     * ABR rules now switch from Throughput to Buffer Occupancy mode when there is sufficient buffer.
24639     * This renders the rich buffer mechanism redundant.
24640     *
24641     * @param {number} value
24642     * @memberof module:MediaPlayer
24643     * @instance
24644     */
24645    function setRichBufferThreshold(value) {
24646        throw new Error('Calling obsolete function - setRichBufferThreshold(' + value + ') has no effect.');
24647    }
24648
24649    /**
24650     * A percentage between 0.0 and 1 to reduce the measured throughput calculations.
24651     * The default is 0.9. The lower the value the more conservative and restricted the
24652     * measured throughput calculations will be. please use carefully. This will directly
24653     * affect the ABR logic in dash.js
24654     *
24655     * @param {number} value
24656     * @memberof module:MediaPlayer
24657     * @instance
24658     */
24659    function setBandwidthSafetyFactor(value) {
24660        mediaPlayerModel.setBandwidthSafetyFactor(value);
24661    }
24662
24663    /**
24664     * Returns the number of the current BandwidthSafetyFactor
24665     *
24666     * @return {number} value
24667     * @see {@link module:MediaPlayer#setBandwidthSafetyFactor setBandwidthSafetyFactor()}
24668     * @memberof module:MediaPlayer
24669     * @instance
24670     */
24671    function getBandwidthSafetyFactor() {
24672        return mediaPlayerModel.getBandwidthSafetyFactor();
24673    }
24674
24675    /**
24676     * Returns the average throughput computed in the ABR logic
24677     *
24678     * @param {string} type
24679     * @return {number} value
24680     * @memberof module:MediaPlayer
24681     * @instance
24682     */
24683    function getAverageThroughput(type) {
24684        var throughputHistory = abrController.getThroughputHistory();
24685        return throughputHistory ? throughputHistory.getAverageThroughput(type) : 0;
24686    }
24687
24688    /**
24689     * A timeout value in seconds, which during the ABRController will block switch-up events.
24690     * This will only take effect after an abandoned fragment event occurs.
24691     *
24692     * @default 10 seconds
24693     * @param {int} value
24694     * @memberof module:MediaPlayer
24695     * @instance
24696     */
24697    function setAbandonLoadTimeout(value) {
24698        mediaPlayerModel.setAbandonLoadTimeout(value);
24699    }
24700
24701    /**
24702     * Total number of retry attempts that will occur on a fragment load before it fails.
24703     * Increase this value to a maximum in order to achieve an automatic playback resume
24704     * in case of completely lost internet connection.
24705     *
24706     * @default 3
24707     * @param {int} value
24708     * @memberof module:MediaPlayer
24709     * @instance
24710     */
24711    function setFragmentLoaderRetryAttempts(value) {
24712        mediaPlayerModel.setFragmentRetryAttempts(value);
24713    }
24714
24715    /**
24716     * Time in milliseconds of which to reload a failed fragment load attempt.
24717     *
24718     * @default 1000 milliseconds
24719     * @param {int} value
24720     * @memberof module:MediaPlayer
24721     * @instance
24722     */
24723    function setFragmentLoaderRetryInterval(value) {
24724        mediaPlayerModel.setFragmentRetryInterval(value);
24725    }
24726
24727    /**
24728     * Total number of retry attempts that will occur on a manifest load before it fails.
24729     *
24730     * @default 4
24731     * @param {int} value
24732     * @memberof module:MediaPlayer
24733     * @instance
24734     */
24735    function setManifestLoaderRetryAttempts(value) {
24736        mediaPlayerModel.setManifestRetryAttempts(value);
24737    }
24738
24739    /**
24740     * Time in milliseconds of which to reload a failed manifest load attempt.
24741     *
24742     * @default 1000 milliseconds
24743     * @param {int} value
24744     * @memberof module:MediaPlayer
24745     * @instance
24746     */
24747    function setManifestLoaderRetryInterval(value) {
24748        mediaPlayerModel.setManifestRetryInterval(value);
24749    }
24750
24751    /**
24752     * Sets whether withCredentials on XHR requests for a particular request
24753     * type is true or false
24754     *
24755     * @default false
24756     * @param {string} type - one of HTTPRequest.*_TYPE
24757     * @param {boolean} value
24758     * @memberof module:MediaPlayer
24759     * @instance
24760     */
24761    function setXHRWithCredentialsForType(type, value) {
24762        mediaPlayerModel.setXHRWithCredentialsForType(type, value);
24763    }
24764
24765    /**
24766     * Gets whether withCredentials on XHR requests for a particular request
24767     * type is true or false
24768     *
24769     * @param {string} type - one of HTTPRequest.*_TYPE
24770     * @return {boolean}
24771     * @memberof module:MediaPlayer
24772     * @instance
24773     */
24774    function getXHRWithCredentialsForType(type) {
24775        return mediaPlayerModel.getXHRWithCredentialsForType(type);
24776    }
24777
24778    /*
24779    ---------------------------------------------------------------------------
24780         METRICS
24781     ---------------------------------------------------------------------------
24782    */
24783    /**
24784     * Returns the DashMetrics.js Module. You use this Module to get access to all the public metrics
24785     * stored in dash.js
24786     *
24787     * @see {@link module:DashMetrics}
24788     * @returns {Object}
24789     * @memberof module:MediaPlayer
24790     * @instance
24791     */
24792    function getDashMetrics() {
24793        return dashMetrics;
24794    }
24795
24796    /**
24797     *
24798     * @param {string} type
24799     * @returns {Object}
24800     * @memberof module:MediaPlayer
24801     * @instance
24802     */
24803    function getMetricsFor(type) {
24804        return metricsModel.getReadOnlyMetricsFor(type);
24805    }
24806    /*
24807    ---------------------------------------------------------------------------
24808         TEXT MANAGEMENT
24809     ---------------------------------------------------------------------------
24810    */
24811    /**
24812     * Use this method to change the current text track for both external time text files and fragmented text tracks. There is no need to
24813     * set the track mode on the video object to switch a track when using this method.
24814     *
24815     * @param {number} idx - Index of track based on the order of the order the tracks are added Use -1 to disable all tracks. (turn captions off).  Use module:MediaPlayer#dashjs.MediaPlayer.events.TEXT_TRACK_ADDED.
24816     * @see {@link module:MediaPlayer#dashjs.MediaPlayer.events.TEXT_TRACK_ADDED}
24817     * @memberof module:MediaPlayer
24818     * @instance
24819     */
24820    function setTextTrack(idx) {
24821        if (!playbackInitialized) {
24822            throw PLAYBACK_NOT_INITIALIZED_ERROR;
24823        }
24824
24825        if (textController === undefined) {
24826            textController = (0, _textTextController2['default'])(context).getInstance();
24827        }
24828
24829        textController.setTextTrack(idx);
24830    }
24831
24832    function getCurrentTextTrackIndex() {
24833        var idx = NaN;
24834        if (textController) {
24835            idx = textController.getCurrentTrackIdx();
24836        }
24837        return idx;
24838    }
24839
24840    /**
24841     * This method serves to control captions z-index value. If 'true' is passed, the captions will have the highest z-index and be
24842     * displayed on top of other html elements. Default value is 'false' (z-index is not set).
24843     * @param {boolean} value
24844     * @memberof module:MediaPlayer
24845     * @instance
24846     */
24847    function displayCaptionsOnTop(value) {
24848        var textTracks = (0, _textTextTracks2['default'])(context).getInstance();
24849        textTracks.setConfig({
24850            videoModel: videoModel
24851        });
24852        textTracks.initialize();
24853        textTracks.displayCConTop(value);
24854    }
24855
24856    /*
24857    ---------------------------------------------------------------------------
24858         VIDEO ELEMENT MANAGEMENT
24859     ---------------------------------------------------------------------------
24860    */
24861
24862    /**
24863     * Returns instance of Video Element that was attached by calling attachView()
24864     * @returns {Object}
24865     * @memberof module:MediaPlayer
24866     * @instance
24867     */
24868    function getVideoElement() {
24869        if (!videoModel) {
24870            throw ELEMENT_NOT_ATTACHED_ERROR;
24871        }
24872        return videoModel.getElement();
24873    }
24874
24875    /**
24876     * Returns instance of Video Container that was attached by calling attachVideoContainer()
24877     * @returns {Object}
24878     * @memberof module:MediaPlayer
24879     * @instance
24880     */
24881    function getVideoContainer() {
24882        return videoModel ? videoModel.getVideoContainer() : null;
24883    }
24884
24885    /**
24886     * Use this method to attach an HTML5 element that wraps the video element.
24887     *
24888     * @param {HTMLElement} container - The HTML5 element containing the video element.
24889     * @memberof module:MediaPlayer
24890     * @instance
24891     */
24892    function attachVideoContainer(container) {
24893        if (!videoModel) {
24894            throw ELEMENT_NOT_ATTACHED_ERROR;
24895        }
24896        videoModel.setVideoContainer(container);
24897    }
24898
24899    /**
24900     * Use this method to attach an HTML5 VideoElement for dash.js to operate upon.
24901     *
24902     * @param {Object} element - An HTMLMediaElement that has already been defined in the DOM (or equivalent stub).
24903     * @memberof module:MediaPlayer
24904     * @instance
24905     */
24906    function attachView(element) {
24907        if (!mediaPlayerInitialized) {
24908            throw MEDIA_PLAYER_NOT_INITIALIZED_ERROR;
24909        }
24910        videoModel = null;
24911        if (element) {
24912            videoModel = (0, _modelsVideoModel2['default'])(context).getInstance();
24913            videoModel.initialize();
24914            videoModel.setElement(element);
24915            detectProtection();
24916            detectMetricsReporting();
24917            detectMss();
24918        }
24919        resetAndInitializePlayback();
24920    }
24921
24922    /**
24923     * Returns instance of Div that was attached by calling attachTTMLRenderingDiv()
24924     * @returns {Object}
24925     * @memberof module:MediaPlayer
24926     * @instance
24927     */
24928    function getTTMLRenderingDiv() {
24929        return videoModel ? videoModel.getTTMLRenderingDiv() : null;
24930    }
24931
24932    /**
24933     * Use this method to attach an HTML5 div for dash.js to render rich TTML subtitles.
24934     *
24935     * @param {HTMLDivElement} div - An unstyled div placed after the video element. It will be styled to match the video size and overlay z-order.
24936     * @memberof module:MediaPlayer
24937     * @instance
24938     */
24939    function attachTTMLRenderingDiv(div) {
24940        if (!videoModel) {
24941            throw ELEMENT_NOT_ATTACHED_ERROR;
24942        }
24943        videoModel.setTTMLRenderingDiv(div);
24944    }
24945
24946    /*
24947    ---------------------------------------------------------------------------
24948         STREAM AND TRACK MANAGEMENT
24949     ---------------------------------------------------------------------------
24950    */
24951    /**
24952     * @param {string} type
24953     * @returns {Array}
24954     * @memberof module:MediaPlayer
24955     * @instance
24956     */
24957    function getBitrateInfoListFor(type) {
24958        if (!playbackInitialized) {
24959            throw PLAYBACK_NOT_INITIALIZED_ERROR;
24960        }
24961        var stream = getActiveStream();
24962        return stream ? stream.getBitrateListFor(type) : [];
24963    }
24964
24965    /**
24966     * This method returns the list of all available streams from a given manifest
24967     * @param {Object} manifest
24968     * @returns {Array} list of {@link StreamInfo}
24969     * @memberof module:MediaPlayer
24970     * @instance
24971     */
24972    function getStreamsFromManifest(manifest) {
24973        if (!playbackInitialized) {
24974            throw PLAYBACK_NOT_INITIALIZED_ERROR;
24975        }
24976        return adapter.getStreamsInfo(manifest);
24977    }
24978
24979    /**
24980     * This method returns the list of all available tracks for a given media type
24981     * @param {string} type
24982     * @returns {Array} list of {@link MediaInfo}
24983     * @memberof module:MediaPlayer
24984     * @instance
24985     */
24986    function getTracksFor(type) {
24987        if (!playbackInitialized) {
24988            throw PLAYBACK_NOT_INITIALIZED_ERROR;
24989        }
24990        var streamInfo = streamController.getActiveStreamInfo();
24991        if (!streamInfo) return [];
24992        return mediaController.getTracksFor(type, streamInfo);
24993    }
24994
24995    /**
24996     * This method returns the list of all available tracks for a given media type and streamInfo from a given manifest
24997     * @param {string} type
24998     * @param {Object} manifest
24999     * @param {Object} streamInfo
25000     * @returns {Array}  list of {@link MediaInfo}
25001     * @memberof module:MediaPlayer
25002     * @instance
25003     */
25004    function getTracksForTypeFromManifest(type, manifest, streamInfo) {
25005        if (!playbackInitialized) {
25006            throw PLAYBACK_NOT_INITIALIZED_ERROR;
25007        }
25008
25009        streamInfo = streamInfo || adapter.getStreamsInfo(manifest)[0];
25010
25011        return streamInfo ? adapter.getAllMediaInfoForType(streamInfo, type, manifest) : [];
25012    }
25013
25014    /**
25015     * @param {string} type
25016     * @returns {Object|null} {@link MediaInfo}
25017     *
25018     * @memberof module:MediaPlayer
25019     * @instance
25020     */
25021    function getCurrentTrackFor(type) {
25022        if (!playbackInitialized) {
25023            throw PLAYBACK_NOT_INITIALIZED_ERROR;
25024        }
25025        var streamInfo = streamController.getActiveStreamInfo();
25026
25027        if (!streamInfo) return null;
25028
25029        return mediaController.getCurrentTrackFor(type, streamInfo);
25030    }
25031
25032    /**
25033     * This method allows to set media settings that will be used to pick the initial track. Format of the settings
25034     * is following:
25035     * {lang: langValue,
25036     *  viewpoint: viewpointValue,
25037     *  audioChannelConfiguration: audioChannelConfigurationValue,
25038     *  accessibility: accessibilityValue,
25039     *  role: roleValue}
25040     *
25041     *
25042     * @param {string} type
25043     * @param {Object} value
25044     * @memberof module:MediaPlayer
25045     * @instance
25046     */
25047    function setInitialMediaSettingsFor(type, value) {
25048        mediaController.setInitialSettings(type, value);
25049    }
25050
25051    /**
25052     * This method returns media settings that is used to pick the initial track. Format of the settings
25053     * is following:
25054     * {lang: langValue,
25055     *  viewpoint: viewpointValue,
25056     *  audioChannelConfiguration: audioChannelConfigurationValue,
25057     *  accessibility: accessibilityValue,
25058     *  role: roleValue}
25059     * @param {string} type
25060     * @returns {Object}
25061     * @memberof module:MediaPlayer
25062     * @instance
25063     */
25064    function getInitialMediaSettingsFor(type) {
25065        return mediaController.getInitialSettings(type);
25066    }
25067
25068    /**
25069     * @param {MediaInfo} track - instance of {@link MediaInfo}
25070     * @memberof module:MediaPlayer
25071     * @instance
25072     */
25073    function setCurrentTrack(track) {
25074        if (!playbackInitialized) {
25075            throw PLAYBACK_NOT_INITIALIZED_ERROR;
25076        }
25077        mediaController.setTrack(track);
25078    }
25079
25080    /**
25081     * This method returns the current track switch mode.
25082     *
25083     * @param {string} type
25084     * @returns {string} mode
25085     * @memberof module:MediaPlayer
25086     * @instance
25087     */
25088    function getTrackSwitchModeFor(type) {
25089        return mediaController.getSwitchMode(type);
25090    }
25091
25092    /**
25093     * This method sets the current track switch mode. Available options are:
25094     *
25095     * MediaController.TRACK_SWITCH_MODE_NEVER_REPLACE
25096     * (used to forbid clearing the buffered data (prior to current playback position) after track switch. Default for video)
25097     *
25098     * MediaController.TRACK_SWITCH_MODE_ALWAYS_REPLACE
25099     * (used to clear the buffered data (prior to current playback position) after track switch. Default for audio)
25100     *
25101     * @param {string} type
25102     * @param {string} mode
25103     * @memberof module:MediaPlayer
25104     * @instance
25105     */
25106    function setTrackSwitchModeFor(type, mode) {
25107        mediaController.setSwitchMode(type, mode);
25108    }
25109
25110    /**
25111     * This method sets the selection mode for the initial track. This mode defines how the initial track will be selected
25112     * if no initial media settings are set. If initial media settings are set this parameter will be ignored. Available options are:
25113     *
25114     * MediaController.TRACK_SELECTION_MODE_HIGHEST_BITRATE
25115     * this mode makes the player select the track with a highest bitrate. This mode is a default mode.
25116     *
25117     * MediaController.TRACK_SELECTION_MODE_WIDEST_RANGE
25118     * this mode makes the player select the track with a widest range of bitrates
25119     *
25120     * @param {string} mode
25121     * @memberof module:MediaPlayer
25122     * @instance
25123     */
25124    function setSelectionModeForInitialTrack(mode) {
25125        mediaController.setSelectionModeForInitialTrack(mode);
25126    }
25127
25128    /**
25129     * This method returns the track selection mode.
25130     *
25131     * @returns {string} mode
25132     * @memberof module:MediaPlayer
25133     * @instance
25134     */
25135    function getSelectionModeForInitialTrack() {
25136        return mediaController.getSelectionModeForInitialTrack();
25137    }
25138
25139    /*
25140    ---------------------------------------------------------------------------
25141         PROTECTION MANAGEMENT
25142     ---------------------------------------------------------------------------
25143    /**
25144     * Detects if Protection is included and returns an instance of ProtectionController.js
25145     * @memberof module:MediaPlayer
25146     * @instance
25147     */
25148    function getProtectionController() {
25149        return detectProtection();
25150    }
25151
25152    /**
25153     * Will override dash.js protection controller.
25154     * @param {ProtectionController} value - valid protection controller instance.
25155     * @memberof module:MediaPlayer
25156     * @instance
25157     */
25158    function attachProtectionController(value) {
25159        protectionController = value;
25160    }
25161
25162    /**
25163     * @param {ProtectionData}
25163 value - object containing
25164     * property names corresponding to key system name strings and associated
25165     * values being instances of.
25166     * @memberof module:MediaPlayer
25167     * @instance
25168     */
25169    function setProtectionData(value) {
25170        protectionData = value;
25171    }
25172
25173    /*
25174    ---------------------------------------------------------------------------
25175         TOOLS AND OTHERS FUNCTIONS
25176     ---------------------------------------------------------------------------
25177    */
25178    /**
25179     * Allows application to retrieve a manifest.  Manifest loading is asynchro
25180     * nous and
25181     * requires the app-provided callback function
25182     *
25183     * @param {string} url - url the manifest url
25184     * @param {function} callback - A Callback function provided when retrieving manifests
25185     * @memberof module:MediaPlayer
25186     * @instance
25187     */
25188    function retrieveManifest(url, callback) {
25189        var manifestLoader = createManifestLoader();
25190        var self = this;
25191
25192        var handler = function handler(e) {
25193            if (!e.error) {
25194                callback(e.manifest);
25195            } else {
25196                callback(null, e.error);
25197            }
25198            eventBus.off(_coreEventsEvents2['default'].INTERNAL_MANIFEST_LOADED, handler, self);
25199            manifestLoader.reset();
25200        };
25201
25202        eventBus.on(_coreEventsEvents2['default'].INTERNAL_MANIFEST_LOADED, handler, self);
25203
25204        var uriQueryFragModel = (0, _modelsURIQueryAndFragmentModel2['default'])(context).getInstance();
25205        uriQueryFragModel.initialize();
25206        manifestLoader.load(uriQueryFragModel.parseURI(url));
25207    }
25208
25209    /**
25210     * Returns the source string or manifest that was attached by calling attachSource()
25211     * @returns {string | manifest}
25212     * @memberof module:MediaPlayer
25213     * @instance
25214     */
25215    function getSource() {
25216        if (!source) {
25217            throw SOURCE_NOT_ATTACHED_ERROR;
25218        }
25219        return source;
25220    }
25221
25222    /**
25223     * Use this method to set a source URL to a valid MPD manifest file OR
25224     * a previously downloaded and parsed manifest object.  Optionally, can
25225     * also provide protection information
25226     *
25227     * @param {string|Object} urlOrManifest - A URL to a valid MPD manifest file, or a
25228     * parsed manifest object.
25229     *
25230     *
25231     * @throws "MediaPlayer not initialized!"
25232     *
25233     * @memberof module:MediaPlayer
25234     * @instance
25235     */
25236    function attachSource(urlOrManifest) {
25237        if (!mediaPlayerInitialized) {
25238            throw MEDIA_PLAYER_NOT_INITIALIZED_ERROR;
25239        }
25240
25241        if (typeof urlOrManifest === 'string') {
25242            var uriQueryFragModel = (0, _modelsURIQueryAndFragmentModel2['default'])(context).getInstance();
25243            uriQueryFragModel.initialize();
25244            source = uriQueryFragModel.parseURI(urlOrManifest);
25245        } else {
25246            source = urlOrManifest;
25247        }
25248
25249        resetAndInitializePlayback();
25250    }
25251
25252    /**
25253     * A utility methods which converts UTC timestamp value into a valid time and date string.
25254     *
25255     * @param {number} time - UTC timestamp to be converted into date and time.
25256     * @param {string} locales - a region identifier (i.e. en_US).
25257     * @param {boolean} hour12 - 12 vs 24 hour. Set to true for 12 hour time formatting.
25258     * @param {boolean} withDate - default is false. Set to true to append current date to UTC time format.
25259     * @returns {string} A formatted time and date string.
25260     * @memberof module:MediaPlayer
25261     * @instance
25262     */
25263    function formatUTC(time, locales, hour12) {
25264        var withDate = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3];
25265
25266        var dt = new Date(time * 1000);
25267        var d = dt.toLocaleDateString(locales);
25268        var t = dt.toLocaleTimeString(locales, {
25269            hour12: hour12
25270        });
25271        return withDate ? t + ' ' + d : t;
25272    }
25273
25274    /**
25275     * A utility method which converts seconds into TimeCode (i.e. 300 --> 05:00).
25276     *
25277     * @param {number} value - A number in seconds to be converted into a formatted time code.
25278     * @returns {string} A formatted time code string.
25279     * @memberof module:MediaPlayer
25280     * @instance
25281     */
25282    function convertToTimeCode(value) {
25283        value = Math.max(value, 0);
25284
25285        var h = Math.floor(value / 3600);
25286        var m = Math.floor(value % 3600 / 60);
25287        var s = Math.floor(value % 3600 % 60);
25288        return (h === 0 ? '' : h < 10 ? '0' + h.toString() + ':' : h.toString() + ':') + (m < 10 ? '0' + m.toString() : m.toString()) + ':' + (s < 10 ? '0' + s.toString() : s.toString());
25289    }
25290
25291    /**
25292     * This method should be used to extend or replace internal dash.js objects.
25293     * There are two ways to extend dash.js (determined by the override argument):
25294     * <ol>
25295     * <li>If you set override to true any public method or property in your custom object will
25296     * override the dash.js parent object's property(ies) and will be used instead but the
25297     * dash.js parent module will still be created.</li>
25298     *
25299     * <li>If you set override to false your object will completely replace the dash.js object.
25300     * (Note: This is how it was in 1.x of Dash.js with Dijon).</li>
25301     * </ol>
25302     * <b>When you extend you get access to this.context, this.factory and this.parent to operate with in your custom object.</b>
25303     * <ul>
25304     * <li><b>this.context</b> - can be used to pass context for singleton access.</li>
25305     * <li><b>this.factory</b> - can be used to call factory.getSingletonInstance().</li>
25306     * <li><b>this.parent</b> - is the reference of the parent object to call other public methods. (this.parent is excluded if you extend with override set to false or option 2)</li>
25307     * </ul>
25308     * <b>You must call extend before you call initialize</b>
25309     * @see {@link module:MediaPlayer#initialize initialize()}
25310     * @param {string} parentNameString - name of parent module
25311     * @param {Object} childInstance - overriding object
25312     * @param {boolean} override - replace only some methods (true) or the whole object (false)
25313     * @memberof module:MediaPlayer
25314     * @instance
25315     */
25316    function extend(parentNameString, childInstance, override) {
25317        _coreFactoryMaker2['default'].extend(parentNameString, childInstance, override, context);
25318    }
25319
25320    /*
25321    ---------------------------------------------------------------------------
25322         DEPRECATED FUNCTIONS
25323     ---------------------------------------------------------------------------
25324    */
25325    /**
25326     * @deprecated Since version 2.1.0.  <b>Instead use:</b>
25327     * <ul>
25328     * <li>{@link module:MediaPlayer#getVideoElement getVideoElement()}</li>
25329     * <li>{@link module:MediaPlayer#getSource getSource()}</li>
25330     * <li>{@link module:MediaPlayer#getVideoContainer getVideoContainer()}</li>
25331     * <li>{@link module:MediaPlayer#getTTMLRenderingDiv getTTMLRenderingDiv()}</li>
25332     * </ul>
25333     *
25334     * @returns {VideoModel}
25335     * @memberof module:MediaPlayer
25336     * @instance
25337     */
25338    function getVideoModel() {
25339        if (!videoModel) {
25340            throw ELEMENT_NOT_ATTACHED_ERROR;
25341        }
25342        return videoModel;
25343    }
25344
25345    /**
25346     * @deprecated since version 2.0 Instead use {@link module:MediaPlayer#getAutoSwitchQualityFor getAutoSwitchQualityFor()}.
25347     * @returns {boolean} Current state of adaptive bitrate switching
25348     * @memberof module:MediaPlayer
25349     * @instance
25350     */
25351    function getAutoSwitchQuality() {
25352        return abrController.getAutoSwitchBitrateFor(_constantsConstants2['default'].VIDEO) || abrController.getAutoSwitchBitrateFor(_constantsConstants2['default'].AUDIO);
25353    }
25354
25355    /**
25356     * Set to false to switch off adaptive bitrate switching.
25357     *
25358     * @deprecated since version 2.0 Instead use {@link module:MediaPlayer#setAutoSwitchQualityFor setAutoSwitchQualityFor()}.
25359     * @param {boolean} value
25360     * @default true
25361     * @memberof module:MediaPlayer
25362     * @instance
25363     */
25364    function setAutoSwitchQuality(value) {
25365        abrController.setAutoSwitchBitrateFor(_constantsConstants2['default'].VIDEO, value);
25366        abrController.setAutoSwitchBitrateFor(_constantsConstants2['default'].AUDIO, value);
25367    }
25368
25369    /**
25370     * Sets whether withCredentials on all XHR requests is true or false
25371     * @default false
25372     * @param {boolean} value
25373     * @memberof module:MediaPlayer
25374     * @instance
25375     * @deprecated since version 2.4 - use setXHRWithCredentialsForType
25376     */
25377    function setXHRWithCredentials(value) {
25378        setXHRWithCredentialsForType(undefined, value);
25379    }
25380
25381    //***********************************
25382    // PRIVATE METHODS
25383    //***********************************
25384
25385    function resetAndInitializePlayback() {
25386        if (playbackInitialized) {
25387            playbackInitialized = false;
25388            adapter.reset();
25389            streamController.reset();
25390            playbackController.reset();
25391            abrController.reset();
25392            mediaController.reset();
25393            textController.reset();
25394            if (protectionController) {
25395                protectionController.reset();
25396                protectionController = null;
25397                detectProtection();
25398            }
25399            if (isReady()) {
25400                initializePlayback();
25401            }
25402        } else if (isReady()) {
25403            initializePlayback();
25404        }
25405    }
25406
25407    function createPlaybackControllers() {
25408
25409        // creates or get objects instances
25410        var manifestLoader = createManifestLoader();
25411
25412        var sourceBufferController = (0, _controllersSourceBufferController2['default'])(context).getInstance({
25413            textController: textController
25414        });
25415
25416        if (!streamController) {
25417            streamController = (0, _controllersStreamController2['default'])(context).getInstance();
25418        }
25419
25420        // configure controllers
25421        mediaController.setConfig({
25422            errHandler: errHandler,
25423            domStorage: domStorage
25424        });
25425
25426        streamController.setConfig({
25427            capabilities: capabilities,
25428            manifestLoader: manifestLoader,
25429            manifestModel: manifestModel,
25430            dashManifestModel: dashManifestModel,
25431            mediaPlayerModel: mediaPlayerModel,
25432            protectionController: protectionController,
25433            adapter: adapter,
25434            metricsModel: metricsModel,
25435            dashMetrics: dashMetrics,
25436            errHandler: errHandler,
25437            timelineConverter: timelineConverter,
25438            videoModel: videoModel,
25439            playbackController: playbackController,
25440            domStorage: domStorage,
25441            abrController: abrController,
25442            mediaController: mediaController,
25443            textController: textController,
25444            sourceBufferController: sourceBufferController
25445        });
25446
25447        playbackController.setConfig({
25448            streamController: streamController,
25449            metricsModel: metricsModel,
25450            dashMetrics: dashMetrics,
25451            manifestModel: manifestModel,
25452            mediaPlayerModel: mediaPlayerModel,
25453            dashManifestModel: dashManifestModel,
25454            adapter: adapter,
25455            videoModel: videoModel
25456        });
25457
25458        abrController.setConfig({
25459            streamController: streamController,
25460            domStorage: domStorage,
25461            mediaPlayerModel: mediaPlayerModel,
25462            metricsModel: metricsModel,
25463            dashMetrics: dashMetrics,
25464            dashManifestModel: dashManifestModel,
25465            manifestModel: manifestModel,
25466            videoModel: videoModel,
25467            adapter: adapter
25468        });
25469        abrController.createAbrRulesCollection();
25470
25471        textController.setConfig({
25472            errHandler: errHandler,
25473            manifestModel: manifestModel,
25474            dashManifestModel: dashManifestModel,
25475            mediaController: mediaController,
25476            streamController: streamController,
25477            videoModel: videoModel
25478        });
25479        // initialises controller
25480        streamController.initialize(autoPlay, protectionData);
25481    }
25482
25483    function createManifestLoader() {
25484        return (0, _ManifestLoader2['default'])(context).create({
25485            errHandler: errHandler,
25486            metricsModel: metricsModel,
25487            mediaPlayerModel: mediaPlayerModel,
25488            requestModifier: (0, _utilsRequestModifier2['default'])(context).getInstance(),
25489            mssHandler: mssHandler
25490        });
25491    }
25492
25493    function detectProtection() {
25494        if (protectionController) {
25495            return protectionController;
25496        }
25497        // do not require Protection as dependencies as this is optional and intended to be loaded separately
25498        var Protection = dashjs.Protection; /* jshint ignore:line */
25499        if (typeof Protection === 'function') {
25500            //TODO need a better way to register/detect plugin components
25501            var protection = Protection(context).create();
25502            _coreEventsEvents2['default'].extend(Protection.events);
25503            _MediaPlayerEvents2['default'].extend(Protection.events, {
25504                publicOnly: true
25505            });
25506            protectionController = protection.createProtectionSystem({
25507                log: log,
25508                errHandler: errHandler,
25509                videoModel: videoModel,
25510                capabilities: capabilities,
25511                eventBus: eventBus,
25512                adapter: adapter,
25513                events: _coreEventsEvents2['default'],
25514                BASE64: _externalsBase642['default'],
25515                constants: _constantsConstants2['default']
25516            });
25517            return protectionController;
25518        }
25519
25520        return null;
25521    }
25522
25523    function detectMetricsReporting() {
25524        if (metricsReportingController) {
25525            return;
25526        }
25527        // do not require MetricsReporting as dependencies as this is optional and intended to be loaded separately
25528        var MetricsReporting = dashjs.MetricsReporting; /* jshint ignore:line */
25529        if (typeof MetricsReporting === 'function') {
25530            //TODO need a better way to register/detect plugin components
25531            var metricsReporting = MetricsReporting(context).create();
25532
25533            metricsReportingController = metricsReporting.createMetricsReporting({
25534                log: log,
25535                eventBus: eventBus,
25536                mediaElement: getVideoElement(),
25537                dashManifestModel: dashManifestModel,
25538                metricsModel: metricsModel,
25539                events: _coreEventsEvents2['default'],
25540                constants: _constantsConstants2['default'],
25541                metricsConstants: _constantsMetricsConstants2['default']
25542            });
25543        }
25544    }
25545
25546    function detectMss() {
25547        if (mssHandler) {
25548            return;
25549        }
25550        // do not require MssHandler as dependencies as this is optional and intended to be loaded separately
25551        var MssHandler = dashjs.MssHandler; /* jshint ignore:line */
25552        if (typeof MssHandler === 'function') {
25553            //TODO need a better way to register/detect plugin components
25554            mssHandler = MssHandler(context).create({
25555                eventBus: eventBus,
25556                mediaPlayerModel: mediaPlayerModel,
25557                metricsModel: metricsModel,
25558                playbackController: playbackController,
25559                protectionController: protectionController,
25560                errHandler: errHandler,
25561                events: _coreEventsEvents2['default'],
25562                constants: _constantsConstants2['default'],
25563                log: log,
25564                initSegmentType: _voMetricsHTTPRequest.HTTPRequest.INIT_SEGMENT_TYPE,
25565                BASE64: _externalsBase642['default'],
25566                ISOBoxer: _codemIsoboxer2['default']
25567            });
25568        }
25569    }
25570
25571    function getDVRInfoMetric() {
25572        var metric = metricsModel.getReadOnlyMetricsFor(_constantsConstants2['default'].VIDEO) || metricsModel.getReadOnlyMetricsFor(_constantsConstants2['default'].AUDIO);
25573        return dashMetrics.getCurrentDVRInfo(metric);
25574    }
25575
25576    function getAsUTC(valToConvert) {
25577        var metric = getDVRInfoMetric();
25578        var availableFrom = undefined,
25579            utcValue = undefined;
25580
25581        if (!metric) {
25582            return 0;
25583        }
25584        availableFrom = metric.manifestInfo.availableFrom.getTime() / 1000;
25585        utcValue = valToConvert + (availableFrom + metric.range.start);
25586        return utcValue;
25587    }
25588
25589    function getActiveStream() {
25590        if (!playbackInitialized) {
25591            throw PLAYBACK_NOT_INITIALIZED_ERROR;
25592        }
25593        var streamInfo = streamController.getActiveStreamInfo();
25594        return streamInfo ? streamController.getStreamById(streamInfo.id) : null;
25595    }
25596
25597    function initializePlayback() {
25598        if (!playbackInitialized) {
25599            createPlaybackControllers();
25600
25601            playbackInitialized = true;
25602            log('Playback Initialized');
25603
25604            if (typeof source === 'string') {
25605                streamController.load(source);
25606            } else {
25607                streamController.loadWithManifest(source);
25608            }
25609        }
25610    }
25611
25612    instance = {
25613        initialize: initialize,
25614        setConfig: setConfig,
25615        on: on,
25616        off: off,
25617        extend: extend,
25618        attachView: attachView,
25619        attachSource: attachSource,
25620        isReady: isReady,
25621        play: play,
25622        isPaused: isPaused,
25623        pause: pause,
25624        isSeeking: isSeeking,
25625        isDynamic: isDynamic,
25626        seek: seek,
25627        setPlaybackRate: setPlaybackRate,
25628        getPlaybackRate: getPlaybackRate,
25629        setMute: setMute,
25630        isMuted: isMuted,
25631        setVolume: setVolume,
25632        getVolume: getVolume,
25633        time: time,
25634        duration: duration,
25635        timeAsUTC: timeAsUTC,
25636        durationAsUTC: durationAsUTC,
25637        getActiveStream: getActiveStream,
25638        getDVRWindowSize: getDVRWindowSize,
25639        getDVRSeekOffset: getDVRSeekOffset,
25640        convertToTimeCode: convertToTimeCode,
25641        formatUTC: formatUTC,
25642        getVersion: getVersion,
25643        getDebug: getDebug,
25644        getBufferLength: getBufferLength,
25645        getVideoModel: getVideoModel,
25646        getVideoContainer: getVideoContainer,
25647        getTTMLRenderingDiv: getTTMLRenderingDiv,
25648        getVideoElement: getVideoElement,
25649        getSource: getSource,
25650        setLiveDelayFragmentCount: setLiveDelayFragmentCount,
25651        setLiveDelay: setLiveDelay,
25652        getLiveDelay: getLiveDelay,
25653        useSuggestedPresentationDelay: useSuggestedPresentationDelay,
25654        enableLastBitrateCaching: enableLastBitrateCaching,
25655        enableLastMediaSettingsCaching: enableLastMediaSettingsCaching,
25656        setMaxAllowedBitrateFor: setMaxAllowedBitrateFor,
25657        getMaxAllowedBitrateFor: getMaxAllowedBitrateFor,
25658        setMinAllowedBitrateFor: setMinAllowedBitrateFor,
25659        getMinAllowedBitrateFor: getMinAllowedBitrateFor,
25660        setMaxAllowedRepresentationRatioFor: setMaxAllowedRepresentationRatioFor,
25661        getMaxAllowedRepresentationRatioFor: getMaxAllowedRepresentationRatioFor,
25662        setAutoPlay: setAutoPlay,
25663        getAutoPlay: getAutoPlay,
25664        setScheduleWhilePaused: setScheduleWhilePaused,
25665        getScheduleWhilePaused: getScheduleWhilePaused,
25666        getDashMetrics: getDashMetrics,
25667        getMetricsFor: getMetricsFor,
25668        getQualityFor: getQualityFor,
25669        setQualityFor: setQualityFor,
25670        updatePortalSize: updatePortalSize,
25671        getLimitBitrateByPortal: getLimitBitrateByPortal,
25672        setLimitBitrateByPortal: setLimitBitrateByPortal,
25673        getUsePixelRatioInLimitBitrateByPortal: getUsePixelRatioInLimitBitrateByPortal,
25674        setUsePixelRatioInLimitBitrateByPortal: setUsePixelRatioInLimitBitrateByPortal,
25675        setTextTrack: setTextTrack,
25676        getBitrateInfoListFor: getBitrateInfoListFor,
25677        setInitialBitrateFor: setInitialBitrateFor,
25678        getInitialBitrateFor: getInitialBitrateFor,
25679        setInitialRepresentationRatioFor: setInitialRepresentationRatioFor,
25680        getInitialRepresentationRatioFor: getInitialRepresentationRatioFor,
25681        getStreamsFromManifest: getStreamsFromManifest,
25682        getTracksFor: getTracksFor,
25683        getTracksForTypeFromManifest: getTracksForTypeFromManifest,
25684        getCurrentTrackFor: getCurrentTrackFor,
25685        setInitialMediaSettingsFor: setInitialMediaSettingsFor,
25686        getInitialMediaSettingsFor: getInitialMediaSettingsFor,
25687        setCurrentTrack: setCurrentTrack,
25688        getTrackSwitchModeFor: getTrackSwitchModeFor,
25689        setTrackSwitchModeFor: setTrackSwitchModeFor,
25690        setSelectionModeForInitialTrack: setSelectionModeForInitialTrack,
25691        getSelectionModeForInitialTrack: getSelectionModeForInitialTrack,
25692        getAutoSwitchQuality: getAutoSwitchQuality,
25693        setAutoSwitchQuality: setAutoSwitchQuality,
25694        setFastSwitchEnabled: setFastSwitchEnabled,
25695        getFastSwitchEnabled: getFastSwitchEnabled,
25696        setMovingAverageMethod: setMovingAverageMethod,
25697        getMovingAverageMethod: getMovingAverageMethod,
25698        getAutoSwitchQualityFor: getAutoSwitchQualityFor,
25699        setAutoSwitchQualityFor: setAutoSwitchQualityFor,
25700        enableBufferOccupancyABR: enableBufferOccupancyABR,
25701        setABRStrategy: setABRStrategy,
25702        getABRStrategy: getABRStrategy,
25703        useDefaultABRRules: useDefaultABRRules,
25704        addABRCustomRule: addABRCustomRule,
25705        removeABRCustomRule: removeABRCustomRule,
25706        removeAllABRCustomRule: removeAllABRCustomRule,
25707        setBandwidthSafetyFactor: setBandwidthSafetyFactor,
25708        getBandwidthSafetyFactor: getBandwidthSafetyFactor,
25709        getAverageThroughput: getAverageThroughput,
25710        setAbandonLoadTimeout: setAbandonLoadTimeout,
25711        retrieveManifest: retrieveManifest,
25712        addUTCTimingSource: addUTCTimingSource,
25713        removeUTCTimingSource: removeUTCTimingSource,
25714        clearDefaultUTCTimingSources: clearDefaultUTCTimingSources,
25715        restoreDefaultUTCTimingSources: restoreDefaultUTCTimingSources,
25716        setBufferToKeep: setBufferToKeep,
25717        setBufferPruningInterval: setBufferPruningInterval,
25718        setStableBufferTime: setStableBufferTime,
25719        getStableBufferTime: getStableBufferTime,
25720        setBufferTimeAtTopQuality: setBufferTimeAtTopQuality,
25721        getBufferTimeAtTopQuality: getBufferTimeAtTopQuality,
25722        setBufferTimeAtTopQualityLongForm: setBufferTimeAtTopQualityLongForm,
25723        getBufferTimeAtTopQualityLongForm: getBufferTimeAtTopQualityLongForm,
25724        setFragmentLoaderRetryAttempts: setFragmentLoaderRetryAttempts,
25725        setFragmentLoaderRetryInterval: setFragmentLoaderRetryInterval,
25726        setManifestLoaderRetryAttempts: setManifestLoaderRetryAttempts,
25727        setManifestLoaderRetryInterval: setManifestLoaderRetryInterval,
25728        setXHRWithCredentials: setXHRWithCredentials,
25729        setXHRWithCredentialsForType: setXHRWithCredentialsForType,
25730        getXHRWithCredentialsForType: getXHRWithCredentialsForType,
25731        setLongFormContentDurationThreshold: setLongFormContentDurationThreshold,
25732        setRichBufferThreshold: setRichBufferThreshold,
25733        getProtectionController: getProtectionController,
25734        attachProtectionController: attachProtectionController,
25735        setProtectionData: setProtectionData,
25736        enableManifestDateHeaderTimeSource: enableManifestDateHeaderTimeSource,
25737        displayCaptionsOnTop: displayCaptionsOnTop,
25738        attachVideoContainer: attachVideoContainer,
25739        attachTTMLRenderingDiv: attachTTMLRenderingDiv,
25740        getCurrentTextTrackIndex: getCurrentTextTrackIndex,
25741        getUseDeadTimeLatencyForAbr: getUseDeadTimeLatencyForAbr,
25742        setUseDeadTimeLatencyForAbr: setUseDeadTimeLatencyForAbr,
25743        reset: reset
25744    };
25745
25746    setup();
25747
25748    return instance;
25749}
25750
25751MediaPlayer.__dashjs_factory_name = 'MediaPlayer';
25752var factory = _coreFactoryMaker2['default'].getClassFactory(MediaPlayer);
25753factory.events = _MediaPlayerEvents2['default'];
25754_coreFactoryMaker2['default'].updateClassFactory(MediaPlayer.__dashjs_factory_name, factory);
25755
25756exports['default'] = factory;
25757module.exports = exports['default'];
25758
25759},{"1":1,"100":100,"101":101,"102":102,"108":108,"11":11,"110":110,"112":112,"113":113,"141":141,"142":142,"143":143,"144":144,"145":145,"186":186,"188":188,"191":191,"193":193,"195":195,"200":200,"224":224,"49":49,"50":50,"51":51,"52":52,"54":54,"56":56,"58"
vendor: 12,298 bytes, lines 25759-26058
25759:58,"63":63,"79":79,"89":89,"91":91,"94":94}],94:[function(_dereq_,module,exports){
25760/**
25761 * The copyright in this software is being made available under the BSD License,
25762 * included below. This software may be subject to other third party and contributor
25763 * rights, including patent rights, and no such rights are granted under this license.
25764 *
25765 * Copyright (c) 2013, Dash Industry Forum.
25766 * All rights reserved.
25767 *
25768 * Redistribution and use in source and binary forms, with or without modification,
25769 * are permitted provided that the following conditions are met:
25770 *  * Redistributions of source code must retain the above copyright notice, this
25771 *  list of conditions and the following disclaimer.
25772 *  * Redistributions in binary form must reproduce the above copyright notice,
25773 *  this list of conditions and the following disclaimer in the documentation and/or
25774 *  other materials provided with the distribution.
25775 *  * Neither the name of Dash Industry Forum nor the names of its
25776 *  contributors may be used to endorse or promote products derived from this software
25777 *  without specific prior written permission.
25778 *
25779 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
25780 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25781 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25782 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25783 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25784 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25785 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25786 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25787 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25788 *  POSSIBILITY OF SUCH DAMAGE.
25789 */
25790'use strict';
25791
25792Object.defineProperty(exports, '__esModule', {
25793  value: true
25794});
25795
25796var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
25797
25798function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
25799
25800function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
25801
25802function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
25803
25804var _coreEventsEventsBase = _dereq_(55);
25805
25806var _coreEventsEventsBase2 = _interopRequireDefault(_coreEventsEventsBase);
25807
25808/**
25809 * @class
25810 *
25811 */
25812
25813var MediaPlayerEvents = (function (_EventsBase) {
25814  _inherits(MediaPlayerEvents, _EventsBase);
25815
25816  /**
25817   * @description Public facing external events to be used when developing a player that implements dash.js.
25818   */
25819
25820  function MediaPlayerEvents() {
25821    _classCallCheck(this, MediaPlayerEvents);
25822
25823    _get(Object.getPrototypeOf(MediaPlayerEvents.prototype), 'constructor', this).call(this);
25824    /**
25825     * Triggered when playback will not start yet
25826     * as the MPD's availabilityStartTime is in the future.
25827     * Check delay property in payload to determine time before playback will start.
25828     */
25829    this.AST_IN_FUTURE = 'astInFuture';
25830    /**
25831     * Triggered when the video element's buffer state changes to stalled.
25832     * Check mediaType in payload to determine type (Video, Audio, FragmentedText).
25833     * @event MediaPlayerEvents#BUFFER_EMPTY
25834     */
25835    this.BUFFER_EMPTY = 'bufferStalled';
25836    /**
25837     * Triggered when the video element's buffer state changes to loaded.
25838     * Check mediaType in payload to determine type (Video, Audio, FragmentedText).
25839     * @event MediaPlayerEvents#BUFFER_LOADED
25840     */
25841    this.BUFFER_LOADED = 'bufferLoaded';
25842
25843    /**
25844     * Triggered when the video element's buffer state changes, either stalled or loaded. Check payload for state.
25845     * @event MediaPlayerEvents#BUFFER_LEVEL_STATE_CHANGED
25846     */
25847    this.BUFFER_LEVEL_STATE_CHANGED = 'bufferStateChanged';
25848
25849    /**
25850     * Triggered when there is an error from the element or MSE source buffer.
25851     * @event MediaPlayerEvents#ERROR
25852     */
25853    this.ERROR = 'error';
25854
25855    /**
25856     * Triggered when a fragment download has completed.
25857     * @event MediaPlayerEvents#FRAGMENT_LOADING_COMPLETED
25858     */
25859    this.FRAGMENT_LOADING_COMPLETED = 'fragmentLoadingCompleted';
25860    /**
25861     * Triggered when a fragment download has started.
25862     * @event MediaPlayerEvents#FRAGMENT_LOADING_STARTED
25863     */
25864    this.FRAGMENT_LOADING_STARTED = 'fragmentLoadingStarted';
25865    /**
25866     * Triggered when a fragment download is abandoned due to detection of slow download base on the ABR abandon rule..
25867     * @event MediaPlayerEvents#FRAGMENT_LOADING_ABANDONED
25868     */
25869    this.FRAGMENT_LOADING_ABANDONED = 'fragmentLoadingAbandoned';
25870    /**
25871     * Triggered when {@link module:Debug} log method is called.
25872     * @event MediaPlayerEvents#LOG
25873     */
25874    this.LOG = 'log';
25875    //TODO refactor with internal event
25876    /**
25877     * Triggered when the manifest load is complete
25878     * @event MediaPlayerEvents#MANIFEST_LOADED
25879     */
25880    this.MANIFEST_LOADED = 'manifestLoaded';
25881    /**
25882     * Triggered anytime there is a change to the overall metrics.
25883     * @event MediaPlayerEvents#METRICS_CHANGED
25884     */
25885    this.METRICS_CHANGED = 'metricsChanged';
25886    /**
25887     * Triggered when an individual metric is added, updated or cleared.
25888     * @event MediaPlayerEvents#METRIC_CHANGED
25889     */
25890    this.METRIC_CHANGED = 'metricChanged';
25891    /**
25892     * Triggered every time a new metric is added.
25893     * @event MediaPlayerEvents#METRIC_ADDED
25894     */
25895    this.METRIC_ADDED = 'metricAdded';
25896    /**
25897     * Triggered every time a metric is updated.
25898     * @event MediaPlayerEvents#METRIC_UPDATED
25899     */
25900    this.METRIC_UPDATED = 'metricUpdated';
25901    /**
25902     * Triggered at the stream end of a period.
25903     * @event MediaPlayerEvents#PERIOD_SWITCH_COMPLETED
25904     */
25905    this.PERIOD_SWITCH_COMPLETED = 'periodSwitchCompleted';
25906    /**
25907     * Triggered when a new period starts.
25908     * @event MediaPlayerEvents#PERIOD_SWITCH_STARTED
25909     */
25910    this.PERIOD_SWITCH_STARTED = 'periodSwitchStarted';
25911
25912    /**
25913     * Triggered when an ABR up /down switch is initialed; either by user in manual mode or auto mode via ABR rules.
25914     * @event MediaPlayerEvents#QUALITY_CHANGE_REQUESTED
25915     */
25916    this.QUALITY_CHANGE_REQUESTED = 'qualityChangeRequested';
25917
25918    /**
25919     * Triggered when the new ABR quality is being rendered on-screen.
25920     * @event MediaPlayerEvents#QUALITY_CHANGE_RENDERED
25921     */
25922    this.QUALITY_CHANGE_RENDERED = 'qualityChangeRendered';
25923
25924    /**
25925     * Triggered when the stream is setup and ready.
25926     * @event MediaPlayerEvents#STREAM_INITIALIZED
25927     */
25928    this.STREAM_INITIALIZED = 'streamInitialized';
25929
25930    /**
25931     * Triggered when the player has been reset.
25932     * @event MediaPlayerEvents#STREAM_TEARDOWN_COMPLETE
25933     */
25934    this.STREAM_TEARDOWN_COMPLETE = 'streamTeardownComplete';
25935
25936    /**
25937     * Triggered once all text tracks detected in the MPD are added to the video element.
25938     * @event MediaPlayerEvents#TEXT_TRACKS_ADDED
25939     */
25940    this.TEXT_TRACKS_ADDED = 'allTextTracksAdded';
25941    /**
25942     * Triggered when a text track is added to the video element's TextTrackList
25943     * @event MediaPlayerEvents#TEXT_TRACK_ADDED
25944     */
25945    this.TEXT_TRACK_ADDED = 'textTrackAdded';
25946
25947    /**
25948     * Sent when enough data is available that the media can be played,
25949     * at least for a couple of frames.  This corresponds to the
25950     * HAVE_ENOUGH_DATA readyState.
25951     * @event MediaPlayerEvents#CAN_PLAY
25952     */
25953    this.CAN_PLAY = 'canPlay';
25954
25955    /**
25956     * Sent when playback completes.
25957     * @event MediaPlayerEvents#PLAYBACK_ENDED
25958     */
25959    this.PLAYBACK_ENDED = 'playbackEnded';
25960
25961    /**
25962     * Sent when an error occurs.  The element's error
25963     * attribute contains more information.
25964     * @event MediaPlayerEvents#PLAYBACK_ERROR
25965     */
25966    this.PLAYBACK_ERROR = 'playbackError';
25967    /**
25968     * Sent when playback is not allowed (for example if user gesture is needed).
25969     * @event MediaPlayerEvents#PLAYBACK_NOT_ALLOWED
25970     */
25971    this.PLAYBACK_NOT_ALLOWED = 'playbackNotAllowed';
25972    /**
25973     * The media's metadata has finished loading; all attributes now
25974     * contain as much useful information as they're going to.
25975     * @event MediaPlayerEvents#PLAYBACK_METADATA_LOADED
25976     */
25977    this.PLAYBACK_METADATA_LOADED = 'playbackMetaDataLoaded';
25978    /**
25979     * Sent when playback is paused.
25980     * @event MediaPlayerEvents#PLAYBACK_PAUSED
25981     */
25982    this.PLAYBACK_PAUSED = 'playbackPaused';
25983    /**
25984     * Sent when the media begins to play (either for the first time, after having been paused,
25985     * or after ending and then restarting).
25986     *
25987     * @event MediaPlayerEvents#PLAYBACK_PLAYING
25988     */
25989    this.PLAYBACK_PLAYING = 'playbackPlaying';
25990    /**
25991     * Sent periodically to inform interested parties of progress downloading
25992     * the media. Information about the current amount of the media that has
25993     * been downloaded is available in the media element's buffered attribute.
25994     * @event MediaPlayerEvents#PLAYBACK_PROGRESS
25995     */
25996    this.PLAYBACK_PROGRESS = 'playbackProgress';
25997    /**
25998     * Sent when the playback speed changes.
25999     * @event MediaPlayerEvents#PLAYBACK_RATE_CHANGED
26000     */
26001    this.PLAYBACK_RATE_CHANGED = 'playbackRateChanged';
26002    /**
26003     * Sent when a seek operation completes.
26004     * @event MediaPlayerEvents#PLAYBACK_SEEKED
26005     */
26006    this.PLAYBACK_SEEKED = 'playbackSeeked';
26007    /**
26008     * Sent when a seek operation begins.
26009     * @event MediaPlayerEvents#PLAYBACK_SEEKING
26010     */
26011    this.PLAYBACK_SEEKING = 'playbackSeeking';
26012
26013    /**
26014     * Sent when a seek operation has been asked.
26015     * @event MediaPlayerEvents#PLAYBACK_SEEK_ASKED
26016     */
26017    this.PLAYBACK_SEEK_ASKED = 'playbackSeekAsked';
26018
26019    /**
26020     * Sent when playback of the media starts after having been paused;
26021     * that is, when playback is resumed after a prior pause event.
26022     *
26023     * @event MediaPlayerEvents#PLAYBACK_STARTED
26024     */
26025    this.PLAYBACK_STARTED = 'playbackStarted';
26026    /**
26027     * The time indicated by the element's currentTime attribute has changed.
26028     * @event MediaPlayerEvents#PLAYBACK_TIME_UPDATED
26029     */
26030    this.PLAYBACK_TIME_UPDATED = 'playbackTimeUpdated';
26031  }
26032
26033  return MediaPlayerEvents;
26034})(_coreEventsEventsBase2['default']);
26035
26036var mediaPlayerEvents = new MediaPlayerEvents();
26037exports['default'] = mediaPlayerEvents;
26038module.exports = exports['default'];
26039
26040},{"55":55}],95:[function(_dereq_,module,exports){
26041'use strict';
26042
26043Object.defineProperty(exports, '__esModule', {
26044    value: true
26045});
26046
26047function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
26048
26049var _MediaPlayer = _dereq_(93);
26050
26051var _MediaPlayer2 = _interopRequireDefault(_MediaPlayer);
26052
26053function MediaPlayerFactory() {
26054
26055    /**
26056     * mime-type identifier for any source content to be accepted as a dash manifest by the create() method.
26057     * @type {string}
26058     */
26059    var SUPPORTED_MIME_TYPE = 'application/dash+xml';
26060
26061    /**
26062     *  A new MediaPlayer is instantiated for the supplied videoElement and optional source and context.  If no context is provided,
26063     *  a default DashContext is used. If no source is provided, the videoElement is interrogated to extract the first source whose
26064     *  type is application/dash+xml.
26065     * The autoplay property of the videoElement is preserved. Any preload attribute is ignored. This method should be called after the page onLoad event is dispatched.
26066     * @param {HTMLMediaElement} video
26067     * @param {HTMLSourceElement} source
26068     * @param {Object} context
26069     * @returns {MediaPlayer|null}
26070     */
26071    function create(video, source, context) {
26072        if (!video || video.nodeName !== 'VIDEO') return null;
26073
26074        if (video._dashjs_player) return video._dashjs_player;
26075
26076        var player = undefined;
26077        var videoID = video.id || video.name || 'video element';
26078
26079        source = source || [].slice.call(video.querySelectorAll('source')).filter(function (s) {
26080            return s.type == SUPPORTED_MIME_TYPE;
26081        })[0];
26082        if (!source && video.src) {
26083            source = document.createElement('source');
26084            source.src = video.src;
26085        } else if (!source && !video.src) {
26086            return null;
26087        }
26088
26089        context = context || {};
26090        player = (0, _MediaPlayer2['default'])(context).create();
26091        player.initialize(video, source.src, video.autoplay);
26092        player.getDebug().log('Converted ' + videoID + ' to dash.js player and added content: ' + source.src);
26093
26094        // Store a reference to the player on the video element so it can be gotten at for debugging and so we know its
26095        // already been setup.
26096        video._dashjs_player = player;
26097
26098        return player;
26099    }
26100
26101    /**
26102     * Searches the provided scope for all instances of the indicated selector. If no scope is provided, document is used. If no selector is
26103     * specified, [data-dashjs-player] is used. The declarative setup also looks for source elements with the type attribute set to 'application/dash+xml'.
26104     * It then looks for those video elements which have a source element defined with a type matching 'application/dash+xml'.
26105     * A new MediaPlayer is instantiated for each matching video element and the appropriate source is assigned.
26106     * The autoplay property of the video element is preserved. Any preload attribute is ignored. This method should be called after the page onLoad event is dispatched.
26107     * Returns an array holding all the MediaPlayer instances that were added by this method.
26108     * @param {string} selector - CSS selector
26109     * @param {Object} scope
26110     * @returns {Array} an array of MediaPlayer objects
26111     */
26112    function createAll(selector, scope) {
26113        var aPlayers = [];
26114        selector = selector || '[data-dashjs-player]';
26115        scope = scope || document;
26116        var videos = scope.querySelectorAll(selector);
26117        for (var i = 0; i < videos.length; i++) {
26118            var player = create(videos[i], null);
26119            aPlayers.push(player);
26120        }
26121
26122        var sources = scope.querySelectorAll('source[type="' + SUPPORTED_MIME_TYPE + '"]');
26123        for (var i = 0; i < sources.length; i++) {
26124            var video = findVideo(sources[i]);
26125            var player = create(video, null);
26126            aPlayers.push(player);
26127        }
26128
26129        return aPlayers;
26130    }
26131
26132    function findVideo(_x) {
26133        var _again = true;
26134
26135        _function: while (_again) {
26136            var el = _x;
26137            _again = false;
26138
26139            if (el.nodeName.toLowerCase() === 'video') {
26140                return el;
26141            } else {
26142                _x = el.parentNode;
26143                _again = true;
26144                continue _function;
26145            }
26146        }
26147    }
26148
26149    return {
26150        create: create,
26151        createAll: createAll
26152    };
26153}
26154
26155var instance = MediaPlayerFactory();
26156var loadInterval = undefined;
26157
26158function loadHandler() {
26159    window.removeEventListener('load', loadHandler);
26160    instance.createAll();
26161}
26162
26163function loadIntervalHandler() {
26164    if (window.dashjs) {
26165        window.clearInterval(loadInterval);
26166        instance.createAll();
26167    }
26168}
26169
26170var avoidAutoCreate = typeof window !== 'undefined' && window && window.dashjs && window.dashjs.skipAutoCreate;
26171
26172if (!avoidAutoCreate && typeof window !== 'undefined' && window && window.addEventListener) {
26173    if (window.document.readyState === 'complete') {
26174        if (window.dashjs) {
26175            instance.createAll();
26176        } else {
26177            // If loaded asynchronously, window.readyState may be 'complete' even if dashjs hasn't loaded yet
26178            loadInterval = window.setInterval(loadIntervalHandler, 500);
26179        }
26180    } else {
26181        window.addEventListener('load', loadHandler);
26182    }
26183}
26184
26185exports['default'] = instance;
26186module.exports = exports['default'];
26187
26188},{"93":93}],96:[function(_dereq_,module,exports){
26189/**
26190 * The copyright in this software is being made available under the BSD License,
26191 * included below. This software may be subject to other third party and contributor
26192 * rights, including patent rights, and no such rights are granted under this license.
26193 *
26194 * Copyright (c) 2013, Dash Industry Forum.
26195 * All rights reserved.
26196 *
26197 * Redistribution and use in source and binary forms, with or without modification,
26198 * are permitted provided that the following conditions are met:
26199 *  * Redistributions of source code must retain the above copyright notice, this
26200 *  list of conditions and the following disclaimer.
26201 *  * Redistributions in binary form must reproduce the above copyright notice,
26202 *  this list of conditions and the following disclaimer in the documentation and/or
26203 *  other materials provided with the distribution.
26204 *  * Neither the name of Dash Industry Forum nor the names of its
26205 *  contributors may be used to endorse or promote products derived from this software
26206 *  without specific prior written permission.
26207 *
26208 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
26209 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26210 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26211 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
26212 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
26212INCLUDING, BUT
26213 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26214 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26215 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26216 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26217 *  POSSIBILITY OF SUCH DAMAGE.
26218 */
26219'use strict';
26220
26221Object.defineProperty(exports, '__esModule', {
26222    value: true
26223});
26224
26225function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
26226
26227var _constantsConstants = _dereq_(100);
26228
26229var _constantsConstants2 = _interopRequireDefault(_constantsConstants);
26230
26231var _StreamProcessor = _dereq_(97);
26232
26233var _StreamProcessor2 = _interopRequireDefault(_StreamProcessor);
26234
26235var _controllersEventController = _dereq_(106);
26236
26237var _controllersEventController2 = _interopRequireDefault(_controllersEventController);
26238
26239var _controllersFragmentController = _dereq_(107);
26240
26241var _controllersFragmentController2 = _interopRequireDefault(_controllersFragmentController);
26242
26243var _coreEventBus = _dereq_(50);
26244
26245var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
26246
26247var _coreEventsEvents = _dereq_(54);
26248
26249var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
26250
26251var _coreDebug = _dereq_(49);
26252
26253var _coreDebug2 = _interopRequireDefault(_coreDebug);
26254
26255var _coreFactoryMaker = _dereq_(51);
26256
26257var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
26258
26259function Stream(config) {
26260
26261    var DATA_UPDATE_FAILED_ERROR_CODE = 1;
26262
26263    var context = this.context;
26264    var log = (0, _coreDebug2['default'])(context).getInstance().log;
26265    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
26266
26267    var manifestModel = config.manifestModel;
26268    var dashManifestModel = config.dashManifestModel;
26269    var mediaPlayerModel = config.mediaPlayerModel;
26270    var manifestUpdater = config.manifestUpdater;
26271    var adapter = config.adapter;
26272    var capabilities = config.capabilities;
26273    var errHandler = config.errHandler;
26274    var timelineConverter = config.timelineConverter;
26275    var metricsModel = config.metricsModel;
26276    var abrController = config.abrController;
26277    var playbackController = config.playbackController;
26278    var mediaController = config.mediaController;
26279    var textController = config.textController;
26280
26281    var instance = undefined,
26282        streamProcessors = undefined,
26283        isStreamActivated = undefined,
26284        isMediaInitialized = undefined,
26285        streamInfo = undefined,
26286        updateError = undefined,
26287        isUpdating = undefined,
26288        protectionController = undefined,
26289        fragmentController = undefined,
26290        eventController = undefined,
26291        trackChangedEvent = undefined;
26292
26293    function setup() {
26294        resetInitialSettings();
26295
26296        fragmentController = (0, _controllersFragmentController2['default'])(context).create({
26297            mediaPlayerModel: mediaPlayerModel,
26298            metricsModel: metricsModel,
26299            errHandler: errHandler
26300        });
26301
26302        eventBus.on(_coreEventsEvents2['default'].BUFFERING_COMPLETED, onBufferingCompleted, instance);
26303        eventBus.on(_coreEventsEvents2['default'].DATA_UPDATE_COMPLETED, onDataUpdateCompleted, instance);
26304    }
26305
26306    function initialize(StreamInfo, ProtectionController) {
26307        streamInfo = StreamInfo;
26308        protectionController = ProtectionController;
26309        if (protectionController) {
26310            eventBus.on(_coreEventsEvents2['default'].KEY_ERROR, onProtectionError, instance);
26311            eventBus.on(_coreEventsEvents2['default'].SERVER_CERTIFICATE_UPDATED, onProtectionError, instance);
26312            eventBus.on(_coreEventsEvents2['default'].LICENSE_REQUEST_COMPLETE, onProtectionError, instance);
26313            eventBus.on(_coreEventsEvents2['default'].KEY_SYSTEM_SELECTED, onProtectionError, instance);
26314            eventBus.on(_coreEventsEvents2['default'].KEY_SESSION_CREATED, onProtectionError, instance);
26315        }
26316    }
26317
26318    /**
26319     * Activates Stream by re-initializing some of its components
26320     * @param {MediaSource} mediaSource
26321     * @memberof Stream#
26322     */
26323    function activate(mediaSource) {
26324        if (!isStreamActivated) {
26325            eventBus.on(_coreEventsEvents2['default'].CURRENT_TRACK_CHANGED, onCurrentTrackChanged, instance);
26326            initializeMedia(mediaSource);
26327            isStreamActivated = true;
26328        }
26329        //else { // TODO Check track change mode but why is this here. commented it out for now to check.
26330        //    createBuffers();
26331        //}
26332    }
26333
26334    /**
26335     * Partially resets some of the Stream elements
26336     * @memberof Stream#
26337     */
26338    function deactivate() {
26339        var ln = streamProcessors ? streamProcessors.length : 0;
26340        for (var i = 0; i < ln; i++) {
26341            streamProcessors[i].reset();
26342        }
26343        streamProcessors = [];
26344        isStreamActivated = false;
26345        isMediaInitialized = false;
26346        clearEventController();
26347        eventBus.off(_coreEventsEvents2['default'].CURRENT_TRACK_CHANGED, onCurrentTrackChanged, instance);
26348    }
26349
26350    function resetInitialSettings() {
26351        deactivate();
26352        streamInfo = null;
26353        updateError = {};
26354        isUpdating = false;
26355    }
26356
26357    function reset() {
26358
26359        if (playbackController) {
26360            playbackController.pause();
26361        }
26362
26363        if (fragmentController) {
26364            fragmentController.reset();
26365            fragmentController = null;
26366        }
26367
26368        resetInitialSettings();
26369
26370        log = null;
26371
26372        eventBus.off(_coreEventsEvents2['default'].DATA_UPDATE_COMPLETED, onDataUpdateCompleted, instance);
26373        eventBus.off(_coreEventsEvents2['default'].BUFFERING_COMPLETED, onBufferingCompleted, instance);
26374        eventBus.off(_coreEventsEvents2['default'].KEY_ERROR, onProtectionError, instance);
26375        eventBus.off(_coreEventsEvents2['default'].SERVER_CERTIFICATE_UPDATED, onProtectionError, instance);
26376        eventBus.off(_coreEventsEvents2['default'].LICENSE_REQUEST_COMPLETE, onProtectionError, instance);
26377        eventBus.off(_coreEventsEvents2['default'].KEY_SYSTEM_SELECTED, onProtectionError, instance);
26378        eventBus.off(_coreEventsEvents2['default'].KEY_SESSION_CREATED, onProtectionError, instance);
26379    }
26380
26381    function getDuration() {
26382        return streamInfo ? streamInfo.duration : NaN;
26383    }
26384
26385    function getStartTime() {
26386        return streamInfo ? streamInfo.start : NaN;
26387    }
26388
26389    function getId() {
26390        return streamInfo ? streamInfo.id : NaN;
26391    }
26392
26393    function getStreamInfo() {
26394        return streamInfo;
26395    }
26396
26397    function getEventController() {
26398        return eventController;
26399    }
26400
26401    function getFragmentController() {
26402        return fragmentController;
26403    }
26404
26405    function checkConfig() {
26406        if (!abrController || !abrController.hasOwnProperty('getBitrateList') || !adapter || !adapter.hasOwnProperty('getAllMediaInfoForType') || !adapter.hasOwnProperty('getEventsFor')) {
26407            throw new Error('Missing config parameter(s)');
26408        }
26409    }
26410
26411    /**
26412     * @param {string} type
26413     * @returns {Array}
26414     * @memberof Stream#
26415     */
26416    function getBitrateListFor(type) {
26417        checkConfig();
26418        var mediaInfo = getMediaInfo(type);
26419        return abrController.getBitrateList(mediaInfo);
26420    }
26421
26422    function startEventController() {
26423        if (eventController) {
26424            eventController.start();
26425        }
26426    }
26427
26428    function clearEventController() {
26429        if (eventController) {
26430            eventController.clear();
26431        }
26432    }
26433
26434    function onProtectionError(event) {
26435        if (event.error) {
26436            errHandler.mediaKeySessionError(event.error);
26437            log(event.error);
26438            reset();
26439        }
26440    }
26441
26442    function getMimeTypeOrType(mediaInfo) {
26443        return mediaInfo.type === _constantsConstants2['default'].TEXT ? mediaInfo.mimeType : mediaInfo.type;
26444    }
26445
26446    function isMediaSupported(mediaInfo) {
26447        var type = mediaInfo.type;
26448        var codec = undefined,
26449            msg = undefined;
26450
26451        if (type === _constantsConstants2['default'].MUXED && mediaInfo) {
26452            msg = 'Multiplexed representations are intentionally not supported, as they are not compliant with the DASH-AVC/264 guidelines';
26453            log(msg);
26454            errHandler.manifestError(msg, 'multiplexedrep', manifestModel.getValue());
26455            return false;
26456        }
26457
26458        if (type === _constantsConstants2['default'].TEXT || type === _constantsConstants2['default'].FRAGMENTED_TEXT || type === _constantsConstants2['default'].EMBEDDED_TEXT) {
26459            return true;
26460        }
26461        codec = mediaInfo.codec;
26462        log(type + ' codec: ' + codec);
26463
26464        if (!!mediaInfo.contentProtection && !capabilities.supportsEncryptedMedia()) {
26465            errHandler.capabilityError('encryptedmedia');
26466        } else if (!capabilities.supportsCodec(codec)) {
26467            msg = type + 'Codec (' + codec + ') is not supported.';
26468            errHandler.manifestError(msg, 'codec', manifestModel.getValue());
26469            log(msg);
26470            return false;
26471        }
26472
26473        return true;
26474    }
26475
26476    function onCurrentTrackChanged(e) {
26477        if (e.newMediaInfo.streamInfo.id !== streamInfo.id) return;
26478
26479        var processor = getProcessorForMediaInfo(e.oldMediaInfo);
26480        if (!processor) return;
26481
26482        var currentTime = playbackController.getTime();
26483        log('Stream -  Process track changed at current time ' + currentTime);
26484        var mediaInfo = e.newMediaInfo;
26485        var manifest = manifestModel.getValue();
26486
26487        log('Stream -  Update stream controller');
26488        if (manifest.refreshManifestOnSwitchTrack) {
26489            log('Stream -  Refreshing manifest for switch track');
26490            trackChangedEvent = e;
26491            manifestUpdater.refreshManifest();
26492        } else {
26493            processor.updateMediaInfo(mediaInfo);
26494            if (mediaInfo.type !== _constantsConstants2['default'].FRAGMENTED_TEXT) {
26495                processor.switchTrackAsked();
26496            }
26497        }
26498    }
26499
26500    function createStreamProcessor(mediaInfo, mediaSource, optionalSettings) {
26501        var streamProcessor = (0, _StreamProcessor2['default'])(context).create({
26502            type: getMimeTypeOrType(mediaInfo),
26503            mimeType: mediaInfo.mimeType,
26504            timelineConverter: timelineConverter,
26505            adapter: adapter,
26506            manifestModel: manifestModel,
26507            dashManifestModel: dashManifestModel,
26508            mediaPlayerModel: mediaPlayerModel,
26509            metricsModel: metricsModel,
26510            dashMetrics: config.dashMetrics,
26511            baseURLController: config.baseURLController,
26512            stream: instance,
26513            abrController: abrController,
26514            domStorage: config.domStorage,
26515            playbackController: playbackController,
26516            mediaController: mediaController,
26517            streamController: config.streamController,
26518            textController: textController,
26519            sourceBufferController: config.sourceBufferController,
26520            errHandler: errHandler
26521        });
26522
26523        var allMediaForType = adapter.getAllMediaInfoForType(streamInfo, mediaInfo.type);
26524        streamProcessor.initialize(mediaSource);
26525        abrController.updateTopQualityIndex(mediaInfo);
26526
26527        if (optionalSettings) {
26528            streamProcessor.setBuffer(optionalSettings.buffer);
26529            streamProcessor.getIndexHandler().setCurrentTime(optionalSettings.currentTime);
26530            streamProcessors[optionalSettings.replaceIdx] = streamProcessor;
26531        } else {
26532            streamProcessors.push(streamProcessor);
26533        }
26534
26535        if (optionalSettings && optionalSettings.ignoreMediaInfo) {
26536            return;
26537        }
26538
26539        if (mediaInfo.type === _constantsConstants2['default'].TEXT || mediaInfo.type === _constantsConstants2['default'].FRAGMENTED_TEXT) {
26540            var idx = undefined;
26541            for (var i = 0; i < allMediaForType.length; i++) {
26542                if (allMediaForType[i].index === mediaInfo.index) {
26543                    idx = i;
26544                }
26545                streamProcessor.updateMediaInfo(allMediaForType[i]); //creates text tracks for all adaptations in one stream processor
26546            }
26547            if (mediaInfo.type === _constantsConstants2['default'].FRAGMENTED_TEXT) {
26548                streamProcessor.updateMediaInfo(allMediaForType[idx]); //sets the initial media info
26549            }
26550        } else {
26551                streamProcessor.updateMediaInfo(mediaInfo);
26552            }
26553    }
26554
26555    function initializeMediaForType(type, mediaSource) {
26556        var allMediaForType = adapter.getAllMediaInfoForType(streamInfo, type);
26557
26558        var mediaInfo = null;
26559        var initialMediaInfo = undefined;
26560
26561        if (!allMediaForType || allMediaForType.length === 0) {
26562            log('No ' + type + ' data.');
26563            return;
26564        }
26565
26566        for (var i = 0, ln = allMediaForType.length; i < ln; i++) {
26567            mediaInfo = allMediaForType[i];
26568
26569            if (type === _constantsConstants2['default'].EMBEDDED_TEXT) {
26570                textController.addEmbeddedTrack(mediaInfo);
26571            } else {
26572                if (!isMediaSupported(mediaInfo)) {
26573                    continue;
26574                }
26575                if (mediaController.isMultiTrackSupportedByType(mediaInfo.type)) {
26576                    mediaController.addTrack(mediaInfo, streamInfo);
26577                }
26578            }
26579        }
26580
26581        if (type === _constantsConstants2['default'].EMBEDDED_TEXT || mediaController.getTracksFor(type, streamInfo).length === 0) {
26582            return;
26583        }
26584
26585        mediaController.checkInitialMediaSettingsForType(type, streamInfo);
26586        initialMediaInfo = mediaController.getCurrentTrackFor(type, streamInfo);
26587
26588        // TODO : How to tell index handler live/duration?
26589        // TODO : Pass to controller and then pass to each method on handler?
26590
26591        createStreamProcessor(initialMediaInfo, mediaSource);
26592    }
26593
26594    function initializeMedia(mediaSource) {
26595        checkConfig();
26596        var events = undefined;
26597
26598        eventController = (0, _controllersEventController2['default'])(context).create();
26599
26600        eventController.setConfig({
26601            manifestModel: manifestModel,
26602            manifestUpdater: manifestUpdater,
26603            playbackController: playbackController
26604        });
26605        events = adapter.getEventsFor(streamInfo);
26606        eventController.addInlineEvents(events);
26607
26608        isUpdating = true;
26609
26610        filterCodecs(_constantsConstants2['default'].VIDEO);
26611        filterCodecs(_constantsConstants2['default'].AUDIO);
26612
26613        initializeMediaForType(_constantsConstants2['default'].VIDEO, mediaSource);
26614        initializeMediaForType(_constantsConstants2['default'].AUDIO, mediaSource);
26615        initializeMediaForType(_constantsConstants2['default'].TEXT, mediaSource);
26616        initializeMediaForType(_constantsConstants2['default'].FRAGMENTED_TEXT, mediaSource);
26617        initializeMediaForType(_constantsConstants2['default'].EMBEDDED_TEXT, mediaSource);
26618        initializeMediaForType(_constantsConstants2['default'].MUXED, mediaSource);
26619
26620        createBuffers();
26621
26622        //TODO. Consider initialization of TextSourceBuffer here if embeddedText, but no sideloadedText.
26623
26624        isMediaInitialized = true;
26625        isUpdating = false;
26626
26627        if (streamProcessors.length === 0) {
26628            var msg = 'No streams to play.';
26629            errHandler.manifestError(msg, 'nostreams', manifestModel.getValue());
26630            log(msg);
26631        } else {
26632            //log("Playback initialized!");
26633            checkIfInitializationCompleted();
26634        }
26635    }
26636
26637    function filterCodecs(type) {
26638        var realAdaptation = dashManifestModel.getAdaptationForType(manifestModel.getValue(), streamInfo.index, type, streamInfo);
26639
26640        if (!realAdaptation || !Array.isArray(realAdaptation.Representation_asArray)) return null;
26641
26642        // Filter codecs that are not supported
26643        realAdaptation.Representation_asArray.filter(function (_, i) {
26644            // keep at least codec from lowest representation
26645            if (i === 0) return true;
26646
26647            var codec = dashManifestModel.getCodec(realAdaptation, i);
26648            if (!capabilities.supportsCodec(codec)) {
26649                log('[Stream] codec not supported: ' + codec);
26650                return false;
26651            }
26652            return true;
26653        });
26654    }
26655
26656    function checkIfInitializationCompleted() {
26657        var ln = streamProcessors.length;
26658        var hasError = !!updateError.audio || !!updateError.video;
26659        var error = hasError ? new Error(DATA_UPDATE_FAILED_ERROR_CODE, 'Data update failed', null) : null;
26660
26661        for (var i = 0; i < ln; i++) {
26662            if (streamProcessors[i].isUpdating() || isUpdating) {
26663                return;
26664            }
26665        }
26666
26667        if (!isMediaInitialized) {
26668            return;
26669        }
26670        if (protectionController) {
26671            protectionController.initialize(manifestModel.getValue(), getMediaInfo(_constantsConstants2['default'].AUDIO), getMediaInfo(_constantsConstants2['default'].VIDEO));
26672        }
26673        eventBus.trigger(_coreEventsEvents2['default'].STREAM_INITIALIZED, {
26674            streamInfo: streamInfo,
26675            error: error
26676        });
26677    }
26678
26679    function getMediaInfo(type) {
26680        var ln = streamProcessors.length;
26681        var mediaCtrl = null;
26682
26683        for (var i = 0; i < ln; i++) {
26684            mediaCtrl = streamProcessors[i];
26685
26686            if (mediaCtrl.getType() === type) {
26687                return mediaCtrl.getMediaInfo();
26688            }
26689        }
26690
26691        return null;
26692    }
26693
26694    function createBuffers() {
26695        for (var i = 0, ln = streamProcessors.length; i < ln; i++) {
26696            streamProcessors[i].createBuffer();
26697        }
26698    }
26699
26700    function onBufferingCompleted(e) {
26701        if (e.streamInfo !== streamInfo) {
26702            return;
26703        }
26704
26705        var processors = getProcessors();
26706        var ln = processors.length;
26707
26708        // if there is at least one buffer controller that has not completed buffering yet do nothing
26709        for (var i = 0; i < ln; i++) {
26710            if (!processors[i].isBufferingCompleted()) {
26711                return;
26712            }
26713        }
26714
26715        eventBus.trigger(_coreEventsEvents2['default'].STREAM_BUFFERING_COMPLETED, {
26716            streamInfo: streamInfo
26717        });
26718    }
26719
26720    function onDataUpdateCompleted(e) {
26721        var sp = e.sender.getStreamProcessor();
26722
26723        if (sp.getStreamInfo() !== streamInfo) {
26724            return;
26725        }
26726
26727        updateError[sp.getType()] = e.error;
26728        checkIfInitializationCompleted();
26729    }
26730
26731    function getProcessorForMediaInfo(mediaInfo) {
26732        if (!mediaInfo) {
26733            return false;
26734        }
26735
26736        var processors = getProcessors();
26737
26738        return processors.filter(function (processor) {
26739            return processor.getType() === mediaInfo.type;
26740        })[0];
26741    }
26742
26743    function getProcessors() {
26744        var ln = streamProcessors.length;
26745        var arr = [];
26746
26747        var type = undefined,
26748            controller = undefined;
26749
26750        for (var i = 0; i < ln; i++) {
26751            controller = streamProcessors[i];
26752            type = controller.getType();
26753
26754            if (type === _constantsConstants2['default'].AUDIO || type === _constantsConstants2['default'].VIDEO || type === _constantsConstants2['default'].FRAGMENTED_TEXT) {
26755                arr.push(controller);
26756            }
26757        }
26758
26759        return arr;
26760    }
26761
26762    function updateData(updatedStreamInfo) {
26763
26764        log('Manifest updated... updating data system wide.');
26765
26766        isStreamActivated = false;
26767        isUpdating = true;
26768        streamInfo = updatedStreamInfo;
26769
26770        if (eventController) {
26771            var events = adapter.getEventsFor(streamInfo);
26772            eventController.addInlineEvents(events);
26773        }
26774
26775        filterCodecs(_constantsConstants2['default'].VIDEO);
26776        filterCodecs(_constantsConstants2['default'].AUDIO);
26777
26778        for (var i = 0, ln = streamProcessors.length; i < ln; i++) {
26779            var streamProcessor = streamProcessors[i];
26780            var mediaInfo = adapter.getMediaInfoForType(streamInfo, streamProcessor.getType());
26781            abrController.updateTopQualityIndex(mediaInfo);
26782            streamProcessor.updateMediaInfo(mediaInfo);
26783        }
26784
26785        if (trackChangedEvent) {
26786            var mediaInfo = trackChangedEvent.newMediaInfo;
26787            if (mediaInfo.type !== 'fragmentedText') {
26788                var processor = getProcessorForMediaInfo(trackChangedEvent.oldMediaInfo);
26789                if (!processor) return;
26790                processor.switchTrackAsked();
26791                trackChangedEvent = undefined;
26792            }
26793        }
26794
26795        isUpdating = false;
26796        checkIfInitializationCompleted();
26797    }
26798
26799    instance = {
26800        initialize: initialize,
26801        activate: activate,
26802        deactivate: deactivate,
26803        getDuration: getDuration,
26804        getStartTime: getStartTime,
26805        getId: getId,
26806        getStreamInfo: getStreamInfo,
26807        getFragmentController: getFragmentController,
26808        getEventController: getEventController,
26809        getBitrateListFor: getBitrateListFor,
26810        startEventController: startEventController,
26811        updateData: updateData,
26812        reset: reset,
26813        getProcessors: getProcessors
26814    };
26815
26816    setup();
26817    return instance;
26818}
26819
26820Stream.__dashjs_factory_name = 'Stream';
26821exports['default'] = _coreFactoryMaker2['default'].getClassFactory(Stream);
26822module.exports = exports['default'];
26823
26824},{"100":100,"106":106,"107":107,"49":49,"50":50,"51":51,"54":54,"97":97}],97:[function(_dereq_,module,exports){
26825/**
26826 * The copyright in this software is being made available under the BSD License,
26827 * included below. This software may be subject to other third party and contributor
26828 * rights, including patent rights, and no such rights are granted under this license.
26829 *
26830 * Copyright (c) 2013, Dash Industry Forum.
26831 * All rights reserved.
26832 *
26833 * Redistribution and use in source and binary forms, with or without modification,
26834 * are permitted provided that the following conditions are met:
26835 *  * Redistributions of source code must retain the above copyright notice, this
26836 *  list of conditions and the following disclaimer.
26837 *  * Redistributions in binary form must reproduce the above copyright notice,
26838 *  this list of conditions and the following disclaimer in the documentation and/or
26839 *  other materials provided with the distribution.
26840 *  * Neither the name of Dash Industry Forum nor the names of its
26841 *  contributors may be used to endorse or promote products derived from this software
26842 *  without specific prior written permission.
26843 *
26844 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
26845 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26846 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26847 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
26848 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26849 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26850 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26851 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26852 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26853 *  POSSIBILITY OF SUCH DAMAGE.
26854 */
26855'use strict';
26856
26857Object.defineProperty(exports, '__esModule', {
26858    value: true
26859});
26860
26861function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
26862
26863var _constantsConstants = _dereq_(100);
26864
26865var _constantsConstants2 = _interopRequireDefault(_constantsConstants);
26866
26867var _utilsLiveEdgeFinder = _dereq_(198);
26868
26869var _utilsLiveEdgeFinder2 = _interopRequireDefault(_utilsLiveEdgeFinder);
26870
26871var _controllersBufferController = _dereq_(105);
26872
26873var _controllersBufferController2 = _interopRequireDefault(_controllersBufferController);
26874
26875var _textTextBufferController = _dereq_(185);
26876
26877var _textTextBufferController2 = _interopRequireDefault(_textTextBufferController);
26878
26879var _controllersScheduleController = _dereq_(111);
26880
26881var _controllersScheduleController2 = _interopRequireDefault(_controllersScheduleController);
26882
26883var _dashControllersRepresentationController = _dereq_(62);
26884
26885var _dashControllersRepresentationController2 = _interopRequireDefault(_dashControllersRepresentationController);
26886
26887var _coreFactoryMaker = _dereq_(51);
26888
26889var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
26890
26891var _dashDashHandler = _dereq_(57);
26892
26893var _dashDashHandler2 = _interopRequireDefault(_dashDashHandler);
26894
26895function StreamProcessor(config) {
26896
26897    var context = this.context;
26898
26899    var indexHandler = undefined;
26900    var type = config.type;
26901    var errHandler = config.errHandler;
26902    var mimeType = config.mimeType;
26903    var timelineConverter = config.timelineConverter;
26904    var adapter = config.adapter;
26905    var manifestModel = config.manifestModel;
26906    var mediaPlayerModel = config.mediaPlayerModel;
26907    var stream = config.stream;
26908    var abrController = config.abrController;
26909    var playbackController = config.playbackController;
26910    var streamController = config.streamController;
26911    var mediaController = config.mediaController;
26912    var textController = config.textController;
26913    var sourceBufferController = config.sourceBufferController;
26914    var domStorage = config.domStorage;
26915    var metricsModel = config.metricsModel;
26916    var dashMetrics = config.dashMetrics;
26917    var dashManifestModel = config.dashManifestModel;
26918
26919    var instance = undefined,
26920        mediaInfo = undefined,
26921        mediaInfoArr = undefined,
26922        bufferController = undefined,
26923        scheduleController = undefined,
26924        liveEdgeFinder = undefined,
26925        representationController = undefined,
26926        fragmentModel = undefined,
26927        spExternalControllers = undefined;
26928
26929    function setup() {
26930        liveEdgeFinder = (0, _utilsLiveEdgeFinder2['default'])(context).create({
26931            timelineConverter: timelineConverter,
26932            streamProcessor: instance
26933        });
26934        resetInitialSettings();
26935    }
26936
26937    function initialize(mediaSource) {
26938
26939        indexHandler = (0, _dashDashHandler2['default'])(context).create({
26940            mimeType: mimeType,
26941            timelineConverter: timelineConverter,
26942            dashMetrics: dashMetrics,
26943            metricsModel: metricsModel,
26944            mediaPlayerModel: mediaPlayerModel,
26945            baseURLController: config.baseURLController,
26946            errHandler: errHandler
26947        });
26948
26949        // initialize controllers
26950        indexHandler.initialize(this);
26951        abrController.registerStreamType(type, this);
26952
26953        fragmentModel = stream.getFragmentController().getModel(type);
26954        fragmentModel.setStreamProcessor(instance);
26955
26956        bufferController = createBufferControllerForType(type);
26957        scheduleController = (0, _controllersScheduleController2['default'])(context).create({
26958            type: type,
26959            metricsModel: metricsModel,
26960            adapter: adapter,
26961            dashMetrics: dashMetrics,
26962            dashManifestModel: dashManifestModel,
26963            timelineConverter: timelineConverter,
26964            mediaPlayerModel: mediaPlayerModel,
26965            abrController: abrController,
26966            playbackController: playbackController,
26967            streamController: streamController,
26968            textController: textController,
26969            sourceBufferController: sourceBufferController,
26970            streamProcessor: this
26971        });
26972
26973        representationController = (0, _dashControllersRepresentationController2['default'])(context).create();
26974
26975        representationController.setConfig({
26976            abrController: abrController,
26977            domStorage: domStorage,
26978            metricsModel: metricsModel,
26979            dashMetrics: dashMetrics,
26980            dashManifestModel: dashManifestModel,
26981            manifestModel: manifestModel,
26982            playbackController: playbackController,
26983            timelineConverter: timelineConverter,
26984            streamProcessor: this
26985        });
26986        bufferController.initialize(mediaSource);
26987        scheduleController.initialize();
26988        representationController.initialize();
26989    }
26990
26991    function registerExternalController(controller) {
26992        spExternalControllers.push(controller);
26993    }
26994
26995    function unregisterExternalController(controller) {
26996        var index = spExternalControllers.indexOf(controller);
26997
26998        if (index !== -1) {
26999            spExternalControllers.splice(index, 1);
27000        }
27001    }
27002
27003    function unregisterAllExternalController() {
27004        spExternalControllers = [];
27005    }
27006
27007    function resetInitialSettings() {
27008        mediaInfoArr = [];
27009        mediaInfo = null;
27010        unregisterAllExternalController();
27011    }
27012
27013    function reset(errored) {
27014
27015        indexHandler.reset();
27016
27017        if (bufferController) {
27018            bufferController.reset(errored);
27019            bufferController = null;
27020        }
27021
27022        if (scheduleController) {
27023            scheduleController.reset();
27024            scheduleController = null;
27025        }
27026
27027        if (representationController) {
27028            representationController.reset();
27029            representationController = null;
27030        }
27031
27032        spExternalControllers.forEach(function (controller) {
27033            controller.reset();
27034        });
27035
27036        resetInitialSettings();
27037        type = null;
27038        stream = null;
27039        liveEdgeFinder.reset();
27040    }
27041
27042    function isUpdating() {
27043        return representationController ? representationController.isUpdating() : false;
27044    }
27045
27046    function getType() {
27047        return type;
27048    }
27049
27050    function getRepresentationController() {
27051        return representationController;
27052    }
27053
27054    function getIndexHandler() {
27055        return indexHandler;
27056    }
27057
27058    function getFragmentController() {
27059        return stream ? stream.getFragmentController() : null;
27060    }
27061
27062    function getBuffer() {
27063        return bufferController.getBuffer();
27064    }
27065
27066    function setBuffer(buffer) {
27067        bufferController.setBuffer(buffer);
27068    }
27069
27070    function getBufferController() {
27071        return bufferController;
27072    }
27073
27074    function getFragmentModel() {
27075        return fragmentModel;
27076    }
27077
27078    function getLiveEdgeFinder() {
27079        return liveEdgeFinder;
27080    }
27081
27082    function getStreamInfo() {
27083        return stream ? stream.getStreamInfo() : null;
27084    }
27085
27086    function getEventController() {
27087        return stream ? stream.getEventController() : null;
27088    }
27089
27090    function updateMediaInfo(newMediaInfo) {
27091        if (newMediaInfo !== mediaInfo && (!newMediaInfo || !mediaInfo || newMediaInfo.type === mediaInfo.type)) {
27092            mediaInfo = newMediaInfo;
27093        }
27094        if (mediaInfoArr.indexOf(newMediaInfo) === -1) {
27095            mediaInfoArr.push(newMediaInfo);
27096        }
27097        adapter.updateData(this);
27098    }
27099
27100    function getMediaInfoArr() {
27101        return mediaInfoArr;
27102    }
27103
27104    function getMediaInfo() {
27105        return mediaInfo;
27106    }
27107
27108    function getMediaSource() {
27109        return bufferController.getMediaSource();
27110    }
27111
27112    function getScheduleController() {
27113        return scheduleController;
27114    }
27115
27116    function getCurrentRepresentationInfo() {
27117        return adapter.getCurrentRepresentationInfo(representationController);
27118    }
27119
27120    function getRepresentationInfoForQuality(quality) {
27121        return adapter.getRepresentationInfoForQuality(representationController, quality);
27122    }
27123
27124    function isBufferingCompleted() {
27125        if (bufferController) {
27126            return bufferController.getIsBufferingCompleted();
27127        }
27128
27129        return false;
27130    }
27131
27132    function getBufferLevel() {
27133        return bufferController.getBufferLevel();
27134    }
27135
27136    function switchInitData(representationId) {
27137        if (bufferController) {
27138            bufferController.switchInitData(getStreamInfo().id, representationId);
27139        }
27140    }
27141
27142    function createBuffer() {
27143        return bufferController.getBuffer() || bufferController.createBuffer(mediaInfo);
27144    }
27145
27146    function switchTrackAsked() {
27147        scheduleController.switchTrackAsked();
27148    }
27149
27150    function createBufferControllerForType(type) {
27151        var controller = null;
27152
27153        if (type === _constantsConstants2['default'].VIDEO || type === _constantsConstants2['default'].AUDIO) {
27154            controller = (0, _controllersBufferController2['default'])(context).create({
27155                type: type,
27156                metricsModel: metricsModel,
27157                mediaPlayerModel: mediaPlayerModel,
27158                manifestModel: manifestModel,
27159                sourceBufferController: sourceBufferController,
27160                errHandler: errHandler,
27161                streamController: streamController,
27162                mediaController: mediaController,
27163                adapter: adapter,
27164                textController: textController,
27165                abrController: abrController,
27166                playbackController: playbackController,
27167                streamProcessor: instance
27168            });
27169        } else {
27170            controller = (0, _textTextBufferController2['default'])(context).create({
27171                type: type,
27172                metricsModel: metricsModel,
27173                mediaPlayerModel: mediaPlayerModel,
27174                manifestModel: manifestModel,
27175                sourceBufferController: sourceBufferController,
27176                errHandler: errHandler,
27177                streamController: streamController,
27178                mediaController: mediaController,
27179                adapter: adapter,
27180                textController: textController,
27181                abrController: abrController,
27182                playbackController: playbackController,
27183                streamProcessor: instance
27184            });
27185        }
27186
27187        return controller;
27188    }
27189
27190    instance = {
27191        initialize: initialize,
27192        isUpdating: isUpdating,
27193        getType: getType,
27194        getBufferController: getBufferController,
27195        getFragmentModel: getFragmentModel,
27196        getScheduleController: getScheduleController,
27197        getLiveEdgeFinder: getLiveEdgeFinder,
27198        getEventController: getEventController,
27199        getFragmentController: getFragmentController,
27200        getRepresentationController: getRepresentationController,
27201        getIndexHandler: getIndexHandler,
27202        getCurrentRepresentationInfo: getCurrentRepresentationInfo,
27203        getRepresentationInfoForQuality: getRepresentationInfoForQuality,
27204        getBufferLevel: getBufferLevel,
27205        switchInitData: switchInitData,
27206        isBufferingCompleted: isBufferingCompleted,
27207        createBuffer: createBuffer,
27208        getStreamInfo: getStreamInfo,
27209        updateMediaInfo: updateMediaInfo,
27210        switchTrackAsked: switchTrackAsked,
27211        getMediaInfoArr: getMediaInfoArr,
27212        getMediaInfo: getMediaInfo,
27213        getMediaSource: getMediaSource,
27214        getBuffer: getBuffer,
27215        setBuffer: setBuffer,
27216        registerExternalController: registerExternalController,
27217        unregisterExternalController: unregisterExternalController,
27218        unregisterAllExternalController: unregisterAllExternalController,
27219        reset: reset
27220    };
27221
27222    setup();
27223    return instance;
27224}
27225StreamProcessor.__dashjs_factory_name = 'StreamProcessor';
27226exports['default'] = _coreFactoryMaker2['default'].getClassFactory(StreamProcessor);
27227module.exports = exports['default'];
27228
27229},{"100":100,"105":105,"111":111,"185":185,"198":198,"51":51,"57":57,"62":62}],98:[function(_dereq_,module,exports){
27230/**
27231 * The copyright in this software is being made available under the BSD License,
27232 * included below. This software may be subject to other third party and contributor
27233 * rights, including patent rights, and no such rights are granted under this license.
27234 *
27235 * Copyright (c) 2013, Dash Industry Forum.
27236 * All rights reserved.
27237 *
27238 * Redistribution and use in source and binary forms, with or without modification,
27239 * are permitted provided that the following conditions are met:
27240 *  * Redistributions of source code must retain the above copyright notice, this
27241 *  list of conditions and the following disclaimer.
27242 *  * Redistributions in binary form must reproduce the above copyright notice,
27243 *  this list of conditions and the following disclaimer in the documentation and/or
27244 *  other materials provided with the distribution.
27245 *  * Neither the name of Dash Industry Forum nor the names of its
27246 *  contributors may be used to endorse or promote products derived from this software
27247 *  without specific prior written permission.
27248 *
27249 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
27250 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27251 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27252 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27253 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
27253INCLUDING, BUT
27254 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27255 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27256 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27257 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27258 *  POSSIBILITY OF SUCH DAMAGE.
27259 */
27260'use strict';
27261
27262Object.defineProperty(exports, '__esModule', {
27263    value: true
27264});
27265
27266function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
27267
27268function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
27269
27270var _voMetricsHTTPRequest = _dereq_(224);
27271
27272var _coreFactoryMaker = _dereq_(51);
27273
27274var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
27275
27276var _utilsErrorHandlerJs = _dereq_(195);
27277
27278var _utilsErrorHandlerJs2 = _interopRequireDefault(_utilsErrorHandlerJs);
27279
27280/**
27281 * @module XHRLoader
27282 * @description Manages download of resources via HTTP.
27283 * @param {Object} cfg - dependancies from parent
27284 */
27285function XHRLoader(cfg) {
27286    //const context = this.context;
27287    //const log = Debug(context).getInstance().log;
27288    var errHandler = cfg.errHandler;
27289    var metricsModel = cfg.metricsModel;
27290    var mediaPlayerModel = cfg.mediaPlayerModel;
27291    var requestModifier = cfg.requestModifier;
27292
27293    var instance = undefined;
27294    var xhrs = undefined;
27295    var delayedXhrs = undefined;
27296    var retryTimers = undefined;
27297    var downloadErrorToRequestTypeMap = undefined;
27298
27299    function setup() {
27300        var _downloadErrorToRequestTypeMap;
27301
27302        xhrs = [];
27303        delayedXhrs = [];
27304        retryTimers = [];
27305
27306        downloadErrorToRequestTypeMap = (_downloadErrorToRequestTypeMap = {}, _defineProperty(_downloadErrorToRequestTypeMap, _voMetricsHTTPRequest.HTTPRequest.MPD_TYPE, _utilsErrorHandlerJs2['default'].DOWNLOAD_ERROR_ID_MANIFEST), _defineProperty(_downloadErrorToRequestTypeMap, _voMetricsHTTPRequest.HTTPRequest.XLINK_EXPANSION_TYPE, _utilsErrorHandlerJs2['default'].DOWNLOAD_ERROR_ID_XLINK), _defineProperty(_downloadErrorToRequestTypeMap, _voMetricsHTTPRequest.HTTPRequest.INIT_SEGMENT_TYPE, _utilsErrorHandlerJs2['default'].DOWNLOAD_ERROR_ID_INITIALIZATION), _defineProperty(_downloadErrorToRequestTypeMap, _voMetricsHTTPRequest.HTTPRequest.MEDIA_SEGMENT_TYPE, _utilsErrorHandlerJs2['default'].DOWNLOAD_ERROR_ID_CONTENT), _defineProperty(_downloadErrorToRequestTypeMap, _voMetricsHTTPRequest.HTTPRequest.INDEX_SEGMENT_TYPE, _utilsErrorHandlerJs2['default'].DOWNLOAD_ERROR_ID_CONTENT), _defineProperty(_downloadErrorToRequestTypeMap, _voMetricsHTTPRequest.HTTPRequest.BITSTREAM_SWITCHING_SEGMENT_TYPE, _utilsErrorHandlerJs2['default'].DOWNLOAD_ERROR_ID_CONTENT), _defineProperty(_downloadErrorToRequestTypeMap, _voMetricsHTTPRequest.HTTPRequest.OTHER_TYPE, _utilsErrorHandlerJs2['default'].DOWNLOAD_ERROR_ID_CONTENT), _downloadErrorToRequestTypeMap);
27307    }
27308
27309    function internalLoad(config, remainingAttempts) {
27310
27311        var request = config.request;
27312        var xhr = new XMLHttpRequest();
27313        var traces = [];
27314        var firstProgress = true;
27315        var needFailureReport = true;
27316        var requestStartTime = new Date();
27317        var lastTraceTime = requestStartTime;
27318        var lastTraceReceivedCount = 0;
27319
27320        var handleLoaded = function handleLoaded(success) {
27321            needFailureReport = false;
27322
27323            request.requestStartDate = requestStartTime;
27324            request.requestEndDate = new Date();
27325            request.firstByteDate = request.firstByteDate || requestStartTime;
27326
27327            if (!request.checkExistenceOnly) {
27328                metricsModel.addHttpRequest(request.mediaType, null, request.type, request.url, xhr.responseURL || null, request.serviceLocation || null, request.range || null, request.requestStartDate, request.firstByteDate, request.requestEndDate, xhr.status, request.duration, xhr.getAllResponseHeaders(), success ? traces : null);
27329            }
27330        };
27331
27332        var onloadend = function onloadend() {
27333            if (xhrs.indexOf(xhr) === -1) {
27334                return;
27335            } else {
27336                xhrs.splice(xhrs.indexOf(xhr), 1);
27337            }
27338
27339            if (needFailureReport) {
27340                handleLoaded(false);
27341
27342                if (remainingAttempts > 0) {
27343                    remainingAttempts--;
27344                    retryTimers.push(setTimeout(function () {
27345                        internalLoad(config, remainingAttempts);
27346                    }, mediaPlayerModel.getRetryIntervalForType(request.type)));
27347                } else {
27348                    errHandler.downloadError(downloadErrorToRequestTypeMap[request.type], request.url, request);
27349
27350                    if (config.error) {
27351                        config.error(request, 'error', xhr.statusText);
27352                    }
27353
27354                    if (config.complete) {
27355                        config.complete(request, xhr.statusText);
27356                    }
27357                }
27358            }
27359        };
27360
27361        var progress = function progress(event) {
27362            var currentTime = new Date();
27363
27364            if (firstProgress) {
27365                firstProgress = false;
27366                if (!event.lengthComputable || event.lengthComputable && event.total !== event.loaded) {
27367                    request.firstByteDate = currentTime;
27368                }
27369            }
27370
27371            if (event.lengthComputable) {
27372                request.bytesLoaded = event.loaded;
27373                request.bytesTotal = event.total;
27374            }
27375
27376            traces.push({
27377                s: lastTraceTime,
27378                d: currentTime.getTime() - lastTraceTime.getTime(),
27379                b: [event.loaded ? event.loaded - lastTraceReceivedCount : 0]
27380            });
27381
27382            lastTraceTime = currentTime;
27383            lastTraceReceivedCount = event.loaded;
27384
27385            if (config.progress) {
27386                config.progress();
27387            }
27388        };
27389
27390        var onload = function onload() {
27391            if (xhr.status >= 200 && xhr.status <= 299) {
27392                handleLoaded(true);
27393
27394                if (config.success) {
27395                    config.success(xhr.response, xhr.statusText, xhr);
27396                }
27397
27398                if (config.complete) {
27399                    config.complete(request, xhr.statusText);
27400                }
27401            }
27402        };
27403
27404        var onabort = function onabort() {
27405            if (config.abort) {
27406                config.abort(request, xhr.status);
27407            }
27408        };
27409
27410        if (!requestModifier || !metricsModel || !errHandler) {
27411            throw new Error('config object is not correct or missing');
27412        }
27413
27414        try {
27415            var modifiedUrl = requestModifier.modifyRequestURL(request.url);
27416            var verb = request.checkExistenceOnly ? _voMetricsHTTPRequest.HTTPRequest.HEAD : _voMetricsHTTPRequest.HTTPRequest.GET;
27417
27418            xhr.open(verb, modifiedUrl, true);
27419
27420            if (request.responseType) {
27421                xhr.responseType = request.responseType;
27422            }
27423
27424            if (request.range) {
27425                xhr.setRequestHeader('Range', 'bytes=' + request.range);
27426            }
27427
27428            if (!request.requestStartDate) {
27429                request.requestStartDate = requestStartTime;
27430            }
27431
27432            xhr = requestModifier.modifyRequestHeader(xhr);
27433
27434            xhr.withCredentials = mediaPlayerModel.getXHRWithCredentialsForType(request.type);
27435
27436            xhr.onload = onload;
27437            xhr.onloadend = onloadend;
27438            xhr.onerror = onloadend;
27439            xhr.onprogress = progress;
27440            xhr.onabort = onabort;
27441
27442            // Adds the ability to delay single fragment loading time to control buffer.
27443            var now = new Date().getTime();
27444            if (isNaN(request.delayLoadingTime) || now >= request.delayLoadingTime) {
27445                // no delay - just send xhr
27446
27447                xhrs.push(xhr);
27448                xhr.send();
27449            } else {
27450                (function () {
27451                    // delay
27452                    var delayedXhr = { xhr: xhr };
27453                    delayedXhrs.push(delayedXhr);
27454                    delayedXhr.delayTimeout = setTimeout(function () {
27455                        if (delayedXhrs.indexOf(delayedXhr) === -1) {
27456                            return;
27457                        } else {
27458                            delayedXhrs.splice(delayedXhrs.indexOf(delayedXhr), 1);
27459                        }
27460                        try {
27461                            requestStartTime = new Date();
27462                            lastTraceTime = requestStartTime;
27463                            xhrs.push(delayedXhr.xhr);
27464                            delayedXhr.xhr.send();
27465                        } catch (e) {
27466                            delayedXhr.xhr.onerror();
27467                        }
27468                    }, request.delayLoadingTime - now);
27469                })();
27470            }
27471        } catch (e) {
27472            xhr.onerror();
27473        }
27474    }
27475
27476    /**
27477     * Initiates a download of the resource described by config.request
27478     * @param {Object} config - contains request (FragmentRequest or derived type), and callbacks
27479     * @memberof module:XHRLoader
27480     * @instance
27481     */
27482    function load(config) {
27483        if (config.request) {
27484            internalLoad(config, mediaPlayerModel.getRetryAttemptsForType(config.request.type));
27485        }
27486    }
27487
27488    /**
27489     * Aborts any inflight downloads
27490     * @memberof module:XHRLoader
27491     * @instance
27492     */
27493    function abort() {
27494        retryTimers.forEach(function (t) {
27495            return clearTimeout(t);
27496        });
27497        retryTimers = [];
27498
27499        delayedXhrs.forEach(function (x) {
27500            return clearTimeout(x.delayTimeout);
27501        });
27502        delayedXhrs = [];
27503
27504        xhrs.forEach(function (x) {
27505            // abort will trigger onloadend which we don't want
27506            // when deliberately aborting inflight requests -
27507            // set them to undefined so they are not called
27508            x.onloadend = x.onerror = x.onprogress = undefined;
27509            x.abort();
27510        });
27511        xhrs = [];
27512    }
27513
27514    instance = {
27515        load: load,
27516        abort: abort
27517    };
27518
27519    setup();
27520
27521    return instance;
27522}
27523
27524XHRLoader.__dashjs_factory_name = 'XHRLoader';
27525
27526var factory = _coreFactoryMaker2['default'].getClassFactory(XHRLoader);
27527exports['default'] = factory;
27528module.exports = exports['default'];
27529
27530},{"195":195,"224":224,"51":51}],99:[function(_dereq_,module,exports){
27531/**
27532 * The copyright in this software is being made available under the BSD License,
27533 * included below. This software may be subject to other third party and contributor
27534 * rights, including patent rights, and no such rights are granted under this license.
27535 *
27536 * Copyright (c) 2013, Dash Industry Forum.
27537 * All rights reserved.
27538 *
27539 * Redistribution and use in source and binary forms, with or without modification,
27540 * are permitted provided that the following conditions are met:
27541 *  * Redistributions of source code must retain the above copyright notice, this
27542 *  list of conditions and the following disclaimer.
27543 *  * Redistributions in binary form must reproduce the above copyright notice,
27544 *  this list of conditions and the following disclaimer in the documentation and/or
27545 *  other materials provided with the distribution.
27546 *  * Neither the name of Dash Industry Forum nor the names of its
27547 *  contributors may be used to endorse or promote products derived from this software
27548 *  without specific prior written permission.
27549 *
27550 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
27551 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27552 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27553 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27554 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27555 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27556 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27557 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27558 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27559 *  POSSIBILITY OF SUCH DAMAGE.
27560 */
27561'use strict';
27562
27563Object.defineProperty(exports, '__esModule', {
27564    value: true
27565});
27566
27567function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
27568
27569var _voDashJSError = _dereq_(207);
27570
27571var _voDashJSError2 = _interopRequireDefault(_voDashJSError);
27572
27573var _XHRLoader = _dereq_(98);
27574
27575var _XHRLoader2 = _interopRequireDefault(_XHRLoader);
27576
27577var _voMetricsHTTPRequest = _dereq_(224);
27578
27579var _voTextRequest = _dereq_(217);
27580
27581var _voTextRequest2 = _interopRequireDefault(_voTextRequest);
27582
27583var _coreEventBus = _dereq_(50);
27584
27585var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
27586
27587var _coreEventsEvents = _dereq_(54);
27588
27589var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
27590
27591var _coreFactoryMaker = _dereq_(51);
27592
27593var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
27594
27595var XLINK_LOADER_ERROR_LOADING_FAILURE = 1;
27596
27597function XlinkLoader(config) {
27598
27599    var RESOLVE_TO_ZERO = 'urn:mpeg:dash:resolve-to-zero:2013';
27600
27601    var context = this.context;
27602    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
27603
27604    var xhrLoader = (0, _XHRLoader2['default'])(context).create({
27605        errHandler: config.errHandler,
27606        metricsModel: config.metricsModel,
27607        mediaPlayerModel: config.mediaPlayerModel,
27608        requestModifier: config.requestModifier
27609    });
27610
27611    var instance = undefined;
27612
27613    function load(url, element, resolveObject) {
27614        var report = function report(content, resolveToZero) {
27615            element.resolved = true;
27616            element.resolvedContent = content ? content : null;
27617
27618            eventBus.trigger(_coreEventsEvents2['default'].XLINK_ELEMENT_LOADED, {
27619                element: element,
27620                resolveObject: resolveObject,
27621                error: content || resolveToZero ? null : new _voDashJSError2['default'](XLINK_LOADER_ERROR_LOADING_FAILURE, 'Failed loading Xlink element: ' + url)
27622            });
27623        };
27624
27625        if (url === RESOLVE_TO_ZERO) {
27626            report(null, true);
27627        } else {
27628            var request = new _voTextRequest2['default'](url, _voMetricsHTTPRequest.HTTPRequest.XLINK_TYPE);
27629
27630            xhrLoader.load({
27631                request: request,
27632                success: function success(data) {
27633                    report(data);
27634                },
27635                error: function error() {
27636                    report(null);
27637                }
27638            });
27639        }
27640    }
27641
27642    function reset() {
27643        if (xhrLoader) {
27644            xhrLoader.abort();
27645            xhrLoader = null;
27646        }
27647    }
27648
27649    instance = {
27650        load: load,
27651        reset: reset
27652    };
27653
27654    return instance;
27655}
27656
27657XlinkLoader.__dashjs_factory_name = 'XlinkLoader';
27658
27659var factory = _coreFactoryMaker2['default'].getClassFactory(XlinkLoader);
27660factory.XLINK_LOADER_ERROR_LOADING_FAILURE = XLINK_LOADER_ERROR_LOADING_FAILURE;
27661_coreFactoryMaker2['default'].updateClassFactory(XlinkLoader.__dashjs_factory_name, factory);
27662exports['default'] = factory;
27663module.exports = exports['default'];
27664
27665},{"207":207,"217":217,"224":224,"50":50,"51":51,"54":54,"98":98}],100:[function(_dereq_,module,exports){
27666/**
27667 * The copyright in this software is being made available under the BSD License,
27668 * included below. This software may be subject to other third party and contributor
27669 * rights, including patent rights, and no such rights are granted under this license.
27670 *
27671 * Copyright (c) 2013, Dash Industry Forum.
27672 * All rights reserved.
27673 *
27674 * Redistribution and use in source and binary forms, with or without modification,
27675 * are permitted provided that the following conditions are met:
27676 *  * Redistributions of source code must retain the above copyright notice, this
27677 *  list of conditions and the following disclaimer.
27678 *  * Redistributions in binary form must reproduce the above copyright notice,
27679 *  this list of conditions and the following disclaimer in the documentation and/or
27680 *  other materials provided with the distribution.
27681 *  * Neither the name of Dash Industry Forum nor the names of its
27682 *  contributors may be used to endorse or promote products derived from this software
27683 *  without specific prior written permission.
27684 *
27685 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
27686 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27687 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27688 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27689 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27690 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27691 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27692 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27693 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27694 *  POSSIBILITY OF SUCH DAMAGE.
27695 */
27696
27697/**
27698 * Constants declaration
27699 * @class
27700 * @ignore
27701 */
27702'use strict';
27703
27704Object.defineProperty(exports, '__esModule', {
27705    value: true
27706});
27707
27708var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
27709
27710function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
27711
27712var Constants = (function () {
27713    _createClass(Constants, [{
27714        key: 'init',
27715        value: function init() {
27716            this.STREAM = 'stream';
27717            this.VIDEO = 'video';
27718            this.AUDIO = 'audio';
27719            this.TEXT = 'text';
27720            this.FRAGMENTED_TEXT = 'fragmentedText';
27721            this.EMBEDDED_TEXT = 'embeddedText';
27722            this.MUXED = 'muxed';
27723            this.LOCATION = 'Location';
27724            this.INITIALIZE = 'initialize';
27725            this.TEXT_SHOWING = 'showing';
27726            this.TEXT_HIDDEN = 'hidden';
27727            this.CC1 = 'CC1';
27728            this.CC3 = 'CC3';
27729            this.STPP = 'stpp';
27730            this.TTML = 'ttml';
27731            this.VTT = 'vtt';
27732            this.WVTT = 'wvtt';
27733            this.UTF8 = 'utf-8';
27734            this.SUGGESTED_PRESENTATION_DELAY = 'suggestedPresentationDelay';
27735            this.SCHEME_ID_URI = 'schemeIdUri';
27736            this.START_TIME = 'starttime';
27737            this.ABR_STRATEGY_DYNAMIC = 'abrDynamic';
27738            this.ABR_STRATEGY_BOLA = 'abrBola';
27739            this.ABR_STRATEGY_THROUGHPUT = 'abrThroughput';
27740            this.MOVING_AVERAGE_SLIDING_WINDOW = 'slidingWindow';
27741            this.MOVING_AVERAGE_EWMA = 'ewma';
27742        }
27743    }]);
27744
27745    function Constants() {
27746        _classCallCheck(this, Constants);
27747
27748        this.init();
27749    }
27750
27751    return Constants;
27752})();
27753
27754var constants = new Constants();
27755exports['default'] = constants;
27756module.exports = exports['default'];
27757
27758},{}],101:[function(_dereq_,module,exports){
27759/**
27760 * The copyright in this software is being made available under the BSD License,
27761 * included below. This software may be subject to other third party and contributor
27762 * rights, including patent rights, and no such rights are granted under this license.
27763 *
27764 * Copyright (c) 2013, Dash Industry Forum.
27765 * All rights reserved.
27766 *
27767 * Redistribution and use in source and binary forms, with or without modification,
27768 * are permitted provided that the following conditions are met:
27769 *  * Redistributions of source code must retain the above copyright notice, this
27770 *  list of conditions and the following disclaimer.
27771 *  * Redistributions in binary form must reproduce the above copyright notice,
27772 *  this list of conditions and the following disclaimer in the documentation and/or
27773 *  other materials provided with the distribution.
27774 *  * Neither the name of Dash Industry Forum nor the names of its
27775 *  contributors may be used to endorse or promote products derived from this software
27776 *  without specific prior written permission.
27777 *
27778 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
27779 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27780 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27781 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27782 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27783 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27784 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27785 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27786 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27787 *  POSSIBILITY OF SUCH DAMAGE.
27788 */
27789
27790/**
27791 * Metrics Constants declaration
27792 * @class
27793 * @ignore
27794 */
27795'use strict';
27796
27797Object.defineProperty(exports, '__esModule', {
27798    value: true
27799});
27800
27801var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
27802
27803function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
27804
27805var MetricsConstants = (function () {
27806    _createClass(MetricsConstants, [{
27807        key: 'init',
27808        value: function init() {
27809            this.TCP_CONNECTION = 'TcpList';
27810            this.HTTP_REQUEST = 'HttpList';
27811            this.TRACK_SWITCH = 'RepSwitchList';
27812            this.BUFFER_LEVEL = 'BufferLevel';
27813            this.BUFFER_STATE = 'BufferState';
27814            this.DVR_INFO = 'DVRInfo';
27815            this.DROPPED_FRAMES = 'DroppedFrames';
27816            this.SCHEDULING_INFO = 'SchedulingInfo';
27817            this.REQUESTS_QUEUE = 'RequestsQueue';
27818            this.MANIFEST_UPDATE = 'ManifestUpdate';
27819            this.MANIFEST_UPDATE_STREAM_INFO = 'ManifestUpdatePeriodInfo';
27820            this.MANIFEST_UPDATE_TRACK_INFO = 'ManifestUpdateRepresentationInfo';
27821            this.PLAY_LIST = 'PlayList';
27822            this.DVB_ERRORS = 'DVBErrors';
27823        }
27824    }]);
27825
27826    function MetricsConstants() {
27827        _classCallCheck(this, MetricsConstants);
27828
27829        this.init();
27830    }
27831
27832    return MetricsConstants;
27833})();
27834
27835var constants = new MetricsConstants();
27836exports['default'] = constants;
27837module.exports = exports['default'];
27838
27839},{}],102:[function(_dereq_,module,exports){
27840/**
27841 * The copyright in this software is being made available under the BSD License,
27842 * included below. This software may be subject to other third party and contributor
27843 * rights, including patent rights, and no such rights are granted under this license.
27844 *
27845 * Copyright (c) 2013, Dash Industry Forum.
27846 * All rights reserved.
27847 *
27848 * Redistribution and use in source and binary forms, with or without modification,
27849 * are permitted provided that the following conditions are met:
27850 *  * Redistributions of source code must retain the above copyright notice, this
27851 *  list of conditions and the following disclaimer.
27852 *  * Redistributions in binary form must reproduce the above copyright notice,
27853 *  this list of conditions and the following disclaimer in the documentation and/or
27854 *  other materials provided with the distribution.
27855 *  * Neither the name of Dash Industry Forum nor the names of its
27856 *  contributors may be used to endorse or promote products derived from this software
27857 *  without specific prior written permission.
27858 *
27859 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
27860 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27861 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27862 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27863 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27864 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27865 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27866 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27867 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27868 *  POSSIBILITY OF SUCH DAMAGE.
27869 */
27870
27871'use strict';
27872
27873Object.defineProperty(exports, '__esModule', {
27874    value: true
27875});
27876
27877function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
27878
27879var _rulesAbrABRRulesCollection = _dereq_(174);
27880
27881var _rulesAbrABRRulesCollection2 = _interopRequireDefault(_rulesAbrABRRulesCollection);
27882
27883var _constantsConstants = _dereq_(100);
27884
27885var _constantsConstants2 = _interopRequireDefault(_constantsConstants);
27886
27887var _constantsMetricsConstants = _dereq_(101);
27888
27889var _constantsMetricsConstants2 = _interopRequireDefault(_constantsMetricsConstants);
27890
27891var _voBitrateInfo = _dereq_(206);
27892
27893var _voBitrateInfo2 = _interopRequireDefault(_voBitrateInfo);
27894
27895var _modelsFragmentModel = _dereq_(140);
27896
27897var _modelsFragmentModel2 = _interopRequireDefault(_modelsFragmentModel);
27898
27899var _coreEventBus = _dereq_(50);
27900
27901var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
27902
27903var _coreEventsEvents = _dereq_(54);
27904
27905var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
27906
27907var _coreFactoryMaker = _dereq_(51);
27908
27909var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
27910
27911var _rulesRulesContextJs = _dereq_(170);
27912
27913var _rulesRulesContextJs2 = _interopRequireDefault(_rulesRulesContextJs);
27914
27915var _rulesSwitchRequestJs = _dereq_(171);
27916
27917var _rulesSwitchRequestJs2 = _interopRequireDefault(_rulesSwitchRequestJs);
27918
27919var _rulesSwitchRequestHistoryJs = _dereq_(172);
27920
27921var _rulesSwitchRequestHistoryJs2 = _interopRequireDefault(_rulesSwitchRequestHistoryJs);
27922
27923var _rulesDroppedFramesHistoryJs = _dereq_(169);
27924
27925var _rulesDroppedFramesHistoryJs2 = _interopRequireDefault(_rulesDroppedFramesHistoryJs);
27926
27927var _rulesThroughputHistoryJs = _dereq_(173);
27928
27929var _rulesThroughputHistoryJs2 = _interopRequireDefault(_rulesThroughputHistoryJs);
27930
27931var _voMetricsHTTPRequest = _dereq_(224);
27932
27933var _coreDebug = _dereq_(49);
27934
27935var _coreDebug2 = _interopRequireDefault(_coreDebug);
27936
27937var ABANDON_LOAD = 'abandonload';
27938var ALLOW_LOAD = 'allowload';
27939var DEFAULT_VIDEO_BITRATE = 1000;
27940var DEFAULT_AUDIO_BITRATE = 100;
27941var QUALITY_DEFAULT = 0;
27942
27943function AbrController() {
27944
27945    var context = this.context;
27946    var debug = (0, _coreDebug2['default'])(context).getInstance();
27947    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
27948
27949    var instance = undefined,
27950        log = undefined,
27951        abrRulesCollection = undefined,
27952        streamController = undefined,
27953        autoSwitchBitrate = undefined,
27954        topQualities = undefined,
27955        qualityDict = undefined,
27956        bitrateDict = undefined,
27957        ratioDict = undefined,
27958        streamProcessorDict = undefined,
27959        abandonmentStateDict = undefined,
27960        abandonmentTimeout = undefined,
27961        limitBitrateByPortal = undefined,
27962        usePixelRatioInLimitBitrateByPortal = undefined,
27963        windowResizeEventCalled = undefined,
27964        elementWidth = undefined,
27965        elementHeight = undefined,
27966        manifestModel = undefined,
27967        dashManifestModel = undefined,
27968        adapter = undefined,
27969        videoModel = undefined,
27970        mediaPlayerModel = undefined,
27971        domStorage = undefined,
27972        playbackIndex = undefined,
27973        switchHistoryDict = undefined,
27974        droppedFramesHistory = undefined,
27975        throughputHistory = undefined,
27976        isUsingBufferOccupancyABRDict = undefined,
27977        metricsModel = undefined,
27978        dashMetrics = undefined,
27979        useDeadTimeLatency = undefined;
27980
27981    function setup() {
27982        log = debug.log.bind(instance);
27983
27984        resetInitialSettings();
27985    }
27986
27987    function registerStreamType(type, streamProcessor) {
27988        switchHistoryDict[type] = (0, _rulesSwitchRequestHistoryJs2['default'])(context).create();
27989        streamProcessorDict[type] = streamProcessor;
27990        abandonmentStateDict[type] = abandonmentStateDict[type] || {};
27991        abandonmentStateDict[type].state = ALLOW_LOAD;
27992        isUsingBufferOccupancyABRDict[type] = false;
27993        eventBus.on(_coreEventsEvents2['default'].LOADING_PROGRESS, onFragmentLoadProgress, this);
27994        if (type == _constantsConstants2['default'].VIDEO) {
27995            eventBus.on(_coreEventsEvents2['default'].QUALITY_CHANGE_RENDERED, onQualityChangeRendered, this);
27996            droppedFramesHistory = (0, _rulesDroppedFramesHistoryJs2['default'])(context).create();
27997            setElementSize();
27998        }
27999        eventBus.on(_coreEventsEvents2['default'].METRIC_ADDED, onMetricAdded, this);
28000        throughputHistory = (0, _rulesThroughputHistoryJs2['default'])(context).create({
28001            mediaPlayerModel: mediaPlayerModel
28002        });
28003    }
28004
28005    function createAbrRulesCollection() {
28006        abrRulesCollection = (0, _rulesAbrABRRulesCollection2['default'])(context).create({
28007            metricsModel: metricsModel,
28008            dashMetrics: dashMetrics,
28009            mediaPlayerModel: mediaPlayerModel,
28010            adapter: adapter
28011        });
28012
28013        abrRulesCollection.initialize();
28014    }
28015
28016    function resetInitialSettings() {
28017        autoSwitchBitrate = { video: true, audio: true };
28018        topQualities = {};
28019        qualityDict = {};
28020        bitrateDict = {};
28021        ratioDict = {};
28022        abandonmentStateDict = {};
28023        streamProcessorDict = {};
28024        switchHistoryDict = {};
28025        isUsingBufferOccupancyABRDict = {};
28026        limitBitrateByPortal = false;
28027        useDeadTimeLatency = true;
28028        usePixelRatioInLimitBitrateByPortal = false;
28029        if (windowResizeEventCalled === undefined) {
28030            windowResizeEventCalled = false;
28031        }
28032        playbackIndex = undefined;
28033        droppedFramesHistory = undefined;
28034        throughputHistory = undefined;
28035        clearTimeout(abandonmentTimeout);
28036        abandonmentTimeout = null;
28037    }
28038
28039    function reset() {
28040
28041        resetInitialSettings();
28042
28043        eventBus.off(_coreEventsEvents2['default'].LOADING_PROGRESS, onFragmentLoadProgress, this);
28044        eventBus.off(_coreEventsEvents2['default'].QUALITY_CHANGE_RENDERED, onQualityChangeRendered, this);
28045        eventBus.off(_coreEventsEvents2['default'].METRIC_ADDED, onMetricAdded, this);
28046
28047        if (abrRulesCollection) {
28048            abrRulesCollection.reset();
28049        }
28050    }
28051
28052    function setConfig(config) {
28053        if (!config) return;
28054
28055        if (config.streamController) {
28056            streamController = config.streamController;
28057        }
28058        if (config.domStorage) {
28059            domStorage = config.domStorage;
28060        }
28061        if (config.mediaPlayerModel) {
28062            mediaPlayerModel = config.mediaPlayerModel;
28063        }
28064        if (config.metricsModel) {
28065            metricsModel = config.metricsModel;
28066        }
28067        if (config.dashMetrics) {
28068            dashMetrics = config.dashMetrics;
28069        }
28070        if (config.dashManifestModel) {
28071            dashManifestModel = config.dashManifestModel;
28072        }
28073        if (config.adapter) {
28074            adapter = config.adapter;
28075        }
28076        if (config.manifestModel) {
28077            manifestModel = config.manifestModel;
28078        }
28079        if (config.videoModel) {
28080            videoModel = config.videoModel;
28081        }
28082    }
28083
28084    function onQualityChangeRendered(e) {
28085        if (e.mediaType === _constantsConstants2['default'].VIDEO) {
28086            playbackIndex = e.oldQuality;
28087            droppedFramesHistory.push(playbackIndex, videoModel.getPlaybackQuality());
28088        }
28089    }
28090
28091    function onMetricAdded(e) {
28092        if (e.metric === _constantsMetricsConstants2['default'].HTTP_REQUEST && e.value && e.value.type === _voMetricsHTTPRequest.HTTPRequest.MEDIA_SEGMENT_TYPE && (e.mediaType === _constantsConstants2['default'].AUDIO || e.mediaType === _constantsConstants2['default'].VIDEO)) {
28093            throughputHistory.push(e.mediaType, e.value, useDeadTimeLatency);
28094        }
28095
28096        if (e.metric === _constantsMetricsConstants2['default'].BUFFER_LEVEL && (e.mediaType === _constantsConstants2['default'].AUDIO || e.mediaType === _constantsConstants2['default'].VIDEO)) {
28097            updateIsUsingBufferOccupancyABR(e.mediaType, 0.001 * e.value.level);
28098        }
28099    }
28100
28101    function getTopQualityIndexFor(type, id) {
28102        var idx = undefined;
28103        topQualities[id] = topQualities[id] || {};
28104
28105        if (!topQualities[id].hasOwnProperty(type)) {
28106            topQualities[id][type] = 0;
28107        }
28108
28109        idx = checkMaxBitrate(topQualities[id][type], type);
28110        idx = checkMaxRepresentationRatio(idx, type, topQualities[id][type]);
28111        idx = checkPortalSize(idx, type);
28112        return idx;
28113    }
28114
28115    /**
28116     * @param {string} type
28117     * @returns {number} A value of the initial bitrate, kbps
28118     * @memberof AbrController#
28119     */
28120    function getInitialBitrateFor(type) {
28121
28122        var savedBitrate = domStorage.getSavedBitrateSettings(type);
28123
28124        if (!bitrateDict.hasOwnProperty(type)) {
28125            if (ratioDict.hasOwnProperty(type)) {
28126                var manifest = manifestModel.getValue();
28127                var representation = dashManifestModel.getAdaptationForType(manifest, 0, type).Representation;
28128
28129                if (Array.isArray(representation)) {
28130                    var repIdx = Math.max(Math.round(representation.length * ratioDict[type]) - 1, 0);
28131                    bitrateDict[type] = representation[repIdx].bandwidth;
28132                } else {
28133                    bitrateDict[type] = 0;
28134                }
28135            } else if (!isNaN(savedBitrate)) {
28136                bitrateDict[type] = savedBitrate;
28137            } else {
28138                bitrateDict[type] = type === _constantsConstants2['default'].VIDEO ? DEFAULT_VIDEO_BITRATE : DEFAULT_AUDIO_BITRATE;
28139            }
28140        }
28141
28142        return bitrateDict[type];
28143    }
28144
28145    /**
28146     * @param {string} type
28147     * @param {number} value A value of the initial bitrate, kbps
28148     * @memberof AbrController#
28149     */
28150    function setInitialBitrateFor(type, value) {
28151        bitrateDict[type] = value;
28152    }
28153
28154    function getInitialRepresentationRatioFor(type) {
28155        if (!ratioDict.hasOwnProperty(type)) {
28156            return null;
28157        }
28158
28159        return ratioDict[type];
28160    }
28161
28162    function setInitialRepresentationRatioFor(type, value) {
28163        ratioDict[type] = value;
28164    }
28165
28166    function getMaxAllowedBitrateFor(type) {
28167        if (bitrateDict.hasOwnProperty('max') && bitrateDict.max.hasOwnProperty(type)) {
28168            return bitrateDict.max[type];
28169        }
28170        return NaN;
28171    }
28172
28173    function getMinAllowedBitrateFor(type) {
28174        if (bitrateDict.hasOwnProperty('min') && bitrateDict.min.hasOwnProperty(type)) {
28175            return bitrateDict.min[type];
28176        }
28177        return NaN;
28178    }
28179
28180    //TODO  change bitrateDict structure to hold one object for video and audio with initial and max values internal.
28181    // This means you need to update all the logic around initial bitrate DOMStorage, RebController etc...
28182    function setMaxAllowedBitrateFor(type, value) {
28183        bitrateDict.max = bitrateDict.max || {};
28184        bitrateDict.max[type] = value;
28185    }
28186
28187    function setMinAllowedBitrateFor(type, value) {
28188        bitrateDict.min = bitrateDict.min || {};
28189        bitrateDict.min[type] = value;
28190    }
28191
28192    function getMaxAllowedRepresentationRatioFor(type) {
28193        if (ratioDict.hasOwnProperty('max') && ratioDict.max.hasOwnProperty(type)) {
28194            return ratioDict.max[type];
28195        }
28196        return 1;
28197    }
28198
28199    function setMaxAllowedRepresentationRatioFor(type, value) {
28200        ratioDict.max = ratioDict.max || {};
28201        ratioDict.max[type] = value;
28202    }
28203
28204    function getAutoSwitchBitrateFor(type) {
28205        return autoSwitchBitrate[type];
28206    }
28207
28208    function setAutoSwitchBitrateFor(type, value) {
28209        autoSwitchBitrate[type] = value;
28210    }
28211
28212    function getLimitBitrateByPortal() {
28213        return limitBitrateByPortal;
28214    }
28215
28216    function setLimitBitrateByPortal(value) {
28217        limitBitrateByPortal = value;
28218    }
28219
28220    function getUsePixelRatioInLimitBitrateByPortal() {
28221        return usePixelRatioInLimitBitrateByPortal;
28222    }
28223
28224    function setUsePixelRatioInLimitBitrateByPortal(value) {
28225        usePixelRatioInLimitBitrateByPortal = value;
28226    }
28227
28228    function getUseDeadTimeLatency() {
28229        return useDeadTimeLatency;
28230    }
28231
28232    function setUseDeadTimeLatency(value) {
28233        useDeadTimeLatency = value;
28234    }
28235
28236    function checkPlaybackQuality(type) {
28237        if (type && streamProcessorDict && streamProcessorDict[type]) {
28238            var streamInfo = streamProcessorDict[type].getStreamInfo();
28239            var streamId = streamInfo ? streamInfo.id : null;
28240            var oldQuality = getQualityFor(type);
28241            var rulesContext = (0, _rulesRulesContextJs2['default'])(context).create({
28242                abrController: instance,
28243                streamProcessor: streamProcessorDict[type],
28244                currentValue: oldQuality,
28245                switchHistory: switchHistoryDict[type],
28246                droppedFramesHistory: droppedFramesHistory,
28247                useBufferOccupancyABR: useBufferOccupancyABR(type)
28248            });
28249
28250            if (droppedFramesHistory) {
28251                droppedFramesHistory.push(playbackIndex, videoModel.getPlaybackQuality());
28252            }
28253
28254            //log("ABR enabled? (" + autoSwitchBitrate + ")");
28255            if (getAutoSwitchBitrateFor(type)) {
28256                var topQualityIdx = getTopQualityIndexFor(type, streamId);
28257                var switchRequest = abrRulesCollection.getMaxQuality(rulesContext);
28258                var newQuality = switchRequest.quality;
28259                if (newQuality > topQualityIdx) {
28260                    newQuality = topQualityIdx;
28261                }
28262                switchHistoryDict[type].push({ oldValue: oldQuality, newValue: newQuality });
28263
28264                if (newQuality > _rulesSwitchRequestJs2['default'].NO_CHANGE && newQuality != oldQuality) {
28265                    if (abandonmentStateDict[type].state === ALLOW_LOAD || newQuality > oldQuality) {
28266                        changeQuality(type, oldQuality, newQuality, topQualityIdx, switchRequest.reason);
28267                    }
28268                } else if (debug.getLogToBrowserConsole()) {
28269                    var bufferLevel = dashMetrics.getCurrentBufferLevel(metricsModel.getReadOnlyMetricsF
28269or(type));
28270                    log('AbrController (' + type + ') stay on ' + oldQuality + '/' + topQualityIdx + ' (buffer: ' + bufferLevel + ')');
28271                }
28272            }
28273        }
28274    }
28275
28276    function setPlaybackQuality(type, streamInfo, newQuality, reason) {
28277        var id = streamInfo.id;
28278        var oldQuality = getQualityFor(type);
28279        var isInt = newQuality !== null && !isNaN(newQuality) && newQuality % 1 === 0;
28280
28281        if (!isInt) throw new Error('argument is not an integer');
28282
28283        var topQualityIdx = getTopQualityIndexFor(type, id);
28284        if (newQuality !== oldQuality && newQuality >= 0 && newQuality <= topQualityIdx) {
28285            changeQuality(type, oldQuality, newQuality, topQualityIdx, reason);
28286        }
28287    }
28288
28289    function changeQuality(type, oldQuality, newQuality, topQualityIdx, reason) {
28290        if (type && streamProcessorDict[type]) {
28291            var streamInfo = streamProcessorDict[type].getStreamInfo();
28292            var id = streamInfo ? streamInfo.id : null;
28293            if (debug.getLogToBrowserConsole()) {
28294                var bufferLevel = dashMetrics.getCurrentBufferLevel(metricsModel.getReadOnlyMetricsFor(type));
28295                log('AbrController (' + type + ') switch from ' + oldQuality + ' to ' + newQuality + '/' + topQualityIdx + ' (buffer: ' + bufferLevel + ')\n' + JSON.stringify(reason));
28296            }
28297            setQualityFor(type, id, newQuality);
28298            eventBus.trigger(_coreEventsEvents2['default'].QUALITY_CHANGE_REQUESTED, { mediaType: type, streamInfo: streamInfo, oldQuality: oldQuality, newQuality: newQuality, reason: reason });
28299        }
28300    }
28301
28302    function setAbandonmentStateFor(type, state) {
28303        abandonmentStateDict[type].state = state;
28304    }
28305
28306    function getAbandonmentStateFor(type) {
28307        return abandonmentStateDict[type].state;
28308    }
28309
28310    /**
28311     * @param {MediaInfo} mediaInfo
28312     * @param {number} bitrate A bitrate value, kbps
28313     * @param {number} latency Expected latency of connection, ms
28314     * @returns {number}
28314 A quality index <= for the given bitrate
28315     * @memberof AbrController#
28316     */
28317    function getQualityForBitrate(mediaInfo, bitrate, latency) {
28318        if (useDeadTimeLatency && latency && streamProcessorDict[mediaInfo.type].getCurrentRepresentationInfo() && streamProcessorDict[mediaInfo.type].getCurrentRepresentationInfo().fragmentDuration) {
28319            latency = latency / 1000;
28320            var fragmentDuration = streamProcessorDict[mediaInfo.type].getCurrentRepresentationInfo().fragmentDuration;
28321            if (latency > fragmentDuration) {
28322                return 0;
28323            } else {
28324                var deadTimeRatio = latency / fragmentDuration;
28325                bitrate = bitrate * (1 - deadTimeRatio);
28326            }
28327        }
28328
28329        var bitrateList = getBitrateList(mediaInfo);
28330        if (!bitrateList || bitrateList.length === 0) {
28331            return QUALITY_DEFAULT;
28332        }
28333
28334        for (var i = bitrateList.length - 1; i >= 0; i--) {
28335            var bitrateInfo = bitrateList[i];
28336            if (bitrate * 1000 >= bitrateInfo.bitrate) {
28337                return i;
28338            }
28339        }
28340        return 0;
28341    }
28342
28343    /**
28344     * @param {MediaInfo} mediaInfo
28345     * @returns {Array|null} A list of {@link BitrateInfo} objects
28346     * @memberof AbrController#
28347     */
28348    function getBitrateList(mediaInfo) {
28349        if (!mediaInfo || !mediaInfo.bitrateList) return null;
28350
28351        var bitrateList = mediaInfo.bitrateList;
28352        var type = mediaInfo.type;
28353
28354        var infoList = [];
28355        var bitrateInfo = undefined;
28356
28357        for (var i = 0, ln = bitrateList.length; i < ln; i++) {
28358            bitrateInfo = new _voBitrateInfo2['default']();
28359            bitrateInfo.mediaType = type;
28360            bitrateInfo.qualityIndex = i;
28361            bitrateInfo.bitrate = bitrateList[i].bandwidth;
28362            bitrateInfo.width = bitrateList[i].width;
28363            bitrateInfo.height = bitrateList[i].height;
28364            bitrateInfo.scanType = bitrateList[i].scanType;
28365            infoList.push(bitrateInfo);
28366        }
28367
28368        return infoList;
28369    }
28370
28371    function updateIsUsingBufferOccupancyABR(mediaType, bufferLevel) {
28372        var strategy = mediaPlayerModel.getABRStrategy();
28373
28374        if (strategy === _constantsConstants2['default'].ABR_STRATEGY_BOLA) {
28375            isUsingBufferOccupancyABRDict[mediaType] = true;
28376            return;
28377        } else if (strategy === _constantsConstants2['default'].ABR_STRATEGY_THROUGHPUT) {
28378            isUsingBufferOccupancyABRDict[mediaType] = false;
28379            return;
28380        }
28381        // else ABR_STRATEGY_DYNAMIC
28382
28383        var stableBufferTime = mediaPlayerModel.getStableBufferTime();
28384        var switchOnThreshold = stableBufferTime;
28385        var switchOffThreshold = 0.5 * stableBufferTime;
28386
28387        var useBufferABR = isUsingBufferOccupancyABRDict[mediaType];
28388        var newUseBufferABR = bufferLevel > (useBufferABR ? switchOffThreshold : switchOnThreshold); // use hysteresis to avoid oscillating rules
28389        isUsingBufferOccupancyABRDict[mediaType] = newUseBufferABR;
28390
28391        if (newUseBufferABR !== useBufferABR) {
28392            if (newUseBufferABR) {
28393                log('AbrController (' + mediaType + ') switching from throughput to buffer occupancy ABR rule (buffer: ' + bufferLevel.toFixed(3) + ').');
28394            } else {
28395                log('AbrController (' + mediaType + ') switching from buffer occupancy to throughput ABR rule (buffer: ' + bufferLevel.toFixed(3) + ').');
28396            }
28397        }
28398    }
28399
28400    function useBufferOccupancyABR(mediaType) {
28401        return isUsingBufferOccupancyABRDict[mediaType];
28402    }
28403
28404    function getThroughputHistory() {
28405        return throughputHistory;
28406    }
28407
28408    function updateTopQualityIndex(mediaInfo) {
28409        var type = mediaInfo.type;
28410        var streamId = mediaInfo.streamInfo.id;
28411        var max = mediaInfo.representationCount - 1;
28412
28413        setTopQualityIndex(type, streamId, max);
28414
28415        return max;
28416    }
28417
28418    function isPlayingAtTopQuality(streamInfo) {
28419        var isAtTop = undefined;
28420        var streamId = streamInfo.id;
28421        var audioQuality = getQualityFor(_constantsConstants2['default'].AUDIO);
28422        var videoQuality = getQualityFor(_constantsConstants2['default'].VIDEO);
28423
28424        isAtTop = audioQuality === getTopQualityIndexFor(_constantsConstants2['default'].AUDIO, streamId) && videoQuality === getTopQualityIndexFor(_constantsConstants2['default'].VIDEO, streamId);
28425
28426        return isAtTop;
28427    }
28428
28429    function getQualityFor(type) {
28430        if (type && streamProcessorDict[type]) {
28431            var streamInfo = streamProcessorDict[type].getStreamInfo();
28432            var id = streamInfo ? streamInfo.id : null;
28433            var quality = undefined;
28434
28435            if (id) {
28436                qualityDict[id] = qualityDict[id] || {};
28437
28438                if (!qualityDict[id].hasOwnProperty(type)) {
28439                    qualityDict[id][type] = QUALITY_DEFAULT;
28440                }
28441
28442                quality = qualityDict[id][type];
28443                return quality;
28444            }
28445        }
28446        return QUALITY_DEFAULT;
28447    }
28448
28449    function setQualityFor(type, id, value) {
28450        qualityDict[id] = qualityDict[id] || {};
28451        qualityDict[id][type] = value;
28452    }
28453
28454    function setTopQualityIndex(type, id, value) {
28455        topQualities[id] = topQualities[id] || {};
28456        topQualities[id][type] = value;
28457    }
28458
28459    function checkMaxBitrate(idx, type) {
28460        var newIdx = idx;
28461
28462        if (!streamProcessorDict[type]) {
28463            return newIdx;
28464        }
28465
28466        var minBitrate = getMinAllowedBitrateFor(type);
28467        if (minBitrate) {
28468            var minIdx = getQualityForBitrate(streamProcessorDict[type].getMediaInfo(), minBitrate);
28469            newIdx = Math.max(idx, minIdx);
28470        }
28471
28472        var maxBitrate = getMaxAllowedBitrateFor(type);
28473        if (maxBitrate) {
28474            var maxIdx = getQualityForBitrate(streamProcessorDict[type].getMediaInfo(), maxBitrate);
28475            newIdx = Math.min(newIdx, maxIdx);
28476        }
28477
28478        return newIdx;
28479    }
28480
28481    function checkMaxRepresentationRatio(idx, type, maxIdx) {
28482        var maxRepresentationRatio = getMaxAllowedRepresentationRatioFor(type);
28483        if (isNaN(maxRepresentationRatio) || maxRepresentationRatio >= 1 || maxRepresentationRatio < 0) {
28484            return idx;
28485        }
28486        return Math.min(idx, Math.round(maxIdx * maxRepresentationRatio));
28487    }
28488
28489    function setWindowResizeEventCalled(value) {
28490        windowResizeEventCalled = value;
28491    }
28492
28493    function setElementSize() {
28494        var hasPixelRatio = usePixelRatioInLimitBitrateByPortal && window.hasOwnProperty('devicePixelRatio');
28495        var pixelRatio = hasPixelRatio ? window.devicePixelRatio : 1;
28496        elementWidth = videoModel.getClientWidth() * pixelRatio;
28497        elementHeight = videoModel.getClientHeight() * pixelRatio;
28498    }
28499
28500    function checkPortalSize(idx, type) {
28501        if (type !== _constantsConstants2['default'].VIDEO || !limitBitrateByPortal || !streamProcessorDict[type]) {
28502            return idx;
28503        }
28504
28505        if (!windowResizeEventCalled) {
28506            setElementSize();
28507        }
28508
28509        var manifest = manifestModel.getValue();
28510        var representation = dashManifestModel.getAdaptationForType(manifest, 0, type).Representation;
28511        var newIdx = idx;
28512
28513        if (elementWidth > 0 && elementHeight > 0) {
28514            while (newIdx > 0 && representation[newIdx] && elementWidth < representation[newIdx].width && elementWidth - representation[newIdx - 1].width < representation[newIdx].width - elementWidth) {
28515                newIdx = newIdx - 1;
28516            }
28517
28518            if (representation.length - 2 >= newIdx && representation[newIdx].width === representation[newIdx + 1].width) {
28519                newIdx = Math.min(idx, newIdx + 1);
28520            }
28521        }
28522
28523        return newIdx;
28524    }
28525
28526    function onFragmentLoadProgress(e) {
28527        var type = e.request.mediaType;
28528        if (getAutoSwitchBitrateFor(type)) {
28529            var streamProcessor = streamProcessorDict[type];
28530            if (!streamProcessor) return; // There may be a fragment load in progress when we switch periods and recreated some controllers.
28531
28532            var rulesContext = (0, _rulesRulesContextJs2['default'])(context).create({
28533                abrController: instance,
28534                streamProcessor: streamProcessor,
28535                currentRequest: e.request,
28536                useBufferOccupancyABR: useBufferOccupancyABR(type)
28537            });
28538            var switchRequest = abrRulesCollection.shouldAbandonFragment(rulesContext);
28539            //Removed overrideFunc
28540            //    function (currentValue, newValue) {
28541            //        return newValue;
28542            //    });
28543
28544            if (switchRequest.quality > _rulesSwitchRequestJs2['default'].NO_CHANGE) {
28545                var fragmentModel = streamProcessor.getFragmentModel();
28546                var request = fragmentModel.getRequests({ state: _modelsFragmentModel2['default'].FRAGMENT_MODEL_LOADING, index: e.request.index })[0];
28547                if (request) {
28548                    //TODO Check if we should abort or if better to finish download. check bytesLoaded/Total
28549                    fragmentModel.abortRequests();
28550                    setAbandonmentStateFor(type, ABANDON_LOAD);
28551                    switchHistoryDict[type].reset();
28552                    switchHistoryDict[type].push({ oldValue: getQualityFor(type, streamController.getActiveStreamInfo()), newValue: switchRequest.quality, confidence: 1, reason: switchRequest.reason });
28553                    setPlaybackQuality(type, streamController.getActiveStreamInfo(), switchRequest.quality, switchRequest.reason);
28554
28555                    clearTimeout(abandonmentTimeout);
28556                    abandonmentTimeout = setTimeout(function () {
28557                        setAbandonmentStateFor(type, ALLOW_LOAD);abandonmentTimeout = null;
28558                    }, mediaPlayerModel.getAbandonLoadTimeout());
28559                }
28560            }
28561        }
28562    }
28563
28564    instance = {
28565        isPlayingAtTopQuality: isPlayingAtTopQuality,
28566        updateTopQualityIndex: updateTopQualityIndex,
28567        getThroughputHistory: getThroughputHistory,
28568        getBitrateList: getBitrateList,
28569        getQualityForBitrate: getQualityForBitrate,
28570        getMaxAllowedBitrateFor: getMaxAllowedBitrateFor,
28571        getMinAllowedBitrateFor: getMinAllowedBitrateFor,
28572        setMaxAllowedBitrateFor: setMaxAllowedBitrateFor,
28573        setMinAllowedBitrateFor: setMinAllowedBitrateFor,
28574        getMaxAllowedRepresentationRatioFor: getMaxAllowedRepresentationRatioFor,
28575        setMaxAllowedRepresentationRatioFor: setMaxAllowedRepresentationRatioFor,
28576        getInitialBitrateFor: getInitialBitrateFor,
28577        setInitialBitrateFor: setInitialBitrateFor,
28578        getInitialRepresentationRatioFor: getInitialRepresentationRatioFor,
28579        setInitialRepresentationRatioFor: setInitialRepresentationRatioFor,
28580        setAutoSwitchBitrateFor: setAutoSwitchBitrateFor,
28581        getAutoSwitchBitrateFor: getAutoSwitchBitrateFor,
28582        getUseDeadTimeLatency: getUseDeadTimeLatency,
28583        setUseDeadTimeLatency: setUseDeadTimeLatency,
28584        setLimitBitrateByPortal: setLimitBitrateByPortal,
28585        getLimitBitrateByPortal: getLimitBitrateByPortal,
28586        getUsePixelRatioInLimitBitrateByPortal: getUsePixelRatioInLimitBitrateByPortal,
28587        setUsePixelRatioInLimitBitrateByPortal: setUsePixelRatioInLimitBitrateByPortal,
28588        getQualityFor: getQualityFor,
28589        getAbandonmentStateFor: getAbandonmentStateFor,
28590        setPlaybackQuality: setPlaybackQuality,
28591        checkPlaybackQuality: checkPlaybackQuality,
28592        getTopQualityIndexFor: getTopQualityIndexFor,
28593        setElementSize: setElementSize,
28594        setWindowResizeEventCalled: setWindowResizeEventCalled,
28595        createAbrRulesCollection: createAbrRulesCollection,
28596        registerStreamType: registerStreamType,
28597        setConfig: setConfig,
28598        reset: reset
28599    };
28600
28601    setup();
28602
28603    return instance;
28604}
28605
28606AbrController.__dashjs_factory_name = 'AbrController';
28607var factory = _coreFactoryMaker2['default'].getSingletonFactory(AbrController);
28608factory.ABANDON_LOAD = ABANDON_LOAD;
28609factory.QUALITY_DEFAULT = QUALITY_DEFAULT;
28610_coreFactoryMaker2['default'].updateSingletonFactory(AbrController.__dashjs_factory_name, factory);
28611exports['default'] = factory;
28612module.exports = exports['default'];
28613
28614},{"100":100,"101":101,"140":140,"169":169,"170":170,"171":171,"172":172,"173":173,"174":174,"206":206,"224":224,"49":49,"50":50,"51":51,"54":54}],103:[function(_dereq_,module,exports){
28615/**
28616 * The copyright in this software is being made available under the BSD License,
28617 * included below. This software may be subject to other third party and contributor
28618 * rights, including patent rights, and no such rights are granted under this license.
28619 *
28620 * Copyright (c) 2013, Dash Industry Forum.
28621 * All rights reserved.
28622 *
28623 * Redistribution and use in source and binary forms, with or without modification,
28624 * are permitted provided that the following conditions are met:
28625 *  * Redistributions of source code must retain the above copyright notice, this
28626 *  list of conditions and the following disclaimer.
28627 *  * Redistributions in binary form must reproduce the above copyright notice,
28628 *  this list of conditions and the following disclaimer in the documentation and/or
28629 *  other materials provided with the distribution.
28630 *  * Neither the name of Dash Industry Forum nor the names of its
28631 *  contributors may be used to endorse or promote products derived from this software
28632 *  without specific prior written permission.
28633 *
28634 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
28635 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28636 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28637 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28638 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
28638INCLUDING, BUT
28639 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28640 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28641 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28642 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28643 *  POSSIBILITY OF SUCH DAMAGE.
28644 */
28645
28646'use strict';
28647
28648Object.defineProperty(exports, '__esModule', {
28649    value: true
28650});
28651
28652function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
28653
28654var _modelsBaseURLTreeModel = _dereq_(139);
28655
28656var _modelsBaseURLTreeModel2 = _interopRequireDefault(_modelsBaseURLTreeModel);
28657
28658var _utilsBaseURLSelector = _dereq_(189);
28659
28660var _utilsBaseURLSelector2 = _interopRequireDefault(_utilsBaseURLSelector);
28661
28662var _utilsURLUtils = _dereq_(202);
28663
28664var _utilsURLUtils2 = _interopRequireDefault(_utilsURLUtils);
28665
28666var _dashVoBaseURL = _dereq_(82);
28667
28668var _dashVoBaseURL2 = _interopRequireDefault(_dashVoBaseURL);
28669
28670var _coreFactoryMaker = _dereq_(51);
28671
28672var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
28673
28674var _coreEventBus = _dereq_(50);
28675
28676var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
28677
28678var _coreEventsEvents = _dereq_(54);
28679
28680var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
28681
28682function BaseURLController() {
28683
28684    var instance = undefined;
28685    var dashManifestModel = undefined;
28686
28687    var context = this.context;
28688    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
28689    var urlUtils = (0, _utilsURLUtils2['default'])(context).getInstance();
28690
28691    var baseURLTreeModel = undefined,
28692        baseURLSelector = undefined;
28693
28694    function onBlackListChanged(e) {
28695        baseURLTreeModel.invalidateSelectedIndexes(e.entry);
28696    }
28697
28698    function setup() {
28699        baseURLTreeModel = (0, _modelsBaseURLTreeModel2['default'])(context).create();
28700        baseURLSelector = (0, _utilsBaseURLSelector2['default'])(context).create();
28701
28702        eventBus.on(_coreEventsEvents2['default'].SERVICE_LOCATION_BLACKLIST_CHANGED, onBlackListChanged, instance);
28703    }
28704
28705    function setConfig(config) {
28706        if (config.baseURLTreeModel) {
28707            baseURLTreeModel = config.baseURLTreeModel;
28708        }
28709
28710        if (config.baseURLSelector) {
28711            baseURLSelector = config.baseURLSelector;
28712        }
28713
28714        if (config.dashManifestModel) {
28715            dashManifestModel = config.dashManifestModel;
28716        }
28717    }
28718
28719    function update(manifest) {
28720        baseURLTreeModel.update(manifest);
28721        baseURLSelector.chooseSelectorFromManifest(manifest);
28722    }
28723
28724    function resolve(path) {
28725        var baseUrls = baseURLTreeModel.getForPath(path);
28726
28727        var baseUrl = baseUrls.reduce(function (p, c) {
28728            var b = baseURLSelector.select(c);
28729
28730            if (b) {
28731                if (!urlUtils.isRelative(b.url)) {
28732                    p.url = b.url;
28733                    p.serviceLocation = b.serviceLocation;
28734                } else {
28735                    p.url = urlUtils.resolve(b.url, p.url);
28736                }
28737            } else {
28738                return new _dashVoBaseURL2['default']();
28739            }
28740
28741            return p;
28742        }, new _dashVoBaseURL2['default']());
28743
28744        if (!urlUtils.isRelative(baseUrl.url)) {
28745            return baseUrl;
28746        }
28747    }
28748
28749    function reset() {
28750        baseURLTreeModel.reset();
28751        baseURLSelector.reset();
28752    }
28753
28754    function initialize(data) {
28755
28756        // report config to baseURLTreeModel and baseURLSelector
28757        baseURLTreeModel.setConfig({
28758            dashManifestModel: dashManifestModel
28759        });
28760        baseURLSelector.setConfig({
28761            dashManifestModel: dashManifestModel
28762        });
28763
28764        update(data);
28765    }
28766
28767    instance = {
28768        reset: reset,
28769        initialize: initialize,
28770        resolve: resolve,
28771        setConfig: setConfig
28772    };
28773
28774    setup();
28775
28776    return instance;
28777}
28778
28779BaseURLController.__dashjs_factory_name = 'BaseURLController';
28780exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(BaseURLController);
28781module.exports = exports['default'];
28782
28783},{"139":139,"189":189,"202":202,"50":50,"51":51,"54":54,"82":82}],104:[function(_dereq_,module,exports){
28784/**
28785 * The copyright in this software is being made available under the BSD License,
28786 * included below. This software may be subject to other third party and contributor
28787 * rights, including patent rights, and no such rights are granted under this license.
28788 *
28789 * Copyright (c) 2013, Dash Industry Forum.
28790 * All rights reserved.
28791 *
28792 * Redistribution and use in source and binary forms, with or without modification,
28793 * are permitted provided that the following conditions are met:
28794 *  * Redistributions of source code must retain the above copyright notice, this
28795 *  list of conditions and the following disclaimer.
28796 *  * Redistributions in binary form must reproduce the above copyright notice,
28797 *  this list of conditions and the following disclaimer in the documentation and/or
28798 *  other materials provided with the distribution.
28799 *  * Neither the name of Dash Industry Forum nor the names of its
28800 *  contributors may be used to endorse or promote products derived from this software
28801 *  without specific prior written permission.
28802 *
28803 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
28804 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28805 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28806 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28807 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
28807INCLUDING, BUT
28808 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28809 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28810 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28811 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28812 *  POSSIBILITY OF SUCH DAMAGE.
28813 */
28814
28815'use strict';
28816
28817Object.defineProperty(exports, '__esModule', {
28818    value: true
28819});
28820
28821function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
28822
28823var _coreFactoryMaker = _dereq_(51);
28824
28825var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
28826
28827var _coreEventBus = _dereq_(50);
28828
28829var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
28830
28831function BlackListController(config) {
28832
28833    var blacklist = [];
28834
28835    var eventBus = (0, _coreEventBus2['default'])(this.context).getInstance();
28836    var updateEventName = config.updateEventName;
28837    var addBlacklistEventName = config.addBlacklistEventName;
28838
28839    function contains(query) {
28840        if (!blacklist.length || !query || !query.length) {
28841            return false;
28842        }
28843
28844        return blacklist.indexOf(query) !== -1;
28845    }
28846
28847    function add(entry) {
28848        if (blacklist.indexOf(entry) !== -1) {
28849            return;
28850        }
28851
28852        blacklist.push(entry);
28853
28854        eventBus.trigger(updateEventName, {
28855            entry: entry
28856        });
28857    }
28858
28859    function onAddBlackList(e) {
28860        add(e.entry);
28861    }
28862
28863    function setup() {
28864        if (addBlacklistEventName) {
28865            eventBus.on(addBlacklistEventName, onAddBlackList, this);
28866        }
28867    }
28868
28869    function reset() {
28870        blacklist = [];
28871    }
28872
28873    setup();
28874
28875    return {
28876        add: add,
28877        contains: contains,
28878        reset: reset
28879    };
28880}
28881
28882BlackListController.__dashjs_factory_name = 'BlackListController';
28883exports['default'] = _coreFactoryMaker2['default'].getClassFactory(BlackListController);
28884module.exports = exports['default'];
28885
28886},{"50":50,"51":51}],105:[function(_dereq_,module,exports){
28887/**
28888 * The copyright in this software is being made available under the BSD License,
28889 * included below. This software may be subject to other third party and contributor
28890 * rights, including patent rights, and no such rights are granted under this license.
28891 *
28892 * Copyright (c) 2013, Dash Industry Forum.
28893 * All rights reserved.
28894 *
28895 * Redistribution and use in source and binary forms, with or without modification,
28896 * are permitted provided that the following conditions are met:
28897 *  * Redistributions of source code must retain the above copyright notice, this
28898 *  list of conditions and the following disclaimer.
28899 *  * Redistributions in binary form must reproduce the above copyright notice,
28900 *  this list of conditions and the following disclaimer in the documentation and/or
28901 *  other materials provided with the distribution.
28902 *  * Neither the name of Dash Industry Forum nor the names of its
28903 *  contributors may be used to endorse or promote products derived from this software
28904 *  without specific prior written permission.
28905 *
28906 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
28907 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28908 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28909 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28910 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28911 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28912 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28913 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28914 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28915 *  POSSIBILITY OF SUCH DAMAGE.
28916 */
28917'use strict';
28918
28919Object.defineProperty(exports, '__esModule', {
28920    value: true
28921});
28922
28923function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
28924
28925var _constantsConstants = _dereq_(100);
28926
28927var _constantsConstants2 = _interopRequireDefault(_constantsConstants);
28928
28929var _modelsFragmentModel = _dereq_(140);
28930
28931var _modelsFragmentModel2 = _interopRequireDefault(_modelsFragmentModel);
28932
28933var _SourceBufferController = _dereq_(112);
28934
28935var _SourceBufferController2 = _interopRequireDefault(_SourceBufferController);
28936
28937var _AbrController = _dereq_(102);
28938
28939var _AbrController2 = _interopRequireDefault(_AbrController);
28940
28941var _MediaController = _dereq_(108);
28942
28943var _MediaController2 = _interopRequireDefault(_MediaController);
28944
28945var _coreEventBus = _dereq_(50);
28946
28947var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
28948
28949var _coreEventsEvents = _dereq_(54);
28950
28951var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
28952
28953var _utilsBoxParser = _dereq_(190);
28954
28955var _utilsBoxParser2 = _interopRequireDefault(_utilsBoxParser);
28956
28957var _coreFactoryMaker = _dereq_(51);
28958
28959var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
28960
28961var _coreDebug = _dereq_(49);
28962
28963var _coreDebug2 = _interopRequireDefault(_coreDebug);
28964
28965var _utilsInitCache = _dereq_(196);
28966
28967var _utilsInitCache2 = _interopRequireDefault(_utilsInitCache);
28968
28969var BUFFER_LOADED = 'bufferLoaded';
28970var BUFFER_EMPTY = 'bufferStalled';
28971var STALL_THRESHOLD = 0.5;
28972
28973var BUFFER_CONTROLLER_TYPE = 'BufferController';
28974
28975function BufferController(config) {
28976
28977    var context = this.context;
28978    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
28979    var metricsModel = config.metricsModel;
28980    var mediaPlayerModel = config.mediaPlayerModel;
28981    var sourceBufferController = config.sourceBufferController;
28982    var errHandler = config.errHandler;
28983    var streamController = config.streamController;
28984    var mediaController = config.mediaController;
28985    var adapter = config.adapter;
28986    var textController = config.textController;
28987    var abrController = config.abrController;
28988    var playbackController = config.playbackController;
28989    var type = config.type;
28990    var streamProcessor = config.streamProcessor;
28991
28992    var instance = undefined,
28993        log = undefined,
28994        requiredQuality = undefined,
28995        isBufferingCompleted = undefined,
28996        bufferLevel = undefined,
28997        criticalBufferLevel = undefined,
28998        mediaSource = undefined,
28999        maxAppendedIndex = undefined,
29000        lastIndex = undefined,
29001        buffer = undefined,
29002        bufferState = undefined,
29003        appendedBytesInfo = undefined,
29004        wallclockTicked = undefined,
29005        appendingMediaChunk = undefined,
29006        isAppendingInProgress = undefined,
29007        isPruningInProgress = undefined,
29008        initCache = undefined,
29009        seekStartTime = undefined,
29010        seekClearedBufferingCompleted = undefined,
29011        isSafariOnMac = undefined;
29012
29013    function setup() {
29014        log = (0, _coreDebug2['default'])(context).getInstance().log.bind(instance);
29015        initCache = (0, _utilsInitCache2['default'])(context).getInstance();
29016
29017        resetInitialSettings();
29018    }
29019
29020    function getBufferControllerType() {
29021        return BUFFER_CONTROLLER_TYPE;
29022    }
29023
29024    function initialize(Source) {
29025        setMediaSource(Source);
29026
29027        requiredQuality = abrController.getQualityFor(type, streamProcessor.getStreamInfo());
29028        var ua = navigator.userAgent.toLowerCase();
29029        //This whole test is just for safari on a mac.
29030        isSafariOnMac = /safari/.test(ua) && /mac/.test(ua) && !/chrome/.test(ua) && !/windows phone/.test(ua);
29031
29032        eventBus.on(_coreEventsEvents2['default'].DATA_UPDATE_COMPLETED, onDataUpdateCompleted, this);
29033        eventBus.on(_coreEventsEvents2['default'].INIT_FRAGMENT_LOADED, onInitFragmentLoaded, this);
29034        eventBus.on(_coreEventsEvents2['default'].MEDIA_FRAGMENT_LOADED, onMediaFragmentLoaded, this);
29035        eventBus.on(_coreEventsEvents2['default'].QUALITY_CHANGE_REQUESTED, onQualityChanged, this);
29036        eventBus.on(_coreEventsEvents2['default'].STREAM_COMPLETED, onStreamCompleted, this);
29037        eventBus.on(_coreEventsEvents2['default'].PLAYBACK_PROGRESS, onPlaybackProgression, this);
29038        eventBus.on(_coreEventsEvents2['default'].PLAYBACK_TIME_UPDATED, onPlaybackProgression, this);
29039        eventBus.on(_coreEventsEvents2['default'].PLAYBACK_RATE_CHANGED, onPlaybackRateChanged, this);
29040        eventBus.on(_coreEventsEvents2['default'].PLAYBACK_SEEKING, onPlaybackSeeking, this);
29041        eventBus.on(_coreEventsEvents2['default'].WALLCLOCK_TIME_UPDATED, onWallclockTimeUpdated, this);
29042        eventBus.on(_coreEventsEvents2['default'].CURRENT_TRACK_CHANGED, onCurrentTrackChanged, this, _coreEventBus2['default'].EVENT_PRIORITY_HIGH);
29043        eventBus.on(_coreEventsEvents2['default'].SOURCEBUFFER_APPEND_COMPLETED, onAppended, this);
29044        eventBus.on(_coreEventsEvents2['default'].SOURCEBUFFER_REMOVE_COMPLETED, onRemoved, this);
29045
29046        if (isSafariOnMac) {
29047            eventBus.on(_coreEventsEvents2['default'].PLAYBACK_SEEKED, onSeeked, this);
29048        }
29049    }
29050
29051    function createBuffer(mediaInfo) {
29052        if (!mediaInfo || !mediaSource || !streamProcessor) return null;
29053
29054        var sourceBuffer = null;
29055
29056        try {
29057            sourceBuffer = sourceBufferController.createSourceBuffer(mediaSource, mediaInfo);
29058
29059            if (sourceBuffer && sourceBuffer.hasOwnProperty(_constantsConstants2['default'].INITIALIZE)) {
29060                sourceBuffer.initialize(type, streamProcessor);
29061            }
29062        } catch (e) {
29063            errHandler.mediaSourceError('Error creating ' + type + ' source buffer.');
29064        }
29065        setBuffer(sourceBuffer);
29066        updateBufferTimestampOffset(streamProcessor.getRepresentationInfoForQuality(requiredQuality).MSETimeOffset);
29067        return sourceBuffer;
29068    }
29069
29070    function isActive() {
29071        return streamProcessor && streamController ? streamProcessor.getStreamInfo().id === streamController.getActiveStreamInfo().id : false;
29072    }
29073
29074    function onInitFragmentLoaded(e) {
29075        if (e.fragmentModel !== streamProcessor.getFragmentModel()) return;
29076        log('Init fragment finished loading saving to', type + '\'s init cache');
29077        initCache.save(e.chunk);
29078        appendToBuffer(e.chunk);
29079    }
29080
29081    function switchInitData(streamId, representationId) {
29082        var chunk = initCache.extract(streamId, representationId);
29083        if (chunk) {
29084            appendToBuffer(chunk);
29085        } else {
29086            eventBus.trigger(_coreEventsEvents2['default'].INIT_REQUESTED, { sender: instance });
29087        }
29088    }
29089
29090    function onMediaFragmentLoaded(e) {
29091        if (e.fragmentModel !== streamProcessor.getFragmentModel()) return;
29092
29093        var chunk = e.chunk;
29094        var bytes = chunk.bytes;
29095        var quality = chunk.quality;
29096        var currentRepresentation = streamProcessor.getRepresentationInfoForQuality(quality);
29097        var eventStreamMedia = adapter.getEventsFor(currentRepresentation.mediaInfo, streamProcessor);
29098        var eventStreamTrack = adapter.getEventsFor(currentRepresentation, streamProcessor);
29099
29100        if (eventStreamMedia && eventStreamMedia.length > 0 || eventStreamTrack && eventStreamTrack.length > 0) {
29101            var request = streamProcessor.getFragmentModel().getRequests({
29102                state: _modelsFragmentModel2['default'].FRAGMENT_MODEL_EXECUTED,
29103                quality: quality,
29104                index: chunk.index
29105            })[0];
29106
29107            var events = handleInbandEvents(bytes, request, eventStreamMedia, eventStreamTrack);
29108            streamProcessor.getEventController().addInbandEvents(events);
29109        }
29110
29111        appendToBuffer(chunk);
29112    }
29113
29114    function appendToBuffer(chunk) {
29115        isAppendingInProgress = true;
29116        appendedBytesInfo = chunk;
29117        sourceBufferController.append(buffer, chunk);
29118
29119        if (chunk.mediaInfo.type === _constantsConstants2['default'].VIDEO) {
29120            eventBus.trigger(_coreEventsEvents2['default'].VIDEO_CHUNK_RECEIVED, { chunk: chunk });
29121        }
29122    }
29123
29124    function onAppended(e) {
29125        if (buffer === e.buffer) {
29126            if (e.error) {
29127                if (e.error.code === _SourceBufferController2['default'].QUOTA_EXCEEDED_ERROR_CODE) {
29128                    criticalBufferLevel = sourceBufferController.getTotalBufferedTime(buffer) * 0.8;
29129                }
29130                if (e.error.code === _SourceBufferController2['default'].QUOTA_EXCEEDED_ERROR_CODE || !hasEnoughSpaceToAppend()) {
29131                    eventBus.trigger(_coreEventsEvents2['default'].QUOTA_EXCEEDED, { sender: instance, criticalBufferLevel: criticalBufferLevel }); //Tells ScheduleController to stop scheduling.
29132                    clearBuffer(getClearRange()); // Then we clear the buffer and onCleared event will tell ScheduleController to start scheduling again.
29133                }
29134                return;
29135            }
29136
29137            if (appendedBytesInfo && !isNaN(appendedBytesInfo.index)) {
29138                maxAppendedIndex = Math.max(appendedBytesInfo.index, maxAppendedIndex);
29139                checkIfBufferingCompleted();
29140            }
29141
29142            var ranges = sourceBufferController.getAllRanges(buffer);
29143            if (ranges && ranges.length > 0) {
29144                for (var i = 0, len = ranges.length; i < len; i++) {
29145                    log('Buffered Range for type:', type, ':', ranges.start(i), ' - ', ranges.end(i));
29146                }
29147            }
29148
29149            onPlaybackProgression();
29150            isAppendingInProgress = false;
29151            if (appendedBytesInfo) {
29152                eventBus.trigger(_coreEventsEvents2['default'].BYTES_APPENDED, {
29153                    sender: instance,
29154                    quality: appendedBytesInfo.quality,
29155                    startTime: appendedBytesInfo.start,
29156                    index: appendedBytesInfo.index,
29157                    bufferedRanges: ranges
29158                });
29159            }
29160        }
29161    }
29162
29163    function onQualityChanged(e) {
29164        if (requiredQuality === e.newQuality || type !== e.mediaType || streamProcessor.getStreamInfo().id !== e.streamInfo.id) return;
29165
29166        updateBufferTimestampOffset(streamProcessor.getRepresentationInfoForQuality(e.newQuality).MSETimeOffset);
29167        requiredQuality = e.newQuality;
29168    }
29169
29170    //**********************************************************************
29171    // START Buffer Level, State & Sufficiency Handling.
29172    //**********************************************************************
29173    function onPlaybackSeeking() {
29174        if (isBufferingCompleted) {
29175            seekClearedBufferingCompleted = true;
29176            isBufferingCompleted = false;
29177            maxAppendedIndex = 0;
29178        }
29179        seekStartTime = undefined;
29180        onPlaybackProgression();
29181    }
29182
29183    function getWorkingTime() {
29184        // This function returns current working time for buffer (either start time or current time if playback has started)
29185        var ret = playbackController.getTime();
29186
29187        if (seekStartTime) {
29188            // if there is a seek start time, the first buffer data will be available on maximum value between first buffer range value and seek start time.
29189            var ranges = sourceBufferController.getAllRanges(buffer);
29190            if (ranges && ranges.length) {
29191                ret = Math.max(ranges.start(0), seekStartTime);
29192            }
29193        }
29194        return ret;
29195    }
29196
29197    function onPlaybackProgression() {
29198        updateBufferLevel();
29199        addBufferMetrics();
29200    }
29201
29202    function updateBufferLevel() {
29203        if (playbackController) {
29204            bufferLevel = sourceBufferController.getBufferLength(buffer, getWorkingTime());
29205            eventBus.trigger(_coreEventsEvents2['default'].BUFFER_LEVEL_UPDATED, { sender: instance, bufferLevel: bufferLevel });
29206            checkIfSufficientBuffer();
29207        }
29208    }
29209
29210    function addBufferMetrics() {
29211        if (!isActive()) return;
29212        metricsModel.addBufferState(type, bufferState, streamProcessor.getScheduleController().getBufferTarget());
29213        metricsModel.addBufferLevel(type, new Date(), bufferLevel * 1000);
29214    }
29215
29216    function checkIfBufferingCompleted() {
29217        var isLastIdxAppended = maxAppendedIndex >= lastIndex - 1; // Handles 0 and non 0 based request index
29218        if (isLastIdxAppended && !isBufferingCompleted) {
29219            isBufferingCompleted = true;
29220            eventBus.trigger(_coreEventsEvents2['default'].BUFFERING_COMPLETED, { sender: instance, streamInfo: streamProcessor.getStreamInfo() });
29221        }
29222    }
29223
29224    function checkIfSufficientBuffer() {
29225        // No need to check buffer if type is not audio or video (for example if several errors occur during text parsing, so that the buffer cannot be filled, no error must occur on video playback)
29226        if (type !== 'audio' && type !== 'video') return;
29227
29228        if (seekClearedBufferingCompleted && !isBufferingCompleted && playbackController && playbackController.getTimeToStreamEnd() - bufferLevel < STALL_THRESHOLD) {
29229            seekClearedBufferingCompleted = false;
29230            isBufferingCompleted = true;
29231            eventBus.trigger(_coreEventsEvents2['default'].BUFFERING_COMPLETED, { sender: instance, streamInfo: streamProcessor.getStreamInfo() });
29232        }
29233
29234        if (bufferLevel < STALL_THRESHOLD && !isBufferingCompleted) {
29235            notifyBufferStateChanged(BUFFER_EMPTY);
29236        } else {
29237            notifyBufferStateChanged(BUFFER_LOADED);
29238        }
29239    }
29240
29241    function notifyBufferStateChanged(state) {
29242        if (bufferState === state || type === _constantsConstants2['default'].FRAGMENTED_TEXT && textController.getAllTracksAreDisabled()) return;
29243        bufferState = state;
29244        addBufferMetrics();
29245        eventBus.trigger(_coreEventsEvents2['default'].BUFFER_LEVEL_STATE_CHANGED, { sender: instance, state: state, mediaType: type, streamInfo: streamProcessor.getStreamInfo() });
29246        eventBus.trigger(state === BUFFER_LOADED ? _coreEventsEvents2['default'].BUFFER_LOADED : _coreEventsEvents2['default'].BUFFER_EMPTY, { mediaType: type });
29247        log(state === BUFFER_LOADED ? 'Got enough buffer to start.' : 'Waiting for more buffer before starting playback.');
29248    }
29249
29250    function handleInbandEvents(data, request, mediaInbandEvents, trackInbandEvents) {
29251        var fragmentStartTime = Math.max(isNaN(request.startTime) ? 0 : request.startTime, 0);
29252        var eventStreams = [];
29253        var events = [];
29254
29255        /* Extract the possible schemeIdUri : If a DASH client detects an event message box with a scheme that is not defined in MPD, the client is expected to ignore it */
29256        var inbandEvents = mediaInbandEvents.concat(trackInbandEvents);
29257        for (var i = 0, ln = inbandEvents.length; i < ln; i++) {
29258            eventStreams[inbandEvents[i].schemeIdUri] = inbandEvents[i];
29259        }
29260
29261        var isoFile = (0, _utilsBoxParser2['default'])(context).getInstance().parse(data);
29262        var eventBoxes = isoFile.getBoxes('emsg');
29263
29264        for (var i = 0, ln = eventBoxes.length; i < ln; i++) {
29265            var _event = adapter.getEvent(eventBoxes[i], eventStreams, fragmentStartTime);
29266
29267            if (_event) {
29268                events.push(_event);
29269            }
29270        }
29271
29272        return events;
29273    }
29274
29275    function hasEnoughSpaceToAppend() {
29276        var totalBufferedTime = sourceBufferController.getTotalBufferedTime(buffer);
29277        return totalBufferedTime < criticalBufferLevel;
29278    }
29279
29280    /* prune buffer on our own in background to avoid browsers pruning buffer silently */
29281    function pruneBuffer() {
29282        if (!buffer) return;
29283        if (type === _constantsConstants2['default'].FRAGMENTED_TEXT) return;
29284        var start = buffer.buffered.length ? buffer.buffered.start(0) : 0;
29285        var bufferToPrune = playbackController.getTime() - start - mediaPlayerModel.getBufferToKeep();
29286        if (bufferToPrune > 0) {
29287            log('pruning buffer: ' + bufferToPrune + ' seconds.');
29288            isPruningInProgress = true;
29289            sourceBufferController.remove(buffer, 0, Math.round(start + bufferToPrune), mediaSource);
29290        }
29291    }
29292
29293    function getClearRange(threshold) {
29294        if (!buffer) return null;
29295
29296        // we need to remove data that is more than one fragment before the video currentTime
29297        var currentTime = playbackController.getTime();
29298        var req = streamProcessor.getFragmentModel().getRequests({ state: _modelsFragmentModel2['default'].FRAGMENT_MODEL_EXECUTED, time: currentTime, threshold: threshold })[0];
29299        var range = sourceBufferController.getBufferRange(buffer, currentTime);
29300
29301        var removeEnd = req && !isNaN(req.startTime) ? req.startTime : Math.floor(currentTime);
29302        if (range === null && buffer.buffered.length > 0) {
29303            removeEnd = buffer.buffered.end(buffer.buffered.length - 1);
29304        }
29305
29306        return {
29307            start: buffer.buffered.start(0),
29308            end: removeEnd
29309        };
29310    }
29311
29312    function clearBuffer(range) {
29313        if (!range || !buffer) return;
29314        sourceBufferController.remove(buffer, range.start, range.end, mediaSource);
29315    }
29316
29317    function onRemoved(e) {
29318        if (buffer !== e.buffer) return;
29319
29320        if (isPruningInProgress) {
29321            isPruningInProgress = false;
29322        }
29323
29324        updateBufferLevel();
29325        eventBus.trigger(_coreEventsEvents2['default'].BUFFER_CLEARED, { sender: instance, from: e.from, to: e.to, hasEnoughSpaceToAppend: hasEnoughSpaceToAppend() });
29326        //TODO - REMEMBER removed a timerout hack calling clearBuffer after manifestInfo.minBufferTime * 1000 if !hasEnoughSpaceToAppend() Aug 04 2016
29327    }
29328
29329    function updateBufferTimestampOffset(MSETimeOffset) {
29330        // Each track can have its own @presentationTimeOffset, so we should set the offset
29331        // if it has changed after switching the quality or updating an mpd
29332        if (buffer && buffer.timestampOffset !== MSETimeOffset && !isNaN(MSETimeOffset)) {
29333            buffer.timestampOffset = MSETimeOffset;
29334        }
29335    }
29336
29337    function onDataUpdateCompleted(e) {
29338        if (e.sender.getStreamProcessor() !== streamProcessor || e.error) return;
29339        updateBufferTimestampOffset(e.currentRepresentation.MSETimeOffset);
29340    }
29341
29342    function onStreamCompleted(e) {
29343        if (e.fragmentModel !== streamProcessor.getFragmentModel()) return;
29344        lastIndex = e.request.index;
29345        checkIfBufferingCompleted();
29346    }
29347
29348    function onCurrentTrackChanged(e) {
29349        if (!buffer || e.newMediaInfo.type !== type || e.newMediaInfo.streamInfo.id !== streamProcessor.getStreamInfo().id) return;
29350        if (mediaController.getSwitchMode(type) === _MediaController2['default'].TRACK_SWITCH_MODE_ALWAYS_REPLACE) {
29351            clearBuffer(getClearRange(0));
29352        }
29353    }
29354
29355    function onWallclockTimeUpdated() {
29356        wallclockTicked++;
29357        var secondsElapsed = wallclockTicked * (mediaPlayerModel.getWallclockTimeUpdateInterval() / 1000);
29358        if (secondsElapsed >= mediaPlayerModel.getBufferPruningInterval() && !isAppendingInProgress) {
29359            wallclockTicked = 0;
29360            pruneBuffer();
29361        }
29362    }
29363
29364    /*
29365     * Listener set only for MacOS Safari.
29366     * MacOS Safari doesn't like buffer being appended to the start of a buffered range.
29367     * It removes a little bit of buffer just after the segment we append.
29368     * Therefore, let's remove all buffer ahead of us after a seek.
29369     */
29370    function onSeeked() {
29371        removeBufferAhead(playbackController.getTime());
29372    }
29373
29374    //Removes buffered ranges ahead. It will not remove anything part of the current buffer timeRange.
29375    function removeBufferAhead(time) {
29376        var ranges = sourceBufferController.getAllRanges(buffer);
29377        for (var i = 0; i < ranges.length; i++) {
29378            if (ranges.start(i) > time) {
29379                log('Removing buffer from: ' + ranges.start(i) + '-' + ranges.end(i));
29380                sourceBufferController.remove(buffer, ranges.start(i), ranges.end(i), mediaSource);
29381            }
29382        }
29383    }
29384
29385    function onPlaybackRateChanged() {
29386        checkIfSufficientBuffer();
29387    }
29388
29389    function getType() {
29390        return type;
29391    }
29392
29393    function getStreamProcessor() {
29394        return streamProcessor;
29395    }
29396
29397    function setSeekStartTime(value) {
29398        seekStartTime = value;
29399    }
29400
29401    function getBuffer() {
29402        return buffer;
29403    }
29404
29405    function setBuffer(value) {
29406        buffer = value;
29407    }
29408
29409    function getBufferLevel() {
29410        return bufferLevel;
29411    }
29412
29413    function setMediaSource(value) {
29414        mediaSource = value;
29415    }
29416
29417    function getMediaSource() {
29418        return mediaSource;
29419    }
29420
29421    function getIsBufferingCompleted() {
29422        return isBufferingCompleted;
29423    }
29424
29425    function resetInitialSettings() {
29426        criticalBufferLevel = Number.POSITIVE_INFINITY;
29427        bufferState = BUFFER_EMPTY;
29428        requiredQuality = _AbrController2['default'].QUALITY_DEFAULT;
29429        lastIndex = Number.POSITIVE_INFINITY;
29430        maxAppendedIndex = 0;
29431        appendedBytesInfo = null;
29432        appendingMediaChunk = false;
29433        isBufferingCompleted = false;
29434        isAppendingInProgress = false;
29435        isPruningInProgress = false;
29436        seekClearedBufferingCompleted = false;
29437        bufferLevel = 0;
29438        wallclockTicked = 0;
29439    }
29440
29441    function reset(errored) {
29442        eventBus.off(_coreEventsEvents2['default'].DATA_UPDATE_COMPLETED, onDataUpdateCompleted, this);
29443        eventBus.off(_coreEventsEvents2['default'].QUALITY_CHANGE_REQUESTED, onQualityChanged, this);
29444        eventBus.off(_coreEventsEvents2['default'].INIT_FRAGMENT_LOADED, onInitFragmentLoaded, this);
29445        eventBus.off(_coreEventsEvents2['default'].MEDIA_FRAGMENT_LOADED, onMediaFragmentLoaded, this);
29446        eventBus.off(_coreEventsEvents2['default'].STREAM_COMPLETED, onStreamCompleted, this);
29447        eventBus.off(_coreEventsEvents2['default'].CURRENT_TRACK_CHANGED, onCurrentTrackChanged, this);
29448        eventBus.off(_coreEventsEvents2['default'].PLAYBACK_PROGRESS, onPlaybackProgression, this);
29449        eventBus.off(_coreEventsEvents2['default'].PLAYBACK_TIME_UPDATED, onPlaybackProgression, this);
29450        eventBus.off(_coreEventsEvents2['default'].PLAYBACK_RATE_CHANGED, onPlaybackRateChanged, this);
29451        eventBus.off(_coreEventsEvents2['default'].PLAYBACK_SEEKING, onPlaybackSeeking, this);
29452        eventBus.off(_coreEventsEvents2['default'].WALLCLOCK_TIME_UPDATED, onWallclockTimeUpdated, this);
29453        eventBus.off(_coreEventsEvents2['default'].SOURCEBUFFER_APPEND_COMPLETED, onAppended, this);
29454        eventBus.off(_coreEventsEvents2['default'].SOURCEBUFFER_REMOVE_COMPLETED, onRemoved, this);
29455
29456        if (isSafariOnMac) {
29457            eventBus.off(_coreEventsEvents2['default'].PLAYBACK_SEEKED, onSeeked, this);
29458        }
29459
29460        resetInitialSettings();
29461
29462        if (!errored) {
29463            sourceBufferController.abort(mediaSource, buffer);
29464            sourceBufferController.removeSourceBuffer(mediaSource, buffer);
29465        }
29466
29467        buffer = null;
29468    }
29469
29470    instance = {
29471        getBufferControllerType: getBufferControllerType,
29472        initialize: initialize,
29473        createBuffer: createBuffer,
29474        getType: getType,
29475        getStreamProcessor: getStreamProcessor,
29476        setSeekStartTime: setSeekStartTime,
29477        getBuffer: getBuffer,
29478        setBuffer: setBuffer,
29479        getBufferLevel: getBufferLevel,
29480        setMediaSource: setMediaSource,
29481        getMediaSource: getMediaSource,
29482        getIsBufferingCompleted: getIsBufferingCompleted,
29483        switchInitData: switchInitData,
29484        reset: reset
29485    };
29486
29487    setup();
29488    return instance;
29489}
29490
29491BufferController.__dashjs_factory_name = BUFFER_CONTROLLER_TYPE;
29492var factory = _coreFactoryMaker2['default'].getClassFactory(BufferController);
29493factory.BUFFER_LOADED = BUFFER_LOADED;
29494factory.BUFFER_EMPTY = BUFFER_EMPTY;
29495_coreFactoryMaker2['default'].updateClassFactory(BufferController.__dashjs_factory_name, factory);
29496exports['default'] = factory;
29497module.exports = exports['default'];
29498
29499},{"100":100,"102":102,"108":108,"112":112,"140":140,"190":190,"196":196,"49":49,"50":50,"51":51,"54":54}],106:[function(_dereq_,module,exports){
29500/**
29501 * The copyright in this software is being made available under the BSD License,
29502 * included below. This software may be subject to other third party and contributor
29503 * rights, including patent rights, and no such rights are granted under this license.
29504 *
29505 * Copyright (c) 2013, Dash Industry Forum.
29506 * All rights reserved.
29507 *
29508 * Redistribution and use in source and binary forms, with or without modification,
29509 * are permitted provided that the following conditions are met:
29510 *  * Redistributions of source code must retain the above copyright notice, this
29511 *  list of conditions and the following disclaimer.
29512 *  * Redistributions in binary form must reproduce the above copyright notice,
29513 *  this list of conditions and the following disclaimer in the documentation and/or
29514 *  other materials provided with the distribution.
29515 *  * Neither the name of Dash Industry Forum nor the names of its
29516 *  contributors may be used to endorse or promote products derived from this software
29517 *  without specific prior written permission.
29518 *
29519 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
29520 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29521 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29522 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29523 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29524 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29525 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29526 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29527 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29528 *  POSSIBILITY OF SUCH DAMAGE.
29529 */
29530
29531'use strict';
29532
29533Object.defineProperty(exports, '__esModule', {
29534    value: true
29535});
29536
29537function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
29538
29539var _coreFactoryMaker = _dereq_(51);
29540
29541var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
29542
29543var _coreDebug = _dereq_(49);
29544
29545var _coreDebug2 = _interopRequireDefault(_coreDebug);
29546
29547var _coreEventBus = _dereq_(50);
29548
29549var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
29550
29551function EventController() {
29552
29553    var MPD_RELOAD_SCHEME = 'urn:mpeg:dash:event:2012';
29554    var MPD_RELOAD_VALUE = 1;
29555
29556    var context = this.context;
29557    var log = (0, _coreDebug2['default'])(context).getInstance().log;
29558    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
29559
29560    var instance = undefined,
29561        inlineEvents = undefined,
29562        // Holds all Inline Events not triggered yet
29563    inbandEvents = undefined,
29564        // Holds all Inband Events not triggered yet
29565    activeEvents = undefined,
29566        // Holds all Events currently running
29567    eventInterval = undefined,
29568        // variable holding the setInterval
29569    refreshDelay = undefined,
29570        // refreshTime for the setInterval
29571    presentationTimeThreshold = undefined,
29572        manifestModel = undefined,
29573        manifestUpdater = undefined,
29574        playbackController = undefined,
29575        isStarted = undefined;
29576
29577    function setup() {
29578        resetInitialSettings();
29579    }
29580
29581    function resetInitialSettings() {
29582        isStarted = false;
29583        inlineEvents = {};
29584        inbandEvents = {};
29585        activeEvents = {};
29586        eventInterval = null;
29587        refreshDelay = 100;
29588        presentationTimeThreshold = refreshDelay / 1000;
29589    }
29590
29591    function checkSetConfigCall() {
29592        if (!manifestModel || !manifestUpdater || !playbackController) {
29593            throw new Error('setConfig function has to be called previously');
29594        }
29595    }
29596
29597    function clear() {
29598        if (eventInterval !== null && isStarted) {
29599            clearInterval(eventInterval);
29600            eventInterval = null;
29601            isStarted = false;
29602        }
29603    }
29604
29605    function start() {
29606        checkSetConfigCall();
29607        log('Start Event Controller');
29608        if (!isStarted && !isNaN(refreshDelay)) {
29609            isStarted = true;
29610            eventInterval = setInterval(onEventTimer, refreshDelay);
29611        }
29612    }
29613
29614    /**
29615     * Add events to the eventList. Events that are not in the mpd anymore but not triggered yet will still be deleted
29616     * @param {Array.<Object>} values
29617     */
29618    function addInlineEvents(values) {
29619        checkSetConfigCall();
29620
29621        inlineEvents = {};
29622
29623        if (values) {
29624            for (var i = 0; i < values.length; i++) {
29625                var event = values[i];
29626                inlineEvents[event.id] = event;
29627                log('Add inline event with id ' + event.id);
29628            }
29629        }
29630        log('Added ' + values.length + ' inline events');
29631    }
29632
29633    /**
29634     * i.e. processing of any one event message box with the same id is sufficient
29635     * @param {Array.<Object>} values
29636     */
29637    function addInbandEvents(values) {
29638        checkSetConfigCall();
29639
29640        for (var i = 0; i < values.length; i++) {
29641            var event = values[i];
29642            if (!(event.id in inbandEvents)) {
29643                inbandEvents[event.id] = event;
29644                log('Add inband event with id ' + event.id);
29645            } else {
29646                log('Repeated event with id ' + event.id);
29647            }
29648        }
29649    }
29650
29651    /**
29652     * Remove events which are over from the list
29653     */
29654    function removeEvents() {
29655        if (activeEvents) {
29656            var currentVideoTime = playbackController.getTime();
29657            var eventIds = Object.keys(activeEvents);
29658
29659            for (var i = 0; i < eventIds.length; i++) {
29660                var eventId = eventIds[i];
29661                var curr = activeEvents[eventId];
29662                if (curr !== null && (curr.duration + curr.presentationTime) / curr.eventStream.timescale < currentVideoTime) {
29663                    log('Remove Event ' + eventId + ' at time ' + currentVideoTime);
29664                    curr = null;
29665                    delete activeEvents[eventId];
29666                }
29667            }
29668        }
29669    }
29670
29671    /**
29672     * Iterate through the eventList and trigger/remove the events
29673     */
29674    function onEventTimer() {
29675        triggerEvents(inbandEvents);
29676        triggerEvents(inlineEvents);
29677        removeEvents();
29678    }
29679
29680    function refreshManifest() {
29681        checkSetConfigCall();
29682        manifestUpdater.refreshManifest();
29683    }
29684
29685    function triggerEvents(events) {
29686        var currentVideoTime = playbackController.getTime();
29687        var presentationTime;
29688
29689        /* == Trigger events that are ready == */
29690        if (events) {
29691            var eventIds = Object.keys(events);
29692            for (var i = 0; i < eventIds.length; i++) {
29693                var eventId = eventIds[i];
29694                var curr = events[eventId];
29695
29696                if (curr !== undefined) {
29697                    presentationTime = curr.presentationTime / curr.eventStream.timescale;
29698                    if (presentationTime === 0 || presentationTime <= currentVideoTime && presentationTime + presentationTimeThreshold > currentVideoTime) {
29699                        log('Start Event ' + eventId + ' at ' + currentVideoTime);
29700                        if (curr.duration > 0) {
29701                            activeEvents[eventId] = curr;
29702                        }
29703                        if (curr.eventStream.schemeIdUri == MPD_RELOAD_SCHEME && curr.eventStream.value == MPD_RELOAD_VALUE) {
29704                            refreshManifest();
29705                        } else {
29706                            eventBus.trigger(curr.eventStream.schemeIdUri, { event: curr });
29707                        }
29708                        delete events[eventId];
29709                    }
29710                }
29711            }
29712        }
29713    }
29714
29715    function setConfig(config) {
29716        if (!config) return;
29717
29718        if (config.manifestModel) {
29719            manifestModel = config.manifestModel;
29720        }
29721
29722        if (config.manifestUpdater) {
29723            manifestUpdater = config.manifestUpdater;
29724        }
29725
29726        if (config.playbackController) {
29727            playbackController = config.playbackController;
29728        }
29729    }
29730
29731    function reset() {
29732        clear();
29733        resetInitialSettings();
29734    }
29735
29736    instance = {
29737        addInlineEvents: addInlineEvents,
29738        addInbandEvents: addInbandEvents,
29739        clear: clear,
29740        start: start,
29741        setConfig: setConfig,
29742        reset: reset
29743    };
29744
29745    setup();
29746
29747    return instance;
29748}
29749
29750EventController.__dashjs_factory_name = 'EventController';
29751exports['default'] = _coreFactoryMaker2['default'].getClassFactory(EventController);
29752module.exports = exports['default'];
29753
29754},{"49":49,"50":50,"51":51}],107:[function(_dereq_,module,exports){
29755/**
29756 * The copyright in this software is being made available under the BSD License,
29757 * included below. This software may be subject to other third party and contributor
29758 * rights, including patent rights, and no such rights are granted under this license.
29759 *
29760 * Copyright (c) 2013, Dash Industry Forum.
29761 * All rights reserved.
29762 *
29763 * Redistribution and use in source and binary forms, with or without modification,
29764 * are permitted provided that the following conditions are met:
29765 *  * Redistributions of source code must retain the above copyright notice, this
29766 *  list of conditions and the following disclaimer.
29767 *  * Redistributions in binary form must reproduce the above copyright notice,
29768 *  this list of conditions and the following disclaimer in the documentation and/or
29769 *  other materials provided with the distribution.
29770 *  * Neither the name of Dash Industry Forum nor the names of its
29771 *  contributors may be used to endorse or promote products derived from this software
29772 *  without specific prior written permission.
29773 *
29774 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
29775 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29776 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29777 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29778 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29779 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29780 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29781 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29782 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29783 *  POSSIBILITY OF SUCH DAMAGE.
29784 */
29785'use strict';
29786
29787Object.defineProperty(exports, '__esModule', {
29788    value: true
29789});
29790
29791function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
29792
29793var _constantsConstants = _dereq_(100);
29794
29795var _constantsConstants2 = _interopRequireDefault(_constantsConstants);
29796
29797var _voMetricsHTTPRequest = _dereq_(224);
29798
29799var _voDataChunk = _dereq_(208);
29800
29801var _voDataChunk2 = _interopRequireDefault(_voDataChunk);
29802
29803var _modelsFragmentModel = _dereq_(140);
29804
29805var _modelsFragmentModel2 = _interopRequireDefault(_modelsFragmentModel);
29806
29807var _FragmentLoader = _dereq_(90);
29808
29809var _FragmentLoader2 = _interopRequireDefault(_FragmentLoader);
29810
29811var _utilsRequestModifier = _dereq_(200);
29812
29813var _utilsRequestModifier2 = _interopRequireDefault(_utilsRequestModifier);
29814
29815var _coreEventBus = _dereq_(50);
29816
29817var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
29818
29819var _coreEventsEvents = _dereq_(54);
29820
29821var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
29822
29823var _coreFactoryMaker = _dereq_(51);
29824
29825var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
29826
29827var _coreDebug = _dereq_(49);
29828
29829var _coreDebug2 = _interopRequireDefault(_coreDebug);
29830
29831function FragmentController(config) {
29832
29833    var context = this.context;
29834    var log = (0, _coreDebug2['default'])(context).getInstance().log;
29835    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
29836
29837    var errHandler = config.errHandler;
29838    var mediaPlayerModel = config.mediaPlayerModel;
29839    var metricsModel = config.metricsModel;
29840
29841    var instance = undefined,
29842        fragmentModels = undefined;
29843
29844    function setup() {
29845        resetInitialSettings();
29846        eventBus.on(_coreEventsEvents2['default'].FRAGMENT_LOADING_COMPLETED, onFragmentLoadingCompleted, instance);
29847    }
29848
29849    function getModel(type) {
29850        var model = fragmentModels[type];
29851        if (!model) {
29852            model = (0, _modelsFragmentModel2['default'])(context).create({
29853                metricsModel: metricsModel,
29854                fragmentLoader: (0, _FragmentLoader2['default'])(context).create({
29855                    metricsModel: metricsModel,
29856                    mediaPlayerModel: mediaPlayerModel,
29857                    errHandler: errHandler,
29858                    requestModifier: (0, _utilsRequestModifier2['default'])(context).getInstance()
29859                })
29860            });
29861
29862            fragmentModels[type] = model;
29863        }
29864
29865        return model;
29866    }
29867
29868    function isInitializationRequest(request) {
29869        return request && request.type && request.type === _voMetricsHTTPRequest.HTTPRequest.INIT_SEGMENT_TYPE;
29870    }
29871
29872    function resetInitialSettings() {
29873        for (var model in fragmentModels) {
29874            fragmentModels[model].reset();
29875        }
29876        fragmentModels = {};
29877    }
29878
29879    function reset() {
29880        eventBus.off(_coreEventsEvents2['default'].FRAGMENT_LOADING_COMPLETED, onFragmentLoadingCompleted, this);
29881        resetInitialSettings();
29882    }
29883
29884    function createDataChunk(bytes, request, streamId) {
29885        var chunk = new _voDataChunk2['default']();
29886
29887        chunk.streamId = streamId;
29888        chunk.mediaInfo = request.mediaInfo;
29889        chunk.segmentType = request.type;
29890        chunk.start = request.startTime;
29891        chunk.duration = request.duration;
29892        chunk.end = chunk.start + chunk.duration;
29893        chunk.bytes = bytes;
29894        chunk.index = request.index;
29895        chunk.quality = request.quality;
29896        chunk.representationId = request.representationId;
29897
29898        return chunk;
29899    }
29900
29901    function onFragmentLoadingCompleted(e) {
29902        if (fragmentModels[e.request.mediaType] !== e.sender) {
29903            return;
29904        }
29905
29906        var request = e.request;
29907        var bytes = e.response;
29908        var isInit = isInitializationRequest(request);
29909        var streamInfo = request.mediaInfo.streamInfo;
29910
29911        if (e.error) {
29912            if (e.request.mediaType === _constantsConstants2['default'].AUDIO || e.request.mediaType === _constantsConstants2['default'].VIDEO) {
29913                // add service location to blacklist controller - only for audio or video. text should not set errors
29914                eventBus.trigger(_coreEventsEvents2['default'].SERVICE_LOCATION_BLACKLIST_ADD, { entry: e.request.serviceLocation });
29915            }
29916        }
29917
29918        if (!bytes || !streamInfo) {
29919            log('No ' + request.mediaType + ' bytes to push or stream is inactive.');
29920            return;
29921        }
29922
29923        var chunk = createDataChunk(bytes, request, streamInfo.id);
29924        eventBus.trigger(isInit ? _coreEventsEvents2['default'].INIT_FRAGMENT_LOADED : _coreEventsEvents2['default'].MEDIA_FRAGMENT_LOADED, {
29925            chunk: chunk,
29926            fragmentModel: e.sender
29927        });
29928    }
29929
29930    instance = {
29931        getModel: getModel,
29932        isInitializationRequest: isInitializationRequest,
29933        reset: reset
29934    };
29935
29936    setup();
29937
29938    return instance;
29939}
29940
29941FragmentController.__dashjs_factory_name = 'FragmentController';
29942exports['default'] = _coreFactoryMaker2['default'].getClassFactory(FragmentController);
29943module.exports = exports['default'];
29944
29945},{"100":100,"140":140,"200":200,"208":208,"224":224,"49":49,"50":50,"51":51,"54":54,"90":90}],108:[function(_dereq_,module,exports){
29946/**
29947 * The copyright in this software is being made available under the BSD License,
29948 * included below. This software may be subject to other third party and contributor
29949 * rights, including patent rights, and no such rights are granted under this license.
29950 *
29951 * Copyright (c) 2013, Dash Industry Forum.
29952 * All rights reserved.
29953 *
29954 * Redistribution and use in source and binary forms, with or without modification,
29955 * are permitted provided that the following conditions are met:
29956 *  * Redistributions of source code must retain the above copyright notice, this
29957 *  list of conditions and the following disclaimer.
29958 *  * Redistributions in binary form must reproduce the above copyright notice,
29959 *  this list of conditions and the following disclaimer in the documentation and/or
29960 *  other materials provided with the distribution.
29961 *  * Neither the name of Dash Industry Forum nor the names of its
29962 *  contributors may be used to endorse or promote products derived from this software
29963 *  without specific prior written permission.
29964 *
29965 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
29966 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29967 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29968 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29969 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29970 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29971 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29972 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29973 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29974 *  POSSIBILITY OF SUCH DAMAGE.
29975 */
29976'use strict';
29977
29978Object.defineProperty(exports, '__esModule', {
29979    value: true
29980});
29981
29982function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
29983
29984var _constantsConstants = _dereq_(100);
29985
29986var _constantsConstants2 = _interopRequireDefault(_constantsConstants);
29987
29988var _coreEventsEvents = _dereq_(54);
29989
29990var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
29991
29992var _coreEventBus = _dereq_(50);
29993
29994var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
29995
29996var _coreFactoryMaker = _dereq_(51);
29997
29998var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
29999
30000var _coreDebug = _dereq_(49);
30001
30002var _coreDebug2 = _interopRequireDefault(_coreDebug);
30003
30004var TRACK_SWITCH_MODE_NEVER_REPLACE = 'neverReplace';
30005var TRACK_SWITCH_MODE_ALWAYS_REPLACE = 'alwaysReplace';
30006var TRACK_SELECTION_MODE_HIGHEST_BITRATE = 'highestBitrate';
30007var TRACK_SELECTION_MODE_WIDEST_RANGE = 'widestRange';
30008var DEFAULT_INIT_TRACK_SELECTION_MODE = TRACK_SELECTION_MODE_HIGHEST_BITRATE;
30009
30010function MediaController() {
30011
30012    var context = this.context;
30013    var log = (0, _coreDebug2['default'])(context).getInstance().log;
30014    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
30015
30016    var instance = undefined,
30017        tracks = undefined,
30018        initialSettings = undefined,
30019        selectionMode = undefined,
30020        switchMode = undefined,
30021        errHandler = undefined,
30022        domStorage = undefined;
30023
30024    var validTrackSwitchModes = [TRACK_SWITCH_MODE_ALWAYS_REPLACE, TRACK_SWITCH_MODE_NEVER_REPLACE];
30025
30026    var validTrackSelectionModes = [TRACK_SELECTION_MODE_HIGHEST_BITRATE, TRACK_SELECTION_MODE_WIDEST_RANGE];
30027
30028    function setup() {
30029        reset();
30030    }
30031
30032    /**
30033     * @param {string} type
30034     * @param {StreamInfo} streamInfo
30035     * @memberof MediaController#
30036     */
30037    function checkInitialMediaSettingsForType(type, streamInfo) {
30038        var settings = getInitialSettings(type);
30039        var tracksForType = getTracksFor(type, streamInfo);
30040        var tracks = [];
30041
30042        if (type === _constantsConstants2['default'].FRAGMENTED_TEXT) {
30043            // Choose the first track
30044            setTrack(tracksForType[0]);
30045            return;
30046        }
30047
30048        if (!settings) {
30049            settings = domStorage.getSavedMediaSettings(type);
30050            setInitialSettings(type, settings);
30051        }
30052
30053        if (!tracksForType || tracksForType.length === 0) return;
30054
30055        if (settings) {
30056            tracksForType.forEach(function (track) {
30057                if (matchSettings(settings, track)) {
30058                    tracks.push(track);
30059                }
30060            });
30061        }
30062
30063        if (tracks.length === 0) {
30064            setTrack(selectInitialTrack(tracksForType));
30065        } else {
30066            if (tracks.length > 1) {
30067                setTrack(selectInitialTrack(tracks));
30068            } else {
30069                setTrack(tracks[0]);
30070            }
30071        }
30072    }
30073
30074    /**
30075     * @param {MediaInfo} track
30076     * @memberof MediaController#
30077     */
30078    function addTrack(track) {
30079        var mediaType = track ? track.type : null;
30080        var streamId = track ? track.streamInfo.id : null;
30081        var initSettings = getInitialSettings(mediaType);
30082
30083        if (!track || !isMultiTrackSupportedByType(mediaType)) return;
30084
30085        tracks[streamId] = tracks[streamId] || createTrackInfo();
30086
30087        if (tracks[streamId][mediaType].list.indexOf(track) >= 0) return;
30088
30089        tracks[streamId][mediaType].list.push(track);
30090
30091        if (initSettings && matchSettings(initSettings, track) && !getCurrentTrackFor(mediaType, track.streamInfo)) {
30092            setTrack(track);
30093        }
30094    }
30095
30096    /**
30097     * @param {string} type
30098     * @param {StreamInfo} streamInfo
30099     * @returns {Array}
30100     * @memberof MediaController#
30101     */
30102    function getTracksFor(type, streamInfo) {
30103        if (!type || !streamInfo) return [];
30104
30105        var id = streamInfo.id;
30106
30107        if (!tracks[id] || !tracks[id][type]) return [];
30108
30109        return tracks[id][type].list;
30110    }
30111
30112    /**
30113     * @param {string} type
30114     * @param {StreamInfo} streamInfo
30115     * @returns {Object|null}
30116     * @memberof MediaController#
30117     */
30118    function getCurrentTrackFor(type, streamInfo) {
30119        if (!type || !streamInfo || streamInfo && !tracks[streamInfo.id]) return null;
30120        return tracks[streamInfo.id][type].current;
30121    }
30122
30123    /**
30124     * @param {MediaInfo} track
30125     * @returns {boolean}
30126     * @memberof MediaController#
30127     */
30128    function isCurrentTrack(track) {
30129        var type = track.type;
30130        var id = track.streamInfo.id;
30131
30132        return tracks[id] && tracks[id][type] && isTracksEqual(tracks[id][type].current, track);
30133    }
30134
30135    /**
30136     * @param {MediaInfo} track
30137     * @memberof MediaController#
30138     */
30139    function setTrack(track) {
30140        if (!track) return;
30141
30142        var type = track.type;
30143        var streamInfo = track.streamInfo;
30144        var id = streamInfo.id;
30145        var current = getCurrentTrackFor(type, streamInfo);
30146
30147        if (!tracks[id] || !tracks[id][type] || current && isTracksEqual(track, current)) return;
30148
30149        tracks[id][type].current = track;
30150
30151        if (current) {
30152            eventBus.trigger(_coreEventsEvents2['default'].CURRENT_TRACK_CHANGED, { oldMediaInfo: current, newMediaInfo: track, switchMode: switchMode[type] });
30153        }
30154
30155        var settings = extractSettings(track);
30156
30157        if (!settings || !tracks[id][type].storeLastSettings) return;
30158
30159        if (settings.roles) {
30160            settings.role = settings.roles[0];
30161            delete settings.roles;
30162        }
30163
30164        if (settings.accessibility) {
30165            settings.accessibility = settings.accessibility[0];
30166        }
30167
30168        if (settings.audioChannelConfiguration) {
30169            settings.audioChannelConfiguration = settings.audioChannelConfiguration[0];
30170        }
30171
30172        domStorage.setSavedMediaSettings(type, settings);
30173    }
30174
30175    /**
30176     * @param {string} type
30177     * @param {Object} value
30178     * @memberof MediaController#
30179     */
30180    function setInitialSettings(type, value) {
30181        if (!type || !value) return;
30182
30183        initialSettings[type] = value;
30184    }
30185
30186    /**
30187     * @param {string} type
30188     * @returns {Object|null}
30189     * @memberof MediaController#
30190     */
30191    function getInitialSettings(type) {
30192        if (!type) return null;
30193
30194        return initialSettings[type];
30195    }
30196
30197    /**
30198     * @param {string} type
30199     * @param {string} mode
30200     * @memberof MediaController#
30201     */
30202    function setSwitchMode(type, mode) {
30203        var isModeSupported = validTrackSwitchModes.indexOf(mode) !== -1;
30204
30205        if (!isModeSupported) {
30206            log('track switch mode is not supported: ' + mode);
30207            return;
30208        }
30209
30210        switchMode[type] = mode;
30211    }
30212
30213    /**
30214     * @param {string} type
30215     * @returns {string} mode
30216     * @memberof MediaController#
30217     */
30218    function getSwitchMode(type) {
30219        return switchMode[type];
30220    }
30221
30222    /**
30223     * @param {string} mode
30224     * @memberof MediaController#
30225     */
30226    function setSelectionModeForInitialTrack(mode) {
30227        var isModeSupported = validTrackSelectionModes.indexOf(mode) !== -1;
30228
30229        if (!isModeSupported) {
30230            log('track selection mode is not supported: ' + mode);
30231            return;
30232        }
30233        selectionMode = mode;
30234    }
30235
30236    /**
30237     * @returns {string} mode
30238     * @memberof MediaController#
30239     */
30240    function getSelectionModeForInitialTrack() {
30241        return selectionMode || DEFAULT_INIT_TRACK_SELECTION_MODE;
30242    }
30243
30244    /**
30245     * @param {string} type
30246     * @returns {boolean}
30247     * @memberof MediaController#
30248     */
30249    function isMultiTrackSupportedByType(type) {
30250        return type === _constantsConstants2['default'].AUDIO || type === _constantsConstants2['default'].VIDEO || type === _constantsConstants2['default'].TEXT || type === _constantsConstants2['default'].FRAGMENTED_TEXT;
30251    }
30252
30253    /**
30254     * @param {MediaInfo} t1 - first track to compare
30255     * @param {MediaInfo} t2 - second track to compare
30256     * @returns {boolean}
30257     * @memberof MediaController#
30258     */
30259    function isTracksEqual(t1, t2) {
30260        var sameId = t1.id === t2.id;
30261        var sameViewpoint = t1.viewpoint === t2.viewpoint;
30262        var sameLang = t1.lang === t2.lang;
30263        var sameRoles = t1.roles.toString() === t2.roles.toString();
30264        var sameAccessibility = t1.accessibility.toString() === t2.accessibility.toString();
30265        var sameAudioChannelConfiguration = t1.audioChannelConfiguration.toString() === t2.audioChannelConfiguration.toString();
30266
30267        return sameId && sameViewpoint && sameLang && sameRoles && sameAccessibility && sameAudioChannelConfiguration;
30268    }
30269
30270    function setConfig(config) {
30271        if (!config) return;
30272
30273        if (config.errHandler) {
30274            errHandler = config.errHandler;
30275        }
30276
30277        if (config.domStorage) {
30278            domStorage = config.domStorage;
30279        }
30280    }
30281
30282    /**
30283     * @memberof MediaController#
30284     */
30285    function reset() {
30286        tracks = {};
30287        resetInitialSettings();
30288        resetSwitchMode();
30289    }
30290
30291    function extractSettings(mediaInfo) {
30292        var settings = {
30293            lang: mediaInfo.lang,
30294            viewpoint: mediaInfo.viewpoint,
30295            roles: mediaInfo.roles,
30296            accessibility: mediaInfo.accessibility,
30297            audioChannelConfiguration: mediaInfo.audioChannelConfiguration
30298        };
30299        var notEmpty = settings.lang || settings.viewpoint || settings.role && settings.role.length > 0 || settings.accessibility && settings.accessibility.length > 0 || settings.audioChannelConfiguration && settings.audioChannelConfiguration.length > 0;
30300
30301        return notEmpty ? settings : null;
30302    }
30303
30304    function matchSettings(settings, track) {
30305        var matchLang = !settings.lang || settings.lang === track.lang;
30306        var matchViewPoint = !settings.viewpoint || settings.viewpoint === track.viewpoint;
30307        var matchRole = !settings.role || !!track.roles.filter(function (item) {
30308            return item === settings.role;
30309        })[0];
30310        var matchAccessibility = !settings.accessibility || !!track.accessibility.filter(function (item) {
30311            return item === settings.accessibility;
30312        })[0];
30313        var matchAudioChannelConfiguration = !settings.audioChannelConfiguration || !!track.audioChannelConfiguration.filter(function (item) {
30314            return item === settings.audioChannelConfiguration;
30315        })[0];
30316
30317        return matchLang && matchViewPoint && matchRole && matchAccessibility && matchAudioChannelConfiguration;
30318    }
30319
30320    function resetSwitchMode() {
30321        switchMode = {
30322            audio: TRACK_SWITCH_MODE_ALWAYS_REPLACE,
30323            video: TRACK_SWITCH_MODE_NEVER_REPLACE
30324        };
30325    }
30326
30327    function resetInitialSettings() {
30328        initialSettings = {
30329            audio: null,
30330            video: null
30331        };
30332    }
30333
30334    function selectInitialTrack(tracks) {
30335        var mode = getSelectionModeForInitialTrack();
30336        var tmpArr = [];
30337        var getTracksWithHighestBitrate = function getTracksWithHighestBitrate(trackArr) {
30338            var max = 0;
30339            var result = [];
30340            var tmp = undefined;
30341
30342            trackArr.forEach(function (track) {
30343                tmp = Math.max.apply(Math, track.bitrateList.map(function (obj) {
30344                    return obj.bandwidth;
30345                }));
30346
30347                if (tmp > max) {
30348                    max = tmp;
30349                    result = [track];
30350                } else if (tmp === max) {
30351                    result.push(track);
30352                }
30353            });
30354
30355            return result;
30356        };
30357        var getTracksWithWidestRange = function getTracksWithWidestRange(trackArr) {
30358            var max = 0;
30359            var result = [];
30360            var tmp = undefined;
30361
30362            trackArr.forEach(function (track) {
30363                tmp = track.representationCount;
30364
30365                if (tmp > max) {
30366                    max = tmp;
30367                    result = [track];
30368                } else if (tmp === max) {
30369                    result.push(track);
30370                }
30371            });
30372
30373            return result;
30374        };
30375
30376        switch (mode) {
30377            case TRACK_SELECTION_MODE_HIGHEST_BITRATE:
30378                tmpArr = getTracksWithHighestBitrate(tracks);
30379
30380                if (tmpArr.length > 1) {
30381                    tmpArr = getTracksWithWidestRange(tmpArr);
30382                }
30383                break;
30384            case TRACK_SELECTION_MODE_WIDEST_RANGE:
30385                tmpArr = getTracksWithWidestRange(tracks);
30386
30387                if (tmpArr.length > 1) {
30388                    tmpArr = getTracksWithHighestBitrate(tracks);
30389                }
30390                break;
30391            default:
30392                log('track selection mode is not supported: ' + mode);
30393                break;
30394        }
30395
30396        return tmpArr[0];
30397    }
30398
30399    function createTrackInfo() {
30400        return {
30401            audio: {
30402                list: [],
30403                storeLastSettings: true,
30404                current: null
30405            },
30406            video: {
30407                list: [],
30408                storeLastSettings: true,
30409                current: null
30410            },
30411            text: {
30412                list: [],
30413                storeLastSettings: true,
30414                current: null
30415            },
30416            fragmentedText: {
30417                list: [],
30418                storeLastSettings: true,
30419                current: null
30420            }
30421        };
30422    }
30423
30424    instance = {
30425        checkInitialMediaSettingsForType: checkInitialMediaSettingsForType,
30426        addTrack: addTrack,
30427        getTracksFor: getTracksFor,
30428        getCurrentTrackFor: getCurrentTrackFor,
30429        isCurrentTrack: isCurrentTrack,
30430        setTrack: setTrack,
30431        setInitialSettings: setInitialSettings,
30432        getInitialSettings: getInitialSettings,
30433        setSwitchMode: setSwitchMode,
30434        getSwitchMode: getSwitchMode,
30435        setSelectionModeForInitialTrack: setSelectionModeForInitialTrack,
30436        getSelectionModeForInitialTrack: getSelectionModeForInitialTrack,
30437        isMultiTrackSupportedByType: isMultiTrackSupportedByType,
30438        isTracksEqual: isTracksEqual,
30439        setConfig: setConfig,
30440        reset: reset
30441    };
30442
30443    setup();
30444
30445    return instance;
30446}
30447
30448MediaController.__dashjs_factory_name = 'MediaController';
30449var factory = _coreFactoryMaker2['default'].getSingletonFactory(MediaController);
30450factory.TRACK_SWITCH_MODE_NEVER_REPLACE = TRACK_SWITCH_MODE_NEVER_REPLACE;
30451factory.TRACK_SWITCH_MODE_ALWAYS_REPLACE = TRACK_SWITCH_MODE_ALWAYS_REPLACE;
30452factory.TRACK_SELECTION_MODE_HIGHEST_BITRATE = TRACK_SELECTION_MODE_HIGHEST_BITRATE;
30453factory.TRACK_SELECTION_MODE_WIDEST_RANGE = TRACK_SELECTION_MODE_WIDEST_RANGE;
30454factory.DEFAULT_INIT_TRACK_SELECTION_MODE = DEFAULT_INIT_TRACK_SELECTION_MODE;
30455_coreFactoryMaker2['default'].updateSingletonFactory(MediaController.__dashjs_factory_name, factory);
30456exports['default'] = factory;
30457module.exports = exports['default'];
30458
30459},{"100":100,"49":49,"50":50,"51":51,"54":54}],109:[function(_dereq_,module,exports){
30460/**
30461 * The copyright in this software is being made available under the BSD License,
30462 * included below. This software may be subject to other third party and contributor
30463 * rights, including patent rights, and no such rights are granted under this license.
30464 *
30465 * Copyright (c) 2013, Dash Industry Forum.
30466 * All rights reserved.
30467 *
30468 * Redistribution and use in source and binary forms, with or without modification,
30469 * are permitted provided that the following conditions are met:
30470 *  * Redistributions of source code must retain the above copyright notice, this
30471 *  list of conditions and the following disclaimer.
30472 *  * Redistributions in binary form must reproduce the above copyright notice,
30473 *  this list of conditions and the following disclaimer in the documentation and/or
30474 *  other materials provided with the distribution.
30475 *  * Neither the name of Dash Industry Forum nor the names of its
30476 *  contributors may be used to endorse or promote products derived from this software
30477 *  without specific prior written permission.
30478 *
30479 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
30480 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
30481 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30482 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
30483 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
30483INCLUDING, BUT
30484 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30485 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30486 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30487 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30488 *  POSSIBILITY OF SUCH DAMAGE.
30489 */
30490'use strict';
30491
30492Object.defineProperty(exports, '__esModule', {
30493    value: true
30494});
30495
30496function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
30497
30498var _coreFactoryMaker = _dereq_(51);
30499
30500var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
30501
30502function MediaSourceController() {
30503
30504    var instance = undefined;
30505
30506    function createMediaSource() {
30507
30508        var hasWebKit = ('WebKitMediaSource' in window);
30509        var hasMediaSource = ('MediaSource' in window);
30510
30511        if (hasMediaSource) {
30512            return new MediaSource();
30513        } else if (hasWebKit) {
30514            return new WebKitMediaSource();
30515        }
30516
30517        return null;
30518    }
30519
30520    function attachMediaSource(source, videoModel) {
30521
30522        var objectURL = window.URL.createObjectURL(source);
30523
30524        videoModel.setSource(objectURL);
30525
30526        return objectURL;
30527    }
30528
30529    function detachMediaSource(videoModel) {
30530        videoModel.setSource(null);
30531    }
30532
30533    function setDuration(source, value) {
30534
30535        if (source.duration != value) source.duration = value;
30536
30537        return source.duration;
30538    }
30539
30540    function setSeekable(source, start, end) {
30541        if (typeof source.setLiveSeekableRange === 'function' && typeof source.clearLiveSeekableRange === 'function' && source.readyState === 'open' && start >= 0 && start < end) {
30542            source.clearLiveSeekableRange();
30543            source.setLiveSeekableRange(start, end);
30544        }
30545    }
30546
30547    function signalEndOfStream(source) {
30548
30549        var buffers = source.sourceBuffers;
30550        var ln = buffers.length;
30551
30552        if (source.readyState !== 'open') return;
30553
30554        for (var i = 0; i < ln; i++) {
30555            if (buffers[i].updating) return;
30556            if (buffers[i].buffered.length === 0) return;
30557        }
30558
30559        source.endOfStream();
30560    }
30561
30562    instance = {
30563        createMediaSource: createMediaSource,
30564        attachMediaSource: attachMediaSource,
30565        detachMediaSource: detachMediaSource,
30566        setDuration: setDuration,
30567        setSeekable: setSeekable,
30568        signalEndOfStream: signalEndOfStream
30569    };
30570
30571    return instance;
30572}
30573
30574MediaSourceController.__dashjs_factory_name = 'MediaSourceController';
30575exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(MediaSourceController);
30576module.exports = exports['default'];
30577
30578},{"51":51}],110:[function(_dereq_,module,exports){
30579/**
30580 * The copyright in this software is being made available under the BSD License,
30581 * included below. This software may be subject to other third party and contributor
30582 * rights, including patent rights, and no such rights are granted under this license.
30583 *
30584 * Copyright (c) 2013, Dash Industry Forum.
30585 * All rights reserved.
30586 *
30587 * Redistribution and use in source and binary forms, with or without modification,
30588 * are permitted provided that the following conditions are met:
30589 *  * Redistributions of source code must retain the above copyright notice, this
30590 *  list of conditions and the following disclaimer.
30591 *  * Redistributions in binary form must reproduce the above copyright notice,
30592 *  this list of conditions and the following disclaimer in the documentation and/or
30593 *  other materials provided with the distribution.
30594 *  * Neither the name of Dash Industry Forum nor the names of its
30595 *  contributors may be used to endorse or promote products derived from this software
30596 *  without specific prior written permission.
30597 *
30598 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
30599 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
30600 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30601 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
30602 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
30602INCLUDING, BUT
30603 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30604 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30605 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30606 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30607 *  POSSIBILITY OF SUCH DAMAGE.
30608 */
30609'use strict';
30610
30611Object.defineProperty(exports, '__esModule', {
30612    value: true
30613});
30614
30615function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
30616
30617var _constantsConstants = _dereq_(100);
30618
30619var _constantsConstants2 = _interopRequireDefault(_constantsConstants);
30620
30621var _BufferController = _dereq_(105);
30622
30623var _BufferController2 = _interopRequireDefault(_BufferController);
30624
30625var _modelsURIQueryAndFragmentModel = _dereq_(144);
30626
30627var _modelsURIQueryAndFragmentModel2 = _interopRequireDefault(_modelsURIQueryAndFragmentModel);
30628
30629var _coreEventBus = _dereq_(50);
30630
30631var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
30632
30633var _coreEventsEvents = _dereq_(54);
30634
30635var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
30636
30637var _coreFactoryMaker = _dereq_(51);
30638
30639var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
30640
30641var _coreDebug = _dereq_(49);
30642
30643var _coreDebug2 = _interopRequireDefault(_coreDebug);
30644
30645function PlaybackController() {
30646
30647    var context = this.context;
30648    var log = (0, _coreDebug2['default'])(context).getInstance().log;
30649    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
30650
30651    var instance = undefined,
30652        streamController = undefined,
30653        metricsModel = undefined,
30654        dashMetrics = undefined,
30655        manifestModel = undefined,
30656        dashManifestModel = undefined,
30657        adapter = undefined,
30658        videoModel = undefined,
30659        currentTime = undefined,
30660        liveStartTime = undefined,
30661        wallclockTimeIntervalId = undefined,
30662        commonEarliestTime = undefined,
30663        bufferedRange = undefined,
30664        streamInfo = undefined,
30665        isDynamic = undefined,
30666        mediaPlayerModel = undefined,
30667        playOnceInitialized = undefined;
30668
30669    function setup() {
30670        reset();
30671    }
30672
30673    function initialize(StreamInfo) {
30674        streamInfo = StreamInfo;
30675        addAllListeners();
30676        isDynamic = streamInfo.manifestInfo.isDynamic;
30677        liveStartTime = streamInfo.start;
30678        eventBus.on(_coreEventsEvents2['default'].DATA_UPDATE_COMPLETED, onDataUpdateCompleted, this);
30679        eventBus.on(_coreEventsEvents2['default'].BYTES_APPENDED, onBytesAppended, this);
30680        eventBus.on(_coreEventsEvents2['default'].BUFFER_LEVEL_STATE_CHANGED, onBufferLevelStateChanged, this);
30681        eventBus.on(_coreEventsEvents2['default'].PERIOD_SWITCH_STARTED, onPeriodSwitchStarted, this);
30682
30683        if (playOnceInitialized) {
30684            playOnceInitialized = false;
30685            play();
30686        }
30687    }
30688
30689    function onPeriodSwitchStarted(e) {
30690        if (!isDynamic && e.fromStreamInfo && commonEarliestTime[e.fromStreamInfo.id] !== undefined) {
30691            delete bufferedRange[e.fromStreamInfo.id];
30692            delete commonEarliestTime[e.fromStreamInfo.id];
30693        }
30694    }
30695
30696    function getTimeToStreamEnd() {
30697        var startTime = getStreamStartTime(true);
30698        var offset = isDynamic ? startTime - streamInfo.start : 0;
30699        return startTime + (streamInfo.duration - offset) - getTime();
30700    }
30701
30702    function play() {
30703        if (videoModel && videoModel.getElement()) {
30704            videoModel.play();
30705        } else {
30706            playOnceInitialized = true;
30707        }
30708    }
30709
30710    function isPaused() {
30711        return videoModel ? videoModel.isPaused() : null;
30712    }
30713
30714    function pause() {
30715        if (videoModel) {
30716            videoModel.pause();
30717        }
30718    }
30719
30720    function isSeeking() {
30721        return videoModel ? videoModel.isSeeking() : null;
30722    }
30723
30724    function seek(time) {
30725        if (videoModel) {
30726            eventBus.trigger(_coreEventsEvents2['default'].PLAYBACK_SEEK_ASKED);
30727            log('Requesting seek to time: ' + time);
30728            videoModel.setCurrentTime(time);
30729        }
30730    }
30731
30732    function getTime() {
30733        return videoModel ? videoModel.getTime() : null;
30734    }
30735
30736    function getPlaybackRate() {
30737        return videoModel ? videoModel.getPlaybackRate() : null;
30738    }
30739
30740    function getPlayedRanges() {
30741        return videoModel ? videoModel.getPlayedRanges() : null;
30742    }
30743
30744    function getEnded() {
30745        return videoModel ? videoModel.getEnded() : null;
30746    }
30747
30748    function getIsDynamic() {
30749        return isDynamic;
30750    }
30751
30752    function getStreamController() {
30753        return streamController;
30754    }
30755
30756    function setLiveStartTime(value) {
30757        liveStartTime = value;
30758    }
30759
30760    function getLiveStartTime() {
30761        return liveStartTime;
30762    }
30763
30764    /**
30765     * Computes the desirable delay for the live edge to avoid a risk of getting 404 when playing at the bleeding edge
30766     * @param {number} fragmentDuration - seconds?
30767     * @param {number} dvrWindowSize - seconds?
30768     * @returns {number} object
30769     * @memberof PlaybackController#
30770     */
30771    function computeLiveDelay(fragmentDuration, dvrWindowSize) {
30772        var mpd = dashManifestModel.getMpd(manifestModel.getValue());
30773
30774        var delay = undefined;
30775        var END_OF_PLAYLIST_PADDING = 10;
30776
30777        if (mediaPlayerModel.getUseSuggestedPresentationDelay() && mpd.hasOwnProperty(_constantsConstants2['default'].SUGGESTED_PRESENTATION_DELAY)) {
30778            delay = mpd.suggestedPresentationDelay;
30779        } else if (mediaPlayerModel.getLiveDelay()) {
30780            delay = mediaPlayerModel.getLiveDelay(); // If set by user, this value takes precedence
30781        } else if (!isNaN(fragmentDuration)) {
30782                delay = fragmentDuration * mediaPlayerModel.getLiveDelayFragmentCount();
30783            } else {
30784                delay = streamInfo.manifestInfo.minBufferTime * 2;
30785            }
30786
30787        if (dvrWindowSize > 0) {
30788            // cap target latency to:
30789            // - dvrWindowSize / 2 for short playlists
30790            // - dvrWindowSize - END_OF_PLAYLIST_PADDING for longer playlists
30791            var targetDelayCapping = Math.max(dvrWindowSize - END_OF_PLAYLIST_PADDING, dvrWindowSize / 2);
30792            return Math.min(delay, targetDelayCapping);
30793        } else {
30794            return delay;
30795        }
30796    }
30797
30798    function reset() {
30799        currentTime = 0;
30800        liveStartTime = NaN;
30801        wallclockTimeIntervalId = null;
30802        playOnceInitialized = false;
30803        commonEarliestTime = {};
30804        bufferedRange = {};
30805        if (videoModel) {
30806            eventBus.off(_coreEventsEvents2['default'].DATA_UPDATE_COMPLETED, onDataUpdateCompleted, this);
30807            eventBus.off(_coreEventsEvents2['default'].BUFFER_LEVEL_STATE_CHANGED, onBufferLevelStateChanged, this);
30808            eventBus.off(_coreEventsEvents2['default'].BYTES_APPENDED, onBytesAppended, this);
30809            stopUpdatingWallclockTime();
30810            removeAllListeners();
30811        }
30812        videoModel = null;
30813        streamInfo = null;
30814        isDynamic = null;
30815    }
30816
30817    function setConfig(config) {
30818        if (!config) return;
30819
30820        if (config.streamController) {
30821            streamController = config.streamController;
30822        }
30823        if (config.metricsModel) {
30824            metricsModel = config.metricsModel;
30825        }
30826        if (config.dashMetrics) {
30827            dashMetrics = config.dashMetrics;
30828        }
30829        if (config.manifestModel) {
30830            manifestModel = config.manifestModel;
30831        }
30832        if (config.dashManifestModel) {
30833            dashManifestModel = config.dashManifestModel;
30834        }
30835        if (config.mediaPlayerModel) {
30836            mediaPlayerModel = config.mediaPlayerModel;
30837        }
30838        if (config.adapter) {
30839            adapter = config.adapter;
30840        }
30841        if (config.videoModel) {
30842            videoModel = config.videoModel;
30843        }
30844    }
30845
30846    /**
30847     * @param {boolean} ignoreStartOffset - ignore URL fragment start offset if true
30848     * @returns {number} object
30849     * @memberof PlaybackController#
30850     */
30851    function getStreamStartTime(ignoreStartOffset) {
30852        var presentationStartTime = undefined;
30853        var fragData = (0, _modelsURIQueryAndFragmentModel2['default'])(context).getInstance().getURIFragmentData();
30854        var startTimeOffset = NaN;
30855
30856        if (fragData) {
30857            var fragS = parseInt(fragData.s, 10);
30858            var fragT = parseInt(fragData.t, 10);
30859            if (!ignoreStartOffset) {
30860                startTimeOffset = !isNaN(fragS) ? fragS : fragT;
30861            }
30862        } else {
30863            // handle case where no media fragments are parsed from the manifest URL
30864            startTimeOffset = 0;
30865        }
30866
30867        if (isDynamic) {
30868            if (!isNaN(startTimeOffset) && startTimeOffset > 1262304000) {
30869                presentationStartTime = startTimeOffset - streamInfo.manifestInfo.availableFrom.getTime() / 1000;
30870
30871                if (presentationStartTime > liveStartTime || presentationStartTime < liveStartTime - streamInfo.manifestInfo.DVRWindowSize) {
30872                    presentationStartTime = null;
30873                }
30874            }
30875            presentationStartTime = presentationStartTime || liveStartTime;
30876        } else {
30877            if (!isNaN(startTimeOffset) && startTimeOffset < Math.max(streamInfo.manifestInfo.duration, streamInfo.duration) && startTimeOffset >= 0) {
30878                presentationStartTime = startTimeOffset;
30879            } else {
30880                var earliestTime = commonEarliestTime[streamInfo.id]; //set by ready bufferStart after first onBytesAppended
30881                if (earliestTime === undefined) {
30882                    earliestTime = streamController.getActiveStreamCommonEarliestTime(); //deal with calculated PST that is none 0 when streamInfo.start is 0
30883                }
30884                presentationStartTime = Math.max(earliestTime, streamInfo.start);
30885            }
30886        }
30887
30888        return presentationStartTime;
30889    }
30890
30891    function getActualPresentationTime(currentTime) {
30892        var metrics = metricsModel.getReadOnlyMetricsFor(_constantsConstants2['default'].VIDEO) || metricsModel.getReadOnlyMetricsFor(_constantsConstants2['default'].AUDIO);
30893        var DVRMetrics = dashMetrics.getCurrentDVRInfo(metrics);
30894        var DVRWindow = DVRMetrics ? DVRMetrics.range : null;
30895        var actualTime = undefined;
30896
30897        if (!DVRWindow) return NaN;
30898        if (currentTime > DVRWindow.end) {
30899            actualTime = Math.max(DVRWindow.end - streamInfo.manifestInfo.minBufferTime * 2, DVRWindow.start);
30900        } else if (currentTime < DVRWindow.start) {
30901            actualTime = DVRWindow.start;
30902        } else {
30903            return currentTime;
30904        }
30905
30906        return actualTime;
30907    }
30908
30909    function startUpdatingWallclockTime() {
30910        if (wallclockTimeIntervalId !== null) return;
30911
30912        var tick = function tick() {
30913            onWallclockTime();
30914        };
30915
30916        wallclockTimeIntervalId = setInterval(tick, mediaPlayerModel.getWallclockTimeUpdateInterval());
30917    }
30918
30919    function stopUpdatingWallclockTime() {
30920        clearInterval(wallclockTimeIntervalId);
30921        wallclockTimeIntervalId = null;
30922    }
30923
30924    function updateCurrentTime() {
30925        if (isPaused() || !isDynamic || videoModel.getReadyState() === 0) return;
30926        var currentTime = getTime();
30927        var actualTime = getActualPresentationTime(currentTime);
30928        var timeChanged = !isNaN(actualTime) && actualTime !== currentTime;
30929        if (timeChanged) {
30930            seek(actualTime);
30931        }
30932    }
30933
30934    function onDataUpdateCompleted(e) {
30935        if (e.error) return;
30936
30937        var representationInfo = adapter.convertDataToRepresentationInfo(e.currentRepresentation);
30938        var info = representationInfo.mediaInfo.streamInfo;
30939
30940        if (streamInfo.id !== info.id) return;
30941        streamInfo = info;
30942
30943        updateCurrentTime();
30944    }
30945
30946    function onCanPlay() {
30947        eventBus.trigger(_coreEventsEvents2['default'].CAN_PLAY);
30948    }
30949
30950    function onPlaybackStart() {
30951        log('Native video element event: play');
30952        updateCurrentTime();
30953        startUpdatingWallclockTime();
30954        eventBus.trigger(_coreEventsEvents2['default'].PLAYBACK_STARTED, {
30955            startTime: getTime()
30956        });
30957    }
30958
30959    function onPlaybackPlaying() {
30960        log('Native video element event: playing');
30961        eventBus.trigger(_coreEventsEvents2['default'].PLAYBACK_PLAYING, {
30962            playingTime: getTime()
30963        });
30964    }
30965
30966    function onPlaybackPaused() {
30967        log('Native video element event: pause');
30968        eventBus.trigger(_coreEventsEvents2['default'].PLAYBACK_PAUSED, {
30969            ended: getEnded()
30970        });
30971    }
30972
30973    function onPlaybackSeeking() {
30974        var seekTime = getTime();
30975        log('Seeking to: ' + seekTime);
30976        startUpdatingWallclockTime();
30977        eventBus.trigger(_coreEventsEvents2['default'].PLAYBACK_SEEKING, {
30978            seekTime: seekTime
30979        });
30980    }
30981
30982    function onPlaybackSeeked() {
30983        log('Native video element event: seeked');
30984        eventBus.trigger(_coreEventsEvents2['default'].PLAYBACK_SEEKED);
30985    }
30986
30987    function onPlaybackTimeUpdated() {
30988        var time = getTime();
30989        if (time === currentTime) return;
30990        currentTime = time;
30991        eventBus.trigger(_coreEventsEvents2['default'].PLAYBACK_TIME_UPDATED, {
30992            timeToEnd: getTimeToStreamEnd(),
30993            time: time
30994        });
30995    }
30996
30997    function onPlaybackProgress() {
30998        eventBus.trigger(_coreEventsEvents2['default'].PLAYBACK_PROGRESS);
30999    }
31000
31001    function onPlaybackRateChanged() {
31002        var rate = getPlaybackRate();
31003        log('Native video element event: ratechange: ', rate);
31004        eventBus.trigger(_coreEventsEvents2['default'].PLAYBACK_RATE_CHANGED, {
31005            playbackRate: rate
31006        });
31007    }
31008
31009    function onPlaybackMetaDataLoaded() {
31010        log('Native video element event: loadedmetadata');
31011        eventBus.trigger(_coreEventsEvents2['default'].PLAYBACK_METADATA_LOADED);
31012        startUpdatingWallclockTime();
31013    }
31014
31015    function onPlaybackEnded() {
31016        log('Native video element event: ended');
31017        pause();
31018        stopUpdatingWallclockTime();
31019        eventBus.trigger(_coreEventsEvents2['default'].PLAYBACK_ENDED);
31020    }
31021
31022    function onPlaybackError(event) {
31023        var target = event.target || event.srcElement;
31024        eventBus.trigger(_coreEventsEvents2['default'].PLAYBACK_ERROR, {
31025            error: target.error
31026        });
31027    }
31028
31029    function onWallclockTime() {
31030        eventBus.trigger(_coreEventsEvents2['default'].WALLCLOCK_TIME_UPDATED, {
31031            isDynamic: isDynamic,
31032            time: new Date()
31033        });
31034    }
31035
31036    function checkTimeInRanges(time, ranges) {
31037        if (ranges && ranges.length > 0) {
31038            for (var i = 0, len = ranges.length; i < len; i++) {
31039                if (time >= ranges.start(i) && time < ranges.end(i)) {
31040                    return true;
31041                }
31042            }
31043        }
31044        return false;
31045    }
31046
31047    function onBytesAppended(e) {
31048        var earliestTime = undefined,
31049            initialStartTime = undefined;
31050        var ranges = e.bufferedRanges;
31051        if (!ranges || !ranges.length) return;
31052        if (commonEarliestTime[streamInfo.id] === false) {
31053            //stream has already been started.
31054            return;
31055        }
31056
31057        var type = e.sender.getType();
31058
31059        if (bufferedRange[streamInfo.id] === undefined) {
31060            bufferedRange[streamInfo.id] = [];
31061        }
31062
31063        bufferedRange[streamInfo.id][type] = ranges;
31064
31065        if (commonEarliestTime[streamInfo.id] === undefined) {
31066            commonEarliestTime[streamInfo.id] = [];
31067        }
31068
31069        if (commonEarliestTime[streamInfo.id][type] === undefined) {
31070            commonEarliestTime[streamInfo.id][type] = Math.max(ranges.start(0), streamInfo.start);
31071        }
31072
31073        var hasVideoTrack = streamController.isVideoTrackPresent();
31074        var hasAudioTrack = streamController.isAudioTrackPresent();
31075
31076        initialStartTime = getStreamStartTime(false);
31077
31078        if (hasAudioTrack && hasVideoTrack) {
31079            //current stream has audio and video contents
31080            if (!isNaN(commonEarliestTime[streamInfo.id].audio) && !isNaN(commonEarliestTime[streamInfo.id].video)) {
31081
31082                if (commonEarliestTime[streamInfo.id].audio < commonEarliestTime[streamInfo.id].video) {
31083                    // common earliest is video time
31084                    // check buffered audio range has video time, if ok, we seek, otherwise, we wait some other data
31085                    earliestTime = commonEarliestTime[streamInfo.id].video > initialStartTime ? commonEarliestTime[streamInfo.id].video : initialStartTime;
31086                    ranges = bufferedRange[streamInfo.id].audio;
31087                } else {
31088                    // common earliest is audio time
31089                    // check buffered video range has audio time, if ok, we seek, otherwise, we wait some other data
31090                    earliestTime = commonEarliestTime[streamInfo.id].audio > initialStartTime ? commonEarliestTime[streamInfo.id].audio : initialStartTime;
31091                    ranges = bufferedRange[streamInfo.id].video;
31092                }
31093                if (checkTimeInRanges(earliestTime, ranges)) {
31094                    seek(earliestTime);
31095                    commonEarliestTime[streamInfo.id] = false;
31096                }
31097            }
31098        } else {
31099            //current stream has only audio or only video content
31100            if (commonEarliestTime[streamInfo.id][type]) {
31101                earliestTime = commonEarliestTime[streamInfo.id][type] > initialStartTime ? commonEarliestTime[streamInfo.id][type] : initialStartTime;
31102                seek(earliestTime);
31103                commonEarliestTime[streamInfo.id] = false;
31104            }
31105        }
31106    }
31107
31108    function onBufferLevelStateChanged(e) {
31109        // do not stall playback when get an event from Stream that is not active
31110        if (e.streamInfo.id !== streamInfo.id) return;
31111        videoModel.setStallState(e.mediaType, e.state === _BufferController2['default'].BUFFER_EMPTY);
31112    }
31113
31114    function addAllListeners() {
31115        videoModel.addEventListener('canplay', onCanPlay);
31116        videoModel.addEventListener('play', onPlaybackStart);
31117        videoModel.addEventListener('playing', onPlaybackPlaying);
31118        videoModel.addEventListener('pause', onPlaybackPaused);
31119        videoModel.addEventListener('error', onPlaybackError);
31120        videoModel.addEventListener('seeking', onPlaybackSeeking);
31121        videoModel.addEventListener('seeked', onPlaybackSeeked);
31122        videoModel.addEventListener('timeupdate', onPlaybackTimeUpdated);
31123        videoModel.addEventListener('progress', onPlaybackProgress);
31124        videoModel.addEventListener('ratechange', onPlaybackRateChanged);
31125        videoModel.addEventListener('loadedmetadata', onPlaybackMetaDataLoaded);
31126        videoModel.addEventListener('ended', onPlaybackEnded);
31127    }
31128
31129    function removeAllListeners() {
31130        videoModel.removeEventListener('canplay', onCanPlay);
31131        videoModel.removeEventListener('play', onPlaybackStart);
31132        videoModel.removeEventListener('playing', onPlaybackPlaying);
31133        videoModel.removeEventListener('pause', onPlaybackPaused);
31134        videoModel.removeEventListener('error', onPlaybackError);
31135        videoModel.removeEventListener('seeking', onPlaybackSeeking);
31136        videoModel.removeEventListener('seeked', onPlaybackSeeked);
31137        videoModel.removeEventListener('timeupdate', onPlaybackTimeUpdated);
31138        videoModel.removeEventListener('progress', onPlaybackProgress);
31139        videoModel.removeEventListener('ratechange', onPlaybackRateChanged);
31140        videoModel.removeEventListener('loadedmetadata', onPlaybackMetaDataLoaded);
31141        videoModel.removeEventListener('ended', onPlaybackEnded);
31142    }
31143
31144    instance = {
31145        initialize: initialize,
31146        setConfig: setConfig,
31147        getStreamStartTime: getStreamStartTime,
31148        getTimeToStreamEnd: getTimeToStreamEnd,
31149        getTime: getTime,
31150        getPlaybackRate: getPlaybackRate,
31151        getPlayedRanges: getPlayedRanges,
31152        getEnded: getEnded,
31153        getIsDynamic: getIsDynamic,
31154        getStreamController: getStreamController,
31155        setLiveStartTime: setLiveStartTime,
31156        getLiveStartTime: getLiveStartTime,
31157        computeLiveDelay: computeLiveDelay,
31158        play: play,
31159        isPaused: isPaused,
31160        pause: pause,
31161        isSeeking: isSeeking,
31162        seek: seek,
31163        reset: reset
31164    };
31165
31166    setup();
31167
31168    return instance;
31169}
31170
31171PlaybackController.__dashjs_factory_name = 'PlaybackController';
31172exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(PlaybackController);
31173module.exports = exports['default'];
31174
31175},{"100":100,"105":105,"144":144,"49":49,"50":50,"51":51,"54":54}],111:[function(_dereq_,module,exports){
31176/**
31177 * The copyright in this software is being made available under the BSD License,
31178 * included below. This software may be subject to other third party and contributor
31179 * rights, including patent rights, and no such rights are granted under this license.
31180 *
31181 * Copyright (c) 2013, Dash Industry Forum.
31182 * All rights reserved.
31183 *
31184 * Redistribution and use in source and binary forms, with or without modification,
31185 * are permitted provided that the following conditions are met:
31186 *  * Redistributions of source code must retain the above copyright notice, this
31187 *  list of conditions and the following disclaimer.
31188 *  * Redistributions in binary form must reproduce the above copyright notice,
31189 *  this list of conditions and the following disclaimer in the documentation and/or
31190 *  other materials provided with the distribution.
31191 *  * Neither the name of Dash Industry Forum nor the names of its
31192 *  contributors may be used to endorse or promote products derived from this software
31193 *  without specific prior written permission.
31194 *
31195 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
31196 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31197 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
31198 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
31199 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31200 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31201 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31202 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31203 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31204 *  POSSIBILITY OF SUCH DAMAGE.
31205 */
31206'use strict';
31207
31208Object.defineProperty(exports, '__esModule', {
31209    value: true
31210});
31211
31212function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
31213
31214var _constantsConstants = _dereq_(100);
31215
31216var _constantsConstants2 = _interopRequireDefault(_constantsConstants);
31217
31218var _voMetricsPlayList = _dereq_(226);
31219
31220var _AbrController = _dereq_(102);
31221
31222var _AbrController2 = _interopRequireDefault(_AbrController);
31223
31224var _BufferController = _dereq_(105);
31225
31226var _BufferController2 = _interopRequireDefault(_BufferController);
31227
31228var _rulesSchedulingBufferLevelRule = _dereq_(181);
31229
31230var _rulesSchedulingBufferLevelRule2 = _interopRequireDefault(_rulesSchedulingBufferLevelRule);
31231
31232var _rulesSchedulingNextFragmentRequestRule = _dereq_(182);
31233
31234var _rulesSchedulingNextFragmentRequestRule2 = _interopRequireDefault(_rulesSchedulingNextFragmentRequestRule);
31235
31236var _modelsFragmentModel = _dereq_(140);
31237
31238var _modelsFragmentModel2 = _interopRequireDefault(_modelsFragmentModel);
31239
31240var _coreEventBus = _dereq_(50);
31241
31242var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
31243
31244var _coreEventsEvents = _dereq_(54);
31245
31246var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
31247
31248var _coreFactoryMaker = _dereq_(51);
31249
31250var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
31251
31252var _coreDebug = _dereq_(49);
31253
31254var _coreDebug2 = _interopRequireDefault(_coreDebug);
31255
31256function ScheduleController(config) {
31257
31258    var context = this.context;
31259    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
31260    var metricsModel = config.metricsModel;
31261    var adapter = config.adapter;
31262    var dashMetrics = config.dashMetrics;
31263    var dashManifestModel = config.dashManifestModel;
31264    var timelineConverter = config.timelineConverter;
31265    var mediaPlayerModel = config.mediaPlayerModel;
31266    var abrController = config.abrController;
31267    var playbackController = config.playbackController;
31268    var streamController = config.streamController;
31269    var textController = config.textController;
31270    var sourceBufferController = config.sourceBufferController;
31271    var type = config.type;
31272    var streamProcessor = config.streamProcessor;
31273
31274    var instance = undefined,
31275        log = undefined,
31276        fragmentModel = undefined,
31277        currentRepresentationInfo = undefined,
31278        initialRequest = undefined,
31279        isStopped = undefined,
31280        playListMetrics = undefined,
31281        playListTraceMetrics = undefined,
31282        playListTraceMetricsClosed = undefined,
31283        isFragmentProcessingInProgress = undefined,
31284        timeToLoadDelay = undefined,
31285        scheduleTimeout = undefined,
31286        seekTarget = undefined,
31287        bufferLevelRule = undefined,
31288        nextFragmentRequestRule = undefined,
31289        scheduleWhilePaused = undefined,
31290        lastQualityIndex = undefined,
31291        topQualityIndex = undefined,
31292        lastInitQuality = undefined,
31293        replaceRequestArray = undefined,
31294        switchTrack = undefined;
31295
31296    function setup() {
31297        log = (0, _coreDebug2['default'])(context).getInstance().log.bind(instance);
31298
31299        resetInitialSettings();
31300    }
31301
31302    function initialize() {
31303        fragmentModel = streamProcessor.getFragmentModel();
31304        scheduleWhilePaused = mediaPlayerModel.getScheduleWhilePaused();
31305
31306        bufferLevelRule = (0, _rulesSchedulingBufferLevelRule2['default'])(context).create({
31307            abrController: abrController,
31308            dashMetrics: dashMetrics,
31309            metricsModel: metricsModel,
31310            mediaPlayerModel: mediaPlayerModel,
31311            textController: textController
31312        });
31313
31314        nextFragmentRequestRule = (0, _rulesSchedulingNextFragmentRequestRule2['default'])(context).create({
31315            adapter: adapter,
31316            sourceBufferController: sourceBufferController,
31317            textController: textController
31318        });
31319
31320        if (dashManifestModel.getIsTextTrack(type)) {
31321            eventBus.on(_coreEventsEvents2['default'].TIMED_TEXT_REQUESTED, onTimedTextRequested, this);
31322        }
31323
31324        //eventBus.on(Events.LIVE_EDGE_SEARCH_COMPLETED, onLiveEdgeSearchCompleted, this);
31325        eventBus.on(_coreEventsEvents2['default'].QUALITY_CHANGE_REQUESTED, onQualityChanged, this);
31326        eventBus.on(_coreEventsEvents2['default'].DATA_UPDATE_STARTED, onDataUpdateStarted, this);
31327        eventBus.on(_coreEventsEvents2['default'].DATA_UPDATE_COMPLETED, onDataUpdateCompleted, this);
31328        eventBus.on(_coreEventsEvents2['default'].FRAGMENT_LOADING_COMPLETED, onFragmentLoadingCompleted, this);
31329        eventBus.on(_coreEventsEvents2['default'].STREAM_COMPLETED, onStreamCompleted, this);
31330        eventBus.on(_coreEventsEvents2['default'].STREAM_INITIALIZED, onStreamInitialized, this);
31331        eventBus.on(_coreEventsEvents2['default'].BUFFER_LEVEL_STATE_CHANGED, onBufferLevelStateChanged, this);
31332        eventBus.on(_coreEventsEvents2['default'].BUFFER_CLEARED, onBufferCleared, this);
31333        eventBus.on(_coreEventsEvents2['default'].BYTES_APPENDED, onBytesAppended, this);
31334        eventBus.on(_coreEventsEvents2['default'].INIT_REQUESTED, onInitRequested, this);
31335        eventBus.on(_coreEventsEvents2['default'].QUOTA_EXCEEDED, onQuotaExceeded, this);
31336        eventBus.on(_coreEventsEvents2['default'].PLAYBACK_SEEKING, onPlaybackSeeking, this);
31337        eventBus.on(_coreEventsEvents2['default'].PLAYBACK_STARTED, onPlaybackStarted, this);
31338        eventBus.on(_coreEventsEvents2['default'].PLAYBACK_RATE_CHANGED, onPlaybackRateChanged, this);
31339        eventBus.on(_coreEventsEvents2['default'].PLAYBACK_TIME_UPDATED, onPlaybackTimeUpdated, this);
31340        eventBus.on(_coreEventsEvents2['default'].URL_RESOLUTION_FAILED, onURLResolutionFailed, this);
31341        eventBus.on(_coreEventsEvents2['default'].FRAGMENT_LOADING_ABANDONED, onFragmentLoadingAbandoned, this);
31342    }
31343
31344    function isStarted() {
31345        return isStopped === false;
31346    }
31347
31348    function start() {
31349        if (!currentRepresentationInfo || streamProcessor.isBufferingCompleted()) {
31350            return;
31351        }
31352
31353        addPlaylistTraceMetrics();
31354        isStopped = false;
31355
31356        if (initialRequest) {
31357            initialRequest = false;
31358        }
31359
31360        startScheduleTimer(0);
31361
31362        log('Schedule controller starting for ' + type);
31363    }
31364
31365    function stop() {
31366        if (isStopped) {
31367            return;
31368        }
31369
31370        isStopped = true;
31371        clearTimeout(scheduleTimeout);
31372        log('Schedule controller stopping for ' + type);
31373    }
31374
31375    function hasTopQualityChanged(type, id) {
31376        topQualityIndex[id] = topQualityIndex[id] || {};
31377        var newTopQualityIndex = abrController.getTopQualityIndexFor(type, id);
31378
31379        if (topQualityIndex[id][type] != newTopQualityIndex) {
31380            log('Top quality' + type + ' index has changed from ' + topQualityIndex[id][type] + ' to ' + newTopQualityIndex);
31381            topQualityIndex[id][type] = newTopQualityIndex;
31382            return true;
31383        }
31384        return false;
31385    }
31386
31387    function schedule() {
31388        if (isStopped || isFragmentProcessingInProgress || !streamProcessor.getBufferController() || playbackController.isPaused() && !scheduleWhilePaused) {
31389            return;
31390        }
31391
31392        validateExecutedFragmentRequest();
31393
31394        var isReplacement = replaceRequestArray.length > 0;
31395        if (switchTrack || isReplacement || hasTopQualityChanged(currentRepresentationInfo.mediaInfo.type, streamProcessor.getStreamInfo().id) || bufferLevelRule.execute(streamProcessor, type, streamController.isVideoTrackPresent())) {
31396
31397            var getNextFragment = function getNextFragment() {
31398                log('ScheduleController - getNextFragment');
31399                var fragmentController = streamProcessor.getFragmentController();
31400                if (switchTrack) {
31401                    log('ScheduleController - switch track has been asked, get init request for ' + type + ' with representationid = ' + currentRepresentationInfo.id);
31402                    streamProcessor.switchInitData(currentRepresentationInfo.id);
31403                    switchTrack = false;
31404                } else if (currentRepresentationInfo.quality !== lastInitQuality) {
31405                    log('ScheduleController - quality has changed, get init request');
31406                    lastInitQuality = currentRepresentationInfo.quality;
31407
31408                    streamProcessor.switchInitData(currentRepresentationInfo.id);
31409                } else {
31410                    var replacement = replaceRequestArray.shift();
31411
31412                    if (fragmentController.isInitializationRequest(replacement)) {
31413                        //to be sure the specific init segment had not already been loaded.
31414                        streamProcessor.switchInitData(replacement.representationId);
31415                    } else {
31416                        var request = nextFragmentRequestRule.execute(streamProcessor, replacement);
31417                        if (request) {
31418                            log('ScheduleController - getNextFragment - request is ' + request.url);
31419                            fragmentModel.executeRequest(request);
31420                        } else {
31421                            //Use case - Playing at the bleeding live edge and frag is not available yet. Cycle back around.
31422                            log('getNextFragment - Playing at the bleeding live edge and frag is not available yet');
31423                            isFragmentProcessingInProgress = false;
31424                            startScheduleTimer(500);
31425                        }
31426                    }
31427                }
31428            };
31429
31430            isFragmentProcessingInProgress = true;
31431            if (isReplacement || switchTrack) {
31432                getNextFragment();
31433            } else {
31434                abrController.checkPlaybackQuality(type);
31435                getNextFragment();
31436            }
31437        } else {
31438            startScheduleTimer(500);
31439        }
31440    }
31441
31442    function validateExecutedFragmentRequest() {
31443        //Validate that the fragment request executed and appended into the source buffer is as
31444        // good of quality as the current quality and is the correct media track.
31445        var safeBufferLevel = currentRepresentationInfo.fragmentDuration * 1.5;
31446        var request = fragmentModel.getRequests({
31447            state: _modelsFragmentModel2['default'].FRAGMENT_MODEL_EXECUTED,
31448            time: playbackController.getTime() + safeBufferLevel,
31449            threshold: 0
31450        })[0];
31451
31452        if (request && replaceRequestArray.indexOf(request) === -1 && !dashManifestModel.getIsTextTrack(type)) {
31453            var fastSwitchModeEnabled = mediaPlayerModel.getFastSwitchEnabled();
31454            var bufferLevel = streamProcessor.getBufferLevel();
31455            var abandonmentState = abrController.getAbandonmentStateFor(type);
31456
31457            if (fastSwitchModeEnabled && request.quality < currentRepresentationInfo.quality && bufferLevel >= safeBufferLevel && abandonmentState !== _AbrController2['default'].ABANDON_LOAD) {
31458                replaceRequest(request);
31459                log('Reloading outdated fragment at index: ', request.index);
31460            } else if (request.quality > currentRepresentationInfo.quality) {
31461                //The buffer has better quality it in then what we would request so set append point to end of buffer!!
31462                setSeekTarget(playbackController.getTime() + streamProcessor.getBufferLevel());
31463            }
31464        }
31465    }
31466
31467    function startScheduleTimer(value) {
31468        clearTimeout(scheduleTimeout);
31469        scheduleTimeout = setTimeout(schedule, value);
31470    }
31471
31472    function onInitRequested(e) {
31473        if (!e.sender || e.sender.getStreamProcessor() !== streamProcessor) {
31474            return;
31475        }
31476
31477        getInitRequest(currentRepresentationInfo.quality);
31478    }
31479
31480    function getInitRequest(quality) {
31481        lastInitQuality = quality;
31482
31483        var request = adapter.getInitRequest(streamProcessor, quality);
31484        if (request) {
31485            isFragmentProcessingInProgress = true;
31486            fragmentModel.executeRequest(request);
31487        }
31488    }
31489
31490    function switchTrackAsked() {
31491        switchTrack = true;
31492    }
31493
31494    function replaceRequest(request) {
31495        replaceRequestArray.push(request);
31496    }
31497
31498    function onQualityChanged(e) {
31499        if (type !== e.mediaType || streamProcessor.getStreamInfo().id !== e.streamInfo.id) {
31500            return;
31501        }
31502
31503        currentRepresentationInfo = streamProcessor.getRepresentationInfoForQuality(e.newQuality);
31504
31505        if (currentRepresentationInfo === null || currentRepresentationInfo === undefined) {
31506            throw new Error('Unexpected error! - currentRepresentationInfo is null or undefined');
31507        }
31508
31509        clearPlayListTraceMetrics(new Date(), _voMetricsPlayList.PlayListTrace.REPRESENTATION_SWITCH_STOP_REASON);
31510        addPlaylistTraceMetrics();
31511    }
31512
31513    function completeQualityChange(trigger) {
31514        if (playbackController && fragmentModel) {
31515            var item = fragmentModel.getRequests({
31516                state: _modelsFragmentModel2['default'].FRAGMENT_MODEL_EXECUTED,
31517                time: playbackController.getTime(),
31518                threshold: 0
31519            })[0];
31520            if (item && playbackController.getTime() >= item.startTime) {
31521                if (item.quality !== lastQualityIndex && trigger) {
31522                    eventBus.trigger(_coreEventsEvents2['default'].QUALITY_CHANGE_RENDERED, {
31523                        mediaType: type,
31524                        oldQuality: lastQualityIndex,
31525                        newQuality: item.quality
31526                    });
31527                }
31528                lastQualityIndex = item.quality;
31529            }
31530        }
31531    }
31532
31533    function onDataUpdateCompleted(e) {
31534        if (e.error || e.sender.getStreamProcessor() !== streamProcessor) {
31535            return;
31536        }
31537
31538        currentRepresentationInfo = adapter.convertDataToRepresentationInfo(e.currentRepresentation);
31539    }
31540
31541    function onStreamInitialized(e) {
31542        if (e.error || streamProcessor.getStreamInfo().id !== e.streamInfo.id) {
31543            return;
31544        }
31545
31546        currentRepresentationInfo = streamProcessor.getCurrentRepresentationInfo();
31547
31548        if (initialRequest) {
31549            if (playbackController.getIsDynamic()) {
31550                timelineConverter.setTimeSyncCompleted(true);
31551                setLiveEdgeSeekTarget();
31552            } else {
31553                seekTarget = playbackController.getStreamStartTime(false);
31554                streamProcessor.getBufferController().setSeekStartTime(seekTarget);
31555            }
31556        }
31557
31558        if (isStopped) {
31559            start();
31560        }
31561    }
31562
31563    function setLiveEdgeSeekTarget() {
31564        var liveEdgeFinder = streamProcessor.getLiveEdgeFinder();
31565        if (liveEdgeFinder) {
31566            var liveEdge = liveEdgeFinder.getLiveEdge();
31567            var dvrWindowSize = currentRepresentationInfo.mediaInfo.streamInfo.manifestInfo.DVRWindowSize / 2;
31568            var startTime = liveEdge - playbackController.computeLiveDelay(currentRepresentationInfo.fragmentDuration, dvrWindowSize);
31569            var request = adapter.getFragmentRequestForTime(streamProcessor, currentRepresentationInfo, startTime, {
31570                ignoreIsFinished: true
31571            });
31572            seekTarget = playbackController.getLiveStartTime();
31573            if (isNaN(seekTarget) || request.startTime > seekTarget) {
31574                //special use case for multi period stream. If the startTime is out of the current period, send a seek command.
31575                //in onPlaybackSeeking callback (StreamController), the detection of switch stream is done.
31576                if (request.startTime > currentRepresentationInfo.mediaInfo.streamInfo.start + currentRepresentationInfo.mediaInfo.streamInfo.duration) {
31577                    playbackController.seek(request.startTime);
31578                }
31579                playbackController.setLiveStartTime(request.startTime);
31580                seekTarget = request.startTime;
31581            }
31582
31583            var manifestUpdateInfo = dashMetrics.getCurrentManifestUpdate(metricsModel.getMetricsFor(_constantsConstants2['default'].STREAM));
31584            metricsModel.updateManifestUpdateInfo(manifestUpdateInfo, {
31585                currentTime: seekTarget,
31586                presentationStartTime: liveEdge,
31587                latency: liveEdge - seekTarget,
31588                clientTimeOffset: timelineConverter.getClientTimeOffset()
31589            });
31590        }
31591    }
31592
31593    function onStreamCompleted(e) {
31594        if (e.fragmentModel !== fragmentModel) {
31595            return;
31596        }
31597
31598        stop();
31599        isFragmentProcessingInProgress = false;
31600        log('Stream is complete');
31601    }
31602
31603    function onFragmentLoadingCompleted(e) {
31604        if (e.sender !== fragmentModel) {
31605            return;
31606        }
31607
31608        if (dashManifestModel.getIsTextTrack(type)) {
31609            isFragmentProcessingInProgress = false;
31610        }
31611
31612        if (e.error && e.request.serviceLocation && !isStopped) {
31613            replaceRequest(e.request);
31614            isFragmentProcessingInProgress = false;
31615            startScheduleTimer(0);
31616        }
31617    }
31618
31619    function onPlaybackTimeUpdated() {
31620        completeQualityChange(true);
31621    }
31622
31623    function onBytesAppended(e) {
31624        if (e.sender.getStreamProcessor() !== streamProcessor) {
31625            return;
31626        }
31627
31628        isFragmentProcessingInProgress = false;
31629        startScheduleTimer(0);
31630    }
31631
31632    function onFragmentLoadingAbandoned(e) {
31633        if (e.streamProcessor !== streamProcessor) {
31634            return;
31635        }
31636        log('[ScheduleController][' + type + '] Request ' + e.request.url + ' has been aborted');
31637        replaceRequest(e.request);
31638        isFragmentProcessingInProgress = false;
31639        startScheduleTimer(0);
31640    }
31641
31642    function onDataUpdateStarted(e) {
31643        if (e.sender.getStreamProcessor() !== streamProcessor) {
31644            return;
31645        }
31646
31647        stop();
31648    }
31649
31650    function onBufferCleared(e) {
31651        if (e.sender.getStreamProcessor() !== streamProcessor) {
31652            return;
31653        }
31654
31655        // after the data has been removed from the buffer we should remove the requests from the list of
31656        // the executed requests for which playback time is inside the time interval that has been removed from the buffer
31657        fragmentModel.removeExecutedRequestsBeforeTime(e.to);
31658
31659        if (e.hasEnoughSpaceToAppend && isStopped) {
31660            start();
31661        }
31662    }
31663
31664    function onBufferLevelStateChanged(e) {
31665        if (e.sender.getStreamProcessor() === streamProcessor && e.state === _BufferController2['default'].BUFFER_EMPTY && !playbackController.isSeeking()) {
31666            log('Buffer is empty! Stalling!');
31667            clearPlayListTraceMetrics(new Date(), _voMetricsPlayList.PlayListTrace.REBUFFERING_REASON);
31668        }
31669    }
31670
31671    function onQuotaExceeded(e) {
31672        if (e.sender.getStreamProcessor() !== streamProcessor) {
31673            return;
31674        }
31675
31676        stop();
31677        isFragmentProcessingInProgress = false;
31678    }
31679
31680    function onURLResolutionFailed() {
31681        fragmentModel.abortRequests();
31682        stop();
31683    }
31684
31685    function onTimedTextRequested(e) {
31686        if (e.sender.getStreamProcessor() !== streamProcessor) {
31687            return;
31688        }
31689
31690        getInitRequest(e.index);
31691    }
31692
31693    function onPlaybackStarted() {
31694        if (isStopped || !scheduleWhilePaused) {
31695            start();
31696        }
31697    }
31698
31699    function onPlaybackSeeking(e) {
31700        seekTarget = e.seekTime;
31701        setTimeToLoadDelay(0);
31702
31703        if (isStopped) {
31704            start();
31705        }
31706
31707        var manifestUpdateInfo = dashMetrics.getCurrentManifestUpdate(metricsModel.getMetricsFor(_constantsConstants2['default'].STREAM));
31708        var latency = currentRepresentationInfo.DVRWindow && playbackController ? currentRepresentationInfo.DVRWindow.end - playbackController.getTime() : NaN;
31709        metricsModel.updateManifestUpdateInfo(manifestUpdateInfo, {
31710            latency: latency
31711        });
31712
31713        //if, during the seek command, the scheduleController is waiting : stop waiting, request chunk as soon as possible
31714        if (!isFragmentProcessingInProgress) {
31715            startScheduleTimer(0);
31716        }
31717    }
31718
31719    function onPlaybackRateChanged(e) {
31720        if (playListTraceMetrics) {
31721            playListTraceMetrics.playbackspeed = e.playbackRate.toString();
31722        }
31723    }
31724
31725    function getSeekTarget() {
31726        return seekTarget;
31727    }
31728
31729    function setSeekTarget(value) {
31730        seekTarget = value;
31731    }
31732
31733    function setTimeToLoadDelay(value) {
31734        timeToLoadDelay = value;
31735    }
31736
31737    function getTimeToLoadDelay() {
31738        return timeToLoadDelay;
31739    }
31740
31741    function getBufferTarget() {
31742        return bufferLevelRule.getBufferTarget(streamProcessor, type, streamController.isVideoTrackPresent());
31743    }
31744
31745    function getType() {
31746        return type;
31747    }
31748
31749    function setPlayList(playList) {
31750        playListMetrics = playList;
31751    }
31752
31753    function finalisePlayList(time, reason) {
31754        clearPlayListTraceMetrics(time, reason);
31755        playListMetrics = null;
31756    }
31757
31758    function clearPlayListTraceMetrics(endTime, stopreason) {
31759        if (playListMetrics && playListTraceMetricsClosed === false) {
31760            var startTime = playListTraceMetrics.start;
31761            var duration = endTime.getTime() - startTime.getTime();
31762            playListTraceMetrics.duration = duration;
31763            playListTraceMetrics.stopreason = stopreason;
31764            playListMetrics.trace.push(playListTraceMetrics);
31765            playListTraceMetricsClosed = true;
31766        }
31767    }
31768
31769    function addPlaylistTraceMetrics() {
31770        if (playListMetrics && playListTraceMetricsClosed === true && currentRepresentationInfo) {
31771            playListTraceMetricsClosed = false;
31772            playListTraceMetrics = new _voMetricsPlayList.PlayListTrace();
31773            playListTraceMetrics.representationid = currentRepresentationInfo.id;
31774            playListTraceMetrics.start = new Date();
31775            playListTraceMetrics.mstart = playbackController.getTime() * 1000;
31776            playListTraceMetrics.playbackspeed = playbackController.getPlaybackRate().toString();
31777        }
31778    }
31779
31780    function resetInitialSettings() {
31781        isFragmentProcessingInProgress = false;
31782        timeToLoadDelay = 0;
31783        seekTarget = NaN;
31784        playListMetrics = null;
31785        playListTraceMetrics = null;
31786        playListTraceMetricsClosed = true;
31787        initialRequest = true;
31788        lastInitQuality = NaN;
31789        lastQualityIndex = NaN;
31790        topQualityIndex = {};
31791        replaceRequestArray = [];
31792        isStopped = true;
31793        switchTrack = true;
31794    }
31795
31796    function reset() {
31797        //eventBus.off(Events.LIVE_EDGE_SEARCH_COMPLETED, onLiveEdgeSearchCompleted, this);
31798        eventBus.off(_coreEventsEvents2['default'].DATA_UPDATE_STARTED, onDataUpdateStarted, this);
31799        eventBus.off(_coreEventsEvents2['default'].DATA_UPDATE_COMPLETED, onDataUpdateCompleted, this);
31800        eventBus.off(_coreEventsEvents2['default'].BUFFER_LEVEL_STATE_CHANGED, onBufferLevelStateChanged, this);
31801        eventBus.off(_coreEventsEvents2['default'].QUALITY_CHANGE_REQUESTED, onQualityChanged, this);
31802        eventBus.off(_coreEventsEvents2['default'].FRAGMENT_LOADING_COMPLETED, onFragmentLoadingCompleted, this);
31803        eventBus.off(_coreEventsEvents2['default'].STREAM_COMPLETED, onStreamCompleted, this);
31804        eventBus.off(_coreEventsEvents2['default'].STREAM_INITIALIZED, onStreamInitialized, this);
31805        eventBus.off(_coreEventsEvents2['default'].QUOTA_EXCEEDED, onQuotaExceeded, this);
31806        eventBus.off(_coreEventsEvents2['default'].BYTES_APPENDED, onBytesAppended, this);
31807        eventBus.off(_coreEventsEvents2['default'].BUFFER_CLEARED, onBufferCleared, this);
31808        eventBus.off(_coreEventsEvents2['default'].INIT_REQUESTED, onInitRequested, this);
31809        eventBus.off(_coreEventsEvents2['default'].PLAYBACK_RATE_CHANGED, onPlaybackRateChanged, this);
31810        eventBus.off(_coreEventsEvents2['default'].PLAYBACK_SEEKING, onPlaybackSeeking, this);
31811        eventBus.off(_coreEventsEvents2['default'].PLAYBACK_STARTED, onPlaybackStarted, this);
31812        eventBus.off(_coreEventsEvents2['default'].PLAYBACK_TIME_UPDATED, onPlaybackTimeUpdated, this);
31813        eventBus.off(_coreEventsEvents2['default'].URL_RESOLUTION_FAILED, onURLResolutionFailed, this);
31814        eventBus.off(_coreEventsEvents2['default'].FRAGMENT_LOADING_ABANDONED, onFragmentLoadingAbandoned, this);
31815        if (dashManifestModel.getIsTextTrack(type)) {
31816            eventBus.off(_coreEventsEvents2['default'].TIMED_TEXT_REQUESTED, onTimedTextRequested, this);
31817        }
31818
31819        stop();
31820        completeQualityChange(false);
31821        resetInitialSettings();
31822    }
31823
31824    instance = {
31825        initialize: initialize,
31826        getType: getType,
31827        getSeekTarget: getSeekTarget,
31828        setSeekTarget: setSeekTarget,
31829        setTimeToLoadDelay: setTimeToLoadDelay,
31830        getTimeToLoadDelay: getTimeToLoadDelay,
31831        replaceRequest: replaceRequest,
31832        switchTrackAsked: switchTrackAsked,
31833        isStarted: isStarted,
31834        start: start,
31835        stop: stop,
31836        reset: reset,
31837        setPlayList: setPlayList,
31838        getBufferTarget: getBufferTarget,
31839        finalisePlayList: finalisePlayList
31840    };
31841
31842    setup();
31843
31844    return instance;
31845}
31846
31847ScheduleController.__dashjs_factory_name = 'ScheduleController';
31848exports['default'] = _coreFactoryMaker2['default'].getClassFactory(ScheduleController);
31849module.exports = exports['default'];
31850
31851},{"100":100,"102":102,"105":105,"140":140,"181":181,"182":182,"226":226,"49":49,"50":50,"51":51,"54":54}],112:[function(_dereq_,module,exports){
31852/**
31853 * The copyright in this software is being made available under the BSD License,
31854 * included below. This software may be subject to other third party and contributor
31855 * rights, including patent rights, and no such rights are granted under this license.
31856 *
31857 * Copyright (c) 2013, Dash Industry Forum.
31858 * All rights reserved.
31859 *
31860 * Redistribution and use in source and binary forms, with or without modification,
31861 * are permitted provided that the following conditions are met:
31862 *  * Redistributions of source code must retain the above copyright notice, this
31863 *  list of conditions and the following disclaimer.
31864 *  * Redistributions in binary form must reproduce the above copyright notice,
31865 *  this list of conditions and the following disclaimer in the documentation and/or
31866 *  other materials provided with the distribution.
31867 *  * Neither the name of Dash Industry Forum nor the names of its
31868 *  contributors may be used to endorse or promote products derived from this software
31869 *  without specific prior written permission.
31870 *
31871 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
31872 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31873 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
31874 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
31875 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
31875INCLUDING, BUT
31876 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31877 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31878 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31879 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31880 *  POSSIBILITY OF SUCH DAMAGE.
31881 */
31882'use strict';
31883
31884Object.defineProperty(exports, '__esModule', {
31885    value: true
31886});
31887
31888function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
31889
31890var _voDashJSError = _dereq_(207);
31891
31892var _voDashJSError2 = _interopRequireDefault(_voDashJSError);
31893
31894var _coreEventBus = _dereq_(50);
31895
31896var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
31897
31898var _coreEventsEvents = _dereq_(54);
31899
31900var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
31901
31902var _coreFactoryMaker = _dereq_(51);
31903
31904var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
31905
31906var QUOTA_EXCEEDED_ERROR_CODE = 22;
31907
31908function SourceBufferController(config) {
31909
31910    var context = this.context;
31911    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
31912    var textController = config.textController;
31913
31914    var instance = undefined;
31915
31916    function createSourceBuffer(mediaSource, mediaInfo) {
31917
31918        var codec = mediaInfo.codec;
31919        var buffer = null;
31920
31921        try {
31922            // Safari claims to support anything starting 'application/mp4'.
31923            // it definitely doesn't understand 'application/mp4;codecs="stpp"'
31924            // - currently no browser does, so check for it and use our own
31925            // implementation. The same is true for codecs="wvtt".
31926            if (codec.match(/application\/mp4;\s*codecs="(stpp|wvtt).*"/i)) {
31927                throw new Error('not really supported');
31928            }
31929
31930            buffer = mediaSource.addSourceBuffer(codec);
31931        } catch (ex) {
31932            // Note that in the following, the quotes are open to allow for extra text after stpp and wvtt
31933            if (mediaInfo.isText || codec.indexOf('codecs="stpp') !== -1 || codec.indexOf('codecs="wvtt') !== -1) {
31934                buffer = textController.getTextSourceBuffer();
31935            } else {
31936                throw ex;
31937            }
31938        }
31939
31940        return buffer;
31941    }
31942
31943    function removeSourceBuffer(mediaSource, buffer) {
31944        try {
31945            mediaSource.removeSourceBuffer(buffer);
31946        } catch (ex) {}
31947    }
31948
31949    function getBufferRange(buffer, time, tolerance) {
31950        var ranges = null;
31951        var start = 0;
31952        var end = 0;
31953        var firstStart = null;
31954        var lastEnd = null;
31955        var gap = 0;
31956
31957        var len = undefined,
31958            i = undefined;
31959
31960        var toler = tolerance || 0.15;
31961
31962        try {
31963            ranges = buffer.buffered;
31964        } catch (ex) {
31965            return null;
31966        }
31967
31968        if (ranges !== null && ranges !== undefined) {
31969            for (i = 0, len = ranges.length; i < len; i++) {
31970                start = ranges.start(i);
31971                end = ranges.end(i);
31972                if (firstStart === null) {
31973                    gap = Math.abs(start - time);
31974                    if (time >= start && time < end) {
31975                        // start the range
31976                        firstStart = start;
31977                        lastEnd = end;
31978                    } else if (gap <= toler) {
31979                        // start the range even though the buffer does not contain time 0
31980                        firstStart = start;
31981                        lastEnd = end;
31982                    }
31983                } else {
31984                    gap = start - lastEnd;
31985                    if (gap <= toler) {
31986                        // the discontinuity is smaller than the tolerance, combine the ranges
31987                        lastEnd = end;
31988                    } else {
31989                        break;
31990                    }
31991                }
31992            }
31993
31994            if (firstStart !== null) {
31995                return {
31996                    start: firstStart,
31997                    end: lastEnd
31998                };
31999            }
32000        }
32001
32002        return null;
32003    }
32004
32005    function getAllRanges(buffer) {
32006        var ranges = null;
32007
32008        try {
32009            ranges = buffer.buffered;
32010            return ranges;
32011        } catch (ex) {
32012            return null;
32013        }
32014    }
32015
32016    function getTotalBufferedTime(buffer) {
32017        var ranges = getAllRanges(buffer);
32018        var totalBufferedTime = 0;
32019        var ln = undefined,
32020            i = undefined;
32021
32022        if (!ranges) return totalBufferedTime;
32023
32024        for (i = 0, ln = ranges.length; i < ln; i++) {
32025            totalBufferedTime += ranges.end(i) - ranges.start(i);
32026        }
32027
32028        return totalBufferedTime;
32029    }
32030
32031    function getBufferLength(buffer, time, tolerance) {
32032
32033        var range = undefined,
32034            length = undefined;
32035
32036        range = getBufferRange(buffer, time, tolerance);
32037
32038        if (range === null) {
32039            length = 0;
32040        } else {
32041            length = range.end - time;
32042        }
32043
32044        return length;
32045    }
32046
32047    function getRangeDifference(currentRanges, buffer) {
32048        if (!buffer) return null;
32049
32050        //TODO we may need to look for a more elegant and robust method
32051        // The logic below checks that is the difference between currentRanges and actual SourceBuffer ranges
32052
32053        var newRanges = getAllRanges(buffer);
32054        var newStart = undefined,
32055            newEnd = undefined,
32056            equalStart = undefined,
32057            equalEnd = undefined,
32058            currentRange = undefined,
32059            nextCurrentRange = undefined,
32060            nextNewRange = undefined,
32061            hasRange = undefined,
32062            diff = undefined;
32063
32064        if (!newRanges) return null;
32065
32066        for (var i = 0, ln = newRanges.length; i < ln; i++) {
32067            hasRange = currentRanges.length > i;
32068            currentRange = hasRange ? {
32069                start: currentRanges.start(i),
32070                end: currentRanges.end(i)
32071            } : null;
32072            newStart = newRanges.start(i);
32073            newEnd = newRanges.end(i);
32074
32075            // if there is no range with the same index it means that a new range has been added. This range is
32076            // the difference we are looking for
32077            // Example
32078            // current ranges
32079            // 0|---range1---|4  8|--range2--|12
32080            // new ranges
32081            // 0|---range1---|4| 8|--range2--|12  16|--range3--|20
32082
32083            if (!currentRange) {
32084                diff = {
32085                    start: newStart,
32086                    end: newEnd
32087                };
32088                return diff;
32089            }
32090
32091            equalStart = currentRange.start === newStart;
32092            equalEnd = currentRange.end === newEnd;
32093
32094            // if ranges are equal do nothing here and go the next ranges
32095            if (equalStart && equalEnd) continue;
32096
32097            // start or/and end of the range has been changed
32098            if (equalStart) {
32099                diff = {
32100                    start: currentRange.end,
32101                    end: newEnd
32102                };
32103            } else if (equalEnd) {
32104                diff = {
32105                    start: newStart,
32106                    end: currentRange.start
32107                };
32108            } else {
32109                // new range has been added before the current one
32110                diff = {
32111                    start: newStart,
32112                    end: newEnd
32113                };
32114                return diff;
32115            }
32116
32117            // if there is next current range but no next new range (it it is not equal the next current range) it means
32118            // that the ranges have been merged
32119            // Example 1
32120            // current ranges
32121            // 0|---range1---|4  8|--range2--|12  16|---range3---|
32122            // new ranges
32123            // 0|-----------range1-----------|12  16|---range3--|
32124            nextCurrentRange = currentRanges.length > i + 1 ? {
32125                start: currentRanges.start(i + 1),
32126                end: currentRanges.end(i + 1)
32127            } : null;
32128            nextNewRange = i + 1 < ln ? {
32129                start: newRanges.start(i + 1),
32130                end: newRanges.end(i + 1)
32131            } : null;
32132
32133            if (nextCurrentRange && (!nextNewRange || nextNewRange.start !== nextCurrentRange.start || nextNewRange.end !== nextCurrentRange.end)) {
32134                diff.end = nextCurrentRange.start;
32135            }
32136
32137            return diff;
32138        }
32139
32140        return null;
32141    }
32142
32143    function append(buffer, chunk) {
32144        var bytes = chunk.bytes;
32145        var appendMethod = 'append' in buffer ? 'append' : 'appendBuffer' in buffer ? 'appendBuffer' : null;
32146        // our user-defined sourcebuffer-like object has Object as its
32147        // prototype whereas built-in SourceBuffers will have something
32148        // more sensible. do not pass chunk to built-in append.
32149        var acceptsChunk = Object.prototype.toString.call(buffer).slice(8, -1) === 'Object';
32150
32151        if (!appendMethod) return;
32152
32153        waitForUpdateEnd(buffer, function () {
32154            try {
32155                if (acceptsChunk) {
32156                    // chunk.start is used in calculations by TextSourceBuffer
32157                    buffer[appendMethod](bytes, chunk);
32158                } else {
32159                    buffer[appendMethod](bytes);
32160                }
32161                // updating is in progress, we should wait for it to complete before signaling that this operation is done
32162                waitForUpdateEnd(buffer, function () {
32163                    eventBus.trigger(_coreEventsEvents2['default'].SOURCEBUFFER_APPEND_COMPLETED, {
32164                        buffer: buffer,
32165                        bytes: bytes
32166                    });
32167                });
32168            } catch (err) {
32169                eventBus.trigger(_coreEventsEvents2['default'].SOURCEBUFFER_APPEND_COMPLETED, {
32170                    buffer: buffer,
32171                    bytes: bytes,
32172                    error: new _voDashJSError2['default'](err.code, err.message, null)
32173                });
32174            }
32175        });
32176    }
32177
32178    function remove(buffer, start, end, mediaSource) {
32179
32180        // make sure that the given time range is correct. Otherwise we will get InvalidAccessError
32181        waitForUpdateEnd(buffer, function () {
32182            try {
32183                if (start >= 0 && end > start && mediaSource.readyState !== 'ended') {
32184                    buffer.remove(start, end);
32185                }
32186                // updating is in progress, we should wait for it to complete before signaling that this operation is done
32187                waitForUpdateEnd(buffer, function () {
32188                    eventBus.trigger(_coreEventsEvents2['default'].SOURCEBUFFER_REMOVE_COMPLETED, {
32189                        buffer: buffer,
32190                        from: start,
32191                        to: end
32192                    });
32193                });
32194            } catch (err) {
32195                eventBus.trigger(_coreEventsEvents2['default'].SOURCEBUFFER_REMOVE_COMPLETED, {
32196                    buffer: buffer,
32197                    from: start,
32198                    to: end,
32199                    error: new _voDashJSError2['default'](err.code, err.message, null)
32200                });
32201            }
32202        });
32203    }
32204
32205    function abort(mediaSource, buffer) {
32206        try {
32207            if (mediaSource.readyState === 'open') {
32208                buffer.abort();
32209            } else if (buffer.resetEmbedded && mediaSource.readyState === 'ended') {
32210                buffer.abort(); //The cues need to be removed from the TextSourceBuffer via a call to abort()
32211            }
32212        } catch (ex) {}
32213    }
32214
32215    function waitForUpdateEnd(buffer, callback) {
32216        var intervalId = undefined;
32217        var CHECK_INTERVAL = 50;
32218
32219        var checkIsUpdateEnded = function checkIsUpdateEnded() {
32220            // if updating is still in progress do nothing and wait for the next check again.
32221            if (buffer.updating) return;
32222            // updating is completed, now we can stop checking and resolve the promise
32223            clearInterval(intervalId);
32224            callback();
32225        };
32226
32227        var updateEndHandler = function updateEndHandler() {
32228            if (buffer.updating) return;
32229
32230            buffer.removeEventListener('updateend', updateEndHandler, false);
32231            callback();
32232        };
32233
32234        if (!buffer.updating) {
32235            callback();
32236            return;
32237        }
32238
32239        // use updateend event if possible
32240        if (typeof buffer.addEventListener === 'function') {
32241            try {
32242                buffer.addEventListener('updateend', updateEndHandler, false);
32243            } catch (err) {
32244                // use setInterval to periodically check if updating has been completed
32245                intervalId = setInterval(checkIsUpdateEnded, CHECK_INTERVAL);
32246            }
32247        } else {
32248            // use setInterval to periodically check if updating has been completed
32249            intervalId = setInterval(checkIsUpdateEnded, CHECK_INTERVAL);
32250        }
32251    }
32252
32253    instance = {
32254        append: append,
32255        remove: remove,
32256        abort: abort,
32257        createSourceBuffer: createSourceBuffer,
32258        removeSourceBuffer: removeSourceBuffer,
32259        getBufferRange: getBufferRange,
32260        getAllRanges: getAllRanges,
32261        getTotalBufferedTime: getTotalBufferedTime,
32262        getBufferLength: getBufferLength,
32263        getRangeDifference: getRangeDifference
32264    };
32265
32266    return instance;
32267}
32268
32269SourceBufferController.__dashjs_factory_name = 'SourceBufferController';
32270var factory = _coreFactoryMaker2['default'].getSingletonFactory(SourceBufferController);
32271factory.QUOTA_EXCEEDED_ERROR_CODE = QUOTA_EXCEEDED_ERROR_CODE;
32272_coreFactoryMaker2['default'].updateSingletonFactory(SourceBufferController.__dashjs_factory_name, factory);
32273exports['default'] = factory;
32274module.exports = exports['default'];
32275
32276},{"207":207,"50":50,"51":51,"54":54}],113:[function(_dereq_,module,exports){
32277/**
32278 * The copyright in this software is being made available under the BSD License,
32279 * included below. This software may be subject to other third party and contributor
32280 * rights, including patent rights, and no such rights are granted under this license.
32281 *
32282 * Copyright (c) 2013, Dash Industry Forum.
32283 * All rights reserved.
32284 *
32285 * Redistribution and use in source and binary forms, with or without modification,
32286 * are permitted provided that the following conditions are met:
32287 *  * Redistributions of source code must retain the above copyright notice, this
32288 *  list of conditions and the following disclaimer.
32289 *  * Redistributions in binary form must reproduce the above copyright notice,
32290 *  this list of conditions and the following disclaimer in the documentation and/or
32291 *  other materials provided with the distribution.
32292 *  * Neither the name of Dash Industry Forum nor the names of its
32293 *  contributors may be used to endorse or promote products derived from this software
32294 *  without specific prior written permission.
32295 *
32296 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
32297 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32298 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
32299 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
32300 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
32300INCLUDING, BUT
32301 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32302 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32303 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32304 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32305 *  POSSIBILITY OF SUCH DAMAGE.
32306 */
32307'use strict';
32308
32309Object.defineProperty(exports, '__esModule', {
32310    value: true
32311});
32312
32313function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
32314
32315var _constantsConstants = _dereq_(100);
32316
32317var _constantsConstants2 = _interopRequireDefault(_constantsConstants);
32318
32319var _constantsMetricsConstants = _dereq_(101);
32320
32321var _constantsMetricsConstants2 = _interopRequireDefault(_constantsMetricsConstants);
32322
32323var _Stream = _dereq_(96);
32324
32325var _Stream2 = _interopRequireDefault(_Stream);
32326
32327var _ManifestUpdater = _dereq_(92);
32328
32329var _ManifestUpdater2 = _interopRequireDefault(_ManifestUpdater);
32330
32331var _coreEventBus = _dereq_(50);
32332
32333var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
32334
32335var _coreEventsEvents = _dereq_(54);
32336
32337var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
32338
32339var _modelsURIQueryAndFragmentModel = _dereq_(144);
32340
32341var _modelsURIQueryAndFragmentModel2 = _interopRequireDefault(_modelsURIQueryAndFragmentModel);
32342
32343var _modelsMediaPlayerModel = _dereq_(142);
32344
32345var _modelsMediaPlayerModel2 = _interopRequireDefault(_modelsMediaPlayerModel);
32346
32347var _coreFactoryMaker = _dereq_(51);
32348
32349var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
32350
32351var _voMetricsPlayList = _dereq_(226);
32352
32353var _coreDebug = _dereq_(49);
32354
32355var _coreDebug2 = _interopRequireDefault(_coreDebug);
32356
32357var _utilsInitCache = _dereq_(196);
32358
32359var _utilsInitCache2 = _interopRequireDefault(_utilsInitCache);
32360
32361var _MediaPlayerEvents = _dereq_(94);
32362
32363var _MediaPlayerEvents2 = _interopRequireDefault(_MediaPlayerEvents);
32364
32365var _TimeSyncController = _dereq_(114);
32366
32367var _TimeSyncController2 = _interopRequireDefault(_TimeSyncController);
32368
32369var _BaseURLController = _dereq_(103);
32370
32371var _BaseURLController2 = _interopRequireDefault(_BaseURLController);
32372
32373var _MediaSourceController = _dereq_(109);
32374
32375var _MediaSourceController2 = _interopRequireDefault(_MediaSourceController);
32376
32377function StreamController() {
32378
32379    var STREAM_END_THRESHOLD = 0.5;
32380    var STREAM_END_TIMEOUT_DELAY = 0.1;
32381
32382    var context = this.context;
32383    var log = (0, _coreDebug2['default'])(context).getInstance().log;
32384    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
32385
32386    var instance = undefined,
32387        capabilities = undefined,
32388        manifestUpdater = undefined,
32389        manifestLoader = undefined,
32390        manifestModel = undefined,
32391        dashManifestModel = undefined,
32392        adapter = undefined,
32393        metricsModel = undefined,
32394        dashMetrics = undefined,
32395        mediaSourceController = undefined,
32396        timeSyncController = undefined,
32397        baseURLController = undefined,
32398        domStorage = undefined,
32399        abrController = undefined,
32400        mediaController = undefined,
32401        textController = undefined,
32402        sourceBufferController = undefined,
32403        initCache = undefined,
32404        errHandler = undefined,
32405        timelineConverter = undefined,
32406        streams = undefined,
32407        activeStream = undefined,
32408        protectionController = undefined,
32409        protectionData = undefined,
32410        autoPlay = undefined,
32411        isStreamSwitchingInProgress = undefined,
32412        hasMediaError = undefined,
32413        hasInitialisationError = undefined,
32414        mediaSource = undefined,
32415        videoModel = undefined,
32416        playbackController = undefined,
32417        mediaPlayerModel = undefined,
32418        isPaused = undefined,
32419        initialPlayback = undefined,
32420        playListMetrics = undefined,
32421        videoTrackDetected = undefined,
32422        audioTrackDetected = undefined,
32423        endedTimeout = undefined;
32424
32425    function setup() {
32426        timeSyncController = (0, _TimeSyncController2['default'])(context).getInstance();
32427        baseURLController = (0, _BaseURLController2['default'])(context).getInstance();
32428        mediaSourceController = (0, _MediaSourceController2['default'])(context).getInstance();
32429        initCache = (0, _utilsInitCache2['default'])(context).getInstance();
32430
32431        resetInitialSettings();
32432    }
32433
32434    function initialize(autoPl, protData) {
32435        checkSetConfigCall();
32436
32437        autoPlay = autoPl;
32438        protectionData = protData;
32439        timelineConverter.initialize();
32440
32441        manifestUpdater = (0, _ManifestUpdater2['default'])(context).create();
32442        manifestUpdater.setConfig({
32443            manifestModel: manifestModel,
32444            dashManifestModel: dashManifestModel,
32445            mediaPlayerModel: mediaPlayerModel,
32446            manifestLoader: manifestLoader
32447        });
32448        manifestUpdater.initialize();
32449
32450        baseURLController.setConfig({
32451            dashManifestModel: dashManifestModel
32452        });
32453
32454        eventBus.on(_coreEventsEvents2['default'].TIME_SYNCHRONIZATION_COMPLETED, onTimeSyncCompleted, this);
32455        eventBus.on(_coreEventsEvents2['default'].PLAYBACK_SEEKING, onPlaybackSeeking, this);
32456        eventBus.on(_coreEventsEvents2['default'].PLAYBACK_TIME_UPDATED, onPlaybackTimeUpdated, this);
32457        eventBus.on(_coreEventsEvents2['default'].PLAYBACK_ENDED, onEnded, this);
32458        eventBus.on(_coreEventsEvents2['default'].PLAYBACK_ERROR, onPlaybackError, this);
32459        eventBus.on(_coreEventsEvents2['default'].PLAYBACK_STARTED, onPlaybackStarted, this);
32460        eventBus.on(_coreEventsEvents2['default'].PLAYBACK_PAUSED, onPlaybackPaused, this);
32461        eventBus.on(_coreEventsEvents2['default'].MANIFEST_UPDATED, onManifestUpdated, this);
32462        eventBus.on(_coreEventsEvents2['default'].STREAM_BUFFERING_COMPLETED, onStreamBufferingCompleted, this);
32463        eventBus.on(_MediaPlayerEvents2['default'].METRIC_ADDED, onMetricAdded, this);
32464    }
32465
32466    /*
32467     * Called when current playback position is changed.
32468     * Used to determine the time current stream is finished and we should switch to the next stream.
32469     */
32470    function onPlaybackTimeUpdated(e) {
32471
32472        if (isVideoTrackPresent()) {
32473            var playbackQuality = videoModel.getPlaybackQuality();
32474            if (playbackQuality) {
32475                metricsModel.addDroppedFrames(_constantsConstants2['default'].VIDEO, playbackQuality);
32476            }
32477        }
32478
32479        // Sometimes after seeking timeUpdateHandler is called before seekingHandler and a new stream starts
32480        // from beginning instead of from a chosen position. So we do nothing if the player is in the seeking state
32481        if (playbackController.isSeeking()) return;
32482
32483        if (e.timeToEnd <= STREAM_END_THRESHOLD) {
32484            // In some cases the ended event is not triggered at the end of the stream, do it artificially here.
32485            // This should only be a fallback, put an extra STREAM_END_TIMEOUT_DELAY to give the real ended event time to trigger.
32486
32487            if (endedTimeout) {
32488                clearTimeout(endedTimeout);
32489                endedTimeout = undefined;
32490            }
32491            endedTimeout = setTimeout(function () {
32492                endedTimeout = undefined;
32493                eventBus.trigger(_coreEventsEvents2['default'].PLAYBACK_ENDED);
32494            }, 1000 * (e.timeToEnd + STREAM_END_TIMEOUT_DELAY));
32495        }
32496    }
32497
32498    function onPlaybackSeeking(e) {
32499        var seekingStream = getStreamForTime(e.seekTime);
32500
32501        if (seekingStream && seekingStream !== activeStream) {
32502            flushPlaylistMetrics(_voMetricsPlayList.PlayListTrace.END_OF_PERIOD_STOP_REASON);
32503            switchStream(activeStream, seekingStream, e.seekTime);
32504        } else {
32505            flushPlaylistMetrics(_voMetricsPlayList.PlayListTrace.USER_REQUEST_STOP_REASON);
32506        }
32507
32508        addPlaylistMetrics(_voMetricsPlayList.PlayList.SEEK_START_REASON);
32509    }
32510
32511    function onPlaybackStarted() /*e*/{
32512        if (initialPlayback) {
32513            initialPlayback = false;
32514            addPlaylistMetrics(_voMetricsPlayList.PlayList.INITIAL_PLAYOUT_START_REASON);
32515        } else {
32516            if (isPaused) {
32517                isPaused = false;
32518                addPlaylistMetrics(_voMetricsPlayList.PlayList.RESUME_FROM_PAUSE_START_REASON);
32519            }
32520        }
32521    }
32522
32523    function onPlaybackPaused(e) {
32524        if (!e.ended) {
32525            isPaused = true;
32526            flushPlaylistMetrics(_voMetricsPlayList.PlayListTrace.USER_REQUEST_STOP_REASON);
32527        }
32528    }
32529
32530    function onStreamBufferingCompleted() {
32531        var isLast = getActiveStreamInfo().isLast;
32532        if (mediaSource && isLast) {
32533            mediaSourceController.signalEndOfStream(mediaSource);
32534        }
32535    }
32536
32537    function getStreamForTime(time) {
32538        var duration = 0;
32539        var stream = null;
32540
32541        var ln = streams.length;
32542
32543        if (ln > 0) {
32544            duration += streams[0].getStartTime();
32545        }
32546
32547        for (var i = 0; i < ln; i++) {
32548            stream = streams[i];
32549            duration += stream.getDuration();
32550
32551            if (time < duration) {
32552                return stream;
32553            }
32554        }
32555
32556        return null;
32557    }
32558
32559    /**
32560     * Returns a playhead time, in seconds, converted to be relative
32561     * to the start of an identified stream/period or null if no such stream
32562     * @param {number} time
32563     * @param {string} id
32564     * @returns {number|null}
32565     */
32566    function getTimeRelativeToStreamId(time, id) {
32567        var stream = null;
32568        var baseStart = 0;
32569        var streamStart = 0;
32570        var streamDur = null;
32571
32572        var ln = streams.length;
32573
32574        for (var i = 0; i < ln; i++) {
32575            stream = streams[i];
32576            streamStart = stream.getStartTime();
32577            streamDur = stream.getDuration();
32578
32579            // use start time, if not undefined or NaN or similar
32580            if (Number.isFinite(streamStart)) {
32581                baseStart = streamStart;
32582            }
32583
32584            if (stream.getId() === id) {
32585                return time - baseStart;
32586            } else {
32587                // use duration if not undefined or NaN or similar
32588                if (Number.isFinite(streamDur)) {
32589                    baseStart += streamDur;
32590                }
32591            }
32592        }
32593
32594        return null;
32595    }
32596
32597    function getActiveStreamProcessors() {
32598        return activeStream ? activeStream.getProcessors() : [];
32599    }
32600
32601    function getActiveStreamCommonEarliestTime() {
32602        var commonEarliestTime = [];
32603        if (activeStream) {
32604            activeStream.getProcessors().forEach(function (p) {
32605                commonEarliestTime.push(p.getIndexHandler().getEarliestTime());
32606            });
32607        }
32608        return Math.min.apply(Math, commonEarliestTime);
32609    }
32610
32611    function onEnded() {
32612        if (endedTimeout) {
32613            clearTimeout(endedTimeout);
32614            endedTimeout = undefined;
32615        }
32616
32617        var nextStream = getNextStream();
32618        if (nextStream) {
32619            switchStream(activeStream, nextStream, NaN);
32620        }
32621        flushPlaylistMetrics(nextStream ? _voMetricsPlayList.PlayListTrace.END_OF_PERIOD_STOP_REASON : _voMetricsPlayList.PlayListTrace.END_OF_CONTENT_STOP_REASON);
32622    }
32623
32624    function getNextStream() {
32625        if (activeStream) {
32626            var _ret = (function () {
32627                var start = activeStream.getStreamInfo().start;
32628                var duration = activeStream.getStreamInfo().duration;
32629
32630                return {
32631                    v: streams.filter(function (stream) {
32632                        return stream.getStreamInfo().start === start + duration;
32633                    })[0]
32634                };
32635            })();
32636
32637            if (typeof _ret === 'object') return _ret.v;
32638        }
32639    }
32640
32641    function switchStream(oldStream, newStream, seekTime) {
32642
32643        if (isStreamSwitchingInProgress || !newStream || oldStream === newStream) return;
32644        isStreamSwitchingInProgress = true;
32645
32646        eventBus.trigger(_coreEventsEvents2['default'].PERIOD_SWITCH_STARTED, {
32647            fromStreamInfo: oldStream ? oldStream.getStreamInfo() : null,
32648            toStreamInfo: newStream.getStreamInfo()
32649        });
32650
32651        if (oldStream) oldStream.deactivate();
32652        activeStream = newStream;
32653        playbackController.initialize(activeStream.getStreamInfo());
32654
32655        //TODO detect if we should close and repose or jump to activateStream.
32656        openMediaSource(seekTime);
32657    }
32658
32659    function openMediaSource(seekTime) {
32660
32661        var sourceUrl = undefined;
32662
32663        function onMediaSourceOpen() {
32664            log('MediaSource is open!');
32665            window.URL.revokeObjectURL(sourceUrl);
32666            mediaSource.removeEventListener('sourceopen', onMediaSourceOpen);
32667            mediaSource.removeEventListener('webkitsourceopen', onMediaSourceOpen);
32668            setMediaDuration();
32669            activateStream(seekTime);
32670        }
32671
32672        if (!mediaSource) {
32673            mediaSource = mediaSourceController.createMediaSource();
32674        } else {
32675            mediaSourceController.detachMediaSource(videoModel);
32676        }
32677
32678        mediaSource.addEventListener('sourceopen', onMediaSourceOpen, false);
32679        mediaSource.addEventListener('webkitsourceopen', onMediaSourceOpen, false);
32680        sourceUrl = mediaSourceController.attachMediaSource(mediaSource, videoModel);
32681        log('MediaSource attached to element.  Waiting on open...');
32682    }
32683
32684    function activateStream(seekTime) {
32685
32686        activeStream.activate(mediaSource);
32687
32688        if (!initialPlayback) {
32689            if (!isNaN(seekTime)) {
32690                playbackController.seek(seekTime); //we only need to call seek here, IndexHandlerTime was set from seeking event
32691            } else {
32692                    (function () {
32693                        var startTime = playbackController.getStreamStartTime(true);
32694                        activeStream.getProcessors().forEach(function (p) {
32695                            adapter.setIndexHandlerTime(p, startTime);
32696                        });
32697                        playbackController.seek(startTime); //seek to period start time
32698                    })();
32699                }
32700        } else {
32701                videoTrackDetected = checkTrackPresence(_constantsConstants2['default'].VIDEO);
32702            }
32703
32704        activeStream.startEventController();
32705        if (autoPlay || !initialPlayback) {
32706            playbackController.play();
32707        }
32708
32709        isStreamSwitchingInProgress = false;
32710        eventBus.trigger(_coreEventsEvents2['default'].PERIOD_SWITCH_COMPLETED, {
32711            toStreamInfo: activeStream.getStreamInfo()
32712        });
32713    }
32714
32715    function setMediaDuration() {
32716        var manifestDuration = activeStream.getStreamInfo().manifestInfo.duration;
32717        var mediaDuration = mediaSourceController.setDuration(mediaSource, manifestDuration);
32718        log('Duration successfully set to: ' + mediaDuration);
32719    }
32720
32721    function getComposedStream(streamInfo) {
32722        for (var i = 0, ln = streams.length; i < ln; i++) {
32723            if (streams[i].getId() === streamInfo.id) {
32724                return streams[i];
32725            }
32726        }
32727        return null;
32728    }
32729
32730    function composeStreams() {
32731
32732        try {
32733            var streamsInfo = adapter.getStreamsInfo();
32734            if (streamsInfo.length === 0) {
32735                throw new Error('There are no streams');
32736            }
32737
32738            var manifestUpdateInfo = dashMetrics.getCurrentManifestUpdate(metricsModel.getMetricsFor(_constantsConstants2['default'].STREAM));
32739            metricsModel.updateManifestUpdateInfo(manifestUpdateInfo, {
32740                currentTime: playbackController.getTime(),
32741                buffered: videoModel.getBufferRange(),
32742                presentationStartTime: streamsInfo[0].start,
32743                clientTimeOffset: timelineConverter.getClientTimeOffset()
32744            });
32745
32746            for (var i = 0, ln = streamsInfo.length; i < ln; i++) {
32747
32748                // If the Stream object does not exist we probably loaded the manifest the first time or it was
32749                // introduced in the updated manifest, so we need to create a new Stream and perform all the initialization operations
32750                var streamInfo = streamsInfo[i];
32751                var stream = getComposedStream(streamInfo);
32752
32753                if (!stream) {
32754
32755                    stream = (0, _Stream2['default'])(context).create({
32756                        manifestModel: manifestModel,
32757                        dashManifestModel: dashManifestModel,
32758                        mediaPlayerModel: mediaPlayerModel,
32759                        metricsModel: metricsModel,
32760                        dashMetrics: dashMetrics,
32761                        manifestUpdater: manifestUpdater,
32762                        adapter: adapter,
32763                        timelineConverter: timelineConverter,
32764                        capabilities: capabilities,
32765                        errHandler: errHandler,
32766                        baseURLController: baseURLController,
32767                        domStorage: domStorage,
32768                        abrController: abrController,
32769                        playbackController: playbackController,
32770                        mediaController: mediaController,
32771                        textController: textController,
32772                        sourceBufferController: sourceBufferController,
32773                        videoModel: videoModel,
32774                        streamController: instance
32775                    });
32776                    streams.push(stream);
32777                    stream.initialize(streamInfo, protectionController);
32778                } else {
32779                    stream.updateData(streamInfo);
32780                }
32781
32782                metricsModel.addManifestUpdateStreamInfo(manifestUpdateInfo, streamInfo.id, streamInfo.index, streamInfo.start, streamInfo.duration);
32783            }
32784
32785            if (!activeStream) {
32786                //const initStream = streamsInfo[0].manifestInfo.isDynamic ? streams[streams.length -1] : streams[0];
32787                //TODO we need to figure out what the correct starting period is here and not just go to first or last in array.
32788                switchStream(null, streams[0], NaN);
32789            }
32790
32791            eventBus.trigger(_coreEventsEvents2['default'].STREAMS_COMPOSED);
32792        } catch (e) {
32793            errHandler.manifestError(e.message, 'nostreamscomposed', manifestModel.getValue());
32794            hasInitialisationError = true;
32795            reset();
32796        }
32797    }
32798
32799    function onTimeSyncCompleted() /*e*/{
32800        var manifest = manifestModel.getValue();
32801        //TODO check if we can move this to initialize??
32802        if (protectionController) {
32803            eventBus.trigger(_coreEventsEvents2['default'].PROTECTION_CREATED, {
32804                controller: protectionController,
32805                manifest: manifest
32806            });
32807            protectionController.setMediaElement(videoModel.getElement());
32808            if (protectionData) {
32809                protectionController.setProtectionData(protectionData);
32810            }
32811        }
32812
32813        composeStreams();
32814    }
32815
32816    function onManifestUpdated(e) {
32817        if (!e.error) {
32818            (function () {
32819                //Since streams are not composed yet , need to manually look up useCalculatedLiveEdgeTime to detect if stream
32820                //is SegmentTimeline to avoid using time source
32821                var manifest = e.manifest;
32822                adapter.updatePeriods(manifest);
32823                var streamInfo = adapter.getStreamsInfo(manifest)[0];
32824                var mediaInfo = adapter.getMediaInfoForType(streamInfo, _constantsConstants2['default'].VIDEO) || adapter.getMediaInfoForType(streamInfo, _constantsConstants2['default'].AUDIO);
32825
32826                var voAdaptation = undefined,
32827                    useCalculatedLiveEdgeTime = undefined;
32828
32829                if (mediaInfo) {
32830                    voAdaptation = adapter.getDataForMedia(mediaInfo);
32831                    useCalculatedLiveEdgeTime = dashManifestModel.getRepresentationsForAdaptation(voAdaptation)[0].useCalculatedLiveEdgeTime;
32832
32833                    if (useCalculatedLiveEdgeTime) {
32834                        log('SegmentTimeline detected using calculated Live Edge Time');
32835                        mediaPlayerModel.setUseManifestDateHeaderTimeSource(false);
32836                    }
32837                }
32838
32839                var manifestUTCTimingSources = dashManifestModel.getUTCTimingSources(e.manifest);
32840                var allUTCTimingSources = !dashManifestModel.getIsDynamic(manifest) || useCalculatedLiveEdgeTime ? manifestUTCTimingSources : manifestUTCTimingSources.concat(mediaPlayerModel.getUTCTimingSources());
32841                var isHTTPS = (0, _modelsURIQueryAndFragmentModel2['default'])(context).getInstance().isManifestHTTPS();
32842
32843                //If https is detected on manifest then lets apply that protocol to only the default time source(s). In the future we may find the need to apply this to more then just default so left code at this level instead of in MediaPlayer.
32844                allUTCTimingSources.forEach(function (item) {
32845                    if (item.value.replace(/.*?:\/\//g, '') === _modelsMediaPlayerModel2['default'].DEFAULT_UTC_TIMING_SOURCE.value.replace(/.*?:\/\//g, '')) {
32846                        item.value = item.value.replace(isHTTPS ? new RegExp(/^(http:)?\/\//i) : new RegExp(/^(https:)?\/\//i), isHTTPS ? 'https://' : 'http://');
32847                        log('Matching default timing source protocol to manifest protocol: ', item.value);
32848                    }
32849                });
32850
32851                baseURLController.initialize(manifest);
32852
32853                timeSyncController.setConfig({
32854                    metricsModel: metricsModel,
32855                    dashMetrics: dashMetrics
32856                });
32857                timeSyncController.initialize(allUTCTimingSources, mediaPlayerModel.getUseManifestDateHeaderTimeSource());
32858            })();
32859        } else {
32860            hasInitialisationError = true;
32861            reset();
32862        }
32863    }
32864
32865    function isAudioTrackPresent() {
32866        if (audioTrackDetected === undefined) {
32867            audioTrackDetected = checkTrackPresence(_constantsConstants2['default'].AUDIO);
32868        }
32869        return audioTrackDetected;
32870    }
32871
32872    function isVideoTrackPresent() {
32873        if (videoTrackDetected === undefined) {
32874            videoTrackDetected = checkTrackPresence(_constantsConstants2['default'].VIDEO);
32875        }
32876        return videoTrackDetected;
32877    }
32878
32879    function checkTrackPresence(type) {
32880        var isDetected = false;
32881        if (activeStream) {
32882            activeStream.getProcessors().forEach(function (p) {
32883                if (p.getMediaInfo().type === type) {
32884                    isDetected = true;
32885                }
32886            });
32887        }
32888        return isDetected;
32889    }
32890
32891    function flushPlaylistMetrics(reason, time) {
32892        time = time || new Date();
32893
32894        if (playListMetrics) {
32895            if (activeStream) {
32896                activeStream.getProcessors().forEach(function (p) {
32897                    var ctrlr = p.getScheduleController();
32898                    if (ctrlr) {
32899                        ctrlr.finalisePlayList(time, reason);
32900                    }
32901                });
32902            }
32903            metricsModel.addPlayList(playListMetrics);
32904            playListMetrics = null;
32905        }
32906    }
32907
32908    function addPlaylistMetrics(startReason) {
32909        playListMetrics = new _voMetricsPlayList.PlayList();
32910        playListMetrics.start = new Date();
32911        playListMetrics.mstart = playbackController.getTime() * 1000;
32912        playListMetrics.starttype = startReason;
32913
32914        if (activeStream) {
32915            activeStream.getProcessors().forEach(function (p) {
32916                var ctrlr = p.getScheduleController();
32917                if (ctrlr) {
32918                    ctrlr.setPlayList(playListMetrics);
32919                }
32920            });
32921        }
32922    }
32923
32924    function onPlaybackError(e) {
32925
32926        if (!e.error) return;
32927
32928        var msg = '';
32929
32930        switch (e.error.code) {
32931            case 1:
32932                msg = 'MEDIA_ERR_ABORTED';
32933                break;
32934            case 2:
32935                msg = 'MEDIA_ERR_NETWORK';
32936                break;
32937            case 3:
32938                msg = 'MEDIA_ERR_DECODE';
32939                break;
32940            case 4:
32941                msg = 'MEDIA_ERR_SRC_NOT_SUPPORTED';
32942                break;
32943            case 5:
32944                msg = 'MEDIA_ERR_ENCRYPTED';
32945                break;
32946            default:
32947                msg = 'UNKNOWN';
32948                break;
32949        }
32950
32951        hasMediaError = true;
32952
32953        if (e.error.message) {
32954            msg += ' (' + e.error.message + ')';
32955        }
32956
32957        if (e.error.msExtendedCode) {
32958            msg += ' (0x' + (e.error.msExtendedCode >>> 0).toString(16).toUpperCase() + ')';
32959        }
32960
32961        log('Video Element Error: ' + msg);
32962        if (e.error) {
32963            log(e.error);
32964        }
32965        errHandler.mediaSourceError(msg);
32966        reset();
32967    }
32968
32969    function getActiveStreamInfo() {
32970        return activeStream ? activeStream.getStreamInfo() : null;
32971    }
32972
32973    function getStreamById(id) {
32974        return streams.filter(function (item) {
32975            return item.getId() === id;
32976        })[0];
32977    }
32978
32979    function checkSetConfigCall() {
32980        if (!manifestLoader || !manifestLoader.hasOwnProperty('load') || !timelineConverter || !timelineConverter.hasOwnProperty('initialize') || !timelineConverter.hasOwnProperty('reset') || !timelineConverter.hasOwnProperty('getClientTimeOffset')) {
32981            throw new Error('setConfig function has to be called previously');
32982        }
32983    }
32984
32985    function checkInitializeCall() {
32986        if (!manifestUpdater || !manifestUpdater.hasOwnProperty('setManifest')) {
32987            throw new Error('initialize function has to be called previously');
32988        }
32989    }
32990
32991    function load(url) {
32992        checkSetConfigCall();
32993        manifestLoader.load(url);
32994    }
32995
32996    function loadWithManifest(manifest) {
32997        checkInitializeCall();
32998        manifestUpdater.setManifest(manifest);
32999    }
33000
33001    function setConfig(config) {
33002        if (!config) return;
33003
33004        if (config.capabilities) {
33005            capabilities = config.capabilities;
33006        }
33007        if (config.manifestLoader) {
33008            manifestLoader = config.manifestLoader;
33009        }
33010        if (config.manifestModel) {
33011            manifestModel = config.manifestModel;
33012        }
33013        if (config.dashManifestModel) {
33014            dashManifestModel = config.dashManifestModel;
33015        }
33016        if (config.mediaPlayerModel) {
33017            mediaPlayerModel = config.mediaPlayerModel;
33018        }
33019        if (config.protectionController) {
33020            protectionController = config.protectionController;
33021        }
33022        if (config.adapter) {
33023            adapter = config.adapter;
33024        }
33025        if (config.metricsModel) {
33026            metricsModel = config.metricsModel;
33027        }
33028        if (config.dashMetrics) {
33029            dashMetrics = config.dashMetrics;
33030        }
33031        if (config.errHandler) {
33032            errHandler = config.errHandler;
33033        }
33034        if (config.timelineConverter) {
33035            timelineConverter = config.timelineConverter;
33036        }
33037        if (config.videoModel) {
33038            videoModel = config.videoModel;
33039        }
33040        if (config.playbackController) {
33041            playbackController = config.playbackController;
33042        }
33043        if (config.domStorage) {
33044            domStorage = config.domStorage;
33045        }
33046        if (config.abrController) {
33047            abrController = config.abrController;
33048        }
33049        if (config.mediaController) {
33050            mediaController = config.mediaController;
33051        }
33052        if (config.textController) {
33053            textController = config.textController;
33054        }
33055        if (config.sourceBufferController) {
33056            sourceBufferController = config.sourceBufferController;
33057        }
33058    }
33059
33060    function resetInitialSettings() {
33061        streams = [];
33062        protectionController = null;
33063        isStreamSwitchingInProgress = false;
33064        activeStream = null;
33065        hasMediaError = false;
33066        hasInitialisationError = false;
33067        videoTrackDetected = undefined;
33068        initialPlayback = true;
33069        isPaused = false;
33070        autoPlay = true;
33071        playListMetrics = null;
33072    }
33073
33074    function reset() {
33075        checkSetConfigCall();
33076
33077        timeSyncController.reset();
33078
33079        flushPlaylistMetrics(hasMediaError || hasInitialisationError ? _voMetricsPlayList.PlayListTrace.FAILURE_STOP_REASON : _voMetricsPlayList.PlayListTrace.USER_REQUEST_STOP_REASON);
33080
33081        for (var i = 0, ln = streams ? streams.length : 0; i < ln; i++) {
33082            var stream = streams[i];
33083            stream.reset(hasMediaError);
33084        }
33085
33086        eventBus.off(_coreEventsEvents2['default'].PLAYBACK_TIME_UPDATED, onPlaybackTimeUpdated, this);
33087        eventBus.off(_coreEventsEvents2['default'].PLAYBACK_SEEKING, onPlaybackSeeking, this);
33088        eventBus.off(_coreEventsEvents2['default'].PLAYBACK_ERROR, onPlaybackError, this);
33089        eventBus.off(_coreEventsEvents2['default'].PLAYBACK_STARTED, onPlaybackStarted, this);
33090        eventBus.off(_coreEventsEvents2['default'].PLAYBACK_PAUSED, onPlaybackPaused, this);
33091        eventBus.off(_coreEventsEvents2['default'].PLAYBACK_ENDED, onEnded, this);
33092        eventBus.off(_coreEventsEvents2['default'].MANIFEST_UPDATED, onManifestUpdated, this);
33093        eventBus.off(_coreEventsEvents2['default'].STREAM_BUFFERING_COMPLETED, onStreamBufferingCompleted, this);
33094        eventBus.off(_MediaPlayerEvents2['default'].METRIC_ADDED, onMetricAdded, this);
33095
33096        baseURLController.reset();
33097        manifestUpdater.reset();
33098        metricsModel.clearAllCurrentMetrics();
33099        manifestModel.setValue(null);
33100        manifestLoader.reset();
33101        timelineConverter.reset();
33102        initCache.reset();
33103
33104        if (mediaSource) {
33105            mediaSourceController.detachMediaSource(videoModel);
33106            mediaSource = null;
33107        }
33108        videoModel = null;
33109        if (protectionController) {
33110            protectionController.setMediaElement(null);
33111            protectionController = null;
33112            protectionData = null;
33113            if (manifestModel.getValue()) {
33114                eventBus.trigger(_coreEventsEvents2['default'].PROTECTION_DESTROYED, {
33115                    data: manifestModel.getValue().url
33116                });
33117            }
33118        }
33119
33120        if (endedTimeout) {
33121            clearTimeout(endedTimeout);
33122            endedTimeout = undefined;
33123        }
33124
33125        eventBus.trigger(_coreEventsEvents2['default'].STREAM_TEARDOWN_COMPLETE);
33126        resetInitialSettings();
33127    }
33128
33129    function onMetricAdded(e) {
33130        if (e.metric === _constantsMetricsConstants2['default'].DVR_INFO) {
33131            //Match media type? How can DVR window be different for media types?
33132            //Should we normalize and union the two?
33133            if (e.mediaType === _constantsConstants2['default'].AUDIO) {
33134                mediaSourceController.setSeekable(mediaSource, e.value.range.start, e.value.range.end);
33135            }
33136        }
33137    }
33138
33139    instance = {
33140        initialize: initialize,
33141        getActiveStreamInfo: getActiveStreamInfo,
33142        isVideoTrackPresent: isVideoTrackPresent,
33143        isAudioTrackPresent: isAudioTrackPresent,
33144        getStreamById: getStreamById,
33145        getTimeRelativeToStreamId: getTimeRelativeToStreamId,
33146        load: load,
33147        loadWithManifest: loadWithManifest,
33148        getActiveStreamProcessors: getActiveStreamProcessors,
33149        getActiveStreamCommonEarliestTime: getActiveStreamCommonEarliestTime,
33150        setConfig: setConfig,
33151        reset: reset
33152    };
33153
33154    setup();
33155
33156    return instance;
33157}
33158
33159StreamController.__dashjs_factory_name = 'StreamController';
33160
33161exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(StreamController);
33162module.exports = exports['default'];
33163
33164},{"100":100,"101":101,"103":103,"109":109,"114":114,"142":142,"144":144,"196":196,"226":226,"49":49,"50":50,"51":51,"54":54,"92":92,"94":94,"96":96}],114:[function(_dereq_,module,exports){
33165/**
33166 * The copyright in this software is being made available under the BSD License,
33167 * included below. This software may be subject to other third party and contributor
33168 * rights, including patent rights, and no such rights are granted under this license.
33169 *
33170 * Copyright (c) 2013, Dash Industry Forum.
33171 * All rights reserved.
33172 *
33173 * Redistribution and use in source and binary forms, with or without modification,
33174 * are permitted provided that the following conditions are met:
33175 *  * Redistributions of source code must retain the above copyright notice, this
33176 *  list of conditions and the following disclaimer.
33177 *  * Redistributions in binary form must reproduce the above copyright notice,
33178 *  this list of conditions and the following disclaimer in the documentation and/or
33179 *  other materials provided with the distribution.
33180 *  * Neither the name of Dash Industry Forum nor the names of its
33181 *  contributors may be used to endorse or promote products derived from this software
33182 *  without specific prior written permission.
33183 *
33184 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
33185 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
33186 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
33187 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33188 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
33189 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33190 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33191 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33192 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33193 *  POSSIBILITY OF SUCH DAMAGE.
33194 */
33195'use strict';
33196
33197Object.defineProperty(exports, '__esModule', {
33198    value: true
33199});
33200
33201function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
33202
33203var _constantsConstants = _dereq_(100);
33204
33205var _constantsConstants2 = _interopRequireDefault(_constantsConstants);
33206
33207var _voDashJSError = _dereq_(207);
33208
33209var _voDashJSError2 = _interopRequireDefault(_voDashJSError);
33210
33211var _voMetricsHTTPRequest = _dereq_(224);
33212
33213var _coreEventBus = _dereq_(50);
33214
33215var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
33216
33217var _coreEventsEvents = _dereq_(54);
33218
33219var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
33220
33221var _coreFactoryMaker = _dereq_(51);
33222
33223var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
33224
33225var _coreDebug = _dereq_(49);
33226
33227var _coreDebug2 = _interopRequireDefault(_coreDebug);
33228
33229var TIME_SYNC_FAILED_ERROR_CODE = 1;
33230var HTTP_TIMEOUT_MS = 5000;
33231
33232function TimeSyncController() {
33233
33234    var context = this.context;
33235    var log = (0, _coreDebug2['default'])(context).getInstance().log;
33236    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
33237
33238    var instance = undefined,
33239        offsetToDeviceTimeMs = undefined,
33240        isSynchronizing = undefined,
33241        isInitialised = undefined,
33242        useManifestDateHeaderTimeSource = undefined,
33243        handlers = undefined,
33244        metricsModel = undefined,
33245        dashMetrics = undefined;
33246
33247    function initialize(timingSources, useManifestDateHeader) {
33248        useManifestDateHeaderTimeSource = useManifestDateHeader;
33249        offsetToDeviceTimeMs = 0;
33250        isSynchronizing = false;
33251        isInitialised = false;
33252
33253        // a list of known schemeIdUris and a method to call with @value
33254        handlers = {
33255            'urn:mpeg:dash:utc:http-head:2014': httpHeadHandler,
33256            'urn:mpeg:dash:utc:http-xsdate:2014': httpHandler.bind(null, xsdatetimeDecoder),
33257            'urn:mpeg:dash:utc:http-iso:2014': httpHandler.bind(null, iso8601Decoder),
33258            'urn:mpeg:dash:utc:direct:2014': directHandler,
33259
33260            // some specs referencing early ISO23009-1 drafts incorrectly use
33261            // 2012 in the URI, rather than 2014. support these for now.
33262            'urn:mpeg:dash:utc:http-head:2012': httpHeadHandler,
33263            'urn:mpeg:dash:utc:http-xsdate:2012': httpHandler.bind(null, xsdatetimeDecoder),
33264            'urn:mpeg:dash:utc:http-iso:2012': httpHandler.bind(null, iso8601Decoder),
33265            'urn:mpeg:dash:utc:direct:2012': directHandler,
33266
33267            // it isn't clear how the data returned would be formatted, and
33268            // no public examples available so http-ntp not supported for now.
33269            // presumably you would do an arraybuffer type xhr and decode the
33270            // binary data returned but I would want to see a sample first.
33271            'urn:mpeg:dash:utc:http-ntp:2014': notSupportedHandler,
33272
33273            // not clear how this would be supported in javascript (in browser)
33274            'urn:mpeg:dash:utc:ntp:2014': notSupportedHandler,
33275            'urn:mpeg:dash:utc:sntp:2014': notSupportedHandler
33276        };
33277
33278        if (!getIsSynchronizing()) {
33279            attemptSync(timingSources);
33280            setIsInitialised(true);
33281        }
33282    }
33283
33284    function setConfig(config) {
33285        if (!config) return;
33286
33287        if (config.metricsModel) {
33288            metricsModel = config.metricsModel;
33289        }
33290
33291        if (config.dashMetrics) {
33292            dashMetrics = config.dashMetrics;
33293        }
33294    }
33295
33296    function getOffsetToDeviceTimeMs() {
33297        return getOffsetMs();
33298    }
33299
33300    function setIsSynchronizing(value) {
33301        isSynchronizing = value;
33302    }
33303
33304    function getIsSynchronizing() {
33305        return isSynchronizing;
33306    }
33307
33308    function setIsInitialised(value) {
33309        isInitialised = value;
33310    }
33311
33312    function setOffsetMs(value) {
33313        offsetToDeviceTimeMs = value;
33314    }
33315
33316    function getOffsetMs() {
33317        return offsetToDeviceTimeMs;
33318    }
33319
33320    // takes xsdatetime and returns milliseconds since UNIX epoch
33321    // may not be necessary as xsdatetime is very similar to ISO 8601
33322    // which is natively understood by javascript Date parser
33323    function alternateXsdatetimeDecoder(xsdatetimeStr) {
33324        // taken from DashParser - should probably refactor both uses
33325        var SECONDS_IN_MIN = 60;
33326        var MINUTES_IN_HOUR = 60;
33327        var MILLISECONDS_IN_SECONDS = 1000;
33328        var datetimeRegex = /^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2})(?::([0-9]*)(\.[0-9]*)?)?(?:([+\-])([0-9]{2})([0-9]{2}))?/;
33329
33330        var utcDate = undefined,
33331            timezoneOffset = undefined;
33332
33333        var match = datetimeRegex.exec(xsdatetimeStr);
33334
33335        // If the string does not contain a timezone offset different browsers can interpret it either
33336        // as UTC or as a local time so we have to parse the string manually to normalize the given date value for
33337        // all browsers
33338        utcDate = Date.UTC(parseInt(match[1], 10), parseInt(match[2], 10) - 1, // months start from zero
33339        parseInt(match[3], 10), parseInt(match[4], 10), parseInt(match[5], 10), match[6] && (parseInt(match[6], 10) || 0), match[7] && parseFloat(match[7]) * MILLISECONDS_IN_SECONDS || 0);
33340        // If the date has timezone offset take it into account as well
33341        if (match[9] && match[10]) {
33342            timezoneOffset = parseInt(match[9], 10) * MINUTES_IN_HOUR + parseInt(match[10], 10);
33343            utcDate += (match[8] === '+' ? -1 : +1) * timezoneOffset * SECONDS_IN_MIN * MILLISECONDS_IN_SECONDS;
33344        }
33345
33346        return new Date(utcDate).getTime();
33347    }
33348
33349    // try to use the built in parser, since xsdate is a constrained ISO8601
33350    // which is supported natively by Date.parse. if that fails, try a
33351    // regex-based version used elsewhere in this application.
33352    function xsdatetimeDecoder(xsdatetimeStr) {
33353        var parsedDate = Date.parse(xsdatetimeStr);
33354
33355        if (isNaN(parsedDate)) {
33356            parsedDate = alternateXsdatetimeDecoder(xsdatetimeStr);
33357        }
33358
33359        return parsedDate;
33360    }
33361
33362    // takes ISO 8601 timestamp and returns milliseconds since UNIX epoch
33363    function iso8601Decoder(isoStr) {
33364        return Date.parse(isoStr);
33365    }
33366
33367    // takes RFC 1123 timestamp (which is same as ISO8601) and returns
33368    // milliseconds since UNIX epoch
33369    function rfc1123Decoder(dateStr) {
33370        return Date.parse(dateStr);
33371    }
33372
33373    function notSupportedHandler(url, onSuccessCB, onFailureCB) {
33374        onFailureCB();
33375    }
33376
33377    function directHandler(xsdatetimeStr, onSuccessCB, onFailureCB) {
33378        var time = xsdatetimeDecoder(xsdatetimeStr);
33379
33380        if (!isNaN(time)) {
33381            onSuccessCB(time);
33382            return;
33383        }
33384
33385        onFailureCB();
33386    }
33387
33388    function httpHandler(decoder, url, onSuccessCB, onFailureCB, isHeadRequest) {
33389        var oncomplete = undefined,
33390            onload = undefined;
33391        var complete = false;
33392        var req = new XMLHttpRequest();
33393
33394        var verb = isHeadRequest ? _voMetricsHTTPRequest.HTTPRequest.HEAD : _voMetricsHTTPRequest.HTTPRequest.GET;
33395        var urls = url.match(/\S+/g);
33396
33397        // according to ISO 23009-1, url could be a white-space
33398        // separated list of URLs. just handle one at a time.
33399        url = urls.shift();
33400
33401        oncomplete = function () {
33402            if (complete) {
33403                return;
33404            }
33405
33406            // we only want to pass through here once per xhr,
33407            // regardless of whether the load was successful.
33408            complete = true;
33409
33410            // if there are more urls to try, call self.
33411            if (urls.length) {
33412                httpHandler(decoder, urls.join(' '), onSuccessCB, onFailureCB, isHeadRequest);
33413            } else {
33414                onFailureCB();
33415            }
33416        };
33417
33418        onload = function () {
33419            var time = undefined,
33420                result = undefined;
33421
33422            if (req.status === 200) {
33423                time = isHeadRequest ? req.getResponseHeader('Date') : req.response;
33424
33425                result = decoder(time);
33426
33427                // decoder returns NaN if non-standard input
33428                if (!isNaN(result)) {
33429                    onSuccessCB(result);
33430                    complete = true;
33431                }
33432            }
33433        };
33434
33435        req.open(verb, url);
33436        req.timeout = HTTP_TIMEOUT_MS || 0;
33437        req.onload = onload;
33438        req.onloadend = oncomplete;
33439        req.send();
33440    }
33441
33442    function httpHeadHandler(url, onSuccessCB, onFailureCB) {
33443        httpHandler(rfc1123Decoder, url, onSuccessCB, onFailureCB, true);
33444    }
33445
33446    function checkForDateHeader() {
33447        var metrics = metricsModel.getReadOnlyMetricsFor(_constantsConstants2['default'].STREAM);
33448        var dateHeaderValue = dashMetrics.getLatestMPDRequestHeaderValueByID(metrics, 'Date');
33449        var dateHeaderTime = dateHeaderValue !== null ? new Date(dateHeaderValue).getTime() : Number.NaN;
33450
33451        if (!isNaN(dateHeaderTime)) {
33452            setOffsetMs(dateHeaderTime - new Date().getTime());
33453            completeTimeSyncSequence(false, dateHeaderTime / 1000, offsetToDeviceTimeMs);
33454        } else {
33455            completeTimeSyncSequence(true);
33456        }
33457    }
33458
33459    function completeTimeSyncSequence(failed, time, offset) {
33460        setIsSynchronizing(false);
33461        eventBus.trigger(_coreEventsEvents2['default'].TIME_SYNCHRONIZATION_COMPLETED, { time: time, offset: offset, error: failed ? new _voDashJSError2['default'](TIME_SYNC_FAILED_ERROR_CODE) : null });
33462    }
33463
33464    function attemptSync(sources, sourceIndex) {
33465
33466        // if called with no sourceIndex, use zero (highest priority)
33467        var index = sourceIndex || 0;
33468
33469        // the sources should be ordered in priority from the manifest.
33470        // try each in turn, from the top, until either something
33471        // sensible happens, or we run out of sources to try.
33472        var source = sources[index];
33473
33474        // callback to emit event to listeners
33475        var onComplete = function onComplete(time, offset) {
33476            var failed = !time || !offset;
33477            if (failed && useManifestDateHeaderTimeSource) {
33478                //Before falling back to binary search , check if date header exists on MPD. if so, use for a time source.
33479                checkForDateHeader();
33480            } else {
33481                completeTimeSyncSequence(failed, time, offset);
33482            }
33483        };
33484
33485        setIsSynchronizing(true);
33486
33487        if (source) {
33488            // check if there is a handler for this @schemeIdUri
33489            if (handlers.hasOwnProperty(source.schemeIdUri)) {
33490                // if so, call it with its @value
33491                handlers[source.schemeIdUri](source.value, function (serverTime) {
33492                    // the timing source returned something useful
33493                    var deviceTime = new Date().getTime();
33494                    var offset = serverTime - deviceTime;
33495
33496                    setOffsetMs(offset);
33497
33498                    log('Local time:      ' + new Date(deviceTime));
33499                    log('Server time:     ' + new Date(serverTime));
33500                    log('Difference (ms): ' + offset);
33501
33502                    onComplete(serverTime, offset);
33503                }, function () {
33504                    // the timing source was probably uncontactable
33505                    // or returned something we can't use - try again
33506                    // with the remaining sources
33507                    attemptSync(sources, index + 1);
33508                });
33509            } else {
33510                // an unknown schemeIdUri must have been found
33511                // try again with the remaining sources
33512                attemptSync(sources, index + 1);
33513            }
33514        } else {
33515            // no valid time source could be found, just use device time
33516            setOffsetMs(0);
33517            onComplete();
33518        }
33519    }
33520
33521    function reset() {
33522        setIsInitialised(false);
33523        setIsSynchronizing(false);
33524    }
33525
33526    instance = {
33527        initialize: initialize,
33528        getOffsetToDeviceTimeMs: getOffsetToDeviceTimeMs,
33529        setConfig: setConfig,
33530        reset: reset
33531    };
33532
33533    return instance;
33534}
33535
33536TimeSyncController.__dashjs_factory_name = 'TimeSyncController';
33537var factory = _coreFactoryMaker2['default'].getSingletonFactory(TimeSyncController);
33538factory.TIME_SYNC_FAILED_ERROR_CODE = TIME_SYNC_FAILED_ERROR_CODE;
33539factory.HTTP_TIMEOUT_MS = HTTP_TIMEOUT_MS;
33540_coreFactoryMaker2['default'].updateSingletonFactory(TimeSyncController.__dashjs_factory_name, factory);
33541exports['default'] = factory;
33542module.exports = exports['default'];
33543
33544},{"100":100,"207":207,"224":224,"49":49,"50":50,"51":51,"54":54}],115:[function(_dereq_,module,exports){
33545/**
33546 * The copyright in this software is being made available under the BSD License,
33547 * included below. This software may be subject to other third party and contributor
33548 * rights, including patent rights, and no such rights are granted under this license.
33549 *
33550 * Copyright (c) 2013, Dash Industry Forum.
33551 * All rights reserved.
33552 *
33553 * Redistribution and use in source and binary forms, with or without modification,
33554 * are permitted provided that the following conditions are met:
33555 *  * Redistributions of source code must retain the above copyright notice, this
33556 *  list of conditions and the following disclaimer.
33557 *  * Redistributions in binary form must reproduce the above copyright notice,
33558 *  this list of conditions and the following disclaimer in the documentation and/or
33559 *  other materials provided with the distribution.
33560 *  * Neither the name of Dash Industry Forum nor the names of its
33561 *  contributors may be used to endorse or promote products derived from this software
33562 *  without specific prior written permission.
33563 *
33564 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
33565 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
33566 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
33567 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33568 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
33568INCLUDING, BUT
33569 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33570 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33571 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33572 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33573 *  POSSIBILITY OF SUCH DAMAGE.
33574 */
33575'use strict';
33576
33577Object.defineProperty(exports, '__esModule', {
33578    value: true
33579});
33580
33581function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
33582
33583var _XlinkLoader = _dereq_(99);
33584
33585var _XlinkLoader2 = _interopRequireDefault(_XlinkLoader);
33586
33587var _coreEventBus = _dereq_(50);
33588
33589var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
33590
33591var _coreEventsEvents = _dereq_(54);
33592
33593var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
33594
33595var _coreFactoryMaker = _dereq_(51);
33596
33597var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
33598
33599var _externalsXml2json = _dereq_(4);
33600
33601var _externalsXml2json2 = _interopRequireDefault(_externalsXml2json);
33602
33603var _utilsURLUtils = _dereq_(202);
33604
33605var _utilsURLUtils2 = _interopRequireDefault(_utilsURLUtils);
33606
33607var RESOLVE_TYPE_ONLOAD = 'onLoad';
33608var RESOLVE_TYPE_ONACTUATE = 'onActuate';
33609var ELEMENT_TYPE_PERIOD = 'Period';
33610var ELEMENT_TYPE_ADAPTATIONSET = 'AdaptationSet';
33611var ELEMENT_TYPE_EVENTSTREAM = 'EventStream';
33612var RESOLVE_TO_ZERO = 'urn:mpeg:dash:resolve-to-zero:2013';
33613
33614function XlinkController(config) {
33615
33616    var context = this.context;
33617    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
33618    var urlUtils = (0, _utilsURLUtils2['default'])(context).getInstance();
33619
33620    var instance = undefined,
33621        matchers = undefined,
33622        iron = undefined,
33623        manifest = undefined,
33624        converter = undefined,
33625        xlinkLoader = undefined;
33626
33627    function setup() {
33628        eventBus.on(_coreEventsEvents2['default'].XLINK_ELEMENT_LOADED, onXlinkElementLoaded, instance);
33629
33630        xlinkLoader = (0, _XlinkLoader2['default'])(context).create({
33631            errHandler: config.errHandler,
33632            metricsModel: config.metricsModel,
33633            mediaPlayerModel: config.mediaPlayerModel,
33634            requestModifier: config.requestModifier
33635        });
33636    }
33637
33638    function setMatchers(value) {
33639        if (value) {
33640            matchers = value;
33641        }
33642    }
33643
33644    function setIron(value) {
33645        if (value) {
33646            iron = value;
33647        }
33648    }
33649
33650    /**
33651     * <p>Triggers the resolution of the xlink.onLoad attributes in the manifest file </p>
33652     * @param {Object} mpd - the manifest
33653     */
33654    function resolveManifestOnLoad(mpd) {
33655        var elements = undefined;
33656        // First resolve all periods, so unnecessary requests inside onLoad Periods with Default content are avoided
33657        converter = new _externalsXml2json2['default']({
33658            escapeMode: false,
33659            attributePrefix: '',
33660            arrayAccessForm: 'property',
33661            emptyNodeForm: 'object',
33662            stripWhitespaces: false,
33663            enableToStringFunc: false,
33664            ignoreRoot: true,
33665            matchers: matchers
33666        });
33667
33668        manifest = mpd;
33669        elements = getElementsToResolve(manifest.Period_asArray, manifest, ELEMENT_TYPE_PERIOD, RESOLVE_TYPE_ONLOAD);
33670        resolve(elements, ELEMENT_TYPE_PERIOD, RESOLVE_TYPE_ONLOAD);
33671    }
33672
33673    function reset() {
33674        eventBus.off(_coreEventsEvents2['default'].XLINK_ELEMENT_LOADED, onXlinkElementLoaded, instance);
33675
33676        if (xlinkLoader) {
33677            xlinkLoader.reset();
33678            xlinkLoader = null;
33679        }
33680    }
33681
33682    function resolve(elements, type, resolveType) {
33683        var resolveObject = {};
33684        var element = undefined,
33685            url = undefined;
33686
33687        resolveObject.elements = elements;
33688        resolveObject.type = type;
33689        resolveObject.resolveType = resolveType;
33690        // If nothing to resolve, directly call allElementsLoaded
33691        if (resolveObject.elements.length === 0) {
33692            onXlinkAllElementsLoaded(resolveObject);
33693        }
33694        for (var i = 0; i < resolveObject.elements.length; i++) {
33695            element = resolveObject.elements[i];
33696            if (urlUtils.isHTTPURL(element.url)) {
33697                url = element.url;
33698            } else {
33699                url = element.originalContent.BaseURL + element.url;
33700            }
33701            xlinkLoader.load(url, element, resolveObject);
33702        }
33703    }
33704
33705    function onXlinkElementLoaded(event) {
33706        var element = undefined,
33707            resolveObject = undefined;
33708
33709        var openingTag = '<response>';
33710        var closingTag = '</response>';
33711        var mergedContent = '';
33712
33713        element = event.element;
33714        resolveObject = event.resolveObject;
33715        // if the element resolved into content parse the content
33716        if (element.resolvedContent) {
33717            var index = 0;
33718            // we add a parent elements so the converter is able to parse multiple elements of the same type which are not wrapped inside a container
33719            if (element.resolvedContent.indexOf('<?xml') === 0) {
33720                index = element.resolvedContent.indexOf('?>') + 2; //find the closing position of the xml declaration, if it exists.
33721            }
33722            mergedContent = element.resolvedContent.substr(0, index) + openingTag + element.resolvedContent.substr(index) + closingTag;
33723            element.resolvedContent = converter.xml_str2json(mergedContent);
33724        }
33725        if (isResolvingFinished(resolveObject)) {
33726            onXlinkAllElementsLoaded(resolveObject);
33727        }
33728    }
33729
33730    // We got to wait till all elements of the current queue are resolved before merging back
33731    function onXlinkAllElementsLoaded(resolveObject) {
33732        var elements = [];
33733        var i = undefined,
33734            obj = undefined;
33735
33736        mergeElementsBack(resolveObject);
33737        if (resolveObject.resolveType === RESOLVE_TYPE_ONACTUATE) {
33738            eventBus.trigger(_coreEventsEvents2['default'].XLINK_READY, { manifest: manifest });
33739        }
33740        if (resolveObject.resolveType === RESOLVE_TYPE_ONLOAD) {
33741            switch (resolveObject.type) {
33742                // Start resolving the other elements. We can do Adaptation Set and EventStream in parallel
33743                case ELEMENT_TYPE_PERIOD:
33744                    for (i = 0; i < manifest[ELEMENT_TYPE_PERIOD + '_asArray'].length; i++) {
33745                        obj = manifest[ELEMENT_TYPE_PERIOD + '_asArray'][i];
33746                        if (obj.hasOwnProperty(ELEMENT_TYPE_ADAPTATIONSET + '_asArray')) {
33747                            elements = elements.concat(getElementsToResolve(obj[ELEMENT_TYPE_ADAPTATIONSET + '_asArray'], obj, ELEMENT_TYPE_ADAPTATIONSET, RESOLVE_TYPE_ONLOAD));
33748                        }
33749                        if (obj.hasOwnProperty(ELEMENT_TYPE_EVENTSTREAM + '_asArray')) {
33750                            elements = elements.concat(getElementsToResolve(obj[ELEMENT_TYPE_EVENTSTREAM + '_asArray'], obj, ELEMENT_TYPE_EVENTSTREAM, RESOLVE_TYPE_ONLOAD));
33751                        }
33752                    }
33753                    resolve(elements, ELEMENT_TYPE_ADAPTATIONSET, RESOLVE_TYPE_ONLOAD);
33754                    break;
33755                case ELEMENT_TYPE_ADAPTATIONSET:
33756                    // TODO: Resolve SegmentList here
33757                    eventBus.trigger(_coreEventsEvents2['default'].XLINK_READY, { manifest: manifest });
33758                    break;
33759            }
33760        }
33761    }
33762
33763    // Returns the elements with the specific resolve Type
33764    function getElementsToResolve(elements, parentElement, type, resolveType) {
33765        var toResolve = [];
33766        var element = undefined,
33767            i = undefined,
33768            xlinkObject = undefined;
33769        // first remove all the resolve-to-zero elements
33770        for (i = elements.length - 1; i >= 0; i--) {
33771            element = elements[i];
33772            if (element.hasOwnProperty('xlink:href') && element['xlink:href'] === RESOLVE_TO_ZERO) {
33773                elements.splice(i, 1);
33774            }
33775        }
33776        // now get the elements with the right resolve type
33777        for (i = 0; i < elements.length; i++) {
33778            element = elements[i];
33779            if (element.hasOwnProperty('xlink:href') && element.hasOwnProperty('xlink:actuate') && element['xlink:actuate'] === resolveType) {
33780                xlinkObject = createXlinkObject(element['xlink:href'], parentElement, type, i, resolveType, element);
33781                toResolve.push(xlinkObject);
33782            }
33783        }
33784        return toResolve;
33785    }
33786
33787    function mergeElementsBack(resolveObject) {
33788        var resolvedElements = [];
33789        var element = undefined,
33790            type = undefined,
33791            obj = undefined,
33792            i = undefined,
33793            j = undefined,
33794            k = undefined;
33795        // Start merging back from the end because of index shifting. Note that the elements with the same parent have to be ordered by index ascending
33796        for (i = resolveObject.elements.length - 1; i >= 0; i--) {
33797            element = resolveObject.elements[i];
33798            type = element.type + '_asArray';
33799
33800            // Element couldn't be resolved or is TODO Inappropriate target: Remove all Xlink attributes
33801            if (!element.resolvedContent || isInappropriateTarget()) {
33802                delete element.originalContent['xlink:actuate'];
33803                delete element.originalContent['xlink:href'];
33804                resolvedElements.push(element.originalContent);
33805            }
33806            // Element was successfully resolved
33807            else if (element.resolvedContent) {
33808                    for (j = 0; j < element.resolvedContent[type].length; j++) {
33809                        //TODO Contains another Xlink attribute with xlink:actuate set to onload. Remove all xLink attributes
33810                        obj = element.resolvedContent[type][j];
33811                        resolvedElements.push(obj);
33812                    }
33813                }
33814            // Replace the old elements in the parent with the resolved ones
33815            element.parentElement[type].splice(element.index, 1);
33816            for (k = 0; k < resolvedElements.length; k++) {
33817                element.parentElement[type].splice(element.index + k, 0, resolvedElements[k]);
33818            }
33819            resolvedElements = [];
33820        }
33821        if (resolveObject.elements.length > 0) {
33822            iron.run(manifest);
33823        }
33824    }
33825
33826    function createXlinkObject(url, parentElement, type, index, resolveType, originalContent) {
33827        return {
33828            url: url,
33829            parentElement: parentElement,
33830            type: type,
33831            index: index,
33832            resolveType: resolveType,
33833            originalContent: originalContent,
33834            resolvedContent: null,
33835            resolved: false
33836        };
33837    }
33838
33839    // Check if all pending requests are finished
33840    function isResolvingFinished(elementsToResolve) {
33841        var i = undefined,
33842            obj = undefined;
33843        for (i = 0; i < elementsToResolve.elements.length; i++) {
33844            obj = elementsToResolve.elements[i];
33845            if (obj.resolved === false) {
33846                return false;
33847            }
33848        }
33849        return true;
33850    }
33851
33852    // TODO : Do some syntax check here if the target is valid or not
33853    function isInappropriateTarget() {
33854        return false;
33855    }
33856
33857    instance = {
33858        resolveManifestOnLoad: resolveManifestOnLoad,
33859        setMatchers: setMatchers,
33860        setIron: setIron,
33861        reset: reset
33862    };
33863
33864    setup();
33865    return instance;
33866}
33867
33868XlinkController.__dashjs_factory_name = 'XlinkController';
33869exports['default'] = _coreFactoryMaker2['default'].getClassFactory(XlinkController);
33870module.exports = exports['default'];
33871
33872},{"202":202,"4":4,"50":50,"51":51,"54":54,"99":99}],116:[function(_dereq_,module,exports){
33873/**
33874 * The copyright in this software is being made available under the BSD License,
33875 * included below. This software may be subject to other third party and contributor
33876 * rights, including patent rights, and no such rights are granted under this license.
33877 *
33878 * Copyright (c) 2013, Dash Industry Forum.
33879 * All rights reserved.
33880 *
33881 * Redistribution and use in source and binary forms, with or without modification,
33882 * are permitted provided that the following conditions are met:
33883 *  * Redistributions of source code must retain the above copyright notice, this
33884 *  list of conditions and the following disclaimer.
33885 *  * Redistributions in binary form must reproduce the above copyright notice,
33886 *  this list of conditions and the following disclaimer in the documentation and/or
33887 *  other materials provided with the distribution.
33888 *  * Neither the name of Dash Industry Forum nor the names of its
33889 *  contributors may be used to endorse or promote products derived from this software
33890 *  without specific prior written permission.
33891 *
33892 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
33893 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
33894 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
33895 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33896 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
33897 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33898 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33899 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33900 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33901 *  POSSIBILITY OF SUCH DAMAGE.
33902 */
33903
33904'use strict';
33905
33906Object.defineProperty(exports, '__esModule', {
33907    value: true
33908});
33909
33910function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
33911
33912var _utilsDVBErrorsTranslator = _dereq_(130);
33913
33914var _utilsDVBErrorsTranslator2 = _interopRequireDefault(_utilsDVBErrorsTranslator);
33915
33916var _MetricsReportingEvents = _dereq_(117);
33917
33918var _MetricsReportingEvents2 = _interopRequireDefault(_MetricsReportingEvents);
33919
33920var _controllersMetricsCollectionController = _dereq_(118);
33921
33922var _controllersMetricsCollectionController2 = _interopRequireDefault(_controllersMetricsCollectionController);
33923
33924var _metricsMetricsHandlerFactory = _dereq_(123);
33925
33926var _metricsMetricsHandlerFactory2 = _interopRequireDefault(_metricsMetricsHandlerFactory);
33927
33928var _reportingReportingFactory = _dereq_(128);
33929
33930var _reportingReportingFactory2 = _interopRequireDefault(_reportingReportingFactory);
33931
33932function MetricsReporting() {
33933
33934    var context = this.context;
33935    var instance = undefined;
33936
33937    var dvbErrorsTranslator = undefined;
33938
33939    /**
33940     * Create a MetricsCollectionController, and a DVBErrorsTranslator
33941     * @param {Object} config - dependancies from owner
33942     * @return {MetricsCollectionController} Metrics Collection Controller
33943     */
33944    function createMetricsReporting(config) {
33945        dvbErrorsTranslator = (0, _utilsDVBErrorsTranslator2['default'])(context).getInstance({
33946            eventBus: config.eventBus,
33947            metricsModel: config.metricsModel,
33948            metricsConstants: config.metricsConstants,
33949            events: config.events
33950        });
33951
33952        return (0, _controllersMetricsCollectionController2['default'])(context).create(config);
33953    }
33954
33955    /**
33956     * Get the ReportingFactory to allow new reporters to be registered
33957     * @return {ReportingFactory} Reporting Factory
33958     */
33959    function getReportingFactory() {
33960        return (0, _reportingReportingFactory2['default'])(context).getInstance();
33961    }
33962
33963    /**
33964     * Get the MetricsHandlerFactory to allow new handlers to be registered
33965     * @return {MetricsHandlerFactory} Metrics Handler Factory
33966     */
33967    function getMetricsHandlerFactory() {
33968        return (0, _metricsMetricsHandlerFactory2['default'])(context).getInstance();
33969    }
33970
33971    instance = {
33972        createMetricsReporting: createMetricsReporting,
33973        getReportingFactory: getReportingFactory,
33974        getMetricsHandlerFactory: getMetricsHandlerFactory
33975    };
33976
33977    return instance;
33978}
33979
33980MetricsReporting.__dashjs_factory_name = 'MetricsReporting';
33981var factory = dashjs.FactoryMaker.getClassFactory(MetricsReporting); /* jshint ignore:line */
33982factory.events = _MetricsReportingEvents2['default'];
33983dashjs.FactoryMaker.updateClassFactory(MetricsReporting.__dashjs_factory_name, factory); /* jshint ignore:line */
33984exports['default'] = factory;
33985module.exports = exports['default'];
33986
33987},{"117":117,"118":118,"123":123,"128":128,"130":130}],117:[function(_dereq_,module,exports){
33988/**
33989 * The copyright in this software is being made available under the BSD License,
33990 * included below. This software may be subject to other third party and contributor
33991 * rights, including patent rights, and no such rights are granted under this license.
33992 *
33993 * Copyright (c) 2013, Dash Industry Forum.
33994 * All rights reserved.
33995 *
33996 * Redistribution and use in source and binary forms, with or without modification,
33997 * are permitted provided that the following conditions are met:
33998 *  * Redistributions of source code must retain the above copyright notice, this
33999 *  list of conditions and the following disclaimer.
34000 *  * Redistributions in binary form must reproduce the above copyright notice,
34001 *  this list of conditions and the following disclaimer in the documentation and/or
34002 *  other materials provided with the distribution.
34003 *  * Neither the name of Dash Industry Forum nor the names of its
34004 *  contributors may be used to endorse or promote products derived from this software
34005 *  without specific prior written permission.
34006 *
34007 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
34008 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34009 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
34010 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
34011 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
34011INCLUDING, BUT
34012 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34013 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
34014 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34015 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34016 *  POSSIBILITY OF SUCH DAMAGE.
34017 */
34018'use strict';
34019
34020Object.defineProperty(exports, '__esModule', {
34021    value: true
34022});
34023
34024var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
34025
34026function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
34027
34028function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
34029
34030function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
34031
34032var _coreEventsEventsBase = _dereq_(55);
34033
34034var _coreEventsEventsBase2 = _interopRequireDefault(_coreEventsEventsBase);
34035
34036var MetricsReportingEvents = (function (_EventsBase) {
34037    _inherits(MetricsReportingEvents, _EventsBase);
34038
34039    function MetricsReportingEvents() {
34040        _classCallCheck(this, MetricsReportingEvents);
34041
34042        _get(Object.getPrototypeOf(MetricsReportingEvents.prototype), 'constructor', this).call(this);
34043
34044        this.METRICS_INITIALISATION_COMPLETE = 'internal_metricsReportingInitialized';
34045        this.BECAME_REPORTING_PLAYER = 'internal_becameReportingPlayer';
34046    }
34047
34048    return MetricsReportingEvents;
34049})(_coreEventsEventsBase2['default']);
34050
34051var metricsReportingEvents = new MetricsReportingEvents();
34052exports['default'] = metricsReportingEvents;
34053module.exports = exports['default'];
34054
34055},{"55":55}],118:[function(_dereq_,module,exports){
34056/**
34057 * The copyright in this software is being made available under the BSD License,
34058 * included below. This software may be subject to other third party and contributor
34059 * rights, including patent rights, and no such rights are granted under this license.
34060 *
34061 * Copyright (c) 2013, Dash Industry Forum.
34062 * All rights reserved.
34063 *
34064 * Redistribution and use in source and binary forms, with or without modification,
34065 * are permitted provided that the following conditions are met:
34066 *  * Redistributions of source code must retain the above copyright notice, this
34067 *  list of conditions and the following disclaimer.
34068 *  * Redistributions in binary form must reproduce the above copyright notice,
34069 *  this list of conditions and the following disclaimer in the documentation and/or
34070 *  other materials provided with the distribution.
34071 *  * Neither the name of Dash Industry Forum nor the names of its
34072 *  contributors may be used to endorse or promote products derived from this software
34073 *  without specific prior written permission.
34074 *
34075 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
34076 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34077 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
34078 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
34079 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
34079INCLUDING, BUT
34080 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34081 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
34082 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34083 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34084 *  POSSIBILITY OF SUCH DAMAGE.
34085 */
34086
34087'use strict';
34088
34089Object.defineProperty(exports, '__esModule', {
34090    value: true
34091});
34092
34093function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
34094
34095var _MetricsController = _dereq_(119);
34096
34097var _MetricsController2 = _interopRequireDefault(_MetricsController);
34098
34099var _utilsManifestParsing = _dereq_(132);
34100
34101var _utilsManifestParsing2 = _interopRequireDefault(_utilsManifestParsing);
34102
34103var _MetricsReportingEvents = _dereq_(117);
34104
34105var _MetricsReportingEvents2 = _interopRequireDefault(_MetricsReportingEvents);
34106
34107function MetricsCollectionController(config) {
34108
34109    var metricsControllers = {};
34110
34111    var context = this.context;
34112    var eventBus = config.eventBus;
34113    var events = config.events;
34114
34115    function update(e) {
34116        if (e.error) {
34117            return;
34118        }
34119
34120        // start by assuming all existing controllers need removing
34121        var controllersToRemove = Object.keys(metricsControllers);
34122
34123        var metrics = (0, _utilsManifestParsing2['default'])(context).getInstance({
34124            dashManifestModel: config.dashManifestModel,
34125            constants: config.constants
34126        }).getMetrics(e.manifest);
34127
34128        metrics.forEach(function (m) {
34129            var key = JSON.stringify(m);
34130
34131            if (!metricsControllers.hasOwnProperty(key)) {
34132                try {
34133                    var controller = (0, _MetricsController2['default'])(context).create(config);
34134                    controller.initialize(m);
34135                    metricsControllers[key] = controller;
34136                } catch (e) {
34137                    // fail quietly
34138                }
34139            } else {
34140                    // we still need this controller - delete from removal list
34141                    controllersToRemove.splice(key, 1);
34142                }
34143        });
34144
34145        // now remove the unwanted controllers
34146        controllersToRemove.forEach(function (c) {
34147            metricsControllers[c].reset();
34148            delete metricsControllers[c];
34149        });
34150
34151        eventBus.trigger(_MetricsReportingEvents2['default'].METRICS_INITIALISATION_COMPLETE);
34152    }
34153
34154    function resetMetricsControllers() {
34155        Object.keys(metricsControllers).forEach(function (key) {
34156            metricsControllers[key].reset();
34157        });
34158
34159        metricsControllers = {};
34160    }
34161
34162    function setup() {
34163        eventBus.on(events.MANIFEST_UPDATED, update);
34164        eventBus.on(events.STREAM_TEARDOWN_COMPLETE, resetMetricsControllers);
34165    }
34166
34167    function reset() {
34168        eventBus.off(events.MANIFEST_UPDATED, update);
34169        eventBus.off(events.STREAM_TEARDOWN_COMPLETE, resetMetricsControllers);
34170    }
34171
34172    setup();
34173
34174    return {
34175        reset: reset
34176    };
34177}
34178
34179MetricsCollectionController.__dashjs_factory_name = 'MetricsCollectionController';
34180exports['default'] = dashjs.FactoryMaker.getClassFactory(MetricsCollectionController);
34181/* jshint ignore:line */
34182module.exports = exports['default'];
34183
34184},{"117":117,"119":119,"132":132}],119:[function(_dereq_,module,exports){
34185/**
34186 * The copyright in this software is being made available under the BSD License,
34187 * included below. This software may be subject to other third party and contributor
34188 * rights, including patent rights, and no such rights are granted under this license.
34189 *
34190 * Copyright (c) 2013, Dash Industry Forum.
34191 * All rights reserved.
34192 *
34193 * Redistribution and use in source and binary forms, with or without modification,
34194 * are permitted provided that the following conditions are met:
34195 *  * Redistributions of source code must retain the above copyright notice, this
34196 *  list of conditions and the following disclaimer.
34197 *  * Redistributions in binary form must reproduce the above copyright notice,
34198 *  this list of conditions and the following disclaimer in the documentation and/or
34199 *  other materials provided with the distribution.
34200 *  * Neither the name of Dash Industry Forum nor the names of its
34201 *  contributors may be used to endorse or promote products derived from this software
34202 *  without specific prior written permission.
34203 *
34204 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
34205 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34206 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
34207 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
34208 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
34208INCLUDING, BUT
34209 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34210 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
34211 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34212 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34213 *  POSSIBILITY OF SUCH DAMAGE.
34214 */
34215
34216'use strict';
34217
34218Object.defineProperty(exports, '__esModule', {
34219    value: true
34220});
34221
34222function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
34223
34224var _RangeController = _dereq_(121);
34225
34226var _RangeController2 = _interopRequireDefault(_RangeController);
34227
34228var _ReportingController = _dereq_(122);
34229
34230var _ReportingController2 = _interopRequireDefault(_ReportingController);
34231
34232var _MetricsHandlersController = _dereq_(120);
34233
34234var _MetricsHandlersController2 = _interopRequireDefault(_MetricsHandlersController);
34235
34236function MetricsController(config) {
34237
34238    var metricsHandlersController = undefined,
34239        reportingController = undefined,
34240        rangeController = undefined,
34241        instance = undefined;
34242
34243    var context = this.context;
34244
34245    function initialize(metricsEntry) {
34246        try {
34247            rangeController = (0, _RangeController2['default'])(context).create({
34248                mediaElement: config.mediaElement
34249            });
34250
34251            rangeController.initialize(metricsEntry.Range);
34252
34253            reportingController = (0, _ReportingController2['default'])(context).create({
34254                log: config.log
34255            });
34256
34257            reportingController.initialize(metricsEntry.Reporting, rangeController);
34258
34259            metricsHandlersController = (0, _MetricsHandlersController2['default'])(context).create({
34260                log: config.log,
34261                eventBus: config.eventBus,
34262                metricsConstants: config.metricsConstants,
34263                events: config.events
34264            });
34265
34266            metricsHandlersController.initialize(metricsEntry.metrics, reportingController);
34267        } catch (e) {
34268            reset();
34269            throw e;
34270        }
34271    }
34272
34273    function reset() {
34274        if (metricsHandlersController) {
34275            metricsHandlersController.reset();
34276        }
34277
34278        if (reportingController) {
34279            reportingController.reset();
34280        }
34281
34282        if (rangeController) {
34283            rangeController.reset();
34284        }
34285    }
34286
34287    instance = {
34288        initialize: initialize,
34289        reset: reset
34290    };
34291
34292    return instance;
34293}
34294
34295MetricsController.__dashjs_factory_name = 'MetricsController';
34296exports['default'] = dashjs.FactoryMaker.getClassFactory(MetricsController);
34297/* jshint ignore:line */
34298module.exports = exports['default'];
34299
34300},{"120":120,"121":121,"122":122}],120:[function(_dereq_,module,exports){
34301/**
34302 * The copyright in this software is being made available under the BSD License,
34303 * included below. This software may be subject to other third party and contributor
34304 * rights, including patent rights, and no such rights are granted under this license.
34305 *
34306 * Copyright (c) 2013, Dash Industry Forum.
34307 * All rights reserved.
34308 *
34309 * Redistribution and use in source and binary forms, with or without modification,
34310 * are permitted provided that the following conditions are met:
34311 *  * Redistributions of source code must retain the above copyright notice, this
34312 *  list of conditions and the following disclaimer.
34313 *  * Redistributions in binary form must reproduce the above copyright notice,
34314 *  this list of conditions and the following disclaimer in the documentation and/or
34315 *  other materials provided with the distribution.
34316 *  * Neither the name of Dash Industry Forum nor the names of its
34317 *  contributors may be used to endorse or promote products derived from this software
34318 *  without specific prior written permission.
34319 *
34320 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
34321 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34322 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
34323 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
34324 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
34324INCLUDING, BUT
34325 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34326 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
34327 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34328 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34329 *  POSSIBILITY OF SUCH DAMAGE.
34330 */
34331
34332'use strict';
34333
34334Object.defineProperty(exports, '__esModule', {
34335    value: true
34336});
34337
34338function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
34339
34340var _metricsMetricsHandlerFactory = _dereq_(123);
34341
34342var _metricsMetricsHandlerFactory2 = _interopRequireDefault(_metricsMetricsHandlerFactory);
34343
34344function MetricsHandlersController(config) {
34345    var handlers = [];
34346
34347    var instance = undefined;
34348    var context = this.context;
34349    var eventBus = config.eventBus;
34350    var Events = config.events;
34351
34352    var metricsHandlerFactory = (0, _metricsMetricsHandlerFactory2['default'])(context).getInstance({
34353        log: config.log,
34354        eventBus: config.eventBus,
34355        metricsConstants: config.metricsConstants
34356    });
34357
34358    function handle(e) {
34359        handlers.forEach(function (handler) {
34360            handler.handleNewMetric(e.metric, e.value, e.mediaType);
34361        });
34362    }
34363
34364    function initialize(metrics, reportingController) {
34365        metrics.split(',').forEach(function (m, midx, ms) {
34366            var handler = undefined;
34367
34368            // there is a bug in ISO23009-1 where the metrics attribute
34369            // is a comma-separated list but HttpList key can contain a
34370            // comma enclosed by ().
34371            if (m.indexOf('(') !== -1 && m.indexOf(')') === -1) {
34372                var nextm = ms[midx + 1];
34373
34374                if (nextm && nextm.indexOf('(') === -1 && nextm.indexOf(')') !== -1) {
34375                    m += ',' + nextm;
34376
34377                    // delete the next metric so forEach does not visit.
34378                    delete ms[midx + 1];
34379                }
34380            }
34381
34382            handler = metricsHandlerFactory.create(m, reportingController);
34383
34384            if (handler) {
34385                handlers.push(handler);
34386            }
34387        });
34388
34389        eventBus.on(Events.METRIC_ADDED, handle, instance);
34390
34391        eventBus.on(Events.METRIC_UPDATED, handle, instance);
34392    }
34393
34394    function reset() {
34395        eventBus.off(Events.METRIC_ADDED, handle, instance);
34396
34397        eventBus.off(Events.METRIC_UPDATED, handle, instance);
34398
34399        handlers.forEach(function (handler) {
34400            return handler.reset();
34401        });
34402
34403        handlers = [];
34404    }
34405
34406    instance = {
34407        initialize: initialize,
34408        reset: reset
34409    };
34410
34411    return instance;
34412}
34413
34414MetricsHandlersController.__dashjs_factory_name = 'MetricsHandlersController';
34415exports['default'] = dashjs.FactoryMaker.getClassFactory(MetricsHandlersController);
34416/* jshint ignore:line */
34417module.exports = exports['default'];
34418
34419},{"123":123}],121:[function(_dereq_,module,exports){
34420/**
34421 * The copyright in this software is being made available under the BSD License,
34422 * included below. This software may be subject to other third party and contributor
34423 * rights, including patent rights, and no such rights are granted under this license.
34424 *
34425 * Copyright (c) 2013, Dash Industry Forum.
34426 * All rights reserved.
34427 *
34428 * Redistribution and use in source and binary forms, with or without modification,
34429 * are permitted provided that the following conditions are met:
34430 *  * Redistributions of source code must retain the above copyright notice, this
34431 *  list of conditions and the following disclaimer.
34432 *  * Redistributions in binary form must reproduce the above copyright notice,
34433 *  this list of conditions and the following disclaimer in the documentation and/or
34434 *  other materials provided with the distribution.
34435 *  * Neither the name of Dash Industry Forum nor the names of its
34436 *  contributors may be used to endorse or promote products derived from this software
34437 *  without specific prior written permission.
34438 *
34439 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
34440 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34441 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
34442 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
34443 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
34443INCLUDING, BUT
34444 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34445 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
34446 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34447 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34448 *  POSSIBILITY OF SUCH DAMAGE.
34449 */
34450
34451'use strict';
34452
34453Object.defineProperty(exports, '__esModule', {
34454    value: true
34455});
34456
34457function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
34458
34459var _utilsCustomTimeRanges = _dereq_(192);
34460
34461var _utilsCustomTimeRanges2 = _interopRequireDefault(_utilsCustomTimeRanges);
34462
34463function RangeController(config) {
34464
34465    var useWallClockTime = false;
34466    var context = this.context;
34467    var instance = undefined,
34468        ranges = undefined;
34469
34470    var mediaElement = config.mediaElement;
34471
34472    function initialize(rs) {
34473        if (rs && rs.length) {
34474            rs.forEach(function (r) {
34475                var start = r.starttime;
34476                var end = start + r.duration;
34477
34478                ranges.add(start, end);
34479            });
34480
34481            useWallClockTime = !!rs[0]._useWallClockTime;
34482        }
34483    }
34484
34485    function reset() {
34486        ranges.clear();
34487    }
34488
34489    function setup() {
34490        ranges = (0, _utilsCustomTimeRanges2['default'])(context).create();
34491    }
34492
34493    function isEnabled() {
34494        var numRanges = ranges.length;
34495        var time = undefined;
34496
34497        if (!numRanges) {
34498            return true;
34499        }
34500
34501        // When not present, DASH Metrics reporting is requested
34502        // for the whole duration of the content.
34503        time = useWallClockTime ? new Date().getTime() / 1000 : mediaElement.currentTime;
34504
34505        for (var i = 0; i < numRanges; i += 1) {
34506            var start = ranges.start(i);
34507            var end = ranges.end(i);
34508
34509            if (start <= time && time < end) {
34510                return true;
34511            }
34512        }
34513
34514        return false;
34515    }
34516
34517    instance = {
34518        initialize: initialize,
34519        reset: reset,
34520        isEnabled: isEnabled
34521    };
34522
34523    setup();
34524
34525    return instance;
34526}
34527
34528RangeController.__dashjs_factory_name = 'RangeController';
34529exports['default'] = dashjs.FactoryMaker.getClassFactory(RangeController);
34530/* jshint ignore:line */
34531module.exports = exports['default'];
34532
34533},{"192":192}],122:[function(_dereq_,module,exports){
34534/**
34535 * The copyright in this software is being made available under the BSD License,
34536 * included below. This software may be subject to other third party and contributor
34537 * rights, including patent rights, and no such rights are granted under this license.
34538 *
34539 * Copyright (c) 2013, Dash Industry Forum.
34540 * All rights reserved.
34541 *
34542 * Redistribution and use in source and binary forms, with or without modification,
34543 * are permitted provided that the following conditions are met:
34544 *  * Redistributions of source code must retain the above copyright notice, this
34545 *  list of conditions and the following disclaimer.
34546 *  * Redistributions in binary form must reproduce the above copyright notice,
34547 *  this list of conditions and the following disclaimer in the documentation and/or
34548 *  other materials provided with the distribution.
34549 *  * Neither the name of Dash Industry Forum nor the names of its
34550 *  contributors may be used to endorse or promote products derived from this software
34551 *  without specific prior written permission.
34552 *
34553 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
34554 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34555 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
34556 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
34557 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
34558 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34559 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
34560 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34561 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34562 *  POSSIBILITY OF SUCH DAMAGE.
34563 */
34564
34565'use strict';
34566
34567Object.defineProperty(exports, '__esModule', {
34568    value: true
34569});
34570
34571function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
34572
34573var _reportingReportingFactory = _dereq_(128);
34574
34575var _reportingReportingFactory2 = _interopRequireDefault(_reportingReportingFactory);
34576
34577function ReportingController(config) {
34578
34579    var reporters = [];
34580    var instance = undefined;
34581
34582    var reportingFactory = (0, _reportingReportingFactory2['default'])(this.context).getInstance({
34583        log: config.log
34584    });
34585
34586    function initialize(reporting, rangeController) {
34587        // "if multiple Reporting elements are present, it is expected that
34588        // the client processes one of the recognized reporting schemes."
34589        // to ignore this, and support multiple Reporting per Metric,
34590        // simply change the 'some' below to 'forEach'
34591        reporting.some(function (r) {
34592            var reporter = reportingFactory.create(r, rangeController);
34593
34594            if (reporter) {
34595                reporters.push(reporter);
34596                return true;
34597            }
34598        });
34599    }
34600
34601    function reset() {
34602        reporters.forEach(function (r) {
34603            return r.reset();
34604        });
34605        reporters = [];
34606    }
34607
34608    function report(type, vos) {
34609        reporters.forEach(function (r) {
34610            return r.report(type, vos);
34611        });
34612    }
34613
34614    instance = {
34615        initialize: initialize,
34616        reset: reset,
34617        report: report
34618    };
34619
34620    return instance;
34621}
34622
34623ReportingController.__dashjs_factory_name = 'ReportingController';
34624exports['default'] = dashjs.FactoryMaker.getClassFactory(ReportingController);
34625/* jshint ignore:line */
34626module.exports = exports['default'];
34627
34628},{"128":128}],123:[function(_dereq_,module,exports){
34629/**
34630 * The copyright in this software is being made available under the BSD License,
34631 * included below. This software may be subject to other third party and contributor
34632 * rights, including patent rights, and no such rights are granted under this license.
34633 *
34634 * Copyright (c) 2013, Dash Industry Forum.
34635 * All rights reserved.
34636 *
34637 * Redistribution and use in source and binary forms, with or without modification,
34638 * are permitted provided that the following conditions are met:
34639 *  * Redistributions of source code must retain the above copyright notice, this
34640 *  list of conditions and the following disclaimer.
34641 *  * Redistributions in binary form must reproduce the above copyright notice,
34642 *  this list of conditions and the following disclaimer in the documentation and/or
34643 *  other materials provided with the distribution.
34644 *  * Neither the name of Dash Industry Forum nor the names of its
34645 *  contributors may be used to endorse or promote products derived from this software
34646 *  without specific prior written permission.
34647 *
34648 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
34649 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34650 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
34651 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
34652 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
34653 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34654 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
34655 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34656 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34657 *  POSSIBILITY OF SUCH DAMAGE.
34658 */
34659
34660'use strict';
34661
34662Object.defineProperty(exports, '__esModule', {
34663    value: true
34664});
34665
34666function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
34667
34668var _handlersBufferLevelHandler = _dereq_(124);
34669
34670var _handlersBufferLevelHandler2 = _interopRequireDefault(_handlersBufferLevelHandler);
34671
34672var _handlersDVBErrorsHandler = _dereq_(125);
34673
34674var _handlersDVBErrorsHandler2 = _interopRequireDefault(_handlersDVBErrorsHandler);
34675
34676var _handlersHttpListHandler = _dereq_(127);
34677
34678var _handlersHttpListHandler2 = _interopRequireDefault(_handlersHttpListHandler);
34679
34680var _handlersGenericMetricHandler = _dereq_(126);
34681
34682var _handlersGenericMetricHandler2 = _interopRequireDefault(_handlersGenericMetricHandler);
34683
34684function MetricsHandlerFactory(config) {
34685
34686    var instance = undefined;
34687    var log = config.log;
34688
34689    // group 1: key, [group 3: n [, group 5: type]]
34690    var keyRegex = /([a-zA-Z]*)(\(([0-9]*)(\,\s*([a-zA-Z]*))?\))?/;
34691
34692    var context = this.context;
34693    var knownFactoryProducts = {
34694        BufferLevel: _handlersBufferLevelHandler2['default'],
34695        DVBErrors: _handlersDVBErrorsHandler2['default'],
34696        HttpList: _handlersHttpListHandler2['default'],
34697        PlayList: _handlersGenericMetricHandler2['default'],
34698        RepSwitchList: _handlersGenericMetricHandler2['default'],
34699        TcpList: _handlersGenericMetricHandler2['default']
34700    };
34701
34702    function create(listType, reportingController) {
34703        var matches = listType.match(keyRegex);
34704        var handler;
34705
34706        if (!matches) {
34707            return;
34708        }
34709
34710        try {
34711            handler = knownFactoryProducts[matches[1]](context).create({
34712                eventBus: config.eventBus,
34713                metricsConstants: config.metricsConstants
34714            });
34715
34716            handler.initialize(matches[1], reportingController, matches[3], matches[5]);
34717        } catch (e) {
34718            handler = null;
34719
34720            log('MetricsHandlerFactory: Could not create handler for type ' + matches[1] + ' with args ' + matches[3] + ', ' + matches[5] + ' (' + e.message + ')');
34721        }
34722
34723        return handler;
34724    }
34725
34726    function register(key, handler) {
34727        knownFactoryProducts[key] = handler;
34728    }
34729
34730    function unregister(key) {
34731        delete knownFactoryProducts[key];
34732    }
34733
34734    instance = {
34735        create: create,
34736        register: register,
34737        unregister: unregister
34738    };
34739
34740    return instance;
34741}
34742
34743MetricsHandlerFactory.__dashjs_factory_name = 'MetricsHandlerFactory';
34744exports['default'] = dashjs.FactoryMaker.getSingletonFactory(MetricsHandlerFactory);
34745/* jshint ignore:line */
34746module.exports = exports['default'];
34747
34748},{"124":124,"125":125,"126":126,"127":127}],124:[function(_dereq_,module,exports){
34749/**
34750 * The copyright in this software is being made available under the BSD License,
34751 * included below. This software may be subject to other third party and contributor
34752 * rights, including patent rights, and no such rights are granted under this license.
34753 *
34754 * Copyright (c) 2013, Dash Industry Forum.
34755 * All rights reserved.
34756 *
34757 * Redistribution and use in source and binary forms, with or without modification,
34758 * are permitted provided that the following conditions are met:
34759 *  * Redistributions of source code must retain the above copyright notice, this
34760 *  list of conditions and the following disclaimer.
34761 *  * Redistributions in binary form must reproduce the above copyright notice,
34762 *  this list of conditions and the following disclaimer in the documentation and/or
34763 *  other materials provided with the distribution.
34764 *  * Neither the name of Dash Industry Forum nor the names of its
34765 *  contributors may be used to endorse or promote products derived from this software
34766 *  without specific prior written permission.
34767 *
34768 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
34769 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34770 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
34771 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
34772 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
34772INCLUDING, BUT
34773 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34774 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
34775 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34776 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34777 *  POSSIBILITY OF SUCH DAMAGE.
34778 */
34779
34780'use strict';
34781
34782Object.defineProperty(exports, '__esModule', {
34783    value: true
34784});
34785
34786function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
34787
34788var _utilsHandlerHelpers = _dereq_(131);
34789
34790var _utilsHandlerHelpers2 = _interopRequireDefault(_utilsHandlerHelpers);
34791
34792function BufferLevelHandler(config) {
34793
34794    var instance = undefined,
34795        reportingController = undefined,
34796        n = undefined,
34797        name = undefined,
34798        interval = undefined,
34799        lastReportedTime = undefined;
34800
34801    var context = this.context;
34802    var handlerHelpers = (0, _utilsHandlerHelpers2['default'])(context).getInstance();
34803
34804    var storedVOs = [];
34805
34806    var metricsConstants = config.metricsConstants;
34807
34808    function getLowestBufferLevelVO() {
34809        try {
34810            return Object.keys(storedVOs).map(function (key) {
34811                return storedVOs[key];
34812            }).reduce(function (a, b) {
34813                return a.level < b.level ? a : b;
34814            });
34815        } catch (e) {
34816            return;
34817        }
34818    }
34819
34820    function intervalCallback() {
34821        var vo = getLowestBufferLevelVO();
34822
34823        if (vo) {
34824            if (lastReportedTime !== vo.t) {
34825                lastReportedTime = vo.t;
34826                reportingController.report(name, vo);
34827            }
34828        }
34829    }
34830
34831    function initialize(basename, rc, n_ms) {
34832        if (rc) {
34833            // this will throw if n is invalid, to be
34834            // caught by the initialize caller.
34835            n = handlerHelpers.validateN(n_ms);
34836            reportingController = rc;
34837            name = handlerHelpers.reconstructFullMetricName(basename, n_ms);
34838            interval = setInterval(intervalCallback, n);
34839        }
34840    }
34841
34842    function reset() {
34843        clearInterval(interval);
34844        interval = null;
34845        n = 0;
34846        reportingController = null;
34847        lastReportedTime = null;
34848    }
34849
34850    function handleNewMetric(metric, vo, type) {
34851        if (metric === metricsConstants.BUFFER_LEVEL) {
34852            storedVOs[type] = vo;
34853        }
34854    }
34855
34856    instance = {
34857        initialize: initialize,
34858        reset: reset,
34859        handleNewMetric: handleNewMetric
34860    };
34861
34862    return instance;
34863}
34864
34865BufferLevelHandler.__dashjs_factory_name = 'BufferLevelHandler';
34866exports['default'] = dashjs.FactoryMaker.getClassFactory(BufferLevelHandler);
34867/* jshint ignore:line */
34868module.exports = exports['default'];
34869
34870},{"131":131}],125:[function(_dereq_,module,exports){
34871/**
34872 * The copyright in this software is being made available under the BSD License,
34873 * included below. This software may be subject to other third party and contributor
34874 * rights, including patent rights, and no such rights are granted under this license.
34875 *
34876 * Copyright (c) 2013, Dash Industry Forum.
34877 * All rights reserved.
34878 *
34879 * Redistribution and use in source and binary forms, with or without modification,
34880 * are permitted provided that the following conditions are met:
34881 *  * Redistributions of source code must retain the above copyright notice, this
34882 *  list of conditions and the following disclaimer.
34883 *  * Redistributions in binary form must reproduce the above copyright notice,
34884 *  this list of conditions and the following disclaimer in the documentation and/or
34885 *  other materials provided with the distribution.
34886 *  * Neither the name of Dash Industry Forum nor the names of its
34887 *  contributors may be used to endorse or promote products derived from this software
34888 *  without specific prior written permission.
34889 *
34890 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
34891 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34892 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
34893 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
34894 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
34895 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34896 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
34897 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34898 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34899 *  POSSIBILITY OF SUCH DAMAGE.
34900 */
34901
34902'use strict';
34903
34904Object.defineProperty(exports, '__esModule', {
34905    value: true
34906});
34907
34908function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
34909
34910var _MetricsReportingEvents = _dereq_(117);
34911
34912var _MetricsReportingEvents2 = _interopRequireDefault(_MetricsReportingEvents);
34913
34914function DVBErrorsHandler(config) {
34915
34916    var instance = undefined,
34917        reportingController = undefined;
34918
34919    var eventBus = config.eventBus;
34920    var metricsConstants = config.metricsConstants;
34921
34922    function onInitialisationComplete() {
34923        // we only want to report this once per call to initialize
34924        eventBus.off(_MetricsReportingEvents2['default'].METRICS_INITIALISATION_COMPLETE, onInitialisationComplete, this);
34925
34926        // Note: A Player becoming a reporting Player is itself
34927        // something which is recorded by the DVBErrors metric.
34928        eventBus.trigger(_MetricsReportingEvents2['default'].BECAME_REPORTING_PLAYER);
34929    }
34930
34931    function initialize(unused, rc) {
34932        if (rc) {
34933            reportingController = rc;
34934
34935            eventBus.on(_MetricsReportingEvents2['default'].METRICS_INITIALISATION_COMPLETE, onInitialisationComplete, this);
34936        }
34937    }
34938
34939    function reset() {
34940        reportingController = null;
34941    }
34942
34943    function handleNewMetric(metric, vo) {
34944        // simply pass metric straight through
34945        if (metric === metricsConstants.DVB_ERRORS) {
34946            if (reportingController) {
34947                reportingController.report(metric, vo);
34948            }
34949        }
34950    }
34951
34952    instance = {
34953        initialize: initialize,
34954        reset: reset,
34955        handleNewMetric: handleNewMetric
34956    };
34957
34958    return instance;
34959}
34960
34961exports['default'] = dashjs.FactoryMaker.getClassFactory(DVBErrorsHandler);
34962/* jshint ignore:line */
34963module.exports = exports['default'];
34964
34965},{"117":117}],126:[function(_dereq_,module,exports){
34966/**
34967 * The copyright in this software is being made available under the BSD License,
34968 * included below. This software may be subject to other third party and contributor
34969 * rights, including patent rights, and no such rights are granted under this license.
34970 *
34971 * Copyright (c) 2013, Dash Industry Forum.
34972 * All rights reserved.
34973 *
34974 * Redistribution and use in source and binary forms, with or without modification,
34975 * are permitted provided that the following conditions are met:
34976 *  * Redistributions of source code must retain the above copyright notice, this
34977 *  list of conditions and the following disclaimer.
34978 *  * Redistributions in binary form must reproduce the above copyright notice,
34979 *  this list of conditions and the following disclaimer in the documentation and/or
34980 *  other materials provided with the distribution.
34981 *  * Neither the name of Dash Industry Forum nor the names of its
34982 *  contributors may be used to endorse or promote products derived from this software
34983 *  without specific prior written permission.
34984 *
34985 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
34986 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34987 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
34988 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
34989 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
34989INCLUDING, BUT
34990 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34991 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
34992 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34993 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34994 *  POSSIBILITY OF SUCH DAMAGE.
34995 */
34996
34997'use strict';
34998
34999Object.defineProperty(exports, '__esModule', {
35000    value: true
35001});
35002function GenericMetricHandler() {
35003
35004    var instance = undefined,
35005        metricName = undefined,
35006        reportingController = undefined;
35007
35008    function initialize(name, rc) {
35009        metricName = name;
35010        reportingController = rc;
35011    }
35012
35013    function reset() {
35014        reportingController = null;
35015        metricName = undefined;
35016    }
35017
35018    function handleNewMetric(metric, vo) {
35019        // simply pass metric straight through
35020        if (metric === metricName) {
35021            if (reportingController) {
35022                reportingController.report(metricName, vo);
35023            }
35024        }
35025    }
35026
35027    instance = {
35028        initialize: initialize,
35029        reset: reset,
35030        handleNewMetric: handleNewMetric
35031    };
35032
35033    return instance;
35034}
35035
35036GenericMetricHandler.__dashjs_factory_name = 'GenericMetricHandler';
35037exports['default'] = dashjs.FactoryMaker.getClassFactory(GenericMetricHandler);
35038/* jshint ignore:line */
35039module.exports = exports['default'];
35040
35041},{}],127:[function(_dereq_,module,exports){
35042/**
35043 * The copyright in this software is being made available under the BSD License,
35044 * included below. This software may be subject to other third party and contributor
35045 * rights, including patent rights, and no such rights are granted under this license.
35046 *
35047 * Copyright (c) 2013, Dash Industry Forum.
35048 * All rights reserved.
35049 *
35050 * Redistribution and use in source and binary forms, with or without modification,
35051 * are permitted provided that the following conditions are met:
35052 *  * Redistributions of source code must retain the above copyright notice, this
35053 *  list of conditions and the following disclaimer.
35054 *  * Redistributions in binary form must reproduce the above copyright notice,
35055 *  this list of conditions and the following disclaimer in the documentation and/or
35056 *  other materials provided with the distribution.
35057 *  * Neither the name of Dash Industry Forum nor the names of its
35058 *  contributors may be used to endorse or promote products derived from this software
35059 *  without specific prior written permission.
35060 *
35061 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
35062 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35063 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
35064 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
35065 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
35066 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
35067 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
35068 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35069 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35070 *  POSSIBILITY OF SUCH DAMAGE.
35071 */
35072
35073'use strict';
35074
35075Object.defineProperty(exports, '__esModule', {
35076    value: true
35077});
35078
35079function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
35080
35081var _utilsHandlerHelpers = _dereq_(131);
35082
35083var _utilsHandlerHelpers2 = _interopRequireDefault(_utilsHandlerHelpers);
35084
35085function HttpListHandler(config) {
35086
35087    var instance = undefined,
35088        reportingController = undefined,
35089        n = undefined,
35090        type = undefined,
35091        name = undefined,
35092        interval = undefined;
35093
35094    var storedVos = [];
35095
35096    var handlerHelpers = (0, _utilsHandlerHelpers2['default'])(this.context).getInstance();
35097
35098    var metricsConstants = config.metricsConstants;
35099
35100    function intervalCallback() {
35101        var vos = storedVos;
35102
35103        if (vos.length) {
35104            if (reportingController) {
35105                reportingController.report(name, vos);
35106            }
35107        }
35108
35109        storedVos = [];
35110    }
35111
35112    function initialize(basename, rc, n_ms, requestType) {
35113        if (rc) {
35114
35115            // this will throw if n is invalid, to be
35116            // caught by the initialize caller.
35117            n = handlerHelpers.validateN(n_ms);
35118
35119            reportingController = rc;
35120
35121            if (requestType && requestType.length) {
35122                type = requestType;
35123            }
35124
35125            name = handlerHelpers.reconstructFullMetricName(basename, n_ms, requestType);
35126
35127            interval = setInterval(intervalCallback, n);
35128        }
35129    }
35130
35131    function reset() {
35132        clearInterval(interval);
35133        interval = null;
35134        n = null;
35135        type = null;
35136        storedVos = [];
35137        reportingController = null;
35138    }
35139
35140    function handleNewMetric(metric, vo) {
35141        if (metric === metricsConstants.HTTP_REQUEST) {
35142            if (!type || type === vo.type) {
35143                storedVos.push(vo);
35144            }
35145        }
35146    }
35147
35148    instance = {
35149        initialize: initialize,
35150        reset: reset,
35151        handleNewMetric: handleNewMetric
35152    };
35153
35154    return instance;
35155}
35156
35157HttpListHandler.__dashjs_factory_name = 'HttpListHandler';
35158exports['default'] = dashjs.FactoryMaker.getClassFactory(HttpListHandler);
35159/* jshint ignore:line */
35160module.exports = exports['default'];
35161
35162},{"131":131}],128:[function(_dereq_,module,exports){
35163/**
35164 * The copyright in this software is being made available under the BSD License,
35165 * included below. This software may be subject to other third party and contributor
35166 * rights, including patent rights, and no such rights are granted under this license.
35167 *
35168 * Copyright (c) 2013, Dash Industry Forum.
35169 * All rights reserved.
35170 *
35171 * Redistribution and use in source and binary forms, with or without modification,
35172 * are permitted provided that the following conditions are met:
35173 *  * Redistributions of source code must retain the above copyright notice, this
35174 *  list of conditions and the following disclaimer.
35175 *  * Redistributions in binary form must reproduce the above copyright notice,
35176 *  this list of conditions and the following disclaimer in the documentation and/or
35177 *  other materials provided with the distribution.
35178 *  * Neither the name of Dash Industry Forum nor the names of its
35179 *  contributors may be used to endorse or promote products derived from this software
35180 *  without specific prior written permission.
35181 *
35182 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
35183 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35184 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
35185 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
35186 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
35187 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
35188 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
35189 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35190 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35191 *  POSSIBILITY OF SUCH DAMAGE.
35192 */
35193
35194'use strict';
35195
35196Object.defineProperty(exports, '__esModule', {
35197    value: true
35198});
35199
35200function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
35201
35202var _reportersDVBReporting = _dereq_(129);
35203
35204var _reportersDVBReporting2 = _interopRequireDefault(_reportersDVBReporting);
35205
35206function ReportingFactory(config) {
35207
35208    var knownReportingSchemeIdUris = {
35209        'urn:dvb:dash:reporting:2014': _reportersDVBReporting2['default']
35210    };
35211
35212    var context = this.context;
35213    var log = config.log;
35214    var instance = undefined;
35215
35216    function create(entry, rangeController) {
35217        var reporting = undefined;
35218
35219        try {
35220            reporting = knownReportingSchemeIdUris[entry.schemeIdUri](context).create();
35221
35222            reporting.initialize(entry, rangeController);
35223        } catch (e) {
35224            reporting = null;
35225
35226            log('ReportingFactory: could not create Reporting with schemeIdUri ' + entry.schemeIdUri + ' (' + e.message + ')');
35227        }
35228
35229        return reporting;
35230    }
35231
35232    function register(schemeIdUri, moduleName) {
35233        knownReportingSchemeIdUris[schemeIdUri] = moduleName;
35234    }
35235
35236    function unregister(schemeIdUri) {
35237        delete knownReportingSchemeIdUris[schemeIdUri];
35238    }
35239
35240    instance = {
35241        create: create,
35242        register: register,
35243        unregister: unregister
35244    };
35245
35246    return instance;
35247}
35248
35249ReportingFactory.__dashjs_factory_name = 'ReportingFactory';
35250exports['default'] = dashjs.FactoryMaker.getSingletonFactory(ReportingFactory);
35251/* jshint ignore:line */
35252module.exports = exports['default'];
35253
35254},{"129":129}],129:[function(_dereq_,module,exports){
35255/**
35256 * The copyright in this software is being made available under the BSD License,
35257 * included below. This software may be subject to other third party and contributor
35258 * rights, including patent rights, and no such rights are granted under this license.
35259 *
35260 * Copyright (c) 2013, Dash Industry Forum.
35261 * All rights reserved.
35262 *
35263 * Redistribution and use in source and binary forms, with or without modification,
35264 * are permitted provided that the following conditions are met:
35265 *  * Redistributions of source code must retain the above copyright notice, this
35266 *  list of conditions and the following disclaimer.
35267 *  * Redistributions in binary form must reproduce the above copyright notice,
35268 *  this list of conditions and the following disclaimer in the documentation and/or
35269 *  other materials provided with the distribution.
35270 *  * Neither the name of Dash Industry Forum nor the names of its
35271 *  contributors may be used to endorse or promote products derived from this software
35272 *  without specific prior written permission.
35273 *
35274 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
35275 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35276 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
35277 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
35278 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
35278INCLUDING, BUT
35279 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
35280 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
35281 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35282 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35283 *  POSSIBILITY OF SUCH DAMAGE.
35284 */
35285
35286'use strict';
35287
35288Object.defineProperty(exports, '__esModule', {
35289    value: true
35290});
35291
35292function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
35293
35294var _utilsMetricSerialiser = _dereq_(133);
35295
35296var _utilsMetricSerialiser2 = _interopRequireDefault(_utilsMetricSerialiser);
35297
35298var _utilsRNG = _dereq_(134);
35299
35300var _utilsRNG2 = _interopRequireDefault(_utilsRNG);
35301
35302function DVBReporting(config) {
35303    var instance = undefined;
35304
35305    var context = this.context;
35306    var metricSerialiser = (0, _utilsMetricSerialiser2['default'])(context).getInstance();
35307    var randomNumberGenerator = (0, _utilsRNG2['default'])(context).getInstance();
35308
35309    var USE_DRAFT_DVB_SPEC = true;
35310    var isReportingPlayer = false;
35311    var reportingPlayerStatusDecided = false;
35312    var reportingUrl = null;
35313    var rangeController = null;
35314    var allowPendingRequestsToCompleteOnReset = true;
35315    var pendingRequests = [];
35316
35317    var metricsConstants = config.metricsConstants;
35318
35319    function doGetRequest(url, successCB, failureCB) {
35320        var req = new XMLHttpRequest();
35321        var oncomplete = function oncomplete() {
35322            var reqIndex = pendingRequests.indexOf(req);
35323
35324            if (reqIndex === -1) {
35325                return;
35326            } else {
35327                pendingRequests.splice(reqIndex, 1);
35328            }
35329
35330            if (req.status >= 200 && req.status < 300) {
35331                if (successCB) {
35332                    successCB();
35333                }
35334            } else {
35335                if (failureCB) {
35336                    failureCB();
35337                }
35338            }
35339        };
35340
35341        pendingRequests.push(req);
35342
35343        try {
35344            req.open('GET', url);
35345            req.onloadend = oncomplete;
35346            req.onerror = oncomplete;
35347            req.send();
35348        } catch (e) {
35349            req.onerror();
35350        }
35351    }
35352
35353    function report(type, vos) {
35354        if (!Array.isArray(vos)) {
35355            vos = [vos];
35356        }
35357
35358        // If the Player is not a reporting Player, then the Player shall
35359        // not report any errors.
35360        // ... In addition to any time restrictions specified by a Range
35361        // element within the Metrics element.
35362        if (isReportingPlayer && rangeController.isEnabled()) {
35363
35364            // This reporting mechanism operates by creating one HTTP GET
35365            // request for every entry in the top level list of the metric.
35366            vos.forEach(function (vo) {
35367                var url = metricSerialiser.serialise(vo);
35368
35369                // this has been proposed for errata
35370                if (USE_DRAFT_DVB_SPEC && type !== metricsConstants.DVB_ERRORS) {
35371                    url = 'metricname=' + type + '&' + url;
35372                }
35373
35374                // Take the value of the @reportingUrl attribute, append a
35375                // question mark ('?') character and then append the string
35376                // created in the previous step.
35377                url = reportingUrl + '?' + url;
35378
35379                // Make an HTTP GET request to the URL contained within the
35380                // string created in the previous step.
35381                doGetRequest(url, null, function () {
35382                    // If the Player is unable to make the report, for
35383                    // example because the @reportingUrl is invalid, the
35384                    // host cannot be reached, or an HTTP status code other
35385                    // than one in the 200 series is received, the Player
35386                    // shall cease being a reporting Player for the
35387                    // duration of the MPD.
35388                    isReportingPlayer = false;
35389                });
35390            });
35391        }
35392    }
35393
35394    function initialize(entry, rc) {
35395        var probability = undefined;
35396
35397        rangeController = rc;
35398
35399        reportingUrl = entry['dvb:reportingUrl'];
35400
35401        // If a required attribute is missing, the Reporting descriptor may
35402        // be ignored by the Player
35403        if (!reportingUrl) {
35404            throw new Error('required parameter missing (dvb:reportingUrl)');
35405        }
35406
35407        // A Player's status, as a reporting Player or not, shall remain
35408        // static for the duration of the MPD, regardless of MPD updates.
35409        // (i.e. only calling reset (or failure) changes this state)
35410        if (!reportingPlayerStatusDecided) {
35411            // NOTE: DVB spec has a typo where it incorrectly references the
35412            // priority attribute, which should be probability
35413            probability = entry['dvb:probability'] || entry['dvb:priority'] || 0;
35414            // If the @priority attribute is set to 1000, it shall be a reporting Player.
35415            // If the @priority attribute is missing, the Player shall not be a reporting Player.
35416            // For any other value of the @probability attribute, it shall decide at random whether to be a
35417            // reporting Player, such that the probability of being one is @probability/1000.
35418            if (probability && (probability === 1000 || probability / 1000 >= randomNumberGenerator.random())) {
35419                isReportingPlayer = true;
35420            }
35421
35422            reportingPlayerStatusDecided = true;
35423        }
35424    }
35425
35426    function reset() {
35427        if (!allowPendingRequestsToCompleteOnReset) {
35428            pendingRequests.forEach(function (req) {
35429                return req.abort();
35430            });
35431            pendingRequests = [];
35432        }
35433
35434        reportingPlayerStatusDecided = false;
35435        isReportingPlayer = false;
35436        reportingUrl = null;
35437        rangeController = null;
35438    }
35439
35440    instance = {
35441        report: report,
35442        initialize: initialize,
35443        reset: reset
35444    };
35445
35446    return instance;
35447}
35448
35449DVBReporting.__dashjs_factory_name = 'DVBReporting';
35450exports['default'] = dashjs.FactoryMaker.getClassFactory(DVBReporting);
35451/* jshint ignore:line */
35452module.exports = exports['default'];
35453
35454},{"133":133,"134":134}],130:[function(_dereq_,module,exports){
35455/**
35456 * The copyright in this software is being made available under the BSD License,
35457 * included below. This software may be subject to other third party and contributor
35458 * rights, including patent rights, and no such rights are granted under this license.
35459 *
35460 * Copyright (c) 2013, Dash Industry Forum.
35461 * All rights reserved.
35462 *
35463 * Redistribution and use in source and binary forms, with or without modification,
35464 * are permitted provided that the following conditions are met:
35465 *  * Redistributions of source code must retain the above copyright notice, this
35466 *  list of conditions and the following disclaimer.
35467 *  * Redistributions in binary form must reproduce the above copyright notice,
35468 *  this list of conditions and the following disclaimer in the documentation and/or
35469 *  other materials provided with the distribution.
35470 *  * Neither the name of Dash Industry Forum nor the names of its
35471 *  contributors may be used to endorse or promote products derived from this software
35472 *  without specific prior written permission.
35473 *
35474 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
35475 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35476 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
35477 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
35478 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
35479 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
35480 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
35481 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35482 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35483 *  POSSIBILITY OF SUCH DAMAGE.
35484 */
35485
35486'use strict';
35487
35488Object.defineProperty(exports, '__esModule', {
35489    value: true
35490});
35491
35492function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
35493
35494var _voDVBErrors = _dereq_(135);
35495
35496var _voDVBErrors2 = _interopRequireDefault(_voDVBErrors);
35497
35498var _MetricsReportingEvents = _dereq_(117);
35499
35500var _MetricsReportingEvents2 = _interopRequireDefault(_MetricsReportingEvents);
35501
35502function DVBErrorsTranslator(config) {
35503
35504    var instance = undefined;
35505    var eventBus = config.eventBus;
35506    var metricModel = config.metricsModel;
35507    var mpd = undefined;
35508
35509    var metricsConstants = config.metricsConstants;
35510    //MediaPlayerEvents have been added to Events in MediaPlayer class
35511    var Events = config.events;
35512
35513    function report(vo) {
35514        var o = new _voDVBErrors2['default']();
35515
35516        if (!mpd) {
35517            return;
35518        }
35519
35520        for (var key in vo) {
35521            if (vo.hasOwnProperty(key)) {
35522                o[key] = vo[key];
35523            }
35524        }
35525
35526        if (!o.mpdurl) {
35527            o.mpdurl = mpd.originalUrl || mpd.url;
35528        }
35529
35530        if (!o.terror) {
35531            o.terror = new Date();
35532        }
35533
35534        metricModel.addDVBErrors(o);
35535    }
35536
35537    function onManifestUpdate(e) {
35538        if (e.error) {
35539            return;
35540        }
35541
35542        mpd = e.manifest;
35543    }
35544
35545    function onServiceLocationChanged(e) {
35546        report({
35547            errorcode: _voDVBErrors2['default'].BASE_URL_CHANGED,
35548            servicelocation: e.entry
35549        });
35550    }
35551
35552    function onBecameReporter() {
35553        report({
35554            errorcode: _voDVBErrors2['default'].BECAME_REPORTER
35555        });
35556    }
35557
35558    function handleHttpMetric(vo) {
35559        if (vo.responsecode === 0 || // connection failure - unknown
35560        vo.responsecode >= 400 || // HTTP error status code
35561        vo.responsecode < 100 || // unknown status codes
35562        vo.responsecode >= 600) {
35563            // unknown status codes
35564            report({
35565                errorcode: vo.responsecode || _voDVBErrors2['default'].CONNECTION_ERROR,
35566                url: vo.url,
35567                terror: vo.tresponse,
35568                servicelocation: vo._serviceLocation
35569            });
35570        }
35571    }
35572
35573    function onMetricEvent(e) {
35574        switch (e.metric) {
35575            case metricsConstants.HTTP_REQUEST:
35576                handleHttpMetric(e.value);
35577                break;
35578            default:
35579                break;
35580        }
35581    }
35582
35583    function onPlaybackError(e) {
35584        var reason = e.error ? e.error.code : 0;
35585        var errorcode = undefined;
35586
35587        switch (reason) {
35588            case MediaError.MEDIA_ERR_NETWORK:
35589                errorcode = _voDVBErrors2['default'].CONNECTION_ERROR;
35590                break;
35591            case MediaError.MEDIA_ERR_DECODE:
35592                errorcode = _voDVBErrors2['default'].CORRUPT_MEDIA_OTHER;
vendor: 4,729 bytes, lines 35593-35716
35593                break;
35594            default:
35595                return;
35596        }
35597
35598        report({
35599            errorcode: errorcode
35600        });
35601    }
35602
35603    function initialise() {
35604        eventBus.on(Events.MANIFEST_UPDATED, onManifestUpdate, instance);
35605        eventBus.on(Events.SERVICE_LOCATION_BLACKLIST_CHANGED, onServiceLocationChanged, instance);
35606        eventBus.on(Events.METRIC_ADDED, onMetricEvent, instance);
35607        eventBus.on(Events.METRIC_UPDATED, onMetricEvent, instance);
35608        eventBus.on(Events.PLAYBACK_ERROR, onPlaybackError, instance);
35609        eventBus.on(_MetricsReportingEvents2['default'].BECAME_REPORTING_PLAYER, onBecameReporter, instance);
35610    }
35611
35612    function reset() {
35613        eventBus.off(Events.MANIFEST_UPDATED, onManifestUpdate, instance);
35614        eventBus.off(Events.SERVICE_LOCATION_BLACKLIST_CHANGED, onServiceLocationChanged, instance);
35615        eventBus.off(Events.METRIC_ADDED, onMetricEvent, instance);
35616        eventBus.off(Events.METRIC_UPDATED, onMetricEvent, instance);
35617        eventBus.off(Events.PLAYBACK_ERROR, onPlaybackError, instance);
35618        eventBus.off(_MetricsReportingEvents2['default'].BECAME_REPORTING_PLAYER, onBecameReporter, instance);
35619    }
35620
35621    instance = {
35622        initialise: initialise,
35623        reset: reset
35624    };
35625
35626    initialise();
35627
35628    return instance;
35629}
35630
35631DVBErrorsTranslator.__dashjs_factory_name = 'DVBErrorsTranslator';
35632exports['default'] = dashjs.FactoryMaker.getSingletonFactory(DVBErrorsTranslator);
35633/* jshint ignore:line */
35634module.exports = exports['default'];
35635
35636},{"117":117,"135":135}],131:[function(_dereq_,module,exports){
35637/**
35638 * The copyright in this software is being made available under the BSD License,
35639 * included below. This software may be subject to other third party and contributor
35640 * rights, including patent rights, and no such rights are granted under this license.
35641 *
35642 * Copyright (c) 2013, Dash Industry Forum.
35643 * All rights reserved.
35644 *
35645 * Redistribution and use in source and binary forms, with or without modification,
35646 * are permitted provided that the following conditions are met:
35647 *  * Redistributions of source code must retain the above copyright notice, this
35648 *  list of conditions and the following disclaimer.
35649 *  * Redistributions in binary form must reproduce the above copyright notice,
35650 *  this list of conditions and the following disclaimer in the documentation and/or
35651 *  other materials provided with the distribution.
35652 *  * Neither the name of Dash Industry Forum nor the names of its
35653 *  contributors may be used to endorse or promote products derived from this software
35654 *  without specific prior written permission.
35655 *
35656 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
35657 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35658 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
35659 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
35660 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
35661 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
35662 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
35663 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35664 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35665 *  POSSIBILITY OF SUCH DAMAGE.
35666 */
35667
35668'use strict';
35669
35670Object.defineProperty(exports, '__esModule', {
35671    value: true
35672});
35673function HandlerHelpers() {
35674    return {
35675        reconstructFullMetricName: function reconstructFullMetricName(key, n, type) {
35676            var mn = key;
35677
35678            if (n) {
35679                mn += '(' + n;
35680
35681                if (type && type.length) {
35682                    mn += ',' + type;
35683                }
35684
35685                mn += ')';
35686            }
35687
35688            return mn;
35689        },
35690
35691        validateN: function validateN(n_ms) {
35692            if (!n_ms) {
35693                throw new Error('missing n');
35694            }
35695
35696            if (isNaN(n_ms)) {
35697                throw new Error('n is NaN');
35698            }
35699
35700            // n is a positive integer is defined to refer to the metric
35701            // in which the buffer level is recorded every n ms.
35702            if (n_ms < 0) {
35703                throw new Error('n must be positive');
35704            }
35705
35706            return n_ms;
35707        }
35708    };
35709}
35710
35711HandlerHelpers.__dashjs_factory_name = 'HandlerHelpers';
35712exports['default'] = dashjs.FactoryMaker.getSingletonFactory(HandlerHelpers);
35713/* jshint ignore:line */
35714module.exports = exports['default'];
35715
35716},{}
35716],132:[function(_dereq_,module,exports){
35717'use strict';
35718
35719Object.defineProperty(exports, '__esModule', {
35720    value: true
35721});
35722
35723function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
35724
35725var _voMetrics = _dereq_(136);
35726
35727var _voMetrics2 = _interopRequireDefault(_voMetrics);
35728
35729var _voRange = _dereq_(137);
35730
35731var _voRange2 = _interopRequireDefault(_voRange);
35732
35733var _voReporting = _dereq_(138);
35734
35735var _voReporting2 = _interopRequireDefault(_voReporting);
35736
35737function ManifestParsing(config) {
35738    var instance = undefined;
35739    var dashManifestModel = config.dashManifestModel;
35740    var constants = config.constants;
35741
35742    function getMetricsRangeStartTime(manifest, dynamic, range) {
35743        var mpd = dashManifestModel.getMpd(manifest);
35744        var voPeriods;
35745        var presentationStartTime = 0;
35746        var reportingStartTime;
35747
35748        if (dynamic) {
35749            // For services with MPD@type='dynamic', the start time is
35750            // indicated in wall clock time by adding the value of this
35751            // attribute to the value of the MPD@availabilityStartTime
35752            // attribute.
35753            presentationStartTime = mpd.availabilityStartTime.getTime() / 1000;
35754        } else {
35755            // For services with MPD@type='static', the start time is indicated
35756            // in Media Presentation time and is relative to the PeriodStart
35757            // time of the first Period in this MPD.
35758            voPeriods = this.getRegularPeriods(mpd);
35759
35760            if (voPeriods.length) {
35761                presentationStartTime = voPeriods[0].start;
35762            }
35763        }
35764
35765        // When not present, DASH Metrics collection is
35766        // requested from the beginning of content
35767        // consumption.
35768        reportingStartTime = presentationStartTime;
35769
35770        if (range && range.hasOwnProperty(constants.START_TIME)) {
35771            reportingStartTime += range.starttime;
35772        }
35773
35774        return reportingStartTime;
35775    }
35776
35777    function getMetrics(manifest) {
35778        var metrics = [];
35779
35780        if (manifest.Metrics_asArray) {
35781            manifest.Metrics_asArray.forEach(function (metric) {
35782                var metricEntry = new _voMetrics2['default']();
35783                var isDynamic = dashManifestModel.getIsDynamic(manifest);
35784
35785                if (metric.hasOwnProperty('metrics')) {
35786                    metricEntry.metrics = metric.metrics;
35787                } else {
35788                    //console.log("Invalid Metrics. metrics must be set. Ignoring.");
35789                    return;
35790                }
35791
35792                if (metric.Range_asArray) {
35793                    metric.Range_asArray.forEach(function (range) {
35794                        var rangeEntry = new _voRange2['default']();
35795
35796                        rangeEntry.starttime = getMetricsRangeStartTime(manifest, isDynamic, range);
35797
35798                        if (range.hasOwnProperty('duration')) {
35799                            rangeEntry.duration = range.duration;
35800                        } else {
35801                            // if not present, the value is identical to the
35802                            // Media Presentation duration.
35803                            rangeEntry.duration = dashManifestModel.getDuration(manifest);
35804                        }
35805
35806                        rangeEntry._useWallClockTime = isDynamic;
35807
35808                        metricEntry.Range.push(rangeEntry);
35809                    });
35810                }
35811
35812                if (metric.Reporting_asArray) {
35813                    metric.Reporting_asArray.forEach(function (reporting) {
35814                        var reportingEntry = new _voReporting2['default']();
35815
35816                        if (reporting.hasOwnProperty(constants.SCHEME_ID_URI)) {
35817                            reportingEntry.schemeIdUri = reporting.schemeIdUri;
35818                        } else {
35819                            // Invalid Reporting. schemeIdUri must be set. Ignore.
35820                            return;
35821                        }
35822
35823                        for (var prop in reporting) {
35824                            if (reporting.hasOwnProperty(prop)) {
35825                                reportingEntry[prop] = reporting[prop];
35826                            }
35827                        }
35828
35829                        metricEntry.Reporting.push(reportingEntry);
35830                    });
35831                } else {
35832                    // Invalid Metrics. At least one reporting must be present. Ignore
35833                    return;
35834                }
35835
35836                metrics.push(metricEntry);
35837            });
35838        }
35839
35840        return metrics;
35841    }
35842
35843    instance = {
35844        getMetrics: getMetrics
35845    };
35846
35847    return instance;
35848}
35849
35850ManifestParsing.__dashjs_factory_name = 'ManifestParsing';
35851exports['default'] = dashjs.FactoryMaker.getSingletonFactory(ManifestParsing);
35852/* jshint ignore:line */
35853module.exports = exports['default'];
35854
35855},{"136":136,"137":137,"138":138}],133:[function(_dereq_,module,exports){
35856/**
35857 * The copyright in this software is being made available under the BSD License,
35858 * included below. This software may be subject to other third party and contributor
35859 * rights, including patent rights, and no such rights are granted under this license.
35860 *
35861 * Copyright (c) 2013, Dash Industry Forum.
35862 * All rights reserved.
35863 *
35864 * Redistribution and use in source and binary forms, with or without modification,
35865 * are permitted provided that the following conditions are met:
35866 *  * Redistributions of source code must retain the above copyright notice, this
35867 *  list of conditions and the following disclaimer.
35868 *  * Redistributions in binary form must reproduce the above copyright notice,
35869 *  this list of conditions and the following disclaimer in the documentation and/or
35870 *  other materials provided with the distribution.
35871 *  * Neither the name of Dash Industry Forum nor the names of its
35872 *  contributors may be used to endorse or promote products derived from this software
35873 *  without specific prior written permission.
35874 *
35875 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
35876 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35877 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
35878 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
35879 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
35879INCLUDING, BUT
35880 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
35881 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
35882 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35883 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35884 *  POSSIBILITY OF SUCH DAMAGE.
35885 */
35886
35887'use strict';
35888
35889Object.defineProperty(exports, '__esModule', {
35890    value: true
35891});
35892function MetricSerialiser() {
35893
35894    // For each entry in the top level list within the metric (in the case
35895    // of the DVBErrors metric each entry corresponds to an "error event"
35896    // described in clause 10.8.4) the Player shall:
35897    function serialise(metric) {
35898        var pairs = [];
35899        var obj = [];
35900        var key = undefined,
35901            value = undefined;
35902
35903        // Take each (key, value) pair from the metric entry and create a
35904        // string consisting of the name of the key, followed by an equals
35905        // ('=') character, followed by the string representation of the
35906        // value. The string representation of the value is created based
35907        // on the type of the value following the instructions in Table 22.
35908        for (key in metric) {
35909            if (metric.hasOwnProperty(key) && key.indexOf('_') !== 0) {
35910                value = metric[key];
35911
35912                // we want to ensure that keys still end up in the report
35913                // even if there is no value
35914                if (value === undefined || value === null) {
35915                    value = '';
35916                }
35917
35918                // DVB A168 10.12.4 Table 22
35919                if (Array.isArray(value)) {
35920                    // if trace or similar is null, do not include in output
35921                    if (!value.length) {
35922                        continue;
35923                    }
35924
35925                    obj = [];
35926
35927                    value.forEach(function (v) {
35928                        var isBuiltIn = Object.prototype.toString.call(v).slice(8, -1) !== 'Object';
35929
35930                        obj.push(isBuiltIn ? v : serialise(v));
35931                    });
35932
35933                    value = obj.map(encodeURIComponent).join(',');
35934                } else if (typeof value === 'string') {
35935                    value = encodeURIComponent(value);
35936                } else if (value instanceof Date) {
35937                    value = value.toISOString();
35938                } else if (typeof value === 'number') {
35939                    value = Math.round(value);
35940                }
35941
35942                pairs.push(key + '=' + value);
35943            }
35944        }
35945
35946        // Concatenate the strings created in the previous step with an
35947        // ampersand ('&') character between each one.
35948        return pairs.join('&');
35949    }
35950
35951    return {
35952        serialise: serialise
35953    };
35954}
35955
35956MetricSerialiser.__dashjs_factory_name = 'MetricSerialiser';
35957exports['default'] = dashjs.FactoryMaker.getSingletonFactory(MetricSerialiser);
35958/* jshint ignore:line */
35959module.exports = exports['default'];
35960
35961},{}],134:[function(_dereq_,module,exports){
35962/**
35963 * The copyright in this software is being made available under the BSD License,
35964 * included below. This software may be subject to other third party and contributor
35965 * rights, including patent rights, and no such rights are granted under this license.
35966 *
35967 * Copyright (c) 2013, Dash Industry Forum.
35968 * All rights reserved.
35969 *
35970 * Redistribution and use in source and binary forms, with or without modification,
35971 * are permitted provided that the following conditions are met:
35972 *  * Redistributions of source code must retain the above copyright notice, this
35973 *  list of conditions and the following disclaimer.
35974 *  * Redistributions in binary form must reproduce the above copyright notice,
35975 *  this list of conditions and the following disclaimer in the documentation and/or
35976 *  other materials provided with the distribution.
35977 *  * Neither the name of Dash Industry Forum nor the names of its
35978 *  contributors may be used to endorse or promote products derived from this software
35979 *  without specific prior written permission.
35980 *
35981 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
35982 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35983 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
35984 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
35985 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
35985INCLUDING, BUT
35986 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
35987 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
35988 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35989 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35990 *  POSSIBILITY OF SUCH DAMAGE.
35991 */
35992
35993'use strict';
35994
35995Object.defineProperty(exports, '__esModule', {
35996    value: true
35997});
35998function RNG() {
35999
36000    // check whether secure random numbers are available. if not, revert to
36001    // using Math.random
36002    var crypto = window.crypto || window.msCrypto;
36003
36004    // could just as easily use any other array type by changing line below
36005    var ArrayType = Uint32Array;
36006    var MAX_VALUE = Math.pow(2, ArrayType.BYTES_PER_ELEMENT * 8) - 1;
36007
36008    // currently there is only one client for this code, and that only uses
36009    // a single random number per initialisation. may want to increase this
36010    // number if more consumers in the future
36011    var NUM_RANDOM_NUMBERS = 10;
36012
36013    var randomNumbers = undefined,
36014        index = undefined,
36015        instance = undefined;
36016
36017    function initialise() {
36018        if (crypto) {
36019            if (!randomNumbers) {
36020                randomNumbers = new ArrayType(NUM_RANDOM_NUMBERS);
36021            }
36022            crypto.getRandomValues(randomNumbers);
36023            index = 0;
36024        }
36025    }
36026
36027    function rand(min, max) {
36028        var r = undefined;
36029
36030        if (!min) {
36031            min = 0;
36032        }
36033
36034        if (!max) {
36035            max = 1;
36036        }
36037
36038        if (crypto) {
36039            if (index === randomNumbers.length) {
36040                initialise();
36041            }
36042
36043            r = randomNumbers[index] / MAX_VALUE;
36044            index += 1;
36045        } else {
36046            r = Math.random();
36047        }
36048
36049        return r * (max - min) + min;
36050    }
36051
36052    instance = {
36053        random: rand
36054    };
36055
36056    initialise();
36057
36058    return instance;
36059}
36060
36061RNG.__dashjs_factory_name = 'RNG';
36062exports['default'] = dashjs.FactoryMaker.getSingletonFactory(RNG);
36063/* jshint ignore:line */
36064module.exports = exports['default'];
36065
36066},{}],135:[function(_dereq_,module,exports){
36067/**
36068 * The copyright in this software is being made available under the BSD License,
36069 * included below. This software may be subject to other third party and contributor
36070 * rights, including patent rights, and no such rights are granted under this license.
36071 *
36072 * Copyright (c) 2013, Dash Industry Forum.
36073 * All rights reserved.
36074 *
36075 * Redistribution and use in source and binary forms, with or without modification,
36076 * are permitted provided that the following conditions are met:
36077 *  * Redistributions of source code must retain the above copyright notice, this
36078 *  list of conditions and the following disclaimer.
36079 *  * Redistributions in binary form must reproduce the above copyright notice,
36080 *  this list of conditions and the following disclaimer in the documentation and/or
36081 *  other materials provided with the distribution.
36082 *  * Neither the name of Dash Industry Forum nor the names of its
36083 *  contributors may be used to endorse or promote products derived from this software
36084 *  without specific prior written permission.
36085 *
36086 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
36087 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
36088 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
36089 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
36090 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36091 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
36092 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
36093 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36094 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36095 *  POSSIBILITY OF SUCH DAMAGE.
36096 */
36097/**
36098 * @class
36099 * @ignore
36100 */
36101'use strict';
36102
36103Object.defineProperty(exports, '__esModule', {
36104    value: true
36105});
36106
36107function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
36108
36109var DVBErrors = function DVBErrors() {
36110    _classCallCheck(this, DVBErrors);
36111
36112    this.mpdurl = null;
36113    // String - Absolute URL from which the MPD was originally
36114    // retrieved (MPD updates will not change this value).
36115
36116    this.errorcode = null;
36117    // String - The value of errorcode depends upon the type
36118    // of error being reported. For an error listed in the
36119    // ErrorType column below the value is as described in the
36120    // Value column.
36121    //
36122    // ErrorType                                            Value
36123    // ---------                                            -----
36124    // HTTP error status code                               HTTP status code
36125    // Unknown HTTP status code                             HTTP status code
36126    // SSL connection failed                                "SSL" followed by SSL alert value
36127    // DNS resolution failed                                "C00"
36128    // Host unreachable                                     "C01"
36129    // Connection refused                                   "C02"
36130    // Connection error – Not otherwise specified           "C03"
36131    // Corrupt media – ISO BMFF container cannot be parsed  "M00"
36132    // Corrupt media – Not otherwise specified              "M01"
36133    // Changing Base URL in use due to errors               "F00"
36134    // Becoming an error reporting Player                   "S00"
36135
36136    this.terror = null;
36137    // Real-Time - Date and time at which error occurred in UTC,
36138    // formatted as a combined date and time according to ISO 8601.
36139
36140    this.url = null;
36141    // String - Absolute URL from which data was being requested
36142    // when this error occurred. If the error report is in relation
36143    // to corrupt media or changing BaseURL, this may be a null
36144    // string if the URL from which the media was obtained or
36145    // which led to the change of BaseURL is no longer known.
36146
36147    this.ipaddress = null;
36148    // String - IP Address which the host name in "url" resolved to.
36149    // If the error report is in relation to corrupt media or
36150    // changing BaseURL, this may be a null string if the URL
36151    // from which the media was obtained or which led to the
36152    // change of BaseURL is no longer known.
36153
36154    this.servicelocation = null;
36155    // String - The value of the serviceLocation field in the
36156    // BaseURL being used. In the event of this report indicating
36157    // a change of BaseURL this is the value from the BaseURL
36158    // being moved from.
36159};
36160
36161DVBErrors.SSL_CONNECTION_FAILED_PREFIX = 'SSL';
36162DVBErrors.DNS_RESOLUTION_FAILED = 'C00';
36163DVBErrors.HOST_UNREACHABLE = 'C01';
36164DVBErrors.CONNECTION_REFUSED = 'C02';
36165DVBErrors.CONNECTION_ERROR = 'C03';
36166DVBErrors.CORRUPT_MEDIA_ISOBMFF = 'M00';
36167DVBErrors.CORRUPT_MEDIA_OTHER = 'M01';
36168DVBErrors.BASE_URL_CHANGED = 'F00';
36169DVBErrors.BECAME_REPORTER = 'S00';
36170
36171exports['default'] = DVBErrors;
36172module.exports = exports['default'];
36173
36174},{}],136:[function(_dereq_,module,exports){
36175/**
36176 * The copyright in this software is being made available under the BSD License,
36177 * included below. This software may be subject to other third party and contributor
36178 * rights, including patent rights, and no such rights are granted under this license.
36179 *
36180 * Copyright (c) 2013, Dash Industry Forum.
36181 * All rights reserved.
36182 *
36183 * Redistribution and use in source and binary forms, with or without modification,
36184 * are permitted provided that the following conditions are met:
36185 *  * Redistributions of source code must retain the above copyright notice, this
36186 *  list of conditions and the following disclaimer.
36187 *  * Redistributions in binary form must reproduce the above copyright notice,
36188 *  this list of conditions and the following disclaimer in the documentation and/or
36189 *  other materials provided with the distribution.
36190 *  * Neither the name of Dash Industry Forum nor the names of its
36191 *  contributors may be used to endorse or promote products derived from this software
36192 *  without specific prior written permission.
36193 *
36194 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
36195 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
36196 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
36197 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
36198 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
36198INCLUDING, BUT
36199 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
36200 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
36201 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36202 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36203 *  POSSIBILITY OF SUCH DAMAGE.
36204 */
36205/**
36206 * @class
36207 * @ignore
36208 */
36209'use strict';
36210
36211Object.defineProperty(exports, '__esModule', {
36212  value: true
36213});
36214
36215function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
36216
36217var Metrics = function Metrics() {
36218  _classCallCheck(this, Metrics);
36219
36220  this.metrics = '';
36221  this.Range = [];
36222  this.Reporting = [];
36223};
36224
36225exports['default'] = Metrics;
36226module.exports = exports['default'];
36227
36228},{}],137:[function(_dereq_,module,exports){
36229/**
36230 * The copyright in this software is being made available under the BSD License,
36231 * included below. This software may be subject to other third party and contributor
36232 * rights, including patent rights, and no such rights are granted under this license.
36233 *
36234 * Copyright (c) 2013, Dash Industry Forum.
36235 * All rights reserved.
36236 *
36237 * Redistribution and use in source and binary forms, with or without modification,
36238 * are permitted provided that the following conditions are met:
36239 *  * Redistributions of source code must retain the above copyright notice, this
36240 *  list of conditions and the following disclaimer.
36241 *  * Redistributions in binary form must reproduce the above copyright notice,
36242 *  this list of conditions and the following disclaimer in the documentation and/or
36243 *  other materials provided with the distribution.
36244 *  * Neither the name of Dash Industry Forum nor the names of its
36245 *  contributors may be used to endorse or promote products derived from this software
36246 *  without specific prior written permission.
36247 *
36248 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
36249 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
36250 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
36251 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
36252 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36253 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
36254 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
36255 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36256 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36257 *  POSSIBILITY OF SUCH DAMAGE.
36258 */
36259/**
36260 * @class
36261 * @ignore
36262 */
36263"use strict";
36264
36265Object.defineProperty(exports, "__esModule", {
36266  value: true
36267});
36268
36269function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
36270
36271var Range = function Range() {
36272  _classCallCheck(this, Range);
36273
36274  // as defined in ISO23009-1
36275  this.starttime = 0;
36276  this.duration = Infinity;
36277
36278  // for internal use
36279  this._useWallClockTime = false;
36280};
36281
36282exports["default"] = Range;
36283module.exports = exports["default"];
36284
36285},{}],138:[function(_dereq_,module,exports){
36286/**
36287 * The copyright in this software is being made available under the BSD License,
36288 * included below. This software may be subject to other third party and contributor
36289 * rights, including patent rights, and no such rights are granted under this license.
36290 *
36291 * Copyright (c) 2013, Dash Industry Forum.
36292 * All rights reserved.
36293 *
36294 * Redistribution and use in source and binary forms, with or without modification,
36295 * are permitted provided that the following conditions are met:
36296 *  * Redistributions of source code must retain the above copyright notice, this
36297 *  list of conditions and the following disclaimer.
36298 *  * Redistributions in binary form must reproduce the above copyright notice,
36299 *  this list of conditions and the following disclaimer in the documentation and/or
36300 *  other materials provided with the distribution.
36301 *  * Neither the name of Dash Industry Forum nor the names of its
36302 *  contributors may be used to endorse or promote products derived from this software
36303 *  without specific prior written permission.
36304 *
36305 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
36306 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
36307 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
36308 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
36309 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
36309INCLUDING, BUT
36310 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
36311 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
36312 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36313 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36314 *  POSSIBILITY OF SUCH DAMAGE.
36315 */
36316/**
36317 * @class
36318 * @ignore
36319 */
36320'use strict';
36321
36322Object.defineProperty(exports, '__esModule', {
36323  value: true
36324});
36325
36326function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
36327
36328var Reporting = function Reporting() {
36329  _classCallCheck(this, Reporting);
36330
36331  // Reporting is a DescriptorType and doesn't have any additional fields
36332  this.schemeIdUri = '';
36333  this.value = '';
36334};
36335
36336exports['default'] = Reporting;
36337module.exports = exports['default'];
36338
36339},{}],139:[function(_dereq_,module,exports){
36340/**
36341 * The copyright in this software is being made available under the BSD License,
36342 * included below. This software may be subject to other third party and contributor
36343 * rights, including patent rights, and no such rights are granted under this license.
36344 *
36345 * Copyright (c) 2013, Dash Industry Forum.
36346 * All rights reserved.
36347 *
36348 * Redistribution and use in source and binary forms, with or without modification,
36349 * are permitted provided that the following conditions are met:
36350 *  * Redistributions of source code must retain the above copyright notice, this
36351 *  list of conditions and the following disclaimer.
36352 *  * Redistributions in binary form must reproduce the above copyright notice,
36353 *  this list of conditions and the following disclaimer in the documentation and/or
36354 *  other materials provided with the distribution.
36355 *  * Neither the name of Dash Industry Forum nor the names of its
36356 *  contributors may be used to endorse or promote products derived from this software
36357 *  without specific prior written permission.
36358 *
36359 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
36360 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
36361 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
36362 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
36363 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36364 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
36365 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
36366 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36367 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36368 *  POSSIBILITY OF SUCH DAMAGE.
36369 */
36370
36371'use strict';
36372
36373Object.defineProperty(exports, '__esModule', {
36374    value: true
36375});
36376
36377function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
36378
36379function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
36380
36381var _utilsObjectUtils = _dereq_(199);
36382
36383var _utilsObjectUtils2 = _interopRequireDefault(_utilsObjectUtils);
36384
36385var _coreFactoryMaker = _dereq_(51);
36386
36387var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
36388
36389var DEFAULT_INDEX = NaN;
36390
36391var Node = function Node(_baseUrls, _selectedIdx) {
36392    _classCallCheck(this, Node);
36393
36394    this.data = {
36395        baseUrls: _baseUrls || null,
36396        selectedIdx: _selectedIdx || DEFAULT_INDEX
36397    };
36398    this.children = [];
36399};
36400
36401function BaseURLTreeModel() {
36402
36403    var instance = undefined;
36404    var root = undefined;
36405    var dashManifestModel = undefined;
36406
36407    var context = this.context;
36408    var objectUtils = (0, _utilsObjectUtils2['default'])(context).getInstance();
36409
36410    function setup() {
36411        reset();
36412    }
36413
36414    function setConfig(config) {
36415        if (config.dashManifestModel) {
36416            dashManifestModel = config.dashManifestModel;
36417        }
36418    }
36419
36420    function updateChildData(node, index, element) {
36421        var baseUrls = dashManifestModel.getBaseURLsFromElement(element);
36422
36423        if (!node[index]) {
36424            node[index] = new Node(baseUrls);
36425        } else {
36426            if (!objectUtils.areEqual(baseUrls, node[index].data.baseUrls)
vendor: 1,548 bytes, lines 36426-36471
36426) {
36427                node[index].data.baseUrls = baseUrls;
36428                node[index].data.selectedIdx = DEFAULT_INDEX;
36429            }
36430        }
36431    }
36432
36433    function getBaseURLCollectionsFromManifest(manifest) {
36434        var baseUrls = dashManifestModel.getBaseURLsFromElement(manifest);
36435
36436        if (!objectUtils.areEqual(baseUrls, root.data.baseUrls)) {
36437            root.data.baseUrls = baseUrls;
36438            root.data.selectedIdx = DEFAULT_INDEX;
36439        }
36440
36441        if (manifest.Period_asArray) {
36442            manifest.Period_asArray.forEach(function (p, pi) {
36443                updateChildData(root.children, pi, p);
36444
36445                if (p.AdaptationSet_asArray) {
36446                    p.AdaptationSet_asArray.forEach(function (a, ai) {
36447                        updateChildData(root.children[pi].children, ai, a);
36448
36449                        if (a.Representation_asArray) {
36450                            a.Representation_asArray.sort(dashManifestModel.getRepresentationSortFunction()).forEach(function (r, ri) {
36451                                updateChildData(root.children[pi].children[ai].children, ri, r);
36452                            });
36453                        }
36454                    });
36455                }
36456            });
36457        }
36458    }
36459
36460    function walk(callback, node) {
36461        var target = node || root;
36462
36463        callback(target.data);
36464
36465        if (target.children) {
36466            target.children.forEach(function (child) {
36467                return walk(callback, child);
36468            });
36469        }
36470    }
36471
36472    function invalidateSelectedIndexes(serviceLocation) {
36473        walk(function (data) {
36474            if (!isNaN(data.selectedIdx)) {
36475                if (serviceLocation === data.baseUrls[data.selectedIdx].serviceLocation) {
36476                    data.selectedIdx = DEFAULT_INDEX;
36477                }
36478            }
36479        });
36480    }
36481
36482    function update(manifest) {
36483        getBaseURLCollectionsFromManifest(manifest);
36484    }
36485
36486    function reset() {
36487        root = new Node();
36488    }
36489
36490    function getForPath(path) {
36491        var target = root;
36492        var nodes = [target.data];
36493
36494        path.forEach(function (p) {
36495            target = target.children[p];
36496
36497            if (target) {
36498                nodes.push(target.data);
36499            }
36500        });
36501
36502        return nodes.filter(function (n) {
36503            return n.baseUrls.length;
36504        });
36505    }
36506
36507    instance = {
36508        reset: reset,
36509        update: update,
36510        getForPath: getForPath,
36511        invalidateSelectedIndexes: invalidateSelectedIndexes,
36512        setConfig: setConfig
36513    };
36514
36515    setup();
36516
36517    return instance;
36518}
36519
36520BaseURLTreeModel.__dashjs_factory_name = 'BaseURLTreeModel';
36521exports['default'] = _coreFactoryMaker2['default'].getClassFactory(BaseURLTreeModel);
36522module.exports = exports['default'];
36523
36524},{"199":199,"51":51}],140:[function(_dereq_,module,exports){
36525/**
36526 * The copyright in this software is being made available under the BSD License,
36527 * included below. This software may be subject to other third party and contributor
36528 * rights, including patent rights, and no such rights are granted under this license.
36529 *
36530 * Copyright (c) 2013, Dash Industry Forum.
36531 * All rights reserved.
36532 *
36533 * Redistribution and use in source and binary forms, with or without modification,
36534 * are permitted provided that the following conditions are met:
36535 *  * Redistributions of source code must retain the above copyright notice, this
36536 *  list of conditions and the following disclaimer.
36537 *  * Redistributions in binary form must reproduce the above copyright notice,
36538 *  this list of conditions and the following disclaimer in the documentation and/or
36539 *  other materials provided with the distribution.
36540 *  * Neither the name of Dash Industry Forum nor the names of its
36541 *  contributors may be used to endorse or promote products derived from this software
36542 *  without specific prior written permission.
36543 *
36544 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
36545 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
36546 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
36547 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
36548 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36549 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
36550 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
36551 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36552 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36553 *  POSSIBILITY OF SUCH DAMAGE.
36554 */
36555
36556'use strict';
36557
36558Object.defineProperty(exports, '__esModule', {
36559    value: true
36560});
36561
36562function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
36563
36564var _coreEventBus = _dereq_(50);
36565
36566var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
36567
36568var _coreEventsEvents = _dereq_(54);
36569
36570var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
36571
36572var _coreFactoryMaker = _dereq_(51);
36573
36574var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
36575
36576var _voFragmentRequest = _dereq_(209);
36577
36578var _voFragmentRequest2 = _interopRequireDefault(_voFragmentRequest);
36579
36580var _coreDebug = _dereq_(49);
36581
36582var _coreDebug2 = _interopRequireDefault(_coreDebug);
36583
36584var FRAGMENT_MODEL_LOADING = 'loading';
36585var FRAGMENT_MODEL_EXECUTED = 'executed';
36586var FRAGMENT_MODEL_CANCELED = 'canceled';
36587var FRAGMENT_MODEL_FAILED = 'failed';
36588
36589function FragmentModel(config) {
36590
36591    var context = this.context;
36592    var log = (0, _coreDebug2['default'])(context).getInstance().log;
36593    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
36594    var metricsModel = config.metricsModel;
36595    var fragmentLoader = config.fragmentLoader;
36596
36597    var instance = undefined,
36598        streamProcessor = undefined,
36599        executedRequests = undefined,
36600        loadingRequests = undefined;
36601
36602    function setup() {
36603        resetInitialSettings();
vendor: 2,894 bytes, lines 36604-36683
36604        eventBus.on(_coreEventsEvents2['default'].LOADING_COMPLETED, onLoadingCompleted, instance);
36605        eventBus.on(_coreEventsEvents2['default'].LOADING_ABANDONED, onLoadingAborted, instance);
36606    }
36607
36608    function setStreamProcessor(value) {
36609        streamProcessor = value;
36610    }
36611
36612    function getStreamProcessor() {
36613        return streamProcessor;
36614    }
36615
36616    function isFragmentLoaded(request) {
36617        var isEqualComplete = function isEqualComplete(req1, req2) {
36618            return req1.action === _voFragmentRequest2['default'].ACTION_COMPLETE && req1.action === req2.action;
36619        };
36620
36621        var isEqualMedia = function isEqualMedia(req1, req2) {
36622            return !isNaN(req1.index) && req1.startTime === req2.startTime && req1.adaptationIndex === req2.adaptationIndex;
36623        };
36624
36625        var isEqualInit = function isEqualInit(req1, req2) {
36626            return isNaN(req1.index) && isNaN(req2.index) && req1.quality === req2.quality;
36627        };
36628
36629        var check = function check(requests) {
36630            var isLoaded = false;
36631            requests.some(function (req) {
36632                if (isEqualMedia(request, req) || isEqualInit(request, req) || isEqualComplete(request, req)) {
36633                    isLoaded = true;
36634                    return isLoaded;
36635                }
36636            });
36637            return isLoaded;
36638        };
36639
36640        if (!request) {
36641            return false;
36642        }
36643
36644        return check(executedRequests);
36645    }
36646
36647    function isFragmentLoadedOrPending(request) {
36648        var isLoaded = false;
36649        var i = 0;
36650        var req = undefined;
36651
36652        // First, check if the fragment has already been loaded
36653        isLoaded = isFragmentLoaded(request);
36654
36655        // Then, check if the fragment is about to be loeaded
36656        if (!isLoaded) {
36657            for (i = 0; i < loadingRequests.length; i++) {
36658                req = loadingRequests[i];
36659                if (request.url === req.url && request.startTime === req.startTime) {
36660                    isLoaded = true;
36661                }
36662            }
36663        }
36664
36665        return isLoaded;
36666    }
36667
36668    /**
36669     *
36670     * Gets an array of {@link FragmentRequest} objects
36671     *
36672     * @param {Object} filter The object with properties by which the method filters the requests to be returned.
36673     *  the only mandatory property is state, which must be a value from
36674     *  other properties should match the properties of {@link FragmentRequest}. E.g.:
36675     *  getRequests({state: FragmentModel.FRAGMENT_MODEL_EXECUTED, quality: 0}) - returns
36676     *  all the requests from executedRequests array where requests.quality = filter.quality
36677     *
36678     * @returns {Array}
36679     * @memberof FragmentModel#
36680     */
36681    function getRequests(filter) {
36682
36683        var states = filter ? filter.state instanceof Array ? filter.state : [filter.state] 
36683: [];
36684
36685        var filteredRequests = [];
36686        states.forEach(function (state) {
36687            var requests = getRequestsForState(state);
36688            filteredRequests = filteredRequests.concat(filterRequests(requests, filter));
36689        });
36690
36691        return filteredRequests;
36692    }
36693
36694    function removeExecutedRequestsBeforeTime(time) {
36695        executedRequests = executedRequests.filter(function (req) {
36696            return isNaN(req.startTime) || req.startTime >= time;
36697        });
36698    }
36699
36700    function abortRequests() {
36701        fragmentLoader.abort();
36702        loadingRequests = [];
36703    }
36704
36705    function executeRequest(request) {
36706
36707        switch (request.action) {
36708            case _voFragmentRequest2['default'].ACTION_COMPLETE:
36709                executedRequests.push(request);
36710                addSchedulingInfoMetrics(request, FRAGMENT_MODEL_EXECUTED);
36711                eventBus.trigger(_coreEventsEvents2['default'].STREAM_COMPLETED, {
36712                    request: request,
36713                    fragmentModel: this
36714                });
36715                break;
36716            case _voFragmentRequest2['default'].ACTION_DOWNLOAD:
36717                addSchedulingInfoMetrics(request, FRAGMENT_MODEL_LOADING);
36718                loadingRequests.push(request);
36719                loadCurrentFragment(request);
36720                break;
36721            default:
36722                log('Unknown request action.');
36723        }
36724    }
36725
36726    function loadCurrentFragment(request) {
36727        eventBus.trigger(_coreEventsEvents2['default'].FRAGMENT_LOADING_STARTED, {
36728            sender: instance,
36729            request: request
36730        });
36731        fragmentLoader.load(request);
36732    }
36733
36734    function getRequestForTime(arr, time, threshold) {
36735        // loop through the executed requests and pick the one for which the playback interval matches the given time
36736        var lastIdx = arr.length - 1;
36737        for (var i = lastIdx; i >= 0; i--) {
36738            var req = arr[i];
36739            var start = req.startTime;
36740            var end = start + req.duration;
36741            threshold = threshold !== undefined ? threshold : req.duration / 2;
36742            if (!isNaN(start) && !isNaN(end) && time + threshold >= start && time - threshold < end || isNaN(start) && isNaN(time)) {
36743                return req;
36744            }
36745        }
36746        return null;
36747    }
36748
36749    function filterRequests(arr, filter) {
36750        // for time use a specific filtration function
36751        if (filter.hasOwnProperty('time')) {
36752            return [getRequestForTime(arr, filter.time, filter.threshold)];
36753        }
36754
36755        return arr.filter(function (request) {
36756            for (var prop in filter) {
36757                if (prop === 'state') continue;
36758                if (filter.hasOwnProperty(prop) && request[prop] != filter[prop]) return false;
36759            }
36760
36761            return true;
36762        });
36763    }
36764
36765    function getRequestsForState(state) {
36766
36767        var requests = undefined;
36768        switch (state) {
36769            case FRAGMENT_MODEL_LOADING:
36770                requests = loadingRequests;
36771                break;
36772            case FRAGMENT_MODEL_EXECUTED:
36773                requests = executedRequests;
36774                break;
36775            default:
36776                requests = [];
36777        }
36778        return requests;
36779    }
36780
36781    function addSchedulingInfoMetrics(request, state) {
36782
36783        metricsModel.addSchedulingInfo(request.mediaType, new Date(), request.type, request.startTime, request.availabilityStartTime, request.duration, request.quality, request.range, state);
36784
36785        metricsModel.addRequestsQueue(request.mediaType, loadingRequests, executedRequests);
36786    }
36787
36788    function onLoadingCompleted(e) {
36789        if (e.sender !== fragmentLoader) return;
36790
36791        loadingRequests.splice(loadingRequests.indexOf(e.request), 1);
36792
36793        if (e.response && !e.error) {
36794            executedRequests.push(e.request);
36795        }
36796
36797        addSchedulingInfoMetrics(e.request, e.error ? FRAGMENT_MODEL_FAILED : FRAGMENT_MODEL_EXECUTED);
36798
36799        eventBus.trigger(_coreEventsEvents2['default'].FRAGMENT_LOADING_COMPLETED, {
36800            request: e.request,
36801            response: e.response,
36802            error: e.error,
36803            sender: this
36804        });
36805    }
36806
36807    function onLoadingAborted(e) {
36808        if (e.sender !== fragmentLoader) return;
36809
36810        eventBus.trigger(_coreEventsEvents2['default'].FRAGMENT_LOADING_ABANDONED, { streamProcessor: this.get
36810StreamProcessor(), request: e.request, mediaType: e.mediaType });
36811    }
36812
36813    function resetInitialSettings() {
36814        executedRequests = [];
36815        loadingRequests = [];
36816    }
36817
36818    function reset() {
36819        eventBus.off(_coreEventsEvents2['default'].LOADING_COMPLETED, onLoadingCompleted, this);
36820        eventBus.off(_coreEventsEvents2['default'].LOADING_ABANDONED, onLoadingAborted, this);
36821
36822        if (fragmentLoader) {
36823            fragmentLoader.reset();
36824        }
36825        resetInitialSettings();
36826    }
36827
36828    instance = {
36829        setStreamProcessor: setStreamProcessor,
36830        getStreamProcessor: getStreamProcessor,
36831        getRequests: getRequests,
36832        isFragmentLoaded: isFragmentLoaded,
36833        isFragmentLoadedOrPending: isFragmentLoadedOrPending,
36834        removeExecutedRequestsBeforeTime: removeExecutedRequestsBeforeTime,
36835        abortRequests: abortRequests,
36836        executeRequest: executeRequest,
36837        reset: reset
36838    };
36839
36840    setup();
36841    return instance;
36842}
36843
36844FragmentModel.__dashjs_factory_name = 'FragmentModel';
36845var factory = _coreFactoryMaker2['default'].getClassFactory(FragmentModel);
36846factory.FRAGMENT_MODEL_LOADING = FRAGMENT_MODEL_LOADING;
36847factory.FRAGMENT_MODEL_EXECUTED = FRAGMENT_MODEL_EXECUTED;
36848factory.FRAGMENT_MODEL_CANCELED = FRAGMENT_MODEL_CANCELED;
36849factory.FRAGMENT_MODEL_FAILED = FRAGMENT_MODEL_FAILED;
36850_coreFactoryMaker2['default'].updateClassFactory(FragmentModel.__dashjs_factory_name, factory);
36851exports['default'] = factory;
36852module.exports = exports['default'];
36853
36854},{"209":209,"49":49,"50":50,"51":51,"54":54}],141:[function(_dereq_,module,exports){
36855/**
36856 * The copyright in this software is being made available under the BSD License,
36857 * included below. This software may be subject to other third party and contributor
36858 * rights, including patent rights, and no such rights are granted under this license.
36859 *
36860 * Copyright (c) 2013, Dash Industry Forum.
36861 * All rights reserved.
36862 *
36863 * Redistribution and use in source and binary forms, with or without modification,
36864 * are permitted provided that the following conditions are met:
36865 *  * Redistributions of source code must retain the above copyright notice, this
36866 *  list of conditions and the following disclaimer.
36867 *  * Redistributions in binary form must reproduce the above copyright notice,
36868 *  this list of conditions and the following disclaimer in the documentation and/or
36869 *  other materials provided with the distribution.
36870 *  * Neither the name of Dash Industry Forum nor the names of its
36871 *  contributors may be used to endorse or promote products derived from this software
36872 *  without specific prior written permission.
36873 *
36874 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
36875 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
36876 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
36877 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
36878 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36879 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
36880 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
36881 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36882 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36883 *  POSSIBILITY OF SUCH DAMAGE.
36884 */
36885'use strict';
36886
36887Object.defineProperty(exports, '__esModule', {
36888    value: true
36889});
36890
36891function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
36892
36893var _coreEventBus = _dereq_(50);
36894
36895var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
36896
36897var _coreEventsEvents = _dereq_(54);
36898
36899var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
36900
36901var _coreFactoryMaker = _dereq_(51);
36902
36903var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
36904
36905function ManifestModel() {
36906
36907    var context = this.context;
36908    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
36909
36910    var instance = undefined,
36911        manifest = undefined;
36912
36913    function getValue() {
36914        return manifest;
36915    }
36916
36917    function setValue(value) {
36918        manifest = value;
36919        if (value) {
36920            eventBus.trigger(_coreEventsEvents2['default'].MANIFEST_LOADED, { data: value });
36921        }
36922    }
36923
36924    instance = {
36925        getValue: getValue,
36926        setValue: setValue
36927    };
36928
36929    return instance;
36930}
36931
36932ManifestModel.__dashjs_factory_name = 'ManifestModel';
36933exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(ManifestModel);
36934module.exports = exports['default'];
36935
36936},{"50":50,"51":51,"54":54}],142:[function(_dereq_,module,exports){
36937/**
36938 * The copyright in this software is being made available under the BSD License,
36939 * included below. This software may be subject to other third party and contributor
36940 * rights, including patent rights, and no such rights are granted under this license.
36941 *
36942 * Copyright (c) 2013, Dash Industry Forum.
36943 * All rights reserved.
36944 *
36945 * Redistribution and use in source and binary forms, with or without modification,
36946 * are permitted provided that the following conditions are met:
36947 *  * Redistributions of source code must retain the above copyright notice, this
36948 *  list of conditions and the following disclaimer.
36949 *  * Redistributions in binary form must reproduce the above copyright notice,
36950 *  this list of conditions and the following disclaimer in the documentation and/or
36951 *  other materials provided with the distribution.
36952 *  * Neither the name of Dash Industry Forum nor the names of its
36953 *  contributors may be used to endorse or promote products derived from this software
36954 *  without specific prior written permission.
36955 *
36956 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
36957 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
36958 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
36959 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
36960 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36961 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
36962 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
36963 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36964 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36965 *  POSSIBILITY OF SUCH DAMAGE.
36966 */
36967'use strict';
36968
36969Object.defineProperty(exports, '__esModule', {
36970    value: true
36971});
36972
36973function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
36974
36975function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
36976
36977var _coreFactoryMaker = _dereq_(51);
36978
36979var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
36980
36981var _voMetricsHTTPRequest = _dereq_(224);
36982
36983var _constantsConstants = _dereq_(100);
36984
36985var _constantsConstants2 = _interopRequireDefault(_constantsConstants);
36986
36987var DEFAULT_UTC_TIMING_SOURCE = {
36988    scheme: 'urn:mpeg:dash:utc:http-xsdate:2014',
36989    value: 'http://time.akamai.com/?iso'
36990};
36991var LIVE_DELAY_FRAGMENT_COUNT = 4;
36992
36993var DEFAULT_LOCAL_STORAGE_BITRATE_EXPIRATION = 360000;
36994var DEFAULT_LOCAL_STORAGE_MEDIA_SETTINGS_EXPIRATION = 360000;
36995
36996var BANDWIDTH_SAFETY_FACTOR = 0.9;
36997var ABANDON_LOAD_TIMEOUT = 10000;
36998
36999var BUFFER_TO_KEEP = 30;
37000var BUFFER_PRUNING_INTERVAL = 30;
37001var DEFAULT_MIN_BUFFER_TIME = 12;
37002var DEFAULT_MIN_BUFFER_TIME_FAST_SWITCH = 20;
37003var BUFFER_TIME_AT_TOP_QUALITY = 30;
37004var BUFFER_TIME_AT_TOP_QUALITY_LONG_FORM = 60;
37005var LONG_FORM_CONTENT_DURATION_THRESHOLD = 600;
37006
37007var FRAGMENT_RETRY_ATTEMPTS = 3;
37008var FRAGMENT_RETRY_INTERVAL = 1000;
37009
37010var MANIFEST_RETRY_ATTEMPTS = 3;
37011var MANIFEST_RETRY_INTERVAL = 500;
37012
37013var XLINK_RETRY_ATTEMPTS = 1;
37014var XLINK_RETRY_INTERVAL = 500;
37015
37016//This value influences the startup time for live (in ms).
37017var WALLCLOCK_TIME_UPDATE_INTERVAL = 50;
37018
37019var DEFAULT_XHR_WITH_CREDENTIALS = false;
37020
37021function MediaPlayerModel() {
37022
37023    var instance = undefined,
37024        useManifestDateHeaderTimeSource = undefined,
37025        useSuggestedPresentationDelay = undefined,
37026        UTCTimingSources = undefined,
37027        liveDelayFragmentCount = undefined,
37028        liveDelay = undefined,
37029        scheduleWhilePaused = undefined,
37030        bufferToKeep = undefined,
37031        bufferPruningInterval = undefined,
37032        lastBitrateCachingInfo = undefined,
37033        lastMediaSettingsCachingInfo = undefined,
37034        stableBufferTime = undefined,
37035        bufferTimeAtTopQuality = undefined,
37036        bufferTimeAtTopQualityLongForm = undefined,
37037        longFormContentDurationThreshold = undefined,
37038        bandwidthSafetyFactor = undefined,
37039        abandonLoadTimeout = undefined,
37040        retryAttempts = undefined,
37041        retryIntervals = undefined,
37042        wallclockTimeUpdateInterval = undefined,
37043        ABRStrategy = undefined,
37044        useDefaultABRRules = undefined,
37045        xhrWithCredentials = undefined,
37046        fastSwitchEnabled = undefined,
37047        customABRRule = undefined,
37048        movingAverageMethod = undefined;
37049
37050    function setup() {
37051        var _retryAttempts, _retryIntervals;
37052
37053        UTCTimingSources = [];
37054        useSuggestedPresentationDelay = false;
37055        useManifestDateHeaderTimeSource = true;
37056        scheduleWhilePaused = true;
37057        ABRStrategy = _constantsConstants2['default'].ABR_STRATEGY_DYNAMIC;
37058        useDefaultABRRules = true;
37059        fastSwitchEnabled = false;
37060        lastBitrateCachingInfo = {
37061            enabled: true,
37062            ttl: DEFAULT_LOCAL_STORAGE_BITRATE_EXPIRATION
37063        };
37064        lastMediaSettingsCachingInfo = {
37065            enabled: true,
37066            ttl: DEFAULT_LOCAL_STORAGE_MEDIA_SETTINGS_EXPIRATION
37067        };
37068        liveDelayFragmentCount = LIVE_DELAY_FRAGMENT_COUNT;
37069        liveDelay = undefined; // Explicitly state that default is undefined
37070        bufferToKeep = BUFFER_TO_KEEP;
37071        bufferPruningInterval = BUFFER_PRUNING_INTERVAL;
37072        stableBufferTime = NaN;
37073        bufferTimeAtTopQuality = BUFFER_TIME_AT_TOP_QUALITY;
37074        bufferTimeAtTopQualityLongForm = BUFFER_TIME_AT_TOP_QUALITY_LONG_FORM;
37075        longFormContentDurationThreshold = LONG_FORM_CONTENT_DURATION_THRESHOLD;
37076        bandwidthSafetyFactor = BANDWIDTH_SAFETY_FACTOR;
37077        abandonLoadTimeout = ABANDON_LOAD_TIMEOUT;
37078        wallclockTimeUpdateInterval = WALLCLOCK_TIME_UPDATE_INTERVAL;
37079        xhrWithCredentials = {
37080            'default': DEFAULT_XHR_WITH_CREDENTIALS
37081        };
37082        customABRRule = [];
37083        movingAverageMethod = _constantsConstants2['default'].MOVING_AVERAGE_SLIDING_WINDOW;
37084
37085        retryAttempts = (_retryAttempts = {}, _defineProperty(_retryAttempts, _voMetricsHTTPRequest.HTTPRequest.MPD_TYPE, MANIFEST_RETRY_ATTEMPTS), _defineProperty(_retryAttempts, _voMetricsHTTPRequest.HTTPRequest.XLINK_EXPANSION_TYPE, XLINK_RETRY_ATTEMPTS), _defineProperty(_retryAttempts, _voMetricsHTTPRequest.HTTPRequest.MEDIA_SEGMENT_TYPE, FRAGMENT_RETRY_ATTEMPTS), _defineProperty(_retryAttempts, _voMetricsHTTPRequest.HTTPRequest.INIT_SEGMENT_TYPE, FRAGMENT_RETRY_ATTEMPTS), _defineProperty(_retryAttempts, _voMetricsHTTPRequest.HTTPRequest.BITSTREAM_SWITCHING_SEGMENT_TYPE, FRAGMENT_RETRY_ATTEMPTS), _defineProperty(_retryAttempts, _voMetricsHTTPRequest.HTTPRequest.INDEX_SEGMENT_TYPE, FRAGMENT_RETRY_ATTEMPTS), _defineProperty(_retryAttempts, _voMetricsHTTPRequest.HTTPRequest.OTHER_TYPE, FRAGMENT_RETRY_ATTEMPTS), _retryAttempts);
37086
37087        retryIntervals = (_retryIntervals = {}, _defineProperty(_retryIntervals, _voMetricsHTTPRequest.HTTPRequest.MPD_TYPE, MANIFEST_RETRY_INTERVAL), _defineProperty(_retryIntervals, _voMetricsHTTPRequest.HTTPRequest.XLINK_EXPANSION_TYPE, XLINK_RETRY_INTERVAL), _defineProperty(_retryIntervals, _voMetricsHTTPRequest.HTTPRequest.MEDIA_SEGMENT_TYPE, FRAGMENT_RETRY_INTERVAL), _defineProperty(_retryIntervals, _voMetricsHTTPRequest.HTTPRequest.INIT_SEGMENT_TYPE, FRAGMENT_RETRY_INTERVAL), _defineProperty(_retryIntervals, _voMetricsHTTPRequest.HTTPRequest.BITSTREAM_SWITCHING_SEGMENT_TYPE, FRAGMENT_RETRY_INTERVAL), _defineProperty(_retryIntervals, _voMetricsHTTPRequest.HTTPRequest.INDEX_SEGMENT_TYPE, FRAGMENT_RETRY_INTERVAL), _defineProperty(_retryIntervals, _voMetricsHTTPRequest.HTTPRequest.OTHER_TYPE, FRAGMENT_RETRY_INTERVAL), _retryIntervals);
37088    }
37089
37090    //TODO Should we use Object.define to have setters/getters? makes more readable code on other side.
37091
37092    function setABRStrategy(value) {
37093        ABRStrategy = value;
37094    }
37095
37096    function getABRStrategy() {
37097        return ABRStrategy;
37098    }
37099
37100    function setUseDefaultABRRules(value) {
37101        useDefaultABRRules = value;
37102    }
37103
37104    function getUseDefaultABRRules() {
37105        return useDefaultABRRules;
37106    }
37107
37108    function findABRCustomRule(rulename) {
37109        var i = undefined;
37110        for (i = 0; i < customABRRule.length; i++) {
37111            if (customABRRule[i].rulename === rulename) {
37112                return i;
37113            }
37114        }
37115        return -1;
37116    }
37117
37118    function getABRCustomRules() {
37119        return customABRRule;
37120    }
37121
37122    function addABRCustomRule(type, rulename, rule) {
37123
37124        var index = findABRCustomRule(rulename);
37125        if (index === -1) {
37126            // add rule
37127            customABRRule.push({
37128                type: type,
37129                rulename: rulename,
37130                rule: rule
37131            });
37132        } else {
37133            // update rule
37134            customABRRule[index].type = type;
37135            customABRRule[index].rule = rule;
37136        }
37137    }
37138
37139    function removeABRCustomRule(rulename) {
37140        var index = findABRCustomRule(rulename);
37141        if (index !== -1) {
37142            // remove rule
37143            customABRRule.splice(index, 1);
37144        }
37145    }
37146
37147    function removeAllABRCustomRule() {
37148        customABRRule = [];
37149    }
37150
37151    function setBandwidthSafetyFactor(value) {
37152        bandwidthSafetyFactor = value;
37153    }
37154
37155    function getBandwidthSafetyFactor() {
37156        return bandwidthSafetyFactor;
37157    }
37158
37159    function setAbandonLoadTimeout(value) {
37160        abandonLoadTimeout = value;
37161    }
37162
37163    function getAbandonLoadTimeout() {
37164        return abandonLoadTimeout;
37165    }
37166
37167    function setStableBufferTime(value) {
37168        stableBufferTime = value;
37169    }
37170
37171    function getStableBufferTime() {
37172        return !isNaN(stableBufferTime) ? stableBufferTime : fastSwitchEnabled ? DEFAULT_MIN_BUFFER_TIME_FAST_SWITCH : DEFAULT_MIN_BUFFER_TIME;
37173    }
37174
37175    function setBufferTimeAtTopQuality(value) {
37176        bufferTimeAtTopQuality = value;
37177    }
37178
37179    function getBufferTimeAtTopQuality() {
37180        return bufferTimeAtTopQuality;
37181    }
37182
37183    function setBufferTimeAtTopQualityLongForm(value) {
37184        bufferTimeAtTopQualityLongForm = value;
37185    }
37186
37187    function getBufferTimeAtTopQualityLongForm() {
37188        return bufferTimeAtTopQualityLongForm;
37189    }
37190
37191    function setLongFormContentDurationThreshold(value) {
37192        longFormContentDurationThreshold = value;
37193    }
37194
37195    function getLongFormContentDurationThreshold() {
37196        return longFormContentDurationThreshold;
37197    }
37198
37199    function setBufferToKeep(value) {
37200        bufferToKeep = value;
37201    }
37202
37203    function getBufferToKeep() {
37204        return bufferToKeep;
37205    }
37206
37207    function setLastBitrateCachingInfo(enable, ttl) {
37208        lastBitrateCachingInfo.enabled = enable;
37209        if (ttl !== undefined && !isNaN(ttl) && typeof ttl === 'number') {
37210            lastBitrateCachingInfo.ttl = ttl;
37211        }
37212    }
37213
37214    function getLastBitrateCachingInfo() {
37215        return lastBitrateCachingInfo;
37216    }
37217
37218    function setLastMediaSettingsCachingInfo(enable, ttl) {
37219        lastMediaSettingsCachingInfo.enabled = enable;
37220        if (ttl !== undefined && !isNaN(ttl) && typeof ttl === 'number') {
37221            lastMediaSettingsCachingInfo.ttl = ttl;
37222        }
37223    }
37224
37225    function getLastMediaSettingsCachingInfo() {
37226        return lastMediaSettingsCachingInfo;
37227    }
37228
37229    function setBufferPruningInterval(value) {
37230        bufferPruningInterval = value;
37231    }
37232
37233    function getBufferPruningInterval() {
37234        return bufferPruningInterval;
37235    }
37236
37237    function setFragmentRetryAttempts(value) {
37238        retryAttempts[_voMetricsHTTPRequest.HTTPRequest.MEDIA_SEGMENT_TYPE] = value;
37239    }
37240
37241    function setManifestRetryAttempts(value) {
37242        retryAttempts[_voMetricsHTTPRequest.HTTPRequest.MPD_TYPE] = value;
37243    }
37244
37245    function setRetryAttemptsForType(type, value) {
37246        retryAttempts[type] = value;
37247    }
37248
37249    function getFragmentRetryAttempts() {
37250        return retryAttempts[_voMetricsHTTPRequest.HTTPRequest.MEDIA_SEGMENT_TYPE];
37251    }
37252
37253    function getManifestRetryAttempts() {
37254        return retryAttempts[_voMetricsHTTPRequest.HTTPRequest.MPD_TYPE];
37255    }
37256
37257    function getRetryAttemptsForType(type) {
37258        return retryAttempts[type];
37259    }
37260
37261    function setFragmentRetryInterval(value) {
37262        retryIntervals[_voMetricsHTTPRequest.HTTPRequest.MEDIA_SEGMENT_TYPE] = value;
37263    }
37264
37265    function setManifestRetryInterval(value) {
37266        retryIntervals[_voMetricsHTTPRequest.HTTPRequest.MPD_TYPE] = value;
37267    }
37268
37269    function setRetryIntervalForType(type, value) {
37270        retryIntervals[type] = value;
37271    }
37272
37273    function getFragmentRetryInterval() {
37274        return retryIntervals[_voMetricsHTTPRequest.HTTPRequest.MEDIA_SEGMENT_TYPE];
37275    }
37276
37277    function getManifestRetryInterval() {
37278        return retryIntervals[_voMetricsHTTPRequest.HTTPRequest.MPD_TYPE];
37279    }
37280
37281    function getRetryIntervalForType(type) {
37282        return retryIntervals[type];
37283    }
37284
37285    function setWallclockTimeUpdateInterval(value) {
37286        wallclockTimeUpdateInterval = value;
37287    }
37288
37289    function getWallclockTimeUpdateInterval() {
37290        return wallclockTimeUpdateInterval;
37291    }
37292
37293    function setScheduleWhilePaused(value) {
37294        scheduleWhilePaused = value;
37295    }
37296
37297    function getScheduleWhilePaused() {
37298        return scheduleWhilePaused;
37299    }
37300
37301    function setLiveDelayFragmentCount(value) {
37302        liveDelayFragmentCount = value;
37303    }
37304
37305    function setLiveDelay(value) {
37306        liveDelay = value;
37307    }
37308
37309    function getLiveDelayFragmentCount() {
37310        return liveDelayFragmentCount;
37311    }
37312
37313    function getLiveDelay() {
37314        return liveDelay;
37315    }
37316
37317    function setUseManifestDateHeaderTimeSource(value) {
37318        useManifestDateHeaderTimeSource = value;
37319    }
37320
37321    function getUseManifestDateHeaderTimeSource() {
37322        return useManifestDateHeaderTimeSource;
37323    }
37324
37325    function setUseSuggestedPresentationDelay(value) {
37326        useSuggestedPresentationDelay = value;
37327    }
37328
37329    function getUseSuggestedPresentationDelay() {
37330        return useSuggestedPresentationDelay;
37331    }
37332
37333    function setUTCTimingSources(value) {
37334        UTCTimingSources = value;
37335    }
37336
37337    function getUTCTimingSources() {
37338        return UTCTimingSources;
37339    }
37340
37341    function setXHRWithCredentialsForType(type, value) {
37342        if (!type) {
37343            Object.keys(xhrWithCredentials).forEach(function (key) {
37344                setXHRWithCredentialsForType(key, value);
37345            });
37346        } else {
37347            xhrWithCredentials[type] = !!value;
37348        }
37349    }
37350
37351    function getXHRWithCredentialsForType(type) {
37352        var useCreds = xhrWithCredentials[type];
37353
37354        if (useCreds === undefined) {
37355            return xhrWithCredentials['default'];
37356        }
37357
37358        return useCreds;
37359    }
37360
37361    function getFastSwitchEnabled() {
37362        return fastSwitchEnabled;
37363    }
37364
37365    function setFastSwitchEnabled(value) {
37366        fastSwitchEnabled = value;
37367    }
37368
37369    function setMovingAverageMethod(value) {
37370        movingAverageMethod = value;
37371    }
37372
37373    function getMovingAverageMethod() {
37374        return movingAverageMethod;
37375    }
37376
37377    function reset() {
37378        //TODO need to figure out what props to persist across sessions and which to reset if any.
37379        //setup();
37380    }
37381
37382    instance = {
37383        setABRStrategy: setABRStrategy,
37384        getABRStrategy: getABRStrategy,
37385        setUseDefaultABRRules: setUseDefaultABRRules,
37386        getUseDefaultABRRules: getUseDefaultABRRules,
37387        getABRCustomRules: getABRCustomRules,
37388        addABRCustomRule: addABRCustomRule,
37389        removeABRCustomRule: removeABRCustomRule,
37390        removeAllABRCustomRule: removeAllABRCustomRule,
37391        setBandwidthSafetyFactor: setBandwidthSafetyFactor,
37392        getBandwidthSafetyFactor: getBandwidthSafetyFactor,
37393        setAbandonLoadTimeout: setAbandonLoadTimeout,
37394        getAbandonLoadTimeout: getAbandonLoadTimeout,
37395        setLastBitrateCachingInfo: setLastBitrateCachingInfo,
37396        getLastBitrateCachingInfo: getLastBitrateCachingInfo,
37397        setLastMediaSettingsCachingInfo: setLastMediaSettingsCachingInfo,
37398        getLastMediaSettingsCachingInfo: getLastMediaSettingsCachingInfo,
37399        setStableBufferTime: setStableBufferTime,
37400        getStableBufferTime: getStableBufferTime,
37401        setBufferTimeAtTopQuality: setBufferTimeAtTopQuality,
37402        getBufferTimeAtTopQuality: getBufferTimeAtTopQuality,
37403        setBufferTimeAtTopQualityLongForm: setBufferTimeAtTopQualityLongForm,
37404        getBufferTimeAtTopQualityLongForm: getBufferTimeAtTopQualityLongForm,
37405        setLongFormContentDurationThreshold: setLongFormContentDurationThreshold,
37406        getLongFormContentDurationThreshold: getLongFormContentDurationThreshold,
37407        setBufferToKeep: setBufferToKeep,
37408        getBufferToKeep: getBufferToKeep,
37409        setBufferPruningInterval: setBufferPruningInterval,
37410        getBufferPruningInterval: getBufferPruningInterval,
37411        setFragmentRetryAttempts: setFragmentRetryAttempts,
37412        getFragmentRetryAttempts: getFragmentRetryAttempts,
37413        setManifestRetryAttempts: setManifestRetryAttempts,
37414        getManifestRetryAttempts: getManifestRetryAttempts,
37415        setRetryAttemptsForType: setRetryAttemptsForType,
37416        getRetryAttemptsForType: getRetryAttemptsForType,
37417        setFragmentRetryInterval: setFragmentRetryInterval,
37418        getFragmentRetryInterval: getFragmentRetryInterval,
37419        setManifestRetryInterval: setManifestRetryInterval,
37420        getManifestRetryInterval: getManifestRetryInterval,
37421        setRetryIntervalForType: setRetryIntervalForType,
37422        getRetryIntervalForType: getRetryIntervalForType,
37423        setWallclockTimeUpdateInterval: setWallclockTimeUpdateInterval,
37424        getWallclockTimeUpdateInterval: getWallclockTimeUpdateInterval,
37425        setScheduleWhilePaused: setScheduleWhilePaused,
37426        getScheduleWhilePaused: getScheduleWhilePaused,
37427        getUseSuggestedPresentationDelay: getUseSuggestedPresentationDelay,
37428        setUseSuggestedPresentationDelay: setUseSuggestedPresentationDelay,
37429        setLiveDelayFragmentCount: setLiveDelayFragmentCount,
37430        getLiveDelayFragmentCount: getLiveDelayFragmentCount,
37431        getLiveDelay: getLiveDelay,
37432        setLiveDelay: setLiveDelay,
37433        setUseManifestDateHeaderTimeSource: setUseManifestDateHeaderTimeSource,
37434        getUseManifestDateHeaderTimeSource: getUseManifestDateHeaderTimeSource,
37435        setUTCTimingSources: setUTCTimingSources,
37436        getUTCTimingSources: getUTCTimingSources,
37437        setXHRWithCredentialsForType: setXHRWithCredentialsForType,
37438        getXHRWithCredentialsForType: getXHRWithCredentialsForType,
37439        setFastSwitchEnabled: setFastSwitchEnabled,
37440        getFastSwitchEnabled: getFastSwitchEnabled,
37441        setMovingAverageMethod: setMovingAverageMethod,
37442        getMovingAverageMethod: getMovingAverageMethod,
37443        reset: reset
37444    };
37445
37446    setup();
37447
37448    return instance;
37449}
37450
37451//TODO see if you can move this and not export and just getter to get default value.
37452MediaPlayerModel.__dashjs_factory_name = 'MediaPlayerModel';
37453var factory = _coreFactoryMaker2['default'].getSingletonFactory(MediaPlayerModel);
37454factory.DEFAULT_UTC_TIMING_SOURCE = DEFAULT_UTC_TIMING_SOURCE;
37455_coreFactoryMaker2['default'].updateSingletonFactory(MediaPlayerModel.__dashjs_factory_name, factory);
37456exports['default'] = factory;
37457module.exports = exports['default'];
37458
37459},{"100":100,"224":224,"51":51}],143:[function(_dereq_,module,exports){
37460/**
37461 * The copyright in this software is being made available under the BSD License,
37462 * included below. This software may be subject to other third party and contributor
37463 * rights, including patent rights, and no such rights are granted under this license.
37464 *
37465 * Copyright (c) 2013, Dash Industry Forum.
37466 * All rights reserved.
37467 *
37468 * Redistribution and use in source and binary forms, with or without modification,
37469 * are permitted provided that the following conditions are met:
37470 *  * Redistributions of source code must retain the above copyright notice, this
37471 *  list of conditions and the following disclaimer.
37472 *  * Redistributions in binary form must reproduce the above copyright notice,
37473 *  this list of conditions and the following disclaimer in the documentation and/or
37474 *  other materials provided with the distribution.
37475 *  * Neither the name of Dash Industry Forum nor the names of its
37476 *  contributors may be used to endorse or promote products derived from this software
37477 *  without specific prior written permission.
37478 *
37479 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
37480 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
37481 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
37482 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
37483 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
37483INCLUDING, BUT
37484 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
37485 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
37486 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37487 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37488 *  POSSIBILITY OF SUCH DAMAGE.
37489 */
37490'use strict';
37491
37492Object.defineProperty(exports, '__esModule', {
37493    value: true
37494});
37495
37496function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
37497
37498var _constantsConstants = _dereq_(100);
37499
37500var _constantsConstants2 = _interopRequireDefault(_constantsConstants);
37501
37502var _constantsMetricsConstants = _dereq_(101);
37503
37504var _constantsMetricsConstants2 = _interopRequireDefault(_constantsMetricsConstants);
37505
37506var _voMetricsList = _dereq_(214);
37507
37508var _voMetricsList2 = _interopRequireDefault(_voMetricsList);
37509
37510var _voMetricsTCPConnection = _dereq_(230);
37511
37512var _voMetricsTCPConnection2 = _interopRequireDefault(_voMetricsTCPConnection);
37513
37514var _voMetricsHTTPRequest = _dereq_(224);
37515
37516var _voMetricsRepresentationSwitch = _dereq_(227);
37517
37518var _voMetricsRepresentationSwitch2 = _interopRequireDefault(_voMetricsRepresentationSwitch);
37519
37520var _voMetricsBufferLevel = _dereq_(220);
37521
37522var _voMetricsBufferLevel2 = _interopRequireDefault(_voMetricsBufferLevel);
37523
37524var _voMetricsBufferState = _dereq_(221);
37525
37526var _voMetricsBufferState2 = _interopRequireDefault(_voMetricsBufferState);
37527
37528var _voMetricsDVRInfo = _dereq_(222);
37529
37530var _voMetricsDVRInfo2 = _interopRequireDefault(_voMetricsDVRInfo);
37531
37532var _voMetricsDroppedFrames = _dereq_(223);
37533
37534var _voMetricsDroppedFrames2 = _interopRequireDefault(_voMetricsDroppedFrames);
37535
37536var _voMetricsManifestUpdate = _dereq_(225);
37537
37538var _voMetricsSchedulingInfo = _dereq_(229);
37539
37540var _voMetricsSchedulingInfo2 = _interopRequireDefault(_voMetricsSchedulingInfo);
37541
37542var _coreEventBus = _dereq_(50);
37543
37544var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
37545
37546var _voMetricsRequestsQueue = _dereq_(228);
37547
37548var _voMetricsRequestsQueue2 = _interopRequireDefault(_voMetricsRequestsQueue);
37549
37550var _coreEventsEvents = _dereq_(54);
37551
37552var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
37553
37554var _coreFactoryMaker = _dereq_(51);
37555
37556var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
37557
37558function MetricsModel() {
37559
37560    var MAXIMUM_LIST_DEPTH = 1000;
37561
37562    var context = this.context;
37563    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
37564
37565    var instance = undefined,
37566        adapter = undefined,
37567        streamMetrics = undefined;
37568
37569    function setup() {
37570        streamMetrics = {};
37571    }
37572
37573    function setConfig(config) {
37574        if (!config) return;
37575
37576        if (config.adapter) {
37577            adapter = config.adapter;
37578        }
37579    }
37580
37581    function metricsChanged() {
37582        eventBus.trigger(_coreEventsEvents2['default'].METRICS_CHANGED);
37583    }
37584
37585    function metricChanged(mediaType) {
37586        eventBus.trigger(_coreEventsEvents2['default'].METRIC_CHANGED, { mediaType: mediaType });
37587        metricsChanged();
37588    }
37589
37590    function metricUpdated(mediaType, metricType, vo) {
37591        eventBus.trigger(_coreEventsEvents2['default'].METRIC_UPDATED, { mediaType: mediaType, metric: metricType, value: vo });
37592        metricChanged(mediaType);
37593    }
37594
37595    function metricAdded(mediaType, metricType, vo) {
37596        eventBus.trigger(_coreEventsEvents2['default'].METRIC_ADDED, { mediaType: mediaType, metric: metricType, value: vo });
37597        metricChanged(mediaType);
37598    }
37599
37600    function clearCurrentMetricsForType(type) {
37601        delete streamMetrics[type];
37602        metricChanged(type);
37603    }
37604
37605    function clearAllCurrentMetrics() {
37606        streamMetrics = {};
37607        metricsChanged();
37608    }
37609
37610    function getReadOnlyMetricsFor(type) {
37611        if (streamMetrics.hasOwnProperty(type)) {
37612            return streamMetrics[type];
37613        }
37614
37615        return null;
37616    }
37617
37618    function getMetricsFor(type) {
37619        var metrics = undefined;
37620
37621        if (streamMetrics.hasOwnProperty(type)) {
37622            metrics = streamMetrics[type];
37623        } else {
37624            metrics = new _voMetricsList2['default']();
37625            streamMetrics[type] = metrics;
37626        }
37627
37628        return metrics;
37629    }
37630
37631    function pushMetrics(type, list, value) {
37632        var metrics = getMetricsFor(type);
37633        metrics[list].push(value);
37634        if (metrics[list].length > MAXIMUM_LIST_DEPTH) {
37635            metrics[list].shift();
37636        }
37637    }
37638
37639    function addTcpConnection(mediaType, tcpid, dest, topen, tclose, tconnect) {
37640        var vo = new _voMetricsTCPConnection2['default']();
37641
37642        vo.tcpid = tcpid;
37643        vo.dest = dest;
37644        vo.topen = topen;
37645        vo.tclose = tclose;
37646        vo.tconnect = tconnect;
37647
37648        pushAndNotify(mediaType, _constantsMetricsConstants2['default'].TCP_CONNECTION, vo);
37649
37650        return vo;
37651    }
37652
37653    function appendHttpTrace(httpRequest, s, d, b) {
37654        var vo = new _voMetricsHTTPRequest.HTTPRequestTrace();
37655
37656        vo.s = s;
37657        vo.d = d;
37658        vo.b = b;
37659
37660        httpRequest.trace.push(vo);
37661
37662        if (!httpRequest.interval) {
37663            httpRequest.interval = 0;
37664        }
37665
37666        httpRequest.interval += d;
37667
37668        return vo;
37669    }
37670
37671    function addHttpRequest(mediaType, tcpid, type, url, actualurl, serviceLocation, range, trequest, tresponse, tfinish, responsecode, mediaduration, responseHeaders, traces) {
37672        var vo = new _voMetricsHTTPRequest.HTTPRequest();
37673
37674        // ISO 23009-1 D.4.3 NOTE 2:
37675        // All entries for a given object will have the same URL and range
37676        // and so can easily be correlated. If there were redirects or
37677        // failures there will be one entry for each redirect/failure.
37678        // The redirect-to URL or alternative url (where multiple have been
37679        // provided in the MPD) will appear as the actualurl of the next
37680        // entry with the same url value.
37681        if (actualurl && actualurl !== url) {
37682
37683            // given the above, add an entry for the original request
37684            addHttpRequest(mediaType, null, type, url, null, null, range, trequest, null, // unknown
37685            null, // unknown
37686            null, // unknown, probably a 302
37687            mediaduration, null, null);
37688
37689            vo.actualurl = actualurl;
37690        }
37691
37692        vo.tcpid = tcpid;
37693        vo.type = type;
37694        vo.url = url;
37695        vo.range = range;
37696        vo.trequest = trequest;
37697        vo.tresponse = tresponse;
37698        vo.responsecode = responsecode;
37699
37700        vo._tfinish = tfinish;
37701        vo._stream = mediaType;
37702        vo._mediaduration = mediaduration;
37703        vo._responseHeaders = responseHeaders;
37704        vo._serviceLocation = serviceLocation;
37705
37706        if (traces) {
37707            traces.forEach(function (trace) {
37708                appendHttpTrace(vo, trace.s, trace.d, trace.b);
37709            });
37710        } else {
37711            // The interval and trace shall be absent for redirect and failure records.
37712            delete vo.interval;
37713            delete vo.trace;
37714        }
37715
37716        pushAndNotify(mediaType, _constantsMetricsConstants2['default'].HTTP_REQUEST, vo);
37717
37718        return vo;
37719    }
37720
37721    function addRepresentationSwitch(mediaType, t, mt, to, lto) {
37722        var vo = new _voMetricsRepresentationSwitch2['default']();
37723
37724        vo.t = t;
37725        vo.mt = mt;
37726        vo.to = to;
37727
37728        if (lto) {
37729            vo.lto = lto;
37730        } else {
37731            delete vo.lto;
37732        }
37733
37734        pushAndNotify(mediaType, _constantsMetricsConstants2['default'].TRACK_SWITCH, vo);
37735
37736        return vo;
37737    }
37738
37739    function pushAndNotify(mediaType, metricType, metricObject) {
37740        pushMetrics(mediaType, metricType, metricObject);
37741        metricAdded(mediaType, metricType, metricObject);
37742    }
37743
37744    function addBufferLevel(mediaType, t, level) {
37745        var vo = new _voMetricsBufferLevel2['default']();
37746        vo.t = t;
37747        vo.level = level;
37748
37749        pushAndNotify(mediaType, _constantsMetricsConstants2['default'].BUFFER_LEVEL, vo);
37750
37751        return vo;
37752    }
37753
37754    function addBufferState(mediaType, state, target) {
37755        var vo = new _voMetricsBufferState2['default']();
37756        vo.target = target;
37757        vo.state = state;
37758
37759        pushAndNotify(mediaType, _constantsMetricsConstants2['default'].BUFFER_STATE, vo);
37760
37761        return vo;
37762    }
37763
37764    function addDVRInfo(mediaType, currentTime, mpd, range) {
37765        var vo = new _voMetricsDVRInfo2['default']();
37766        vo.time = currentTime;
37767        vo.range = range;
37768        vo.manifestInfo = mpd;
37769
37770        pushAndNotify(mediaType, _constantsMetricsConstants2['default'].DVR_INFO, vo);
37771
37772        return vo;
37773    }
37774
37775    function addDroppedFrames(mediaType, quality) {
37776        var vo = new _voMetricsDroppedFrames2['default']();
37777        var list = getMetricsFor(mediaType).DroppedFrames;
37778
37779        vo.time = quality.creationTime;
37780        vo.droppedFrames = quality.droppedVideoFrames;
37781
37782        if (list.length > 0 && list[list.length - 1] == vo) {
37783            return list[list.length - 1];
37784        }
37785
37786        pushAndNotify(mediaType, _constantsMetricsConstants2['default'].DROPPED_FRAMES, vo);
37787
37788        return vo;
37789    }
37790
37791    function addSchedulingInfo(mediaType, t, type, startTime, availabilityStartTime, duration, quality, range, state) {
37792        var vo = new _voMetricsSchedulingInfo2['default']();
37793
37794        vo.mediaType = mediaType;
37795        vo.t = t;
37796
37797        vo.type = type;
37798        vo.startTime = startTime;
37799        vo.availabilityStartTime = availabilityStartTime;
37800        vo.duration = duration;
37801        vo.quality = quality;
37802        vo.range = range;
37803
37804        vo.state = state;
37805
37806        pushAndNotify(mediaType, _constantsMetricsConstants2['default'].SCHEDULING_INFO, vo);
37807
37808        return vo;
37809    }
37810
37811    function addRequestsQueue(mediaType, loadingRequests, executedRequests) {
37812        var vo = new _voMetricsRequestsQueue2['default']();
37813        vo.loadingRequests = loadingRequests;
37814        vo.executedRequests = executedRequests;
37815
37816        getMetricsFor(mediaType).RequestsQueue = vo;
37817        metricAdded(mediaType, _constantsMetricsConstants2['default'].REQUESTS_QUEUE, vo);
37818    }
37819
37820    function addManifestUpdate(mediaType, type, requestTime, fetchTime, availabilityStartTime, presentationStartTime, clientTimeOff
37820set, currentTime, buffered, latency) {
37821        var vo = new _voMetricsManifestUpdate.ManifestUpdate();
37822
37823        vo.mediaType = mediaType;
37824        vo.type = type;
37825        vo.requestTime = requestTime; // when this manifest update was requested
37826        vo.fetchTime = fetchTime; // when this manifest update was received
37827        vo.availabilityStartTime = availabilityStartTime;
37828        vo.presentationStartTime = presentationStartTime; // the seek point (liveEdge for dynamic, Stream[0].startTime for static)
37829        vo.clientTimeOffset = clientTimeOffset; // the calculated difference between the server and client wall clock time
37830        vo.currentTime = currentTime; // actual element.currentTime
37831        vo.buffered = buffered; // actual element.ranges
37832        vo.latency = latency; // (static is fixed value of zero. dynamic should be ((Now-@availabilityStartTime) - currentTime)
37833
37834        pushMetrics(_constantsConstants2['default'].STREAM, _constantsMetricsConstants2['default'].MANIFEST_UPDATE, vo);
37835        metricAdded(mediaType, _constantsMetricsConstants2['default'].MANIFEST_UPDATE, vo);
37836
37837        return vo;
37838    }
37839
37840    function updateManifestUpdateInfo(manifestUpdate, updatedFields) {
37841        if (manifestUpdate) {
37842            for (var field in updatedFields) {
37843                manifestUpdate[field] = updatedFields[field];
37844            }
37845
37846            metricUpdated(manifestUpdate.mediaType, _constantsMetricsConstants2['default'].MANIFEST_UPDATE, manifestUpdate);
37847        }
37848    }
37849
37850    function addManifestUpdateStreamInfo(manifestUpdate, id, index, start, duration) {
37851        if (manifestUpdate) {
37852            var vo = new _voMetricsManifestUpdate.ManifestUpdateStreamInfo();
37853
37854            vo.id = id;
37855            vo.index = index;
37856            vo.start = start;
37857            vo.duration = duration;
37858
37859            manifestUpdate.streamInfo.push(vo);
37860            metricUpdated(manifestUpdate.mediaType, _constantsMetricsConstants2['default'].MANIFEST_UPDATE_STREAM_INFO, manifestUpdate);
37861
37862            return vo;
37863        }
37864        return null;
37865    }
37866
37867    function addManifestUpdateRepresentationInfo(manifestUpdate, id, index, streamIndex, mediaType, presentationTimeOffset, startNumber, fragmentInfoType) {
37868        if (manifestUpdate) {
37869
37870            var vo = new _voMetricsManifestUpdate.ManifestUpdateRepresentationInfo();
37871            vo.id = id;
37872            vo.index = index;
37873            vo.streamIndex = streamIndex;
37874            vo.mediaType = mediaType;
37875            vo.startNumber = startNumber;
37876            vo.fragmentInfoType = fragmentInfoType;
37877            vo.presentationTimeOffset = presentationTimeOffset;
37878
37879            manifestUpdate.representationInfo.push(vo);
37880            metricUpdated(manifestUpdate.mediaType, _constantsMetricsConstants2['default'].MANIFEST_UPDATE_TRACK_INFO, manifestUpdate);
37881
37882            return vo;
37883        }
37884        return null;
37885    }
37886
37887    function addPlayList(vo) {
37888        var type = _constantsConstants2['default'].STREAM;
37889
37890        if (vo.trace && Array.isArray(vo.trace)) {
37891            vo.trace.forEach(function (trace) {
37892                if (trace.hasOwnProperty('subreplevel') && !trace.subreplevel) {
37893                    delete trace.subreplevel;
37894                }
37895            });
37896        } else {
37897            delete vo.trace;
37898        }
37899
37900        pushAndNotify(type, _constantsMetricsConstants2['default'].PLAY_LIST, vo);
37901
37902        return vo;
37903    }
37904
37905    function addDVBErrors(vo) {
37906        var type = _constantsConstants2['default'].STREAM;
37907
37908        pushAndNotify(type, _constantsMetricsConstants2['default'].DVB_ERRORS, vo);
37909
37910        return vo;
37911    }
37912
37913    instance = {
37914        clearCurrentMetricsForType: clearCurrentMetricsForType,
37915        clearAllCurrentMetrics: clearAllCurrentMetrics,
37916        getReadOnlyMetricsFor: getReadOnlyMetricsFor,
37917        getMetricsFor: getMetricsFor,
37918        addTcpConnection: addTcpConnection,
37919        addHttpRequest: addHttpRequest,
37920        addRepresentationSwitch: addRepresentationSwitch,
37921        addBufferLevel: addBufferLevel,
37922        addBufferState: addBufferState,
37923        addDVRInfo: addDVRInfo,
37924        addDroppedFrames: addDroppedFrames,
37925        addSchedulingInfo: addSchedulingInfo,
37926        addRequestsQueue: addRequestsQueue,
37927        addManifestUpdate: addManifestUpdate,
37928        updateManifestUpdateInfo: updateManifestUpdateInfo,
37929        addManifestUpdateStreamInfo: addManifestUpdateStreamInfo,
37930        addManifestUpdateRepresentationInfo: addManifestUpdateRepresentationInfo,
37931        addPlayList: addPlayList,
37932        addDVBErrors: addDVBErrors,
37933        setConfig: setConfig
37934    };
37935
37936    setup();
37937    return instance;
37938}
37939
37940MetricsModel.__dashjs_factory_name = 'MetricsModel';
37941exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(MetricsModel);
37942module.exports = exports['default'];
37943
37944},{"100":100,"101":101,"214":214,"220":220,"221":221,"222":222,"223":223,"224":224,"225":225,"227":227,"228":228,"229":229,"230":230,"50":50,"51":51,"54":54}],144:[function(_dereq_,module,exports){
37945/**
37946 * The copyright in this software is being made available under the BSD License,
37947 * included below. This software may be subject to other third party and contributor
37948 * rights, including patent rights, and no such rights are granted under this license.
37949 *
37950 * Copyright (c) 2013, Dash Industry Forum.
37951 * All rights reserved.
37952 *
37953 * Redistribution and use in source and binary forms, with or without modification,
37954 * are permitted provided that the following conditions are met:
37955 *  * Redistributions of source code must retain the above copyright notice, this
37956 *  list of conditions and the following disclaimer.
37957 *  * Redistributions in binary form must reproduce the above copyright notice,
37958 *  this list of conditions and the following disclaimer in the documentation and/or
37959 *  other materials provided with the distribution.
37960 *  * Neither the name of Dash Industry Forum nor the names of its
37961 *  contributors may be used to endorse or promote products derived from this software
37962 *  without specific prior written permission.
37963 *
37964 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
37965 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
37966 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
37967 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
37968 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
37968INCLUDING, BUT
37969 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
37970 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
37971 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37972 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37973 *  POSSIBILITY OF SUCH DAMAGE.
37974 */
37975
37976'use strict';
37977
37978Object.defineProperty(exports, '__esModule', {
37979    value: true
37980});
37981
37982function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
37983
37984var _voURIFragmentData = _dereq_(219);
37985
37986var _voURIFragmentData2 = _interopRequireDefault(_voURIFragmentData);
37987
37988var _coreFactoryMaker = _dereq_(51);
37989
37990var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
37991
37992function URIQueryAndFragmentModel() {
37993
37994    var instance = undefined,
37995        URIFragmentDataVO = undefined,
37996        URIQueryData = undefined,
37997        isHTTPS = undefined;
37998
37999    function initialize() {
38000        URIFragmentDataVO = new _voURIFragmentData2['default']();
38001        URIQueryData = [];
38002        isHTTPS = false;
38003    }
38004
38005    function getURIFragmentData() {
38006        return URIFragmentDataVO;
38007    }
38008
38009    function getURIQueryData() {
38010        return URIQueryData;
38011    }
38012
38013    function isManifestHTTPS() {
38014        return isHTTPS;
38015    }
38016
38017    function parseURI(uri) {
38018        if (!uri) return null;
38019
38020        var URIFragmentData = [];
38021        var mappedArr = undefined;
38022
38023        var testQuery = new RegExp(/[?]/);
38024        var testFragment = new RegExp(/[#]/);
38025        var testHTTPS = new RegExp(/^(https:)?\/\//i);
38026        var isQuery = testQuery.test(uri);
38027        var isFragment = testFragment.test(uri);
38028
38029        isHTTPS = testHTTPS.test(uri);
38030
38031        function reduceArray(previousValue, currentValue, index, array) {
38032            var arr = array[0].split(/[=]/);
38033            array.push({ key: arr[0], value: arr[1] });
38034            array.shift();
38035            return array;
38036        }
38037
38038        function mapArray(currentValue, index, array) {
38039            if (index > 0) {
38040                if (isQuery && URIQueryData.length === 0) {
38041                    URIQueryData = array[index].split(/[&]/);
38042                } else if (isFragment) {
38043                    URIFragmentData = array[index].split(/[&]/);
38044                }
38045            }
38046
38047            return array;
38048        }
38049
38050        mappedArr = uri.split(/[?#]/).map(mapArray);
38051
38052        if (URIQueryData.length > 0) {
38053            URIQueryData = URIQueryData.reduce(reduceArray, null);
38054        }
38055
38056        if (URIFragmentData.length > 0) {
38057            URIFragmentData = URIFragmentData.reduce(reduceArray, null);
38058            URIFragmentData.forEach(function (object) {
38059                URIFragmentDataVO[object.key] = object.value;
38060            });
38061        }
38062
38063        return uri;
38064    }
38065
38066    instance = {
38067        initialize: initialize,
38068        parseURI: parseURI,
38069        getURIFragmentData: getURIFragmentData,
38070        getURIQueryData: getURIQueryData,
38071        isManifestHTTPS: isManifestHTTPS
38072    };
38073
38074    return instance;
38075}
38076
38077URIQueryAndFragmentModel.__dashjs_factory_name = 'URIQueryAndFragmentModel';
38078exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(URIQueryAndFragmentModel);
38079module.exports = exports['default'];
38080
38081},{"219":219,"51":51}],145:[function(_dereq_,module,exports){
38082/**
38083 * The copyright in this software is being made available under the BSD License,
38084 * included below. This software may be subject to other third party and contributor
38085 * rights, including patent rights, and no such rights are granted under this license.
38086 *
38087 * Copyright (c) 2013, Dash Industry Forum.
38088 * All rights reserved.
38089 *
38090 * Redistribution and use in source and binary forms, with or without modification,
38091 * are permitted provided that the following conditions are met:
38092 *  * Redistributions of source code must retain the above copyright notice, this
38093 *  list of conditions and the following disclaimer.
38094 *  * Redistributions in binary form must reproduce the above copyright notice,
38095 *  this list of conditions and the following disclaimer in the documentation and/or
38096 *  other materials provided with the distribution.
38097 *  * Neither the name of Dash Industry Forum nor the names of its
38098 *  contributors may be used to endorse or promote products derived from this software
38099 *  without specific prior written permission.
38100 *
38101 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
38102 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
38103 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
38104 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
38105 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
38105INCLUDING, BUT
38106 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
38107 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
38108 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38109 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38110 *  POSSIBILITY OF SUCH DAMAGE.
38111 */
38112
38113'use strict';
38114
38115Object.defineProperty(exports, '__esModule', {
38116    value: true
38117});
38118
38119function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
38120
38121var _coreFactoryMaker = _dereq_(51);
38122
38123var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
38124
38125var _coreEventBus = _dereq_(50);
38126
38127var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
38128
38129var _coreEventsEvents = _dereq_(54);
38130
38131var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
38132
38133var _coreDebug = _dereq_(49);
38134
38135var _coreDebug2 = _interopRequireDefault(_coreDebug);
38136
38137function VideoModel() {
38138
38139    var instance = undefined,
38140        element = undefined,
38141        TTMLRenderingDiv = undefined,
38142        videoContainer = undefined,
38143        stalledStreams = undefined,
38144        previousPlaybackRate = undefined;
38145
38146    var context = this.context;
38147    var log = (0, _coreDebug2['default'])(context).getInstance().log;
38148    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
38149
38150    function initialize() {
38151        stalledStreams = [];
38152    }
38153
38154    function onPlaybackCanPlay() {
38155        element.playbackRate = previousPlaybackRate || 1;
38156        element.removeEventListener('canplay', onPlaybackCanPlay);
38157    }
38158
38159    function setPlaybackRate(value) {
38160        if (!element) return;
38161        if (element.readyState <= 2 && value > 0) {
38162            // If media element hasn't loaded enough data to play yet, wait until it has
38163            element.addEventListener('canplay', onPlaybackCanPlay);
38164        } else {
38165            element.playbackRate = value;
38166        }
38167    }
38168
38169    //TODO Move the DVR window calculations from MediaPlayer to Here.
38170    function setCurrentTime(currentTime) {
38171        //_currentTime = currentTime;
38172
38173        // We don't set the same currentTime because it can cause firing unexpected Pause event in IE11
38174        // providing playbackRate property equals to zero.
38175        if (element.currentTime == currentTime) return;
38176
38177        // TODO Despite the fact that MediaSource 'open' event has been fired IE11 cannot set videoElement.currentTime
38178        // immediately (it throws InvalidStateError). It seems that this is related to videoElement.readyState property
38179        // Initially it is 0, but soon after 'open' event it goes to 1 and setting currentTime is allowed. Chrome allows to
38180        // set currentTime even if readyState = 0.
38181        // setTimeout is used to workaround InvalidStateError in IE11
38182        try {
38183            element.currentTime = currentTime;
38184        } catch (e) {
38185            if (element.readyState === 0 && e.code === e.INVALID_STATE_ERR) {
38186                setTimeout(function () {
38187                    element.currentTime = currentTime;
38188                }, 400);
38189            }
38190        }
38191    }
38192
38193    function getElement() {
38194        return element;
38195    }
38196
38197    function setElement(value) {
38198        element = value;
38199        // Workaround to force Firefox to fire the canplay event.
38200        element.preload = 'auto';
38201    }
38202
38203    function setSource(source) {
38204        if (source) {
38205            element.src = source;
38206        } else {
38207            element.removeAttribute('src');
38208            element.load();
38209        }
38210    }
38211
38212    function getSource() {
38213        return element.src;
38214    }
38215
38216    function getVideoContainer() {
38217        return videoContainer;
38218    }
38219
38220    function setVideoContainer(value) {
38221        videoContainer = value;
38222    }
38223
38224    function getTTMLRenderingDiv() {
38225        return TTMLRenderingDiv;
38226    }
38227
38228    function setTTMLRenderingDiv(div) {
38229        TTMLRenderingDiv = div;
38230        // The styling will allow the captions to match the video window size and position.
38231        TTMLRenderingDiv.style.position = 'absolute';
38232        TTMLRenderingDiv.style.display = 'flex';
38233        TTMLRenderingDiv.style.overflow = 'hidden';
38234        TTMLRenderingDiv.style.pointerEvents = 'none';
38235        TTMLRenderingDiv.style.top = 0;
38236        TTMLRenderingDiv.style.left = 0;
38237    }
38238
38239    function setStallState(type, state) {
38240        stallStream(type, state);
38241    }
38242
38243    function isStalled() {
38244        return stalledStreams.length > 0;
38245    }
38246
38247    function addStalledStream(type) {
38248
38249        var event = undefined;
38250
38251        if (type === null || element.seeking || stalledStreams.indexOf(type) !== -1) {
38252            return;
38253        }
38254
38255        stalledStreams.push(type);
38256        if (stalledStreams.length === 1) {
38257            // Halt playback until nothing is stalled.
38258            event = document.createEvent('Event');
38259            event.initEvent('waiting', true, false);
38260            previousPlaybackRate = element.playbackRate;
38261            setPlaybackRate(0);
38262            element.dispatchEvent(event);
38263        }
38264    }
38265
38266    function removeStalledStream(type) {
38267        var index = stalledStreams.indexOf(type);
38268        var event = undefined;
38269
38270        if (type === null) {
38271            return;
38272        }
38273        if (index !== -1) {
38274            stalledStreams.splice(index, 1);
38275        }
38276        // If nothing is stalled resume playback.
38277        if (isStalled() === false && element.playbackRate === 0) {
38278            setPlaybackRate(previousPlaybackRate || 1);
38279            if (!element.paused) {
38280                event = document.createEvent('Event');
38281                event.initEvent('playing', true, false);
38282                element.dispatchEvent(event);
38283            }
38284        }
38285    }
38286
38287    function stallStream(type, isStalled) {
38288        if (isStalled) {
38289            addStalledStream(type);
38290        } else {
38291            removeStalledStream(type);
38292        }
38293    }
38294
38295    function getPlaybackQuality() {
38296        var hasWebKit = 'webkitDroppedFrameCount' in element && 'webkitDecodedFrameCount' in element;
38297        var hasQuality = ('getVideoPlaybackQuality' in element);
38298        var result = null;
38299
38300        if (hasQuality) {
38301            result = element.getVideoPlaybackQuality();
38302        } else if (hasWebKit) {
38303            result = {
38304                droppedVideoFrames: element.webkitDroppedFrameCount,
38305                totalVideoFrames: element.webkitDroppedFrameCount + element.webkitDecodedFrameCount,
38306                creationTime: new Date()
38307            };
38308        }
38309
38310        return result;
38311    }
38312
38313    function play() {
38314        if (element) {
38315            element.autoplay = true;
38316            var p = element.play();
38317            if (p && typeof Promise !== 'undefined' && p instanceof Promise) {
38318                p['catch'](function (e) {
38319                    if (e.name === 'NotAllowedError') {
38320                        eventBus.trigger(_coreEventsEvents2['default'].PLAYBACK_NOT_ALLOWED);
38321                    }
38322                    log('Caught pending play exception - continuing (' + e + ')');
38323                });
38324            }
38325        }
38326    }
38327
38328    function isPaused() {
38329        return element ? element.paused : null;
38330    }
38331
38332    function pause() {
38333        if (element) {
38334            element.pause();
38335            element.autoplay = false;
38336        }
38337    }
38338
38339    function isSeeking() {
38340        return element ? element.seeking : null;
38341    }
38342
38343    function getTime() {
38344        return element ? element.currentTime : null;
38345    }
38346
38347    function getPlaybackRate() {
38348        return element ? element.playbackRate : null;
38349    }
38350
38351    function getPlayedRanges() {
38352        return element ? element.played : null;
38353    }
38354
38355    function getEnded() {
38356        return element ? element.ended : null;
38357    }
38358
38359    function addEventListener(eventName, eventCallBack) {
38360        if (element) {
38361            element.addEventListener(eventName, eventCallBack);
38362        }
38363    }
38364
38365    function removeEventListener(eventName, eventCallBack) {
38366        if (element) {
38367            element.removeEventListener(eventName, eventCallBack);
38368        }
38369    }
38370
38371    function getReadyState() {
38372        return element ? element.readyState : NaN;
38373    }
38374
38375    function getBufferRange() {
38376        return element ? element.buffered : null;
38377    }
38378
38379    function getClientWidth() {
38380        return element ? element.clientWidth : NaN;
38381    }
38382
38383    function getClientHeight() {
38384        return element ? element.clientHeight : NaN;
38385    }
38386
38387    function getVideoWidth() {
38388        return element ? element.videoWidth : NaN;
38389    }
38390
38391    function getVideoHeight() {
38392        return element ? element.videoHeight : NaN;
38393    }
38394
38395    function getTextTracks() {
38396        return element ? element.textTracks : [];
38397    }
38398
38399    function getTextTrack(kind, label, lang) {
38400        if (element) {
38401            for (var i = 0; i < element.textTracks.length; i++) {
38402                //label parameter could be a number (due to adaptationSet), but label, the attribute of textTrack, is a string => to modify...
38403                //label could also be undefined (due to adaptationSet)
38404                if (element.textTracks[i].kind === kind && (label ? element.textTracks[i].label == label : true) && element.textTracks[i].language === lang) {
38405                    return element.textTracks[i];
38406                }
38407            }
38408        }
38409
38410        return null;
38411    }
38412
38413    function addTextTrack(kind, label, lang) {
38414        if (element) {
38415            return element.addTextTrack(kind, label, lang);
38416        }
38417        return null;
38418    }
38419
38420    function appendChild(childElement) {
38421        if (element) {
38422            element.appendChild(childElement);
38423        }
38424    }
38425
38426    function removeChild(childElement) {
38427        if (element) {
38428            element.removeChild(childElement);
38429        }
38430    }
38431
38432    instance = {
38433        initialize: initialize,
38434        setCurrentTime: setCurrentTime,
38435        play: play,
38436        isPaused: isPaused,
38437        pause: pause,
38438        isSeeking: isSeeking,
38439        getTime: getTime,
38440        getPlaybackRate: getPlaybackRate,
38441        getPlayedRanges: getPlayedRanges,
38442        getEnded: getEnded,
38443        setStallState: setStallState,
38444        getElement: getElement,
38445        setElement: setElement,
38446        setSource: setSource,
38447        getSource: getSource,
38448        getVideoContainer: getVideoContainer,
38449        setVideoContainer: setVideoContainer,
38450        getTTMLRenderingDiv: getTTMLRenderingDiv,
38451        setTTMLRenderingDiv: setTTMLRenderingDiv,
38452        getPlaybackQuality: getPlaybackQuality,
38453        addEventListener: addEventListener,
38454        removeEventListener: removeEventListener,
38455        getReadyState: getReadyState,
38456        getBufferRange: getBufferRange,
38457        getClientWidth: getClientWidth,
38458        getClientHeight: getClientHeight,
38459        getTextTracks: getTextTracks,
38460        getTextTrack: getTextTrack,
38461        addTextTrack: addTextTrack,
38462        appendChild: appendChild,
38463        removeChild: removeChild,
38464        getVideoWidth: getVideoWidth,
38465        getVideoHeight: getVideoHeight
38466    };
38467
38468    return instance;
38469}
38470
38471VideoModel.__dashjs_factory_name = 'VideoModel';
38472exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(VideoModel);
38473module.exports = exports['default'];
38474
38475},{"49":49,"50":50,"51":51,"54":54}],146:[function(_dereq_,module,exports){
38476/**
38477 * The copyright in this software is being made available under the BSD License,
38478 * included below. This software may be subject to other third party and contributor
38479 * rights, including patent rights, and no such rights are granted under this license.
38480 *
38481 * Copyright (c) 2013, Dash Industry Forum.
38482 * All rights reserved.
38483 *
38484 * Redistribution and use in source and binary forms, with or without modification,
38485 * are permitted provided that the following conditions are met:
38486 *  * Redistributions of source code must retain the above copyright notice, this
38487 *  list of conditions and the following disclaimer.
38488 *  * Redistributions in binary form must reproduce the above copyright notice,
38489 *  this list of conditions and the following disclaimer in the documentation and/or
38490 *  other materials provided with the distribution.
38491 *  * Neither the name of Dash Industry Forum nor the names of its
38492 *  contributors may be used to endorse or promote products derived from this software
38493 *  without specific prior written permission.
38494 *
38495 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
38496 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
38497 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
38498 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
38499 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
38499INCLUDING, BUT
38500 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
38501 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
38502 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38503 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38504 *  POSSIBILITY OF SUCH DAMAGE.
38505 */
38506
38507'use strict';
38508
38509Object.defineProperty(exports, '__esModule', {
38510    value: true
38511});
38512
38513var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
38514
38515function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
38516
38517var CommonEncryption = (function () {
38518    function CommonEncryption() {
38519        _classCallCheck(this, CommonEncryption);
38520    }
38521
38522    _createClass(CommonEncryption, null, [{
38523        key: 'findCencContentProtection',
38524
38525        /**
38526         * Find and return the ContentProtection element in the given array
38527         * that indicates support for MPEG Common Encryption
38528         *
38529         * @param {Array} cpArray array of content protection elements
38530         * @returns {Object|null} the Common Encryption content protection element or
38531         * null if one was not found
38532         */
38533        value: function findCencContentProtection(cpArray) {
38534            var retVal = null;
38535            for (var i = 0; i < cpArray.length; ++i) {
38536                var cp = cpArray[i];
38537                if (cp.schemeIdUri.toLowerCase() === 'urn:mpeg:dash:mp4protection:2011' && cp.value.toLowerCase() === 'cenc') retVal = cp;
38538            }
38539            return retVal;
38540        }
38541
38542        /**
38543         * Returns just the data portion of a single PSSH
38544         *
38545         * @param {ArrayBuffer} pssh - the PSSH
38546         * @return {ArrayBuffer} data portion of the PSSH
38547         */
38548    }, {
38549        key: 'getPSSHData',
38550        value: function getPSSHData(pssh) {
38551            var offset = 8; // Box size and type fields
38552            var view = new DataView(pssh);
38553
38554            // Read version
38555            var version = view.getUint8(offset);
38556
38557            offset += 20; // Version (1), flags (3), system ID (16)
38558
38559            if (version > 0) {
38560                offset += 4 + 16 * view.getUint32(offset); // Key ID count (4) and All key IDs (16*count)
38561            }
38562
38563            offset += 4; // Data size
38564            return pssh.slice(offset);
38565        }
38566
38567        /**
38568         * Returns the PSSH associated with the given key system from the concatenated
38569         * list of PSSH boxes in the given initData
38570         *
38571         * @param {KeySystem} keySystem the desired
38572         * key system
38573         * @param {ArrayBuffer} initData 'cenc' initialization data.  Concatenated list of PSSH.
38574         * @returns {ArrayBuffer|null} The PSSH box data corresponding to the given key system, null if not found
38575         * or null if a valid association could not be found.
38576         */
38577    }, {
38578        key: 'getPSSHForKeySystem',
38579        value: function getPSSHForKeySystem(keySystem, initData) {
38580            var psshList = CommonEncryption.parsePSSHList(initData);
38581            if (psshList.hasOwnProperty(keySystem.uuid.toLowerCase())) {
38582                return psshList[keySystem.uuid.toLowerCase()];
38583            }
38584            return null;
38585        }
38586
38587        /**
38588         * Parse a standard common encryption PSSH which contains a simple
38589         * base64-encoding of the init data
38590         *
38591         * @param {Object} cpData the ContentProtection element
38592         * @param {BASE64} BASE64 reference
38593         * @returns {ArrayBuffer|null} the init data or null if not found
38594         */
38595    }, {
38596        key: 'parseInitDataFromContentProtection',
38597        value: function parseInitDataFromContentProtection(cpData, BASE64) {
38598            if ('pssh' in cpData) {
38599                return BASE64.decodeArray(cpData.pssh.__text).buffer;
38600            }
38601            return null;
38602        }
38603
38604        /**
38605         * Parses list of PSSH boxes into keysystem-specific PSSH data
38606         *
38607         * @param {ArrayBuffer} data - the concatenated list of PSSH boxes as provided by
38608         * CDM as initialization data when CommonEncryption content is detected
38609         * @returns {Object|Array} an object that has a property named according to each of
38610         * the detected key system UUIDs (e.g. 00000000-0000-0000-0000-0000000000)
38611         * and a ArrayBuffer (the entire PSSH box) as the property value
38612         */
38613    }, {
38614        key: 'parsePSSHList',
38615        value: function parsePSSHList(data) {
38616
38617            if (data === null) return [];
38618
38619            var dv = new DataView(data);
38620            var done = false;
38621            var pssh = {};
38622
38623            // TODO: Need to check every data read for end of buffer
38624            var byteCursor = 0;
38625            while (!done) {
38626
38627                var size = undefined,
38628                    nextBox = undefined,
38629                    version = undefined,
38630                    systemID = undefined,
38631                    psshDataSize = undefined;
38632                var boxStart = byteCursor;
38633
38634                if (byteCursor >= dv.buffer.byteLength) break;
38635
38636                /* Box size */
38637                size = dv.getUint32(byteCursor);
38638                nextBox = byteCursor + size;
38639                byteCursor += 4;
38640
38641                /* Verify PSSH */
38642                if (dv.getUint32(byteCursor) !== 0x70737368) {
38643                    byteCursor = nextBox;
38644                    continue;
38645                }
38646                byteCursor += 4;
38647
38648                /* Version must be 0 or 1 */
38649                version = dv.getUint8(byteCursor);
38650                if (version !== 0 && version !== 1) {
38651                    byteCursor = nextBox;
38652                    continue;
38653                }
38654                byteCursor++;
38655
38656                byteCursor += 3; /* skip flags */
38657
38658                // 16-byte UUID/SystemID
38659                systemID = '';
38660                var i = undefined,
38661                    val = undefined;
38662                for (i = 0; i < 4; i++) {
38663                    val = dv.getUint8(byteCursor + i).toString(16);
38664                    systemID += val.length === 1 ? '0' + val : val;
38665                }
38666                byteCursor += 4;
38667                systemID += '-';
38668                for (i = 0; i < 2; i++) {
38669                    val = dv.getUint8(byteCursor + i).toString(16);
38670                    systemID += val.length === 1 ? '0' + val : val;
38671                }
38672                byteCursor += 2;
38673                systemID += '-';
38674                for (i = 0; i < 2; i++) {
38675                    val = dv.getUint8(byteCursor + i).toString(16);
38676                    systemID += val.length === 1 ? '0' + val : val;
38677                }
38678                byteCursor += 2;
38679                systemID += '-';
38680                for (i = 0; i < 2; i++) {
38681                    val = dv.getUint8(byteCursor + i).toString(16);
38682                    systemID += val.length === 1 ? '0' + val : val;
38683                }
38684                byteCursor += 2;
38685                systemID += '-';
38686                for (i = 0; i < 6; i++) {
38687                    val = dv.getUint8(byteCursor + i).toString(16);
38688                    systemID += val.length === 1 ? '0' + val : val;
38689                }
38690                byteCursor += 6;
38691
38692                systemID = systemID.toLowerCase();
38693
38694                /* PSSH Data Size */
38695                psshDataSize = dv.getUint32(byteCursor);
38696                byteCursor += 4;
38697
38698                /* PSSH Data */
38699                pssh[systemID] = dv.buffer.slice(boxStart, nextBox);
38700                byteCursor = nextBox;
38701            }
38702
38703            return pssh;
38704        }
38705    }]);
38706
38707    return CommonEncryption;
38708})();
38709
38710exports['default'] = CommonEncryption;
38711module.exports = exports['default'];
38712
38713},{}],147:[function(_dereq_,module,exports){
38714/**
38715 * The copyright in this software is being made available under the BSD License,
38716 * included below. This software may be subject to other third party and contributor
38717 * rights, including patent rights, and no such rights are granted under this license.
38718 *
38719 * Copyright (c) 2013, Dash Industry Forum.
38720 * All rights reserved.
38721 *
38722 * Redistribution and use in source and binary forms, with or without modification,
38723 * are permitted provided that the following conditions are met:
38724 *  * Redistributions of source code must retain the above copyright notice, this
38725 *  list of conditions and the following disclaimer.
38726 *  * Redistributions in binary form must reproduce the above copyright notice,
38727 *  this list of conditions and the following disclaimer in the documentation and/or
38728 *  other materials provided with the distribution.
38729 *  * Neither the name of Dash Industry Forum nor the names of its
38730 *  contributors may be used to endorse or promote products derived from this software
38731 *  without specific prior written permission.
38732 *
38733 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
38734 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
38735 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
38736 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
38737 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
38737INCLUDING, BUT
38738 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
38739 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
38740 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38741 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38742 *  POSSIBILITY OF SUCH DAMAGE.
38743 */
38744'use strict';
38745
38746Object.defineProperty(exports, '__esModule', {
38747    value: true
38748});
38749
38750function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
38751
38752var _controllersProtectionController = _dereq_(149);
38753
38754var _controllersProtectionController2 = _interopRequireDefault(_controllersProtectionController);
38755
38756var _controllersProtectionKeyController = _dereq_(150);
38757
38758var _controllersProtectionKeyController2 = _interopRequireDefault(_controllersProtectionKeyController);
38759
38760var _ProtectionEvents = _dereq_(148);
38761
38762var _ProtectionEvents2 = _interopRequireDefault(_ProtectionEvents);
38763
38764var _modelsProtectionModel_21Jan2015 = _dereq_(155);
38765
38766var _modelsProtectionModel_21Jan20152 = _interopRequireDefault(_modelsProtectionModel_21Jan2015);
38767
38768var _modelsProtectionModel_3Feb2014 = _dereq_(156);
38769
38770var _modelsProtectionModel_3Feb20142 = _interopRequireDefault(_modelsProtectionModel_3Feb2014);
38771
38772var _modelsProtectionModel_01b = _dereq_(154);
38773
38774var _modelsProtectionModel_01b2 = _interopRequireDefault(_modelsProtectionModel_01b);
38775
38776var APIS_ProtectionModel_01b = [
38777// Un-prefixed as per spec
38778{
38779    // Video Element
38780    generateKeyRequest: 'generateKeyRequest',
38781    addKey: 'addKey',
38782    cancelKeyRequest: 'cancelKeyRequest',
38783
38784    // Events
38785    needkey: 'needkey',
38786    keyerror: 'keyerror',
38787    keyadded: 'keyadded',
38788    keymessage: 'keymessage'
38789},
38790// Webkit-prefixed (early Chrome versions and Chrome with EME disabled in chrome://flags)
38791{
38792    // Video Element
38793    generateKeyRequest: 'webkitGenerateKeyRequest',
38794    addKey: 'webkitAddKey',
38795    cancelKeyRequest: 'webkitCancelKeyRequest',
38796
38797    // Events
38798    needkey: 'webkitneedkey',
38799    keyerror: 'webkitkeyerror',
38800    keyadded: 'webkitkeyadded',
38801    keymessage: 'webkitkeymessage'
38802}];
38803
38804var APIS_ProtectionModel_3Feb2014 = [
38805// Un-prefixed as per spec
38806// Chrome 38-39 (and some earlier versions) with chrome://flags -- Enable Encrypted Media Extensions
38807{
38808    // Video Element
38809    setMediaKeys: 'setMediaKeys',
38810    // MediaKeys
38811    MediaKeys: 'MediaKeys',
38812    // MediaKeySession
38813    release: 'close',
38814
38815    // Events
38816    needkey: 'needkey',
38817    error: 'keyerror',
38818    message: 'keymessage',
38819    ready: 'keyadded',
38820    close: 'keyclose'
38821},
38822// MS-prefixed (IE11, Windows 8.1)
38823{
38824    // Video Element
38825    setMediaKeys: 'msSetMediaKeys',
38826    // MediaKeys
38827    MediaKeys: 'MSMediaKeys',
38828    // MediaKeySession
38829    release: 'close',
38830    // Events
38831    needkey: 'msneedkey',
38832    error: 'mskeyerror',
38833    message: 'mskeymessage',
38834    ready: 'mskeyadded',
38835    close: 'mskeyclose'
38836}];
38837
38838function Protection() {
38839
38840    var instance = undefined;
38841    var context = this.context;
38842
38843    /**
38844     * Create a ProtectionController and associated ProtectionModel for use with
38845     * a single piece of content.
38846     *
38847     * @param {Object} config
38848     * @return {ProtectionController} protection controller
38849     *
38850     */
38851    function createProtectionSystem(config) {
38852
38853        var controller = null;
38854
38855        var protectionKeyController = (0, _controllersProtectionKeyController2['default'])(context).getInstance();
38856        protectionKeyController.setConfig({ log: config.log, BASE64: config.BASE64 });
38857        protectionKeyController.initialize();
38858
38859        var protectionModel = getProtectionModel(config);
38860
38861        if (!controller && protectionModel) {
38862            //TODO add ability to set external controller if still needed at all?
38863            controller = (0, _controllersProtectionController2['default'])(context).create({
38864                protectionModel: protectionModel,
38865                protectionKeyController: protectionKeyController,
38866                adapter: config.adapter,
38867                eventBus: config.eventBus,
38868                log: config.log,
38869                events: config.events,
38870                BASE64: config.BASE64,
38871                Constants: config.Constants
38872            });
38873            config.capabilities.setEncryptedMediaSupported(true);
38874        }
38875        return controller;
38876    }
38877
38878    function getProtectionModel(config) {
38879
38880        var log = config.log;
38881        var eventBus = config.eventBus;
38882        var errHandler = config.errHandler;
38883        var videoElement = config.videoModel.getElement();
38884
38885        if (videoElement.onencrypted !== undefined && videoElement.mediaKeys !== undefined && navigator.requestMediaKeySystemAccess !== undefined && typeof navigator.requestMediaKeySystemAccess === 'function') {
38886
38887            log('EME detected on this user agent! (ProtectionModel_21Jan2015)');
38888            return (0, _modelsProtectionModel_21Jan20152['default'])(context).create({ log: log, eventBus: eventBus, events: config.events });
38889        } else if (getAPI(videoElement, APIS_ProtectionModel_3Feb2014)) {
38890
38891            log('EME detected on this user agent! (ProtectionModel_3Feb2014)');
38892            return (0, _modelsProtectionModel_3Feb20142['default'])(context).create({ log: log, eventBus: eventBus, events: config.events, api: getAPI(videoElement, APIS_ProtectionModel_3Feb2014) });
38893        } else if (getAPI(videoElement, APIS_ProtectionModel_01b)) {
38894
38895            log('EME detected on this user agent! (ProtectionModel_01b)');
38896            return (0, _modelsProtectionModel_01b2['default'])(context).create({ log: log, eventBus: eventBus, errHandler: errHandler, events: config.events, api: getAPI(videoElement, APIS_ProtectionModel_01b) });
38897        } else {
38898
38899            log('No supported version of EME detected on this user agent! - Attempts to play encrypted content will fail!');
38900            return null;
38901        }
38902    }
38903
38904    function getAPI(videoElement, apis) {
38905
38906        for (var i = 0; i < apis.length; i++) {
38907            var api = apis[i];
38908            // detect if api is supported by browser
38909            // check only first function in api -> should be fine
38910            if (typeof videoElement[api[Object.keys(api)[0]]] !== 'function') {
38911                continue;
38912            }
38913
38914            return api;
38915        }
38916
38917        return null;
38918    }
38919
38920    instance = {
38921        createProtectionSystem: createProtectionSystem
38922    };
38923
38924    return instance;
38925}
38926
38927Protection.__dashjs_factory_name = 'Protection';
38928var factory = dashjs.FactoryMaker.getClassFactory(Protection); /* jshint ignore:line */
38929factory.events = _ProtectionEvents2['default'];
38930dashjs.FactoryMaker.updateClassFactory(Protection.__dashjs_factory_name, factory); /* jshint ignore:line */
38931exports['default'] = factory;
38932module.exports = exports['default'];
38933
38934},{"148":148,"149":149,"150":150,"154":154,"155":155,"156":156}],148:[function(_dereq_,module,exports){
38935/**
38936 * The copyright in this software is being made available under the BSD License,
38937 * included below. This software may be subject to other third party and contributor
38938 * rights, including patent rights, and no such rights are granted under this license.
38939 *
38940 * Copyright (c) 2013, Dash Industry Forum.
38941 * All rights reserved.
38942 *
38943 * Redistribution and use in source and binary forms, with or without modification,
38944 * are permitted provided that the following conditions are met:
38945 *  * Redistributions of source code must retain the above copyright notice, this
38946 *  list of conditions and the following disclaimer.
38947 *  * Redistributions in binary form must reproduce the above copyright notice,
38948 *  this list of conditions and the following disclaimer in the documentation and/or
38949 *  other materials provided with the distribution.
38950 *  * Neither the name of Dash Industry Forum nor the names of its
38951 *  contributors may be used to endorse or promote products derived from this software
38952 *  without specific prior written permission.
38953 *
38954 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
38955 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
38956 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
38957 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
38958 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
38958INCLUDING, BUT
38959 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
38960 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
38961 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38962 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38963 *  POSSIBILITY OF SUCH DAMAGE.
38964 */
38965'use strict';
38966
38967Object.defineProperty(exports, '__esModule', {
38968  value: true
38969});
38970
38971var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
38972
38973function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
38974
38975function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
38976
38977function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
38978
38979var _coreEventsEventsBase = _dereq_(55);
38980
38981var _coreEventsEventsBase2 = _interopRequireDefault(_coreEventsEventsBase);
38982
38983/**
38984 * @class
38985 *
38986 */
38987
38988var ProtectionEvents = (function (_EventsBase) {
38989  _inherits(ProtectionEvents, _EventsBase);
38990
38991  /**
38992   * @description Public facing external events to be used when including protection package.
38993   * All public events will be aggregated into the MediaPlayerEvents Class and can be accessed
38994   * via MediaPlayer.events.  public_ is the prefix that we use to move event names to MediaPlayerEvents.
38995   */
38996
38997  function ProtectionEvents() {
38998    _classCallCheck(this, ProtectionEvents);
38999
39000    _get(Object.getPrototypeOf(ProtectionEvents.prototype), 'constructor', this).call(this);
39001
39002    /**
39003     * Event ID for events delivered when the protection set receives
39004     * a key message from the CDM
39005     *
39006     * @ignore
39007     */
39008    this.INTERNAL_KEY_MESSAGE = 'internalKeyMessage';
39009
39010    /**
39011     * Event ID for events delivered when a key system selection procedure
39012     * completes
39013     * @ignore
39014     */
39015    this.INTERNAL_KEY_SYSTEM_SELECTED = 'internalKeySystemSelected';
39016
39017    /**
39018     * Event ID for events delivered when a new key has been added
39019     *
39020     * @constant
39021     * @deprecated The latest versions of the EME specification no longer
39022     * use this event.  {@MediaPlayer.models.protectionModel.eventList.KEY_STATUSES_CHANGED}
39023     * is preferred.
39024     * @event ProtectionEvents#KEY_ADDED
39025     */
39026    this.KEY_ADDED = 'public_keyAdded';
39027    /**
39028     * Event ID for events delivered when an error is encountered by the CDM
39029     * while processing a license server response message
39030     * @event ProtectionEvents#KEY_ERROR
39031     */
39032    this.KEY_ERROR = 'public_keyError';
39033
39034    /**
39035     * Event ID for events delivered when the protection set receives
39036     * a key message from the CDM
39037     * @event ProtectionEvents#KEY_MESSAGE
39038     */
39039    this.KEY_MESSAGE = 'public_keyMessage';
39040
39041    /**
39042     * Event ID for events delivered when a key session close
39043     * process has completed
39044     * @event ProtectionEvents#KEY_SESSION_CLOSED
39045     */
39046    this.KEY_SESSION_CLOSED = 'public_keySessionClosed';
39047
39048    /**
39049     * Event ID for events delivered when a new key sessions creation
39050     * process has completed
39051     * @event ProtectionEvents#KEY_SESSION_CREATED
39052     */
39053    this.KEY_SESSION_CREATED = 'public_keySessionCreated';
39054
39055    /**
39056     * Event ID for events delivered when a key session removal
39057     * process has completed
39058     * @event ProtectionEvents#KEY_SESSION_REMOVED
39059     */
39060    this.KEY_SESSION_REMOVED = 'public_keySessionRemoved';
39061
39062    /**
39063     * Event ID for events delivered when the status of one or more
39064     * decryption keys has changed
39065     * @event ProtectionEvents#KEY_STATUSES_CHANGED
39066     */
39067    this.KEY_STATUSES_CHANGED = 'public_keyStatusesChanged';
39068
39069    /**
39070     * Event ID for events delivered when a key system access procedure
39071     * has completed
39072     * @ignore
39073     */
39074    this.KEY_SYSTEM_ACCESS_COMPLETE = 'keySystemAccessComplete';
39075
39076    /**
39077     * Event ID for events delivered when a key system selection procedure
39078     * completes
39079     * @event ProtectionEvents#KEY_SYSTEM_SELECTED
39080     */
39081    this.KEY_SYSTEM_SELECTED = 'public_keySystemSelected';
39082
39083    /**
39084     * Event ID for events delivered when a license request procedure
39085     * has completed
39086     * @event ProtectionEvents#LICENSE_REQUEST_COMPLETE
39087     */
39088    this.LICENSE_REQUEST_COMPLETE = 'public_licenseRequestComplete';
39089
39090    /**
39091     * Event ID for needkey/encrypted events
39092     * @ignore
39093     */
39094    this.NEED_KEY = 'needkey';
39095
39096    /**
39097     * Event ID for events delivered when the Protection system is detected and created.
39098     * @event ProtectionEvents#PROTECTION_CREATED
39099     */
39100    this.PROTECTION_CREATED = 'public_protectioncreated';
39101
39102    /**
39103     * Event ID for events delivered when the Protection system is destroyed.
39104     * @event ProtectionEvents#PROTECTION_DESTROYED
39105     */
39106    this.PROTECTION_DESTROYED = 'public_protectiondestroyed';
39107
39108    /**
39109     * Event ID for events delivered when a new server certificate has
39110     * been delivered to the CDM
39111     * @ignore
39112     */
39113    this.SERVER_CERTIFICATE_UPDATED = 'serverCertificateUpdated';
39114
39115    /**
39116     * Event ID for events delivered when the process of shutting down
39117     * a protection set has completed
39118     * @ignore
39119     */
39120    this.TEARDOWN_COMPLETE = 'protectionTeardownComplete';
39121
39122    /**
39123     * Event ID for events delivered when a HTMLMediaElement has been
39124     * associated with the protection set
39125     * @ignore
39126     */
39127    this.VIDEO_ELEMENT_SELECTED = 'videoElementSelected';
39128  }
39129
39130  return ProtectionEvents;
39131})(_coreEventsEventsBase2['default']);
39132
39133var protectionEvents = new ProtectionEvents();
39134exports['default'] = protectionEvents;
39135module.exports = exports['default'];
39136
39137},{"55":55}],149:[function(_dereq_,module,exports){
39138/**
39139 * The copyright in this software is being made available under the BSD License,
39140 * included below. This software may be subject to other third party and contributor
39141 * rights, including patent rights, and no such rights are granted under this license.
39142 *
39143 * Copyright (c) 2013, Dash Industry Forum.
39144 * All rights reserved.
39145 *
39146 * Redistribution and use in source and binary forms, with or without modification,
39147 * are permitted provided that the following conditions are met:
39148 *  * Redistributions of source code must retain the above copyright notice, this
39149 *  list of conditions and the following disclaimer.
39150 *  * Redistributions in binary form must reproduce the above copyright notice,
39151 *  this list of conditions and the following disclaimer in the documentation and/or
39152 *  other materials provided with the distribution.
39153 *  * Neither the name of Dash Industry Forum nor the names of its
39154 *  contributors may be used to endorse or promote products derived from this software
39155 *  without specific prior written permission.
39156 *
39157 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
39158 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
39159 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
39160 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
39161 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
39161INCLUDING, BUT
39162 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
39163 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
39164 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
39165 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39166 *  POSSIBILITY OF SUCH DAMAGE.
39167 */
39168
39169'use strict';
39170
39171Object.defineProperty(exports, '__esModule', {
39172    value: true
39173});
39174
39175function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
39176
39177var _CommonEncryption = _dereq_(146);
39178
39179var _CommonEncryption2 = _interopRequireDefault(_CommonEncryption);
39180
39181var _voMediaCapability = _dereq_(167);
39182
39183var _voMediaCapability2 = _interopRequireDefault(_voMediaCapability);
39184
39185var _voKeySystemConfiguration = _dereq_(166);
39186
39187var _voKeySystemConfiguration2 = _interopRequireDefault(_voKeySystemConfiguration);
39188
39189/**
39190 * @module ProtectionController
39191 * @description Provides access to media protection information and functionality.  Each
39192 * ProtectionController manages a single {@link MediaPlayer.models.ProtectionModel}
39193 * which encapsulates a set of protection information (EME APIs, selected key system,
39194 * key sessions).  The APIs of ProtectionController mostly align with the latest EME
39195 * APIs.  Key system selection is mostly automated when combined with app-overrideable
39196 * functionality provided in {@link ProtectionKeyController}.
39197 * @todo ProtectionController does almost all of its tasks automatically after init() is
39198 * called.  Applications might want more control over this process and want to go through
39199 * each step manually (key system selection, session creation, session maintenance).
39200 * @param {Object} config
39201 */
39202
39203function ProtectionController(config) {
39204
39205    var protectionKeyController = config.protectionKeyController;
39206    var protectionModel = config.protectionModel;
39207    var adapter = config.adapter;
39208    var eventBus = config.eventBus;
39209    var events = config.events;
39210    var log = config.log;
39211    var BASE64 = config.BASE64;
39212    var Constants = config.Constants;
39213
39214    var instance = undefined,
39215        pendingNeedKeyData = undefined,
39216        audioInfo = undefined,
39217        videoInfo = undefined,
39218        protDataSet = undefined,
39219        initialized = undefined,
39220        sessionType = undefined,
39221        robustnessLevel = undefined,
39222        keySystem = undefined;
39223
39224    function setup() {
39225        pendingNeedKeyData = [];
39226        initialized = false;
39227        sessionType = 'temporary';
39228        robustnessLevel = '';
39229    }
39230
39231    /**
39232     * Initialize this protection system with a given manifest and optional audio
39233     * and video stream information.
39234     *
39235     * @param {Object} manifest the json version of the manifest XML document for the
39236     * desired content.  Applications can download their manifest using
39237     * {@link module:MediaPlayer#retrieveManifest}
39238     * @param {StreamInfo} [aInfo] audio stream information
39239     * @param {StreamInfo} [vInfo] video stream information
39240     * @memberof module:ProtectionController
39241     * @instance
39242     * @todo This API will change when we have better support for allowing applications
39243     * to select different adaptation sets for playback.  Right now it is clunky for
39244     * applications to create {@link StreamInfo} with the right information,
39245     */
39246    function initialize(manifest, aInfo, vInfo) {
39247        // TODO: We really need to do much more here... We need to be smarter about knowing
39248        // which adaptation sets for which we have initialized, including the default key ID
39249        // value from the ContentProtection elements so we know whether or not we still need to
39250        // select key systems and acquire keys.
39251        if (!initialized) {
39252            var streamInfo = undefined;
39253
39254            if (!aInfo && !vInfo) {
39255                // Look for ContentProtection elements.  InitData can be provided by either the
39256                // dash264drm:Pssh ContentProtection format or a DRM-specific format.
39257                streamInfo = adapter.getStreamsInfo()[0]; // TODO: Single period only for now. See TODO above
39258            }
39259
39260            audioInfo = aInfo || (streamInfo ? adapter.getMediaInfoForType(streamInfo, Constants.AUDIO) : null);
39261            videoInfo = vInfo || (streamInfo ? adapter.getMediaInfoForType(streamInfo, Constants.VIDEO) : null);
39262            var mediaInfo = videoInfo ? videoInfo : audioInfo; // We could have audio or video only
39263
39264            // ContentProtection elements are specified at the AdaptationSet level, so the CP for audio
39265            // and video will be the same.  Just use one valid MediaInfo object
39266            var supportedKS = protectionKeyController.getSupportedKeySystemsFromContentProtection(mediaInfo.contentProtection);
39267            if (supportedKS && supportedKS.length > 0) {
39268                selectKeySystem(supportedKS, true);
39269            }
39270
39271            initialized = true;
39272        }
39273    }
39274
39275    /**
39276     * Returns a set of supported key systems and CENC initialization data
39277     * from the given array of ContentProtection elements.  Only
39278     * key systems that are supported by this player will be returned.
39279     * Key systems are returned in priority order (highest first).
39280     *
39281     * @param {Array.<Object>} cps - array of content protection elements parsed
39282     * from the manifest
39283     * @returns {Array.<Object>} array of objects indicating which supported key
39284     * systems were found.  Empty array is returned if no
39285     * supported key systems were found
39286     * @memberof module:ProtectionKeyController
39287     * @instance
39288     */
39289    function getSupportedKeySystemsFromContentProtection(cps) {
39290        return protectionKeyController.getSupportedKeySystemsFromContentProtection(cps);
39291    }
39292
39293    /**
39294     * Create a new key session associated with the given initialization data from
39295     * the MPD or from the PSSH box in the media
39296     *
39297     * @param {ArrayBuffer} initData the initialization data
39298     * @memberof module:ProtectionController
39299     * @instance
39300     * @fires ProtectionController#KeySessionCreated
39301     * @todo In older versions of the EME spec, there was a one-to-one relationship between
39302     * initialization data and key sessions.  That is no longer true in the latest APIs.  This
39303     * API will need to modified (and a new "generateRequest(keySession, initData)" API created)
39304     * to come up to speed with the latest EME standard
39305     */
39306    function createKeySession(initData) {
39307        var initDataForKS = _CommonEncryption2['default'].getPSSHForKeySystem(keySystem, initData);
39308        if (initDataForKS) {
39309
39310            // Check for duplicate initData
39311            var currentInitData = protectionModel.getAllInitData();
39312            for (var i = 0; i < currentInitData.length; i++) {
39313                if (protectionKeyController.initDataEquals(initDataForKS, currentInitData[i])) {
39314                    log('DRM: Ignoring initData because we have already seen it!');
39315                    return;
39316                }
39317            }
39318            try {
39319                protectionModel.createKeySession(initDataForKS, sessionType);
39320            } catch (error) {
39321                eventBus.trigger(events.KEY_SESSION_CREATED, { data: null, error: 'Error creating key session! ' + error.message });
39322            }
39323        } else {
39324            eventBus.trigger(events.KEY_SESSION_CREATED, { data: null, error: 'Selected key system is ' + keySystem.systemString + '.  needkey/encrypted event contains no initData corresponding to that key system!' });
39325        }
39326    }
39327
39328    /**
39329     * Loads a key session with the given session ID from persistent storage.  This
39330     * essentially creates a new key session
39331     *
39332     * @param {string} sessionID
39333     * @memberof module:ProtectionController
39334     * @instance
39335     * @fires ProtectionController#KeySessionCreated
39336     */
39337    function loadKeySession(sessionID) {
39338        protectionModel.loadKeySession(sessionID);
39339    }
39340
39341    /**
39342     * Removes the given key session from persistent storage and closes the session
39343     * as if {@link ProtectionController#closeKeySession}
39344     * was called
39345     *
39346     * @param {SessionToken} sessionToken the session
39347     * token
39348     * @memberof module:ProtectionController
39349     * @instance
39350     * @fires ProtectionController#KeySessionRemoved
39351     * @fires ProtectionController#KeySessionClosed
39352     */
39353    function removeKeySession(sessionToken) {
39354        protectionModel.removeKeySession(sessionToken);
39355    }
39356
39357    /**
39358     * Closes the key session and releases all associated decryption keys.  These
39359     * keys will no longer be available for decrypting media
39360     *
39361     * @param {SessionToken} sessionToken the session
39362     * token
39363     * @memberof module:ProtectionController
39364     * @instance
39365     * @fires ProtectionController#KeySessionClosed
39366     */
39367    function closeKeySession(sessionToken) {
39368        protectionModel.closeKeySession(sessionToken);
39369    }
39370
39371    /**
39372     * Sets a server certificate for use by the CDM when signing key messages
39373     * intended for a particular license server.  This will fire
39374     * an error event if a key system has not yet been selected.
39375     *
39376     * @param {ArrayBuffer} serverCertificate a CDM-specific license server
39377     * certificate
39378     * @memberof module:ProtectionController
39379     * @instance
39380     * @fires ProtectionController#ServerCertificateUpdated
39381     */
39382    function setServerCertificate(serverCertificate) {
39383        protectionModel.setServerCertificate(serverCertificate);
39384    }
39385
39386    /**
39387     * Associate this protection system with the given HTMLMediaElement.  This
39388     * causes the system to register for needkey/encrypted events from the given
39389     * element and provides a destination for setting of MediaKeys
39390     *
39391     * @param {HTMLMediaElement} element the media element to which the protection
39392     * system should be associated
39393     * @memberof module:ProtectionController
39394     * @instance
39395     */
39396    function setMediaElement(element) {
39397        if (element) {
39398            protectionModel.setMediaElement(element);
39399            eventBus.on(events.NEED_KEY, onNeedKey, this);
39400            eventBus.on(events.INTERNAL_KEY_MESSAGE, onKeyMessage, this);
39401        } else if (element === null) {
39402            protectionModel.setMediaElement(element);
39403            eventBus.off(events.NEED_KEY, onNeedKey, this);
39404            eventBus.off(events.INTERNAL_KEY_MESSAGE, onKeyMessage, this);
39405        }
39406    }
39407
39408    /**
39409     * Sets the session type to use when creating key sessions.  Either "temporary" or
39410     * "persistent-license".  Default is "temporary".
39411     *
39412     * @param {string} value the session type
39413     * @memberof module:ProtectionController
39414     * @instance
39415     */
39416    function setSessionType(value) {
39417        sessionType = value;
39418    }
39419
39420    /**
39421     * Sets the robustness level for video and audio capabilities. Optional to remove Chrome warnings.
39422     * Possible values are SW_SECURE_CRYPTO, SW_SECURE_DECODE, HW_SECURE_CRYPTO, HW_SECURE_CRYPTO, HW_SECURE_DECODE, HW_SECURE_ALL.
39423     *
39424     * @param {string} level the robustness level
39425     * @memberof module:ProtectionController
39426     * @instance
39427     */
39428    function setRobustnessLevel(level) {
39429        robustnessLevel = level;
39430    }
39431
39432    /**
39433     * Attach KeySystem-specific data to use for license acquisition with EME
39434     *
39435     * @param {Object}
39435 data an object containing property names corresponding to
39436     * key system name strings (e.g. "org.w3.clearkey") and associated values
39437     * being instances of {@link ProtectionData}
39438     * @memberof module:ProtectionController
39439     * @instance
39440     */
39441    function setProtectionData(data) {
39442        protDataSet = data;
39443        protectionKeyController.setProtectionData(data);
39444    }
39445
39446    /**
39447     * Destroys all protection data associated with this protection set.  This includes
39448     * deleting all key sessions.  In the case of persistent key sessions, the sessions
39449     * will simply be unloaded and not deleted.  Additionally, if this protection set is
39450     * associated with a HTMLMediaElement, it will be detached from that element.
39451     *
39452     * @memberof module:ProtectionController
39453     * @instance
39454     */
39455    function reset() {
39456        setMediaElement(null);
39457
39458        keySystem = undefined; //TODO-Refactor look at why undefined is needed for this. refactor
39459
39460        if (protectionModel) {
39461            protectionModel.reset();
39462            protectionModel = null;
39463        }
39464    }
39465
39466    ///////////////
39467    // Private
39468    ///////////////
39469
39470    function getProtData(keySystem) {
39471        var protData = null;
39472        var keySystemString = keySystem.systemString;
39473
39474        if (protDataSet) {
39475            protData = keySystemString in protDataSet ? protDataSet[keySystemString] : null;
39476        }
39477        return protData;
39478    }
39479
39480    function getKeySystemConfiguration(keySystem) {
39481        var protData = getProtData(keySystem);
39482        var audioCapabilities = [];
39483        var videoCapabilities = [];
39484        var audioRobustness = protData && protData.audioRobustness && protData.audioRobustness.length > 0 ? protData.audioRobustness : robustnessLevel;
39485        var videoRobustness = protData && protData.videoRobustness && protData.videoRobustness.length > 0 ? protData.videoRobustness : robustnessLevel;
39486
39487        if (audioInfo) {
39488            audioCapabilities.push(new _voMediaCapability2['default'](audioInfo.codec, audioRobustness));
39489        }
39490        if (videoInfo) {
39491            videoCapabilities.push(new _voMediaCapability2['default'](videoInfo.codec, videoRobustness));
39492        }
39493
39494        return new _voKeySystemConfiguration2['default'](audioCapabilities, videoCapabilities, 'optional', sessionType === 'temporary' ? 'optional' : 'required', [sessionType]);
39495    }
39496
39497    function selectKeySystem(supportedKS, fromManifest) {
39498        var self = this;
39499        var requestedKeySystems = [];
39500
39501        var ksIdx = undefined;
39502        if (keySystem) {
39503            // We have a key system
39504            for (ksIdx = 0; ksIdx < supportedKS.length; ksIdx++) {
39505                if (keySystem === supportedKS[ksIdx].ks) {
39506                    var _ret = (function () {
39507
39508                        requestedKeySystems.push({ ks: supportedKS[ksIdx].ks, configs: [getKeySystemConfiguration(keySystem)] });
39509
39510                        // Ensure that we would be granted key system access using the key
39511                        // system and codec information
39512                        var onKeySystemAccessComplete = function onKeySystemAccessComplete(event) {
39513                            eventBus.off(events.KEY_SYSTEM_ACCESS_COMPLETE, onKeySystemAccessComplete, self);
39514                            if (event.error) {
39515                                if (!fromManifest) {
39516                                    eventBus.trigger(events.KEY_SYSTEM_SELECTED, { error: 'DRM: KeySystem Access Denied! -- ' + event.error });
39517                                }
39518                            } else {
39519                                log('DRM: KeySystem Access Granted');
39520                                eventBus.trigger(events.KEY_SYSTEM_SELECTED, { data: event.data });
39521                                createKeySession(supportedKS[ksIdx].initData);
39522                            }
39523                        };
39524                        eventBus.on(events.KEY_SYSTEM_ACCESS_COMPLETE, onKeySystemAccessComplete, self);
39525                        protectionModel.requestKeySystemAccess(requestedKeySystems);
39526                        return 'break';
39527                    })();
39528
39529                    if (_ret === 'break') break;
39530                }
39531            }
39532        } else if (keySystem === undefined) {
39533            var onKeySystemSelected;
39534
39535            (function () {
39536                // First time through, so we need to select a key system
39537                keySystem = null;
39538                pendingNeedKeyData.push(supportedKS);
39539
39540                // Add all key systems to our request list since we have yet to select a key system
39541                for (var i = 0; i < supportedKS.length; i++) {
39542                    requestedKeySystems.push({ ks: supportedKS[i].ks, configs: [getKeySystemConfiguration(supportedKS[i].ks)] });
39543                }
39544
39545                var keySystemAccess = undefined;
39546                var onKeySystemAccessComplete = function onKeySystemAccessComplete(event) {
39547                    eventBus.off(events.KEY_SYSTEM_ACCESS_COMPLETE, onKeySystemAccessComplete, self);
39548                    if (event.error) {
39549                        keySystem = undefined;
39550                        eventBus.off(events.INTERNAL_KEY_SYSTEM_SELECTED, onKeySystemSelected, self);
39551
39552                        if (!fromManifest) {
39553                            eventBus.trigger(events.KEY_SYSTEM_SELECTED, { data: null, error: 'DRM: KeySystem Access Denied! -- ' + event.error });
39554                        }
39555                    } else {
39556                        keySystemAccess = event.data;
39557                        log('DRM: KeySystem Access Granted (' + keySystemAccess.keySystem.systemString + ')!  Selecting key system...');
39558                        protectionModel.selectKeySystem(keySystemAccess);
39559                    }
39560                };
39561
39562                onKeySystemSelected = function onKeySystemSelected(event) {
39563                    eventBus.off(events.INTERNAL_KEY_SYSTEM_SELECTED, onKeySystemSelected, self);
39564                    eventBus.off(events.KEY_SYSTEM_ACCESS_COMPLETE, onKeySystemAccessComplete, self);
39565                    if (!event.error) {
39566                        keySystem = protectionModel.getKeySystem();
39567                        eventBus.trigger(events.KEY_SYSTEM_SELECTED, { data: keySystemAccess });
39568                        // Set server certificate from protData
39569                        var protData = getProtData(keySystem);
39570                        if (protData && protData.serverCertificate && protData.serverCertificate.length > 0) {
39571                            protectionModel.setServerCertificate(BASE64.decodeArray(protData.serverCertificate).buffer);
39572                        }
39573                        for (var i = 0; i < pendingNeedKeyData.length; i++) {
39574                            for (ksIdx = 0; ksIdx < pendingNeedKeyData[i].length; ksIdx++) {
39575                                if (keySystem === pendingNeedKeyData[i][ksIdx].ks) {
39576                                    createKeySession(pendingNeedKeyData[i][ksIdx].initData);
39577                                    break;
39578                                }
39579                            }
39580                        }
39581                    } else {
39582                        keySystem = undefined;
39583                        if (!fromManifest) {
39584                            eventBus.trigger(events.KEY_SYSTEM_SELECTED, { data: null, error: 'DRM: Error selecting key system! -- ' + event.error });
39585                        }
39586                    }
39587                };
39588
39589                eventBus.on(events.INTERNAL_KEY_SYSTEM_SELECTED, onKeySystemSelected, self);
39590                eventBus.on(events.KEY_SYSTEM_ACCESS_COMPLETE, onKeySystemAccessComplete, self);
39591                protectionModel.requestKeySystemAccess(requestedKeySystems);
39592            })();
39593        } else {
39594            // We are in the process of selecting a key system, so just save the data
39595            pendingNeedKeyData.push(supportedKS);
39596        }
39597    }
39598
39599    function sendLicenseRequestCompleteEvent(data, error) {
39600        eventBus.trigger(events.LICENSE_REQUEST_COMPLETE, { data: data, error: error });
39601    }
39602
39603    function onKeyMessage(e) {
39604        log('DRM: onKeyMessage');
39605        if (e.error) {
39606            log(e.error);
39607            return;
39608        }
39609
39610        // Dispatch event to applications indicating we received a key message
39611        var keyMessage = e.data;
39612        eventBus.trigger(events.KEY_MESSAGE, { data: keyMessage });
39613        var messageType = keyMessage.messageType ? keyMessage.messageType : 'license-request';
39614        var message = keyMessage.message;
39615        var sessionToken = keyMessage.sessionToken;
39616        var protData = getProtData(keySystem);
39617        var keySystemString = keySystem.systemString;
39618        var licenseServerData = protectionKeyController.getLicenseServer(keySystem, protData, messageType);
39619        var eventData = { sessionToken: sessionToken, messageType: messageType };
39620
39621        // Message not destined for license server
39622        if (!licenseServerData) {
39623            log('DRM: License server request not required for this message (type = ' + e.data.messageType + ').  Session ID = ' + sessionToken.getSessionID());
39624            sendLicenseRequestCompleteEvent(eventData);
39625            return;
39626        }
39627
39628        // Perform any special handling for ClearKey
39629        if (protectionKeyController.isClearKey(keySystem)) {
39630            var clearkeys = protectionKeyController.processClearKeyLicenseRequest
39630(protData, message);
39631            if (clearkeys) {
39632                log('DRM: ClearKey license request handled by application!');
39633                sendLicenseRequestCompleteEvent(eventData);
39634                protectionModel.updateKeySession(sessionToken, clearkeys);
39635                return;
39636            }
39637        }
39638
39639        // All remaining key system scenarios require a request to a remote license server
39640        var xhr = new XMLHttpRequest();
39641
39642        // Determine license server URL
39643        var url = null;
39644        if (protData && protData.serverURL) {
39645            var serverURL = protData.serverURL;
39646            if (typeof serverURL === 'string' && serverURL !== '') {
39647                url = serverURL;
39648            } else if (typeof serverURL === 'object' && serverURL.hasOwnProperty(messageType)) {
39649                url = serverURL[messageType];
39650            }
39651        } else if (protData && protData.laURL && protData.laURL !== '') {
39652            // TODO: Deprecated!
39653            url = protData.laURL;
39654        } else {
39655            url = keySystem.getLicenseServerURLFromInitData(_CommonEncryption2['default'].getPSSHData(sessionToken.initData));
39656            if (!url) {
39657                url = e.data.laURL;
39658            }
39659        }
39660        // Possibly update or override the URL based on the message
39661        url = licenseServerData.getServerURLFromMessage(url, message, messageType);
39662
39663        // Ensure valid license server URL
39664        if (!url) {
39665            sendLicenseRequestCompleteEvent(eventData, 'DRM: No license server URL specified!');
39666            return;
39667        }
39668
39669        var reportError = function reportError(xhr, eventData, keySystemString, messageType) {
39670            var errorMsg = xhr.response ? licenseServerData.getErrorResponse(xhr.response, keySystemString, messageType) : 'NONE';
39671            sendLicenseRequestCompleteEvent(eventData, 'DRM: ' + keySystemString + ' update, XHR complete. status is "' + xhr.statusText + '" (' + xhr.status + '), readyState is ' + xhr.readyState + '.  Response is ' + errorMsg);
39672        };
39673
39674        xhr.open(licenseServerData.getHTTPMethod(messageType), url, true);
39675        xhr.responseType = licenseServerData.getResponseType(keySystemString, messageType);
39676        xhr.onload = function () {
39677            if (this.status == 200) {
39678                var licenseMessage = licenseServerData.getLicenseMessage(this.response, keySystemString, messageType);
39679                if (licenseMessage !== null) {
39680                    sendLicenseRequestCompleteEvent(eventData);
39681                    protectionModel.updateKeySession(sessionToken, licenseMessage);
39682                } else {
39683                    reportError(this, eventData, keySystemString, messageType);
39684                }
39685            } else {
39686                reportError(this, eventData, keySystemString, messageType);
39687            }
39688        };
39689        xhr.onabort = function () {
39690            sendLicenseRequestCompleteEvent(eventData, 'DRM: ' + keySystemString + ' update, XHR aborted. status is "' + this.statusText + '" (' + this.status + '), readyState is ' + this.readyState);
39691        };
39692        xhr.onerror = function () {
39693            sendLicenseRequestCompleteEvent(eventData, 'DRM: ' + keySystemString + ' update, XHR error. status is "' + this.statusText + '" (' + this.status + '), readyState is ' + this.readyState);
39694        };
39695
39696        // Set optional XMLHttpRequest headers from protection data and message
39697        var updateHeaders = function updateHeaders(headers) {
39698            if (headers) {
39699                for (var key in headers) {
39700                    if ('authorization' === key.toLowerCase()) {
39701                        xhr.withCredentials = true;
39702                    }
39703                    xhr.setRequestHeader(key, headers[key]);
39704                }
39705            }
39706        };
39707        if (protData) {
39708            updateHeaders(protData.httpRequestHeaders);
39709        }
39710        updateHeaders(keySystem.getRequestHeadersFromMessage(message));
39711
39712        // Set withCredentials property from protData
39713        if (protData && protData.withCredentials) {
39714            xhr.withCredentials = true;
39715        }
39716
39717        xhr.send(keySystem.getLicenseRequestFromMessage(message));
39718    }
39719
39720    function onNeedKey(event) {
39721        log('DRM: onNeedKey');
39722        // Ignore non-cenc initData
39723        if (event.key.initDataType !== 'cenc') {
39724            log('DRM:  Only \'cenc\' initData is supported!  Ignoring initData of type: ' + event.key.initDataType);
39725            return;
39726        }
39727
39728        // Some browsers return initData as Uint8Array (IE), some as ArrayBuffer (Chrome).
39729        // Convert to ArrayBuffer
39730        var abInitData = event.key.initData;
39731        if (ArrayBuffer.isView(abInitData)) {
39732            abInitData = abInitData.buffer;
39733        }
39734
39735        // If key system has already been selected and initData already seen, then do nothing
39736        if (keySystem) {
39737            var initDataForKS = _CommonEncryption2['default'].getPSSHForKeySystem(keySystem, abInitData);
39738            if (initDataForKS) {
39739
39740                // Check for duplicate initData
39741                var currentInitData = protectionModel.getAllInitData();
39742                for (var i = 0; i < currentInitData.length; i++) {
39743                    if (protectionKeyController.initDataEquals(initDataForKS, currentInitData[i])) {
39744                        log('DRM: Ignoring initData because we have already seen it!');
39745                        return;
39746                    }
39747                }
39748            }
39749        }
39750
39751        log('DRM: initData:', String.fromCharCode.apply(null, new Uint8Array(abInitData)));
39752
39753        var supportedKS = protectionKeyController.getSupportedKeySystems(abInitData, protDataSet);
39754        if (supportedKS.length === 0) {
39755            log('DRM: Received needkey event with initData, but we don\'t support any of the key systems!');
39756            return;
39757        }
39758
39759        selectKeySystem(supportedKS, false);
39760    }
39761
39762    function getKeySystems() {
39763        return protectionKeyController ? protectionKeyController.getKeySystems() : [];
39764    }
39765
39766    instance = {
39767        initialize: initialize,
39768        createKeySession: createKeySession,
39769        loadKeySession: loadKeySession,
39770        removeKeySession: removeKeySession,
39771        closeKeySession: closeKeySession,
39772        setServerCertificate: setServerCertificate,
39773        setMediaElement: setMediaElement,
39774        setSessionType: setSessionType,
39775        setRobustnessLevel: setRobustnessLevel,
39776        setProtectionData: setProtectionData,
39777        getSupportedKeySystemsFromContentProtection: getSupportedKeySystemsFromContentProtection,
39778        getKeySystems: getKeySystems,
39779        reset: reset
39780    };
39781
39782    setup();
39783    return instance;
39784}
39785
39786ProtectionController.__dashjs_factory_name = 'ProtectionController';
39787exports['default'] = dashjs.FactoryMaker.getClassFactory(ProtectionController);
39788/* jshint ignore:line */
39789module.exports = exports['default'];
39790
39791},{"146":146,"166":166,"167":167}],150:[function(_dereq_,module,exports){
39792/**
39793 * The copyright in this software is being made available under the BSD License,
39794 * included below. This software may be subject to other third party and contributor
39795 * rights, including patent rights, and no such rights are granted under this license.
39796 *
39797 * Copyright (c) 2013, Dash Industry Forum.
39798 * All rights reserved.
39799 *
39800 * Redistribution and use in source and binary forms, with or without modification,
39801 * are permitted provided that the following conditions are met:
39802 *  * Redistributions of source code must retain the above copyright notice, this
39803 *  list of conditions and the following disclaimer.
39804 *  * Redistributions in binary form must reproduce the above copyright notice,
39805 *  this list of conditions and the following disclaimer in the documentation and/or
39806 *  other materials provided with the distribution.
39807 *  * Neither the name of Dash Industry Forum nor the names of its
39808 *  contributors may be used to endorse or promote products derived from this software
39809 *  without specific prior written permission.
39810 *
39811 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
39812 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
39813 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
39814 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
39815 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
39816 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
39817 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
39818 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
39819 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39820 *  POSSIBILITY OF SUCH DAMAGE.
39821 */
39822'use strict';
39823
39824Object.defineProperty(exports, '__esModule', {
39825    value: true
39826});
39827
39828function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
39829
39830var _CommonEncryption = _dereq_(146);
39831
39832var _CommonEncryption2 = _interopRequireDefault(_CommonEncryption);
39833
39834var _drmKeySystemClearKey = _dereq_(151);
39835
39836var _drmKeySystemClearKey2 = _interopRequireDefault(_drmKeySystemClearKey);
39837
39838var _drmKeySystemWidevine = _dereq_(153);
39839
39840var _drmKeySystemWidevine2 = _interopRequireDefault(_drmKeySystemWidevine);
39841
39842var _drmKeySystemPlayReady = _dereq_(152);
39843
39844var _drmKeySystemPlayReady2 = _interopRequireDefault(_drmKeySystemPlayReady);
39845
39846var _serversDRMToday = _dereq_(158);
39847
39848var _serversDRMToday2 = _interopRequireDefault(_serversDRMToday);
39849
39850var _serversPlayReady = _dereq_(159);
39851
39852var _serversPlayReady2 = _interopRequireDefault(_serversPlayReady);
39853
39854var _serversWidevine = _dereq_(160);
39855
39856var _serversWidevine2 = _interopRequireDefault(_serversWidevine);
39857
39858var _serversClearKey = _dereq_(157);
39859
39860var _serversClearKey2 = _interopRequireDefault(_serversClearKey);
39861
39862/**
39863 * @module ProtectionKeyController
39864 * @description Media protection key system functionality that can be modified/overridden by applications
39865 */
39866function ProtectionKeyController() {
39867
39868    var context = this.context;
39869
39870    var instance = undefined,
39871        log = undefined,
39872        keySystems = undefined,
39873        BASE64 = undefined,
39874        clearkeyKeySystem = undefined;
39875
39876    function setConfig(config) {
39877        if (!config) return;
39878
39879        if (config.log) {
39880            log = config.log;
39881        }
39882
39883        if (config.BASE64) {
39884            BASE64 = config.BASE64;
39885        }
39886    }
39887
39888    function initialize() {
39889        keySystems = [];
39890
39891        var keySystem = undefined;
39892
39893        // PlayReady
39894        keySystem = (0, _drmKeySystemPlayReady2['default'])(context).getInstance({ BASE64: BASE64 });
39895        keySystems.push(keySystem);
39896
39897        // Widevine
39898        keySystem = (0, _drmKeySystemWidevine2['default'])(context).getInstance({ BASE64: BASE64 });
39899        keySystems.push(keySystem);
39900
39901        // ClearKey
39902        keySystem = (0, _drmKeySystemClearKey2['default'])(context).getInstance({ BASE64: BASE64 });
39903        keySystems.push(keySystem);
39904        clearkeyKeySystem = keySystem;
39905    }
39906
39907    /**
39908     * Returns a prioritized list of key systems supported
39909     * by this player (not necessarily those supported by the
39910     * user agent)
39911     *
39912     * @returns {Array.<KeySystem>} a prioritized
39913     * list of key systems
39914     * @memberof module:ProtectionKeyController
39915     * @instance
39916     */
39917    function getKeySystems() {
39918        return keySystems;
39919    }
39920
39921    /**
39922     * Returns the key system associated with the given key system string
39923     * name (i.e. 'org.w3.clearkey')
39924     *
39925     * @param {string} systemString the system string
39926     * @returns {KeySystem|null} the key system
39927     * or null if no supported key system is associated with the given key
39928     * system string
39929     * @memberof module:ProtectionKeyController
39930     * @instance
39931     */
39932    function getKeySystemBySystemString(systemString) {
39933        for (var i = 0; i < keySystems.length; i++) {
39934            if (keySystems[i].systemString === systemString) {
39935                return keySystems[i];
39936            }
39937        }
39938        return null;
39939    }
39940
39941    /**
39942     * Determines whether the given key system is ClearKey.  This is
39943     * necessary because the EME spec defines ClearKey and its method
39944     * for providing keys to the key session; and this method has changed
39945     * between the various API versions.  Our EME-specific ProtectionModels
39946     * must know if the system is ClearKey so that it can format the keys
39947     * according to the particular spec version.
39948     *
39949     * @param {Object} keySystem the key
39950     * @returns {boolean} true if this is the ClearKey key system, false
39951     * otherwise
39952     * @memberof module:ProtectionKeyController
39953     * @instance
39954     */
39955    function isClearKey(keySystem) {
39956        return keySystem === clearkeyKeySystem;
39957    }
39958
39959    /**
39960     * Check equality of initData array buffers.
39961     *
39962     * @param {ArrayBuffer} initData1 - first initData
39963     * @param {ArrayBuffer} initData2 - second initData
39964     * @returns {boolean} true if the initData arrays are equal in size and
39965     * contents, false otherwise
39966     * @memberof module:ProtectionKeyController
39967     * @instance
39968     */
39969    function initDataEquals(initData1, initData2) {
39970        if (initData1.byteLength === initData2.byteLength) {
39971            var data1 = new Uint8Array(initData1);
39972            var data2 = new Uint8Array(initData2);
39973
39974            for (var j = 0; j < data1.length; j++) {
39975                if (data1[j] !== data2[j]) {
39976                    return false;
39977                }
39978            }
39979            return true;
39980        }
39981        return false;
39982    }
39983
39984    /**
39985     * Returns a set of supported key systems and CENC initialization data
39986     * from the given array of ContentProtection elements.  Only
39987     * key systems that are supported by this player will be returned.
39988     * Key systems are returned in priority order (highest first).
39989     *
39990     * @param {Array.<Object>} cps - array of content protection elements parsed
39991     * from the manifest
39992     * @returns {Array.<Object>} array of objects indicating which supported key
39993     * systems were found.  Empty array is returned if no
39994     * supported key systems were found
39995     * @memberof module:ProtectionKeyController
39996     * @instance
39997     */
39998    function getSupportedKeySystemsFromContentProtection(cps) {
39999        var cp = undefined,
40000            ks = undefined,
40001            ksIdx = undefined,
40002            cpIdx = undefined;
40003        var supportedKS = [];
40004
40005        if (cps) {
40006            for (ksIdx = 0; ksIdx < keySystems.length; ++ksIdx) {
40007                ks = keySystems[ksIdx];
40008                for (cpIdx = 0; cpIdx < cps.length; ++cpIdx) {
40009                    cp = cps[cpIdx];
40010                    if (cp.schemeIdUri.toLowerCase() === ks.schemeIdURI) {
40011
40012                        // Look for DRM-specific ContentProtection
40013                        var initData = ks.getInitData(cp);
40014                        if (!!initData) {
40015                            supportedKS.push({
40016                                ks: keySystems[ksIdx],
40017                                initData: initData
40018                            });
40019                        }
40020                    }
40021                }
40022            }
40023        }
40024        return supportedKS;
40025    }
40026
40027    /**
40028     * Returns key systems supported by this player for the given PSSH
40029     * initializationData. Only key systems supported by this player
40030     * that have protection data present will be returned.  Key systems are returned in priority order
40031     * (highest priority first)
40032     *
40033     * @param {ArrayBuffer} initData Concatenated PSSH data for all DRMs
40034     * supported by the content
40035     * @param {ProtectionData} protDataSet user specified protection data - license server url etc
40036     * supported by the content
40037     * @returns {Array.<Object>} array of objects indicating which supported key
40038     * systems were found.  Empty array is returned if no
40039     * supported key systems were found
40040     * @memberof module:ProtectionKeyController
40041     * @instance
40042     */
40043    function getSupportedKeySystems(initData, protDataSet) {
40044        var supportedKS = [];
40045        var pssh = _CommonEncryption2['default'].parsePSSHList(initData);
40046
40047        for (var ksIdx = 0; ksIdx < keySystems.length; ++ksIdx) {
40048            var keySystemString = keySystems[ksIdx].systemString;
40049            var shouldNotFilterOutKeySystem = protDataSet ? keySystemString in protDataSet : true;
40050
40051            if (keySystems[ksIdx].uuid in pssh && shouldNotFilterOutKeySystem) {
40052                supportedKS.push({
40053                    ks: keySystems[ksIdx],
40054                    initData: pssh[keySystems[ksIdx].uuid]
40055                });
40056            }
40057        }
40058        return supportedKS;
40059    }
40060
40061    /**
40062     * Returns the license server implementation data that should be used for this request.
40063     *
40064     * @param {KeySystem} keySystem the key system
40065     * associated with this license request
40066     * @param {ProtectionData} protData protection data to use for the
40067     * request
40068     * @param {string} [messageType="license-request"] the message type associated with this
40069     * request.  Supported message types can be found
40070     * {@link https://w3c.github.io/encrypted-media/#idl-def-MediaKeyMessageType|here}.
40071     * @returns {LicenseServer|null} the license server
40072     * implementation that should be used for this request or null if the player should not
40073     * pass messages of the given type to a license server
40074     * @memberof module:ProtectionKeyController
40075     * @instance
40076     *
40077     */
40078    function getLicenseServer(keySystem, protData, messageType) {
40079
40080        // Our default server implementations do not do anything with "license-release" or
40081        // "individualization-request" messages, so we just send a success event
40082        if (messageType === 'license-release' || messageType === 'individualization-request') {
40083            return null;
40084        }
40085
40086        var licenseServerData = null;
40087        if (protData && protData.hasOwnProperty('drmtoday')) {
40088            licenseServerData = (0, _serversDRMToday2['default'])(context).getInstance({ BASE64: BASE64 });
40089        } else if (keySystem.systemString === 'com.widevine.alpha') {
40090            licenseServerData = (0, _serversWidevine2['default'])(context).getInstance();
40091        } else if (keySystem.systemString === 'com.microsoft.playready') {
40092            licenseServerData = (0, _serversPlayReady2['default'])(context).getInstance();
40093        } else if (keySystem.systemString === 'org.w3.clearkey') {
40094            licenseServerData = (0, _serversClearKey2['default'])(context).getInstance();
40095        }
40096
40097        return licenseServerData;
40098    }
40099
40100    /**
40101     * Allows application-specific retrieval of ClearKey keys.
40102     *
40103     * @param {ProtectionData} protData protection data to use for the
40104     * request
40105     * @param {ArrayBuffer} message the key message from the CDM
40106     * @return {ClearKeyKeySet|null} the clear keys associated with
40107     * the request or null if no keys can be returned by this function
40108     * @memberof module:ProtectionKeyController
40109     * @instance
40110     */
40111    function processClearKeyLicenseRequest(protData, message) {
40112        try {
40113            return clearkeyKeySystem.getClearKeysFromProtectionData(protData, message);
40114        } catch (error) {
40115            log('Failed to retrieve clearkeys from ProtectionData');
40116            return null;
40117        }
40118    }
40119
40120    function setProtectionData(protectionDataSet) {
40121        var getProtectionData = function getProtectionData(keySystemString) {
40122            var protData = null;
40123            if (protectionDataSet) {
40124                protData = keySystemString in protectionDataSet ? protectionDataSet[keySystemString] : null;
40125            }
40126            return protData;
40127        };
40128
40129        for (var i = 0; i < keySystems.length; i++) {
40130            var keySystem = keySystems[i];
40131            if (keySystem.hasOwnProperty('init')) {
40132                keySystem.init(getProtectionData(keySystem.systemString));
40133            }
40134        }
40135    }
40136
40137    instance = {
40138        initialize: initialize,
40139        setProtectionData: setProtectionData,
40140        isClearKey: isClearKey,
40141        initDataEquals: initDataEquals,
40142        getKeySystems: getKeySystems,
40143        getKeySystemBySystemString: getKeySystemBySystemString,
40144        getSupportedKeySystemsFromContentProtection: getSupportedKeySystemsFromContentProtection,
40145        getSupportedKeySystems: getSupportedKeySystems,
40146        getLicenseServer: getLicenseServer,
40147        processClearKeyLicenseRequest: processClearKeyLicenseRequest,
40148        setConfig: setConfig
40149    };
40150
40151    return instance;
40152}
40153
40154ProtectionKeyController.__dashjs_factory_name = 'ProtectionKeyController';
40155exports['default'] = dashjs.FactoryMaker.getSingletonFactory(ProtectionKeyController);
40156/* jshint ignore:line */
40157module.exports = exports['default'];
40158
40159},{"146":146,"151":151,"152":152,"153":153,"157":157,"158":158,"159":159,"160":160}],151:[function(_dereq_,module,exports){
40160/**
40161 * The copyright in this software is being made available under the BSD License,
40162 * included below. This software may be subject to other third party and contributor
40163 * rights, including patent rights, and no such rights are granted under this license.
40164 *
40165 * Copyright (c) 2013, Dash Industry Forum.
40166 * All rights reserved.
40167 *
40168 * Redistribution and use in source and binary forms, with or without modification,
40169 * are permitted provided that the following conditions are met:
40170 *  * Redistributions of source code must retain the above copyright notice, this
40171 *  list of conditions and the following disclaimer.
40172 *  * Redistributions in binary form must reproduce the above copyright notice,
40173 *  this list of conditions and the following disclaimer in the documentation and/or
40174 *  other materials provided with the distribution.
40175 *  * Neither the name of Dash Industry Forum nor the names of its
40176 *  contributors may be used to endorse or promote products derived from this software
40177 *  without specific prior written permission.
40178 *
40179 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
40180 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
40181 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
40182 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
40183 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
40184 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
40185 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
40186 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40187 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40188 *  POSSIBILITY OF SUCH DAMAGE.
40189 */
40190
40191'use strict';
40192
40193Object.defineProperty(exports, '__esModule', {
40194    value: true
40195});
40196
40197function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
40198
40199var _voKeyPair = _dereq_(164);
40200
40201var _voKeyPair2 = _interopRequireDefault(_voKeyPair);
40202
40203var _voClearKeyKeySet = _dereq_(161);
40204
40205var _voClearKeyKeySet2 = _interopRequireDefault(_voClearKeyKeySet);
40206
40207var _CommonEncryption = _dereq_(146);
40208
40209var _CommonEncryption2 = _interopRequireDefault(_CommonEncryption);
40210
40211var uuid = '1077efec-c0b2-4d02-ace3-3c1e52e2fb4b';
40212var systemString = 'org.w3.clearkey';
40213var schemeIdURI = 'urn:uuid:' + uuid;
40214
40215function KeySystemClearKey(config) {
40216
40217    var instance = undefined;
40218    var BASE64 = config.BASE64;
40219    /**
40220     * Returns desired clearkeys (as specified in the CDM message) from protection data
40221     *
40222     * @param {ProtectionData} protectionData the protection data
40223     * @param {ArrayBuffer} message the ClearKey CDM message
40224     * @returns {ClearKeyKeySet} the key set or null if none found
40225     * @throws {Error} if a keyID specified in the CDM message was not found in the
40226     * protection data
40227     * @memberof KeySystemClearKey
40228     */
40229    function getClearKeysFromProtectionData(protectionData, message) {
40230        var clearkeySet = null;
40231        if (protectionData) {
40232            // ClearKey is the only system that does not require a license server URL, so we
40233            // handle it here when keys are specified in protection data
40234            var jsonMsg = JSON.parse(String.fromCharCode.apply(null, new Uint8Array(message)));
40235            var keyPairs = [];
40236            for (var i = 0; i < jsonMsg.kids.length; i++) {
40237                var clearkeyID = jsonMsg.kids[i];
40238                var clearkey = protectionData.clearkeys.hasOwnProperty(clearkeyID) ? protectionData.clearkeys[clearkeyID] : null;
40239                if (!clearkey) {
40240                    throw new Error('DRM: ClearKey keyID (' + clearkeyID + ') is not known!');
40241                }
40242                // KeyIDs from CDM are not base64 padded.  Keys may or may not be padded
40243                keyPairs.push(new _voKeyPair2['default'](clearkeyID, clearkey));
40244            }
40245            clearkeySet = new _voClearKeyKeySet2['default'](keyPairs);
40246        }
40247        return clearkeySet;
40248    }
40249
40250    function getInitData(cp) {
40251        return _CommonEncryption2['default'].parseInitDataFromContentProtection(cp, BASE64);
40252    }
40253
40254    function getRequestHeadersFromMessage() /*message*/{
40255        return null;
40256    }
40257
40258    function getLicenseRequestFromMessage(message) {
40259        return new Uint8Array(message);
40260    }
40261
40262    function getLicenseServerURLFromInitData() /*initData*/{
40263        return null;
40264    }
40265
40266    instance = {
40267        uuid: uuid,
40268        schemeIdURI: schemeIdURI,
40269        systemString: systemString,
40270        getInitData: getInitData,
40271        getRequestHeadersFromMessage: getRequestHeadersFromMessage,
40272        getLicenseRequestFromMessage: getLicenseRequestFromMessage,
40273        getLicenseServerURLFromInitData: getLicenseServerURLFromInitData,
40274        getClearKeysFromProtectionData: getClearKeysFromProtectionData
40275    };
40276
40277    return instance;
40278}
40279
40280KeySystemClearKey.__dashjs_factory_name = 'KeySystemClearKey';
40281exports['default'] = dashjs.FactoryMaker.getSingletonFactory(KeySystemClearKey);
40282/* jshint ignore:line */
40283module.exports = exports['default'];
40284
40285},{"146":146,"161":161,"164":164}],152:[function(_dereq_,module,exports){
40286/**
40287 * The copyright in this software is being made available under the BSD License,
40288 * included below. This software may be subject to other third party and contributor
40289 * rights, including patent rights, and no such rights are granted under this license.
40290 *
40291 * Copyright (c) 2013, Dash Industry Forum.
40292 * All rights reserved.
40293 *
40294 * Redistribution and use in source and binary forms, with or without modification,
40295 * are permitted provided that the following conditions are met:
40296 *  * Redistributions of source code must retain the above copyright notice, this
40297 *  list of conditions and the following disclaimer.
40298 *  * Redistributions in binary form must reproduce the above copyright notice,
40299 *  this list of conditions and the following disclaimer in the documentation and/or
40300 *  other materials provided with the distribution.
40301 *  * Neither the name of Dash Industry Forum nor the names of its
40302 *  contributors may be used to endorse or promote products derived from this software
40303 *  without specific prior written permission.
40304 *
40305 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
40306 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
40307 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
40308 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
40309 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
40309INCLUDING, BUT
40310 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
40311 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
40312 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40313 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40314 *  POSSIBILITY OF SUCH DAMAGE.
40315 */
40316
40317/**
40318 * Microsoft PlayReady DRM
40319 *
40320 * @class
40321 * @implements KeySystem
40322 */
40323'use strict';
40324
40325Object.defineProperty(exports, '__esModule', {
40326    value: true
40327});
40328
40329function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
40330
40331var _CommonEncryption = _dereq_(146);
40332
40333var _CommonEncryption2 = _interopRequireDefault(_CommonEncryption);
40334
40335var uuid = '9a04f079-9840-4286-ab92-e65be0885f95';
40336var systemString = 'com.microsoft.playready';
40337var schemeIdURI = 'urn:uuid:' + uuid;
40338
40339function KeySystemPlayReady(config) {
40340
40341    var instance = undefined;
40342    var messageFormat = 'utf16';
40343    var BASE64 = config.BASE64;
40344
40345    function getRequestHeadersFromMessage(message) {
40346        var msg = undefined,
40347            xmlDoc = undefined;
40348        var headers = {};
40349        var parser = new DOMParser();
40350        var dataview = messageFormat === 'utf16' ? new Uint16Array(message) : new Uint8Array(message);
40351
40352        msg = String.fromCharCode.apply(null, dataview);
40353        xmlDoc = parser.parseFromString(msg, 'application/xml');
40354
40355        var headerNameList = xmlDoc.getElementsByTagName('name');
40356        var headerValueList = xmlDoc.getElementsByTagName('value');
40357        for (var i = 0; i < headerNameList.length; i++) {
40358            headers[headerNameList[i].childNodes[0].nodeValue] = headerValueList[i].childNodes[0].nodeValue;
40359        }
40360        // some versions of the PlayReady CDM return 'Content' instead of 'Content-Type'.
40361        // this is NOT w3c conform and license servers may reject the request!
40362        // -> rename it to proper w3c definition!
40363        if (headers.hasOwnProperty('Content')) {
40364            headers['Content-Type'] = headers.Content;
40365            delete headers.Content;
40366        }
40367        return headers;
40368    }
40369
40370    function getLicenseRequestFromMessage(message) {
40371        var msg = undefined,
40372            xmlDoc = undefined;
40373        var licenseRequest = null;
40374        var parser = new DOMParser();
40375        var dataview = messageFormat === 'utf16' ? new Uint16Array(message) : new Uint8Array(message);
40376
40377        msg = String.fromCharCode.apply(null, dataview);
40378        xmlDoc = parser.parseFromString(msg, 'application/xml');
40379
40380        if (xmlDoc.getElementsByTagName('Challenge')[0]) {
40381            var Challenge = xmlDoc.getElementsByTagName('Challenge')[0].childNodes[0].nodeValue;
40382            if (Challenge) {
40383                licenseRequest = BASE64.decode(Challenge);
40384            }
40385        }
40386        return licenseRequest;
40387    }
40388
40389    function getLicenseServerURLFromInitData(initData) {
40390        if (initData) {
40391            var data = new DataView(initData);
40392            var numRecords = data.getUint16(4, true);
40393            var offset = 6;
40394            var parser = new DOMParser();
40395
40396            for (var i = 0; i < numRecords; i++) {
40397                // Parse the PlayReady Record header
40398                var recordType = data.getUint16(offset, true);
40399                offset += 2;
40400                var recordLength = data.getUint16(offset, true);
40401                offset += 2;
40402                if (recordType !== 0x0001) {
40403                    offset += recordLength;
40404                    continue;
40405                }
40406
40407                var recordData = initData.slice(offset, offset + recordLength);
40408                var record = String.fromCharCode.apply(null, new Uint16Array(recordData));
40409                var xmlDoc = parser.parseFromString(record, 'application/xml');
40410
40411                // First try <LA_URL>
40412                if (xmlDoc.getElementsByTagName('LA_URL')[0]) {
40413                    var laurl = xmlDoc.getElementsByTagName('LA_URL')[0].childNodes[0].nodeValue;
40414                    if (laurl) {
40415                        return laurl;
40416                    }
40417                }
40418
40419                // Optionally, try <LUI_URL>
40420                if (xmlDoc.getElementsByTagName('LUI_URL')[0]) {
40421                    var luiurl = xmlDoc.getElementsByTagName('LUI_URL')[0].childNodes[0].nodeValue;
40422                    if (luiurl) {
40423                        return luiurl;
40424                    }
40425                }
40426            }
40427        }
40428
40429        return null;
40430    }
40431
40432    function getInitData(cpData) {
40433        // * desc@ getInitData
40434        // *   generate PSSH data from PROHeader defined in MPD file
40435        // *   PSSH format:
40436        // *   size (4)
40437        // *   box type(PSSH) (8)
40438        // *   Protection SystemID (16)
40439        // *   protection system data size (4) - length of decoded PROHeader
40440        // *   decoded PROHeader data from MPD file
40441        var PSSHBoxType = new Uint8Array([0x70, 0x73, 0x73, 0x68, 0x00, 0x00, 0x00, 0x00]); //'PSSH' 8 bytes
40442        var playreadySystemID = new Uint8Array([0x9a, 0x04, 0xf0, 0x79, 0x98, 0x40, 0x42, 0x86, 0xab, 0x92, 0xe6, 0x5b, 0xe0, 0x88, 0x5f, 0x95]);
40443
40444        var byteCursor = 0;
40445        var uint8arraydecodedPROHeader = null;
40446
40447        var PROSize = undefined,
40448            PSSHSize = undefined,
40449            PSSHBoxBuffer = undefined,
40450            PSSHBox = undefined,
40451            PSSHData = undefined;
40452
40453        // Handle common encryption PSSH
40454        if ('pssh' in cpData) {
40455            return _CommonEncryption2['default'].parseInitDataFromContentProtection(cpData, BASE64);
40456        }
40457        // Handle native MS PlayReady ContentProtection elements
40458        if ('pro' in cpData) {
40459            uint8arraydecodedPROHeader = BASE64.decodeArray(cpData.pro.__text);
40460        } else if ('prheader' in cpData) {
40461            uint8arraydecodedPROHeader = BASE64.decodeArray(cpData.prheader.__text);
40462        } else {
40463            return null;
40464        }
40465
40466        PROSize = uint8arraydecodedPROHeader.length;
40467        PSSHSize = 0x4 + PSSHBoxType.length + playreadySystemID.length + 0x4 + PROSize;
40468
40469        PSSHBoxBuffer = new ArrayBuffer(PSSHSize);
40470
40471        PSSHBox = new Uint8Array(PSSHBoxBuffer);
40472        PSSHData = new DataView(PSSHBoxBuffer);
40473
40474        PSSHData.setUint32(byteCursor, PSSHSize);
40475        byteCursor += 0x4;
40476
40477        PSSHBox.set(PSSHBoxType, byteCursor);
40478        byteCursor += PSSHBoxType.length;
40479
40480        PSSHBox.set(playreadySystemID, byteCursor);
40481        byteCursor += playreadySystemID.length;
40482
40483        PSSHData.setUint32(byteCursor, PROSize);
40484        byteCursor += 0x4;
40485
40486        PSSHBox.set(uint8arraydecodedPROHeader, byteCursor);
40487        byteCursor += PROSize;
40488
40489        return PSSHBox.buffer;
40490    }
40491
40492    /**
40493     * It seems that some PlayReady implementations return their XML-based CDM
40494     * messages using UTF16, while others return them as UTF8.  Use this function
40495     * to modify the message format to expect when parsing CDM messages.
40496     *
40497     * @param {string} format the expected message format.  Either "utf8" or "utf16".
40498     * @throws {Error} Specified message format is not one of "utf8" or "utf16"
40499     */
40500    function setPlayReadyMessageFormat(format) {
40501        if (format !== 'utf8' && format !== 'utf16') {
40502            throw new Error('Illegal PlayReady message format! -- ' + format);
40503        }
40504        messageFormat = format;
40505    }
40506
40507    instance = {
40508        uuid: uuid,
40509        schemeIdURI: schemeIdURI,
40510        systemString: systemString,
40511        getInitData: getInitData,
40512        getRequestHeadersFromMessage: getRequestHeadersFromMessage,
40513        getLicenseRequestFromMessage: getLicenseRequestFromMessage,
40514        getLicenseServerURLFromInitData: getLicenseServerURLFromInitData,
40515        setPlayReadyMessageFormat: setPlayReadyMessageFormat
40516    };
40517
40518    return instance;
40519}
40520
40521KeySystemPlayReady.__dashjs_factory_name = 'KeySystemPlayReady';
40522exports['default'] = dashjs.FactoryMaker.getSingletonFactory(KeySystemPlayReady);
40523/* jshint ignore:line */
40524module.exports = exports['default'];
40525
40526},{"146":146}],153:[function(_dereq_,module,exports){
40527/**
40528 * The copyright in this software is being made available under the BSD License,
40529 * included below. This software may be subject to other third party and contributor
40530 * rights, including patent rights, and no such rights are granted under this license.
40531 *
40532 * Copyright (c) 2013, Dash Industry Forum.
40533 * All rights reserved.
40534 *
40535 * Redistribution and use in source and binary forms, with or without modification,
40536 * are permitted provided that the following conditions are met:
40537 *  * Redistributions of source code must retain the above copyright notice, this
40538 *  list of conditions and the following disclaimer.
40539 *  * Redistributions in binary form must reproduce the above copyright notice,
40540 *  this list of conditions and the following disclaimer in the documentation and/or
40541 *  other materials provided with the distribution.
40542 *  * Neither the name of Dash Industry Forum nor the names of its
40543 *  contributors may be used to endorse or promote products derived from this software
40544 *  without specific prior written permission.
40545 *
40546 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
40547 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
40548 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
40549 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
40550 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
40551 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
40552 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
40553 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40554 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40555 *  POSSIBILITY OF SUCH DAMAGE.
40556 */
40557
40558/**
40559 * Google Widevine DRM
40560 *
40561 * @class
40562 * @implements MediaPlayer.dependencies.protection.KeySystem
40563 */
40564
40565'use strict';
40566
40567Object.defineProperty(exports, '__esModule', {
40568    value: true
40569});
40570
40571function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
40572
40573var _CommonEncryption = _dereq_(146);
40574
40575var _CommonEncryption2 = _interopRequireDefault(_CommonEncryption);
40576
40577var uuid = 'edef8ba9-79d6-4ace-a3c8-27dcd51d21ed';
40578var systemString = 'com.widevine.alpha';
40579var schemeIdURI = 'urn:uuid:' + uuid;
40580
40581function KeySystemWidevine(config) {
40582
40583    var instance = undefined;
40584    var protData = null;
40585    var BASE64 = config.BASE64;
40586
40587    function init(protectionData) {
40588        if (protectionData) {
40589            protData = protectionData;
40590        }
40591    }
40592
40593    function replaceKID(pssh, KID) {
40594        var pssh_array = undefined;
40595        var replace = true;
40596        var kidLen = 16;
40597        var pos = undefined;
40598        var i = undefined,
40599            j = undefined;
40600
40601        pssh_array = new Uint8Array(pssh);
40602
40603        for (i = 0; i <= pssh_array.length - (kidLen + 2); i++) {
40604            if (pssh_array[i] === 0x12 && pssh_array[i + 1] === 0x10) {
40605                pos = i + 2;
40606                for (j = pos; j < pos + kidLen; j++) {
40607                    if (pssh_array[j] !== 0xFF) {
40608                        replace = false;
40609                        break;
40610                    }
40611                }
40612                break;
40613            }
40614        }
40615
40616        if (replace) {
40617            pssh_array.set(KID, pos);
40618        }
40619
40620        return pssh_array.buffer;
40621    }
40622
40623    function getInitData(cp) {
40624        var pssh = null;
40625        // Get pssh from protectionData or from manifest
40626        if (protData && protData.pssh) {
40627            pssh = BASE64.decodeArray(protData.pssh).buffer;
40628        } else {
40629            pssh = _CommonEncryption2['default'].parseInitDataFromContentProtection(cp, BASE64);
40630        }
40631
40632        // Check if KID within pssh is empty, in that case set KID value according to 'cenc:default_KID' value
40633        if (pssh) {
40634            pssh = replaceKID(pssh, cp['cenc:default_KID']);
40635        }
40636
40637        return pssh;
40638    }
40639
40640    function getRequestHeadersFromMessage() /*message*/{
40641        return null;
40642    }
40643
40644    function getLicenseRequestFromMessage(message) {
40645        return new Uint8Array(message);
40646    }
40647
40648    function getLicenseServerURLFromInitData() /*initData*/{
40649        return null;
40650    }
40651
40652    instance = {
40653        uuid: uuid,
40654        schemeIdURI: schemeIdURI,
40655        systemString: systemString,
40656        init: init,
40657        getInitData: getInitData,
40658        getRequestHeadersFromMessage: getRequestHeadersFromMessage,
40659        getLicenseRequestFromMessage: getLicenseRequestFromMessage,
40660        getLicenseServerURLFromInitData: getLicenseServerURLFromInitData
40661    };
40662
40663    return instance;
40664}
40665
40666KeySystemWidevine.__dashjs_factory_name = 'KeySystemWidevine';
40667exports['default'] = dashjs.FactoryMaker.getSingletonFactory(KeySystemWidevine);
40668/* jshint ignore:line */
40669module.exports = exports['default'];
40670
40671},{"146":146}],154:[function(_dereq_,module,exports){
40672/**
40673 * The copyright in this software is being made available under the BSD License,
40674 * included below. This software may be subject to other third party and contributor
40675 * rights, including patent rights, and no such rights are granted under this license.
40676 *
40677 * Copyright (c) 2013, Dash Industry Forum.
40678 * All rights reserved.
40679 *
40680 * Redistribution and use in source and binary forms, with or without modification,
40681 * are permitted provided that the following conditions are met:
40682 *  * Redistributions of source code must retain the above copyright notice, this
40683 *  list of conditions and the following disclaimer.
40684 *  * Redistributions in binary form must reproduce the above copyright notice,
40685 *  this list of conditions and the following disclaimer in the documentation and/or
40686 *  other materials provided with the distribution.
40687 *  * Neither the name of Dash Industry Forum nor the names of its
40688 *  contributors may be used to endorse or promote products derived from this software
40689 *  without specific prior written permission.
40690 *
40691 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
40692 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
40693 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
40694 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
40695 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
40696 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
40697 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
40698 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40699 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40700 *  POSSIBILITY OF SUCH DAMAGE.
40701 */
40702
40703/**
40704 * Initial implementation of EME
40705 *
40706 * Implemented by Google Chrome prior to v36
40707 *
40708 * @implements ProtectionModel
40709 * @class
40710 */
40711'use strict';
40712
40713Object.defineProperty(exports, '__esModule', {
40714    value: true
40715});
40716
40717function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
40718
40719var _controllersProtectionKeyController = _dereq_(150);
40720
40721var _controllersProtectionKeyController2 = _interopRequireDefault(_controllersProtectionKeyController);
40722
40723var _voNeedKey = _dereq_(168);
40724
40725var _voNeedKey2 = _interopRequireDefault(_voNeedKey);
40726
40727var _voKeyError = _dereq_(162);
40728
40729var _voKeyError2 = _interopRequireDefault(_voKeyError);
40730
40731var _voKeyMessage = _dereq_(163);
40732
40733var _voKeyMessage2 = _interopRequireDefault(_voKeyMessage);
40734
40735var _voKeySystemConfiguration = _dereq_(166);
40736
40737var _voKeySystemConfiguration2 = _interopRequireDefault(_voKeySystemConfiguration);
40738
40739var _voKeySystemAccess = _dereq_(165);
40740
40741var _voKeySystemAccess2 = _interopRequireDefault(_voKeySystemAccess);
40742
40743function ProtectionModel_01b(config) {
40744
40745    var context = this.context;
40746    var eventBus = config.eventBus; //Need to pass in here so we can use same instance since this is optional module
40747    var events = config.events;
40748    var log = config.log;
40749    var api = config.api;
40750    var errHandler = config.errHandler;
40751
40752    var instance = undefined,
40753        videoElement = undefined,
40754        keySystem = undefined,
40755        protectionKeyController = undefined,
40756
40757    // With this version of the EME APIs, sessionIDs are not assigned to
40758    // sessions until the first key message is received.  We are assuming
40759    // that in the case of multiple sessions, key messages will be received
40760    // in the order that generateKeyRequest() is called.
40761    // Holding spot for newly-created sessions until we determine whether or
40762    // not the CDM supports sessionIDs
40763    pendingSessions = undefined,
40764
40765    // List of sessions that have been initialized.  Only the first position will
40766    // be used in the case that the CDM does not support sessionIDs
40767    sessions = undefined,
40768
40769    // Not all CDMs support the notion of sessionIDs.  Without sessionIDs
40770    // there is no way for us to differentiate between sessions, therefore
40771    // we must only allow a single session.  Once we receive the first key
40772    // message we can set this flag to determine if more sessions are allowed
40773    moreSessionsAllowed = undefined,
40774
40775    // This is our main event handler for all desired HTMLMediaElement events
40776    // related to EME.  These events are translated into our API-independent
40777    // versions of the same events
40778    eventHandler = undefined;
40779
40780    function setup() {
40781        videoElement = null;
40782        keySystem = null;
40783        pendingSessions = [];
40784        sessions = [];
40785        protectionKeyController = (0, _controllersProtectionKeyController2['default'])(context).getInstance();
40786        eventHandler = createEventHandler();
40787    }
40788
40789    function reset() {
40790        if (videoElement) {
40791            removeEventListeners();
40792        }
40793        for (var i = 0; i < sessions.length; i++) {
40794            closeKeySession(sessions[i]);
40795        }
40796        eventBus.trigger(events.TEARDOWN_COMPLETE);
40797    }
40798
40799    function getKeySystem() {
40800        return keySystem;
40801    }
40802
40803    function getAllInitData() {
40804        var retVal = [];
40805        for (var i = 0; i < pendingSessions.length; i++) {
40806            retVal.push(pendingSessions[i].initData);
40807        }
40808        for (var i = 0; i < sessions.length; i++) {
40809            retVal.push(sessions[i].initData);
40810        }
40811        return retVal;
40812    }
40813
40814    function requestKeySystemAccess(ksConfigurations) {
40815        var ve = videoElement;
40816        if (!ve) {
40817            // Must have a video element to do this capability tests
40818            ve = document.createElement('video');
40819        }
40820
40821        // Try key systems in order, first one with supported key system configuration
40822        // is used
40823        var found = false;
40824        for (var ksIdx = 0; ksIdx < ksConfigurations.length; ksIdx++) {
40825            var systemString = ksConfigurations[ksIdx].ks.systemString;
40826            var configs = ksConfigurations[ksIdx].configs;
40827            var supportedAudio = null;
40828            var supportedVideo = null;
40829
40830            // Try key system configs in order, first one with supported audio/video
40831            // is used
40832            for (var configIdx = 0; configIdx < configs.length; configIdx++) {
40833                //let audios = configs[configIdx].audioCapabilities;
40834                var videos = configs[configIdx].videoCapabilities;
40835                // Look for supported video container/codecs
40836                if (videos && videos.length !== 0) {
40837                    supportedVideo = []; // Indicates that we have a requested video config
40838                    for (var videoIdx = 0; videoIdx < videos.length; videoIdx++) {
40839                        if (ve.canPlayType(videos[videoIdx].contentType, systemString) !== '') {
40840                            supportedVideo.push(videos[videoIdx]);
40841                        }
40842                    }
40843                }
40844
40845                // No supported audio or video in this configuration OR we have
40846                // requested audio or video configuration that is not supported
40847                if (!supportedAudio && !supportedVideo || supportedAudio && supportedAudio.length === 0 || supportedVideo && supportedVideo.length === 0) {
40848                    continue;
40849                }
40850
40851                // This configuration is supported
40852                found = true;
40853                var ksConfig = new _voKeySystemConfiguration2['default'](supportedAudio, supportedVideo);
40854                var ks = protectionKeyController.getKeySystemBySystemString(systemString);
40855                eventBus.trigger(events.KEY_SYSTEM_ACCESS_COMPLETE, { data: new _voKeySystemAccess2['default'](ks, ksConfig) });
40856                break;
40857            }
40858        }
40859        if (!found) {
40860            eventBus.trigger(events.KEY_SYSTEM_ACCESS_COMPLETE, { error: 'Key system access denied! -- No valid audio/video content configurations detected!' });
40861        }
40862    }
40863
40864    function selectKeySystem(keySystemAccess) {
40865        keySystem = keySystemAccess.keySystem;
40866        eventBus.trigger(events.INTERNAL_KEY_SYSTEM_SELECTED);
40867    }
40868
40869    function setMediaElement(mediaElement) {
40870        if (videoElement === mediaElement) {
40871            return;
40872        }
40873
40874        // Replacing the previous element
40875        if (videoElement) {
40876            removeEventListeners();
40877        }
40878
40879        videoElement = mediaElement;
40880
40881        // Only if we are not detaching from the existing element
40882        if (videoElement) {
40883            videoElement.addEventListener(api.keyerror, eventHandler);
40884            videoElement.addEventListener(api.needkey, eventHandler);
40885            videoElement.addEventListener(api.keymessage, eventHandler);
40886            videoElement.addEventListener(api.keyadded, eventHandler);
40887            eventBus.trigger(events.VIDEO_ELEMENT_SELECTED);
40888        }
40889    }
40890
40891    function createKeySession(initData /*, keySystemType */) {
40892
40893        if (!keySystem) {
40894            throw new Error('Can not create sessions until you have selected a key system');
40895        }
40896
40897        // Determine if creating a new session is allowed
40898        if (moreSessionsAllowed || sessions.length === 0) {
40899
40900            var newSession = { // Implements SessionToken
40901                sessionID: null,
40902                initData: initData,
40903                getSessionID: function getSessionID() {
40904                    return this.sessionID;
40905                },
40906
40907                getExpirationTime: function getExpirationTime() {
40908                    return NaN;
40909                },
40910
40911                getSessionType: function getSessionType() {
40912                    return 'temporary';
40913                }
40914            };
40915            pendingSessions.push(newSession);
40916
40917            // Send our request to the CDM
40918            videoElement[api.generateKeyRequest](keySystem.systemString, new Uint8Array(initData));
40919
40920            return newSession;
40921        } else {
40922            throw new Error('Multiple sessions not allowed!');
40923        }
40924    }
40925
40926    function updateKeySession(sessionToken, message) {
40927        var sessionID = sessionToken.sessionID;
40928        if (!protectionKeyController.isClearKey(keySystem)) {
40929            // Send our request to the CDM
40930            videoElement[api.addKey](keySystem.systemString, new Uint8Array(message), new Uint8Array(sessionToken.initData), sessionID);
40931        } else {
40932            // For clearkey, message is a ClearKeyKeySet
40933            for (var i = 0; i < message.keyPairs.length; i++) {
40934                videoElement[api.addKey](keySystem.systemString, message.keyPairs[i].key, message.keyPairs[i].keyID, sessionID);
40935            }
40936        }
40937    }
40938
40939    function closeKeySession(sessionToken) {
40940        // Send our request to the CDM
40941        videoElement[api.cancelKeyRequest](keySystem.systemString, sessionToken.sessionID);
40942    }
40943
40944    function setServerCertificate() /*serverCertificate*/{/* Not supported */}
40945    function loadKeySession() /*sessionID*/{/* Not supported */}
40946    function removeKeySession() /*sessionToken*/{/* Not supported */}
40947
40948    function createEventHandler() {
40949        return {
40950            handleEvent: function handleEvent(event) {
40951                var sessionToken = null;
40952                switch (event.type) {
40953
40954                    case api.needkey:
40955                        var initData = ArrayBuffer.isView(event.initData) ? event.initData.buffer : event.initData;
40956                        eventBus.trigger(events.NEED_KEY, { key: new _voNeedKey2['default'](initData, 'cenc') });
40957                        break;
40958
40959                    case api.keyerror:
40960                        sessionToken = findSessionByID(sessions, event.sessionId);
40961                        if (!sessionToken) {
40962                            sessionToken = findSessionByID(pendingSessions, event.sessionId);
40963                        }
40964
40965                        if (sessionToken) {
40966                            var msg = '';
40967                            switch (event.errorCode.code) {
40968                                case 1:
40969                                    msg += 'MEDIA_KEYERR_UNKNOWN - An unspecified error occurred. This value is used for errors that don\'t match any of the other codes.';
40970                                    break;
40971                                case 2:
40972                                    msg += 'MEDIA_KEYERR_CLIENT - The Ke
40972y System could not be installed or updated.';
40973                                    break;
40974                                case 3:
40975                                    msg += 'MEDIA_KEYERR_SERVICE - The message passed into update indicated an error from the license service.';
40976                                    break;
40977                                case 4:
40978                                    msg += 'MEDIA_KEYERR_OUTPUT - There is no available output device with the required characteristics for the content protection system.';
40979                                    break;
40980                                case 5:
40981                                    msg += 'MEDIA_KEYERR_HARDWARECHANGE - A hardware configuration change caused a content protection error.';
40982                                    break;
40983                                case 6:
40984                                    msg += 'MEDIA_KEYERR_DOMAIN - An error occurred in a multi-device domain licensing configuration. The most common error is a failure to join the domain.';
40985                                    break;
40986                            }
40987                            msg += '  System Code = ' + event.systemCode;
40988                            // TODO: Build error string based on key error
40989                            eventBus.trigger(events.KEY_ERROR, { data: new _voKeyError2['default'](sessionToken, msg) });
40990                        } else {
40991                            log('No session token found for key error');
40992                        }
40993                        break;
40994
40995                    case api.keyadded:
40996                        sessionToken = findSessionByID(sessions, event.sessionId);
40997                        if (!sessionToken) {
40998                            sessionToken = findSessionByID(pendingSessions, event.sessionId);
40999                        }
41000
41001                        if (sessionToken) {
41002                            log('DRM: Key added.');
41003                            eventBus.trigger(events.KEY_ADDED, { data: sessionToken }); //TODO not sure anything is using sessionToken? why there?
41004                        } else {
41005                                log('No session token found for key added');
41006                            }
41007                        break;
41008
41009                    case api.keymessage:
41010
41011                        // If this CDM does not support session IDs, we will be limited
41012                        // to a single session
41013                        moreSessionsAllowed = event.sessionId !== null && event.sessionId !== undefined;
41014
41015                        // SessionIDs supported
41016                        if (moreSessionsAllowed) {
41017
41018                            // Attempt to find an uninitialized token with this sessionID
41019                            sessionToken = findSessionByID(sessions, event.sessionId);
41020                            if (!sessionToken && pendingSessions.length > 0) {
41021
41022                                // This is the first message for our latest session, so set the
41023                                // sessionID and add it to our list
41024                                sessionToken = pendingSessions.shift();
41025                                sessions.push(sessionToken);
41026                                sessionToken.sessionID = event.sessionId;
41027                            }
41028                        } else if (pendingSessions.length > 0) {
41029                            // SessionIDs not supported
41030
41031                            sessionToken = pendingSessions.shift();
41032                            sessions.push(sessionToken);
41033
41034                            if (pendingSessions.length !== 0) {
41035                                errHandler.mediaKeyMessageError('Multiple key sessions were creates with a user-agent that does not support sessionIDs!! Unpredictable behavior ahead!');
41036                            }
41037                        }
41038
41039                        if (sessionToken) {
41040                            var message = ArrayBuffer.isView(event.message) ? event.message.buffer : event.message;
41041
41042                            // For ClearKey, the spec mandates that you pass this message to the
41043                            // addKey method, so we always save it to the token since there is no
41044                            // way to tell which key system is in use
41045                            sessionToken.keyMessage = message;
41046                            eventBus.trigger(events.INTERNAL_KEY_MESSAGE, { data: new _voKeyMessage2['default'](sessionToken, message, event.defaultURL) });
41047                        } else {
41048                            log('No session token found for key message');
41049                        }
41050                        break;
41051                }
41052            }
41053        };
41054    }
41055
41056    /**
41057     * Helper function to retrieve the stored session token based on a given
41058     * sessionID value
41059     *
41060     * @param {Array} sessionArray - the array of sessions to search
41061     * @param {*}
41061 sessionID - the sessionID to search for
41062     * @returns {*} the session token with the given sessionID
41063     */
41064    function findSessionByID(sessionArray, sessionID) {
41065
41066        if (!sessionID || !sessionArray) {
41067            return null;
41068        } else {
41069            var len = sessionArray.length;
41070            for (var i = 0; i < len; i++) {
41071                if (sessionArray[i].sessionID == sessionID) {
41072                    return sessionArray[i];
41073                }
41074            }
41075            return null;
41076        }
41077    }
41078
41079    function removeEventListeners() {
41080        videoElement.removeEventListener(api.keyerror, eventHandler);
41081        videoElement.removeEventListener(api.needkey, eventHandler);
41082        videoElement.removeEventListener(api.keymessage, eventHandler);
41083        videoElement.removeEventListener(api.keyadded, eventHandler);
41084    }
41085
41086    instance = {
41087        getAllInitData: getAllInitData,
41088        requestKeySystemAccess: requestKeySystemAccess,
41089        getKeySystem: getKeySystem,
41090        selectKeySystem: selectKeySystem,
41091        setMediaElement: setMediaElement,
41092        createKeySession: createKeySession,
41093        updateKeySession: updateKeySession,
41094        closeKeySession: closeKeySession,
41095        setServerCertificate: setServerCertificate,
41096        loadKeySession: loadKeySession,
41097        removeKeySession: removeKeySession,
41098        reset: reset
41099    };
41100
41101    setup();
41102
41103    return instance;
41104}
41105
41106ProtectionModel_01b.__dashjs_factory_name = 'ProtectionModel_01b';
41107exports['default'] = dashjs.FactoryMaker.getClassFactory(ProtectionModel_01b);
41108/* jshint ignore:line */
41109module.exports = exports['default'];
41110
41111},{"150":150,"162":162,"163":163,"165":165,"166":166,"168":168}],155:[function(_dereq_,module,exports){
41112/**
41113 * The copyright in this software is being made available under the BSD License,
41114 * included below. This software may be subject to other third party and contributor
41115 * rights, including patent rights, and no such rights are granted under this license.
41116 *
41117 * Copyright (c) 2013, Dash Industry Forum.
41118 * All rights reserved.
41119 *
41120 * Redistribution and use in source and binary forms, with or without modification,
41121 * are permitted provided that the following conditions are met:
41122 *  * Redistributions of source code must retain the above copyright notice, this
41123 *  list of conditions and the following disclaimer.
41124 *  * Redistributions in binary form must reproduce the above copyright notice,
41125 *  this list of conditions and the following disclaimer in the documentation and/or
41126 *  other materials provided with the distribution.
41127 *  * Neither the name of Dash Industry Forum nor the names of its
41128 *  contributors may be used to endorse or promote products derived from this software
41129 *  without specific prior written permission.
41130 *
41131 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
41132 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
41133 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
41134 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
41135 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41136 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
41137 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
41138 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41139 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41140 *  POSSIBILITY OF SUCH DAMAGE.
41141 */
41142
41143/**
41144 * Most recent EME implementation
41145 *
41146 * Implemented by Google Chrome v36+ (Windows, OSX, Linux)
41147 *
41148 * @implements ProtectionModel
41149 * @class
41150 */
41151'use strict';
41152
41153Object.defineProperty(exports, '__esModule', {
41154    value: true
41155});
41156
41157function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
41158
41159var _controllersProtectionKeyController = _dereq_(150);
41160
41161var _controllersProtectionKeyController2 = _interopRequireDefault(_controllersProtectionKeyController);
41162
41163var _voNeedKey = _dereq_(168);
41164
41165var _voNeedKey2 = _interopRequireDefault(_voNeedKey);
41166
41167var _voKeyError = _dereq_(162);
41168
41169var _voKeyError2 = _interopRequireDefault(_voKeyError);
41170
41171var _voKeyMessage = _dereq_(163);
41172
41173var _voKeyMessage2 = _interopRequireDefault(_voKeyMessage);
41174
41175var _voKeySystemAccess = _dereq_(165);
41176
41177var _voKeySystemAccess2 = _interopRequireDefault(_voKeySystemAccess);
41178
41179function ProtectionModel_21Jan2015(config) {
41180
41181    var context = this.context;
41182    var eventBus = config.eventBus; //Need to pass in here so we can use same instance since this is optional module
41183    var events = config.events;
41184    var log = config.log;
41185
41186    var instance = undefined,
41187        keySystem = undefined,
41188        videoElement = undefined,
41189        mediaKeys = undefined,
41190        sessions = undefined,
41191        eventHandler = undefined,
41192        protectionKeyController = undefined;
41193
41194    function setup() {
41195        keySystem = null;
41196        videoElement = null;
41197        mediaKeys = null;
41198        sessions = [];
41199        protectionKeyController = (0, _controllersProtectionKeyController2['default'])(context).getInstance();
41200        eventHandler = createEventHandler();
41201    }
41202
41203    function reset() {
41204        var numSessions = sessions.length;
41205        var session = undefined;
41206
41207        if (numSessions !== 0) {
41208            (function () {
41209                // Called when we are done closing a session.  Success or fail
41210                var done = function done(session) {
41211                    removeSession(session);
41212                    if (sessions.length === 0) {
41213                        if (videoElement) {
41214                            videoElement.removeEventListener('encrypted', eventHandler);
41215                            videoElement.setMediaKeys(null).then(function () {
41216                                eventBus.trigger(events.TEARDOWN_COMPLETE);
41217                            });
41218                        } else {
41219                            eventBus.trigger(events.TEARDOWN_COMPLETE);
41220                        }
41221                    }
41222                };
41223                for (var i = 0; i < numSessions; i++) {
41224                    session = sessions[i];
41225                    (function (s) {
41226                        // Override closed promise resolver
41227                        session.session.closed.then(function () {
41228                            done(s);
41229                        });
41230                        // Close the session and handle errors, otherwise promise
41231                        // resolver above will be called
41232                        closeKeySessionInternal(session)['catch'](function () {
41233                            done(s);
41234                        });
41235                    })(session);
41236                }
41237            })();
41238        } else {
41239            eventBus.trigger(events.TEARDOWN_COMPLETE);
41240        }
41241    }
41242
41243    function getKeySystem() {
41244        return keySystem;
41245    }
41246
41247    function getAllInitData() {
41248        var retVal = [];
41249        for (var i = 0; i < sessions.length; i++) {
41250            retVal.push(sessions[i].initData);
41251        }
41252        return retVal;
41253    }
41254
41255    function requestKeySystemAccess(ksConfigurations) {
41256        requestKeySystemAccessInternal(ksConfigurations, 0);
41257    }
41258
41259    function selectKeySystem(keySystemAccess) {
41260        keySystemAccess.mksa.createMediaKeys().then(function (mkeys) {
41261            keySystem = keySystemAccess.keySystem;
41262            mediaKeys = mkeys;
41263            if (videoElement) {
41264                videoElement.setMediaKeys(mediaKeys).then(function () {
41265                    eventBus.trigger(events.INTERNAL_KEY_SYSTEM_SELECTED);
41266                });
41267            }
41268        })['catch'](function () {
41269            eventBus.trigger(events.INTERNAL_KEY_SYSTEM_SELECTED, { error: 'Error selecting keys system (' + keySystemAccess.keySystem.systemString + ')! Could not create MediaKeys -- TODO' });
41270        });
41271    }
41272
41273    function setMediaElement(mediaElement) {
41274        if (videoElement === mediaElement) return;
41275
41276        // Replacing the previous element
41277        if (videoElement) {
41278            videoElement.removeEventListener('encrypted', eventHandler);
41279            videoElement.setMediaKeys(null);
41280        }
41281
41282        videoElement = mediaElement;
41283
41284        // Only if we are not detaching from the existing element
41285        if (videoElement) {
41286            videoElement.addEventListener('encrypted', eventHandler);
41287            if (mediaKeys) {
41288                videoElement.setMediaKeys(mediaKeys);
41289            }
41290        }
41291    }
41292
41293    function setServerCertificate(serverCertificate) {
41294        if (!keySystem || !mediaKeys) {
41295            throw new Error('Can not set server certificate until you have selected a key system');
41296        }
41297        mediaKeys.setServerCertificate(serverCertificate).then(function () {
41298            log('DRM: License server certificate successfully updated.');
41299            eventBus.trigger(events.SERVER_CERTIFICATE_UPDATED);
41300        })['catch'](function (error) {
41301            eventBus.trigger(events.SERVER_CERTIFICATE_UPDATED, { error: 'Error updating server certificate -- ' + error.name });
41302        });
41303    }
41304
41305    function createKeySession(initData, sessionType) {
41306
41307        if (!keySystem || !mediaKeys) {
41308            throw new Error('Can not create sessions until you have selected a key system');
41309        }
41310
41311        var session = mediaKeys.createSession(sessionType);
41312        var sessionToken = createSessionToken(session, initData, sessionType);
41313
41314        // Generate initial key request
41315        session.generateRequest('cenc', initData).then(function () {
41316            log('DRM: Session created.  SessionID = ' + sessionToken.getSessionID());
41317            eventBus.trigger(events.KEY_SESSION_CREATED, { data: sessionToken });
41318        })['catch'](function (error) {
41319            // TODO: Better error string
41320            removeSession(sessionToken);
41321            eventBus.trigger(events.KEY_SESSION_CREATED, { data: null, error: 'Error generating key request -- ' + error.name });
41322        });
41323    }
41324
41325    function updateKeySession(sessionToken, message) {
41326
41327        var session = sessionToken.session;
41328
41329        // Send our request to the key session
41330        if (protectionKeyController.isClearKey(keySystem)) {
41331            message = message.toJWK();
41332        }
41333        session.update(message)['catch'](function (error) {
41334            eventBus.trigger(events.KEY_ERROR, { data: new _voKeyError2['default'](sessionToken, 'Error sending update() message! ' + error.name) });
41335        });
41336    }
41337
41338    function loadKeySession(sessionID) {
41339        if (!keySystem || !mediaKeys) {
41340            throw new Error('Can not load sessions until you have selected a key system');
41341        }
41342
41343        var session = mediaKeys.createSession();
41344
41345        // Load persisted session data into our newly created session object
41346        session.load(sessionID).then(function (success) {
41347            if (success) {
41348                var sessionToken = createSessionToken(session);
41349                log('DRM: Session created.  SessionID = ' + sessionToken.getSessionID());
41350                eventBus.trigger(events.KEY_SESSION_CREATED, { data: sessionToken });
41351            } else {
41352                eventBus.trigger(events.KEY_SESSION_CREATED, { data: null, error: 'Could not load session! Invalid Session ID (' + sessionID + ')' });
41353            }
41354        })['catch'](function (error) {
41355            eventBus.trigger(events.KEY_SESSION_CREATED, { data: null, error: 'Could not load session (' + sessionID + ')! ' + error.name });
41356        });
41357    }
41358
41359    function removeKeySession(sessionToken) {
41360        var session = sessionToken.session;
41361
41362        session.remove().then(function () {
41363            log('DRM: Session removed.  SessionID = ' + sessionToken.getSessionID());
41364            eventBus.trigger(events.KEY_SESSION_REMOVED, { data: sessionToken.getSessionID() });
41365        }, function (error) {
41366            eventBus.trigger(events.KEY_SESSION_REMOVED, { data: null, error: 'Error removing session (' + sessionToken.getSessionID() + '). ' + error.name });
41367        });
41368    }
41369
41370    function closeKeySession(sessionToken) {
41371        // Send our request to the key session
41372        closeKeySessionInternal(sessionToken)['catch'](function (error) {
41373            removeSession(sessionToken);
41374            eventBus.trigger(events.KEY_SESSION_CLOSED, { data: null, error: 'Error closing session (' + sessionToken.getSessionID() + ') ' + error.name });
41375        });
41376    }
41377
41378    function requestKeySystemAccessInternal(ksConfigurations, idx) {
41379        (function (i) {
41380            var keySystem = ksConfigurations[i].ks;
41381            var configs = ksConfigurations[i].configs;
41382            navigator.requestMediaKeySystemAccess(keySystem.systemString, configs).then(function (mediaKeySystemAccess) {
41383
41384                // Chrome 40 does not currently implement MediaKeySystemAccess.getConfiguration()
41385                var configuration = typeof mediaKeySystemAccess.getConfiguration === 'function' ? mediaKeySystemAccess.getConfiguration() : null;
41386                var keySystemAccess = new _voKeySystemAccess2['default'](keySystem, configuration);
41387                keySystemAccess.mksa = mediaKeySystemAccess;
41388                eventBus.trigger(events.KEY_SYSTEM_ACCESS_COMPLETE, { data: keySystemAccess });
41389            })['catch'](function () {
41390                if (++i < ksConfigurations.length) {
41391                    requestKeySystemAccessInternal(ksConfigurations, i);
41392                } else {
41393                    eventBus.trigger(events.KEY_SYSTEM_ACCESS_COMPLETE, { error: 'Key system access denied!' });
41394                }
41395            });
41396        })(idx);
41397    }
41398
41399    function closeKeySessionInternal(sessionToken) {
41400        var session = sessionToken.session;
41401
41402        // Remove event listeners
41403        session.removeEventListener('keystatuseschange', sessionToken);
41404        session.removeEventListener('message', sessionToken);
41405
41406        // Send our request to the key session
41407        return session.close();
41408    }
41409
41410    // This is our main event handler for all desired HTMLMediaElement events
41411    // related to EME.  These events are translated into our API-independent
41412    // versions of the same events
41413    function createEventHandler() {
41414        return {
41415            handleEvent: function handleEvent(event) {
41416                switch (event.type) {
41417
41418                    case 'encrypted':
41419                        if (event.initData) {
41420                            var initData = ArrayBuffer.isView(event.initData) ? event.initData.buffer : event.initData;
41421                            eventBus.trigger(events.NEED_KEY, { key: new _voNeedKey2['default'](initData, event.initDataType) });
41422                        }
41423                        break;
41424                }
41425            }
41426        };
41427    }
41428
41429    function removeSession(token) {
41430        // Remove from our session list
41431        for (var i = 0; i < sessions.length; i++) {
41432            if (sessions[i] === token) {
41433                sessions.splice(i, 1);
41434                break;
41435            }
41436        }
41437    }
41438
41439    // Function to create our session token objects which manage the EME
41440    // MediaKeySession and session-specific event handler
41441    function createSessionToken(session, initData, sessionType) {
41442
41443        var token = { // Implements SessionToken
41444            session: session,
41445            initData: initData,
41446
41447            // This is our main event handler for all desired MediaKeySession events
41448            // These events are translated into our API-independent versions of the
41449            // same events
41450            handleEvent: function handleEvent(event) {
41451                switch (event.type) {
41452                    case 'keystatuseschange':
41453                        eventBus.trigger(events.KEY_STATUSES_CHANGED, { data: this });
41454                        break;
41455
41456                    case 'message':
41457                        var message = ArrayBuffer.isView(event.message) ? event.message.buffer : event.message;
41458                        eventBus.trigger(events.INTERNAL_KEY_MESSAGE, { data: new _voKeyMessage2['default'](this, message, undefined, event.messageType) });
41459                        break;
41460                }
41461            },
41462
41463            getSessionID: function getSessionID() {
41464                return session.sessionId;
41465            },
41466
41467            getExpirationTime: function getExpirationTime() {
41468                return session.expiration;
41469            },
41470
41471            getKeyStatuses: function getKeyStatuses() {
41472                return session.keyStatuses;
41473            },
41474
41475            getSessionType: function getSessionType() {
41476                return sessionType;
41477            }
41478        };
41479
41480        // Add all event listeners
41481        session.addEventListener('keystatuseschange', token);
41482        session.addEventListener('message', token);
41483
41484        // Register callback for session closed Promise
41485        session.closed.then(function () {
41486            removeSession(token);
41487            log('DRM: Session closed.  SessionID = ' + token.getSessionID());
41488            eventBus.trigger(events.KEY_SESSION_CLOSED, { data: token.getSessionID() });
41489        });
41490
41491        // Add to our session list
41492        sessions.push(token);
41493
41494        return token;
41495    }
41496
41497    instance = {
41498        getAllInitData: getAllInitData,
41499        requestKeySystemAccess: requestKeySystemAccess,
41500        getKeySystem: getKeySystem,
41501        selectKeySystem: selectKeySystem,
41502        setMediaElement: setMediaElement,
41503        setServerCertificate: setServerCertificate,
41504        createKeySession: createKeySession,
41505        updateKeySession: updateKeySession,
41506        loadKeySession: loadKeySession,
41507        removeKeySession: removeKeySession,
41508        closeKeySession: closeKeySession,
41509        reset: reset
41510    };
41511
41512    setup();
41513
41514    return instance;
41515}
41516
41517ProtectionModel_21Jan2015.__dashjs_factory_name = 'ProtectionModel_21Jan2015';
41518exports['default'] = dashjs.FactoryMaker.getClassFactory(ProtectionModel_21Jan2015);
41519/* jshint ignore:line */
41520module.exports = exports['default'];
41521
41522},{"150":150,"162":162,"163":163,"165":165,"168":168}],156:[function(_dereq_,module,exports){
41523/**
41524 * The copyright in this software is being made available under the BSD License,
41525 * included below. This software may be subject to other third party and contributor
41526 * rights, including patent rights, and no such rights are granted under this license.
41527 *
41528 * Copyright (c) 2013, Dash Industry Forum.
41529 * All rights reserved.
41530 *
41531 * Redistribution and use in source and binary forms, with or without modification,
41532 * are permitted provided that the following conditions are met:
41533 *  * Redistributions of source code must retain the above copyright notice, this
41534 *  list of conditions and the following disclaimer.
41535 *  * Redistributions in binary form must reproduce the above copyright notice,
41536 *  this list of conditions and the following disclaimer in the documentation and/or
41537 *  other materials provided with the distribution.
41538 *  * Neither the name of Dash Industry Forum nor the names of its
41539 *  contributors may be used to endorse or promote products derived from this software
41540 *  without specific prior written permission.
41541 *
41542 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
41543 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
41544 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
41545 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
41546 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
41546INCLUDING, BUT
41547 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
41548 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
41549 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41550 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41551 *  POSSIBILITY OF SUCH DAMAGE.
41552 */
41553
41554/**
41555 * Implementation of the EME APIs as of the 3 Feb 2014 state of the specification.
41556 *
41557 * Implemented by Internet Explorer 11 (Windows 8.1)
41558 *
41559 * @implements ProtectionModel
41560 * @class
41561 */
41562
41563'use strict';
41564
41565Object.defineProperty(exports, '__esModule', {
41566    value: true
41567});
41568
41569function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
41570
41571var _controllersProtectionKeyController = _dereq_(150);
41572
41573var _controllersProtectionKeyController2 = _interopRequireDefault(_controllersProtectionKeyController);
41574
41575var _voNeedKey = _dereq_(168);
41576
41577var _voNeedKey2 = _interopRequireDefault(_voNeedKey);
41578
41579var _voKeyError = _dereq_(162);
41580
41581var _voKeyError2 = _interopRequireDefault(_voKeyError);
41582
41583var _voKeyMessage = _dereq_(163);
41584
41585var _voKeyMessage2 = _interopRequireDefault(_voKeyMessage);
41586
41587var _voKeySystemConfiguration = _dereq_(166);
41588
41589var _voKeySystemConfiguration2 = _interopRequireDefault(_voKeySystemConfiguration);
41590
41591var _voKeySystemAccess = _dereq_(165);
41592
41593var _voKeySystemAccess2 = _interopRequireDefault(_voKeySystemAccess);
41594
41595function ProtectionModel_3Feb2014(config) {
41596
41597    var context = this.context;
41598    var eventBus = config.eventBus; //Need to pass in here so we can use same instance since this is optional module
41599    var events = config.events;
41600    var log = config.log;
41601    var api = config.api;
41602
41603    var instance = undefined,
41604        videoElement = undefined,
41605        keySystem = undefined,
41606        mediaKeys = undefined,
41607        keySystemAccess = undefined,
41608        sessions = undefined,
41609        eventHandler = undefined,
41610        protectionKeyController = undefined;
41611
41612    function setup() {
41613        videoElement = null;
41614        keySystem = null;
41615        mediaKeys = null;
41616        keySystemAccess = null;
41617        sessions = [];
41618        protectionKeyController = (0, _controllersProtectionKeyController2['default'])(context).getInstance();
41619        eventHandler = createEventHandler();
41620    }
41621
41622    function reset() {
41623        try {
41624            for (var i = 0; i < sessions.length; i++) {
41625                closeKeySession(sessions[i]);
41626            }
41627            if (videoElement) {
41628                videoElement.removeEventListener(api.needkey, eventHandler);
41629            }
41630            eventBus.trigger(events.TEARDOWN_COMPLETE);
41631        } catch (error) {
41632            eventBus.trigger(events.TEARDOWN_COMPLETE, { error: 'Error tearing down key sessions and MediaKeys! -- ' + error.message });
41633        }
41634    }
41635
41636    function getKeySystem() {
41637        return keySystem;
41638    }
41639
41640    function getAllInitData() {
41641        var retVal = [];
41642        for (var i = 0; i < sessions.length; i++) {
41643            retVal.push(sessions[i].initData);
41644        }
41645        return retVal;
41646    }
41647
41648    function requestKeySystemAccess(ksConfigurations) {
41649
41650        // Try key systems in order, first one with supported key system configuration
41651        // is used
41652        var found = false;
41653        for (var ksIdx = 0; ksIdx < ksConfigurations.length; ksIdx++) {
41654            var systemString = ksConfigurations[ksIdx].ks.systemString;
41655            var configs = ksConfigurations[ksIdx].configs;
41656            var supportedAudio = null;
41657            var supportedVideo = null;
41658
41659            // Try key system configs in order, first one with supported audio/video
41660            // is used
41661            for (var configIdx = 0; configIdx < configs.length; configIdx++) {
41662                var audios = configs[configIdx].audioCapabilities;
41663                var videos = configs[configIdx].videoCapabilities;
41664
41665                // Look for supported audio container/codecs
41666                if (audios && audios.length !== 0) {
41667                    supportedAudio = []; // Indicates that we have a requested audio config
41668                    for (var audioIdx = 0; audioIdx < audios.length; audioIdx++) {
vendor: 9,593 bytes, lines 41669-41889
41669                        if (window[api.MediaKeys].isTypeSupported(systemString, audios[audioIdx].contentType)) {
41670                            supportedAudio.push(audios[audioIdx]);
41671                        }
41672                    }
41673                }
41674
41675                // Look for supported video container/codecs
41676                if (videos && videos.length !== 0) {
41677                    supportedVideo = []; // Indicates that we have a requested video config
41678                    for (var videoIdx = 0; videoIdx < videos.length; videoIdx++) {
41679                        if (window[api.MediaKeys].isTypeSupported(systemString, videos[videoIdx].contentType)) {
41680                            supportedVideo.push(videos[videoIdx]);
41681                        }
41682                    }
41683                }
41684
41685                // No supported audio or video in this configuration OR we have
41686                // requested audio or video configuration that is not supported
41687                if (!supportedAudio && !supportedVideo || supportedAudio && supportedAudio.length === 0 || supportedVideo && supportedVideo.length === 0) {
41688                    continue;
41689                }
41690
41691                // This configuration is supported
41692                found = true;
41693                var ksConfig = new _voKeySystemConfiguration2['default'](supportedAudio, supportedVideo);
41694                var ks = protectionKeyController.getKeySystemBySystemString(systemString);
41695                eventBus.trigger(events.KEY_SYSTEM_ACCESS_COMPLETE, { data: new _voKeySystemAccess2['default'](ks, ksConfig) });
41696                break;
41697            }
41698        }
41699        if (!found) {
41700            eventBus.trigger(events.KEY_SYSTEM_ACCESS_COMPLETE, { error: 'Key system access denied! -- No valid audio/video content configurations detected!' });
41701        }
41702    }
41703
41704    function selectKeySystem(ksAccess) {
41705        try {
41706            mediaKeys = ksAccess.mediaKeys = new window[api.MediaKeys](ksAccess.keySystem.systemString);
41707            keySystem = ksAccess.keySystem;
41708            keySystemAccess = ksAccess;
41709            if (videoElement) {
41710                setMediaKeys();
41711            }
41712            eventBus.trigger(events.INTERNAL_KEY_SYSTEM_SELECTED);
41713        } catch (error) {
41714            eventBus.trigger(events.INTERNAL_KEY_SYSTEM_SELECTED, { error: 'Error selecting keys system (' + keySystem.systemString + ')! Could not create MediaKeys -- TODO' });
41715        }
41716    }
41717
41718    function setMediaElement(mediaElement) {
41719        if (videoElement === mediaElement) return;
41720
41721        // Replacing the previous element
41722        if (videoElement) {
41723            videoElement.removeEventListener(api.needkey, eventHandler);
41724        }
41725
41726        videoElement = mediaElement;
41727
41728        // Only if we are not detaching from the existing element
41729        if (videoElement) {
41730            videoElement.addEventListener(api.needkey, eventHandler);
41731            if (mediaKeys) {
41732                setMediaKeys();
41733            }
41734        }
41735    }
41736
41737    function createKeySession(initData /*, keySystemType */) {
41738
41739        if (!keySystem || !mediaKeys || !keySystemAccess) {
41740            throw new Error('Can not create sessions until you have selected a key system');
41741        }
41742
41743        // Use the first video capability for the contentType.
41744        // TODO:  Not sure if there is a way to concatenate all capability data into a RFC6386-compatible format
41745
41746        // If player is trying to playback Audio only stream - don't error out.
41747        var capabilities = null;
41748
41749        if (keySystemAccess.ksConfiguration.videoCapabilities !== null && keySystemAccess.ksConfiguration.videoCapabilities.length > 0) capabilities = keySystemAccess.ksConfiguration.videoCapabilities[0];
41750
41751        if (capabilities === null && keySystemAccess.ksConfiguration.audioCapabilities !== null && keySystemAccess.ksConfiguration.audioCapabilities.length > 0) capabilities = keySystemAccess.ksConfiguration.audioCapabilities[0];
41752
41753        if (capabilities === null) throw new Error('Can not create sessions for unknown content types.');
41754
41755        var contentType = capabilities.contentType;
41756        var session = mediaKeys.createSession(contentType, new Uint8Array(initData));
41757        var sessionToken = createSessionToken(session, initData);
41758
41759        // Add all event listeners
41760        session.addEventListener(api.error, sessionToken);
41761        session.addEventListener(api.message, sessionToken);
41762        session.addEventListener(api.ready, sessionToken);
41763        session.addEventListener(api.close, sessionToken);
41764
41765        // Add to our session list
41766        sessions.push(sessionToken);
41767        log('DRM: Session created.  SessionID = ' + sessionToken.getSessionID());
41768        eventBus.trigger(events.KEY_SESSION_CREATED, { data: sessionToken });
41769    }
41770
41771    function updateKeySession(sessionToken, message) {
41772
41773        var session = sessionToken.session;
41774
41775        if (!protectionKeyController.isClearKey(keySystem)) {
41776            // Send our request to the key session
41777            session.update(new Uint8Array(message));
41778        } else {
41779            // For clearkey, message is a ClearKeyKeySet
41780            session.update(new Uint8Array(message.toJWK()));
41781        }
41782    }
41783
41784    /**
41785     * Close the given session and release all associated keys.  Following
41786     * this call, the sessionToken becomes invalid
41787     *
41788     * @param {Object} sessionToken - the session token
41789     */
41790    function closeKeySession(sessionToken) {
41791
41792        var session = sessionToken.session;
41793
41794        // Remove event listeners
41795        session.removeEventListener(api.error, sessionToken);
41796        session.removeEventListener(api.message, sessionToken);
41797        session.removeEventListener(api.ready, sessionToken);
41798        session.removeEventListener(api.close, sessionToken);
41799
41800        // Remove from our session list
41801        for (var i = 0; i < sessions.length; i++) {
41802            if (sessions[i] === sessionToken) {
41803                sessions.splice(i, 1);
41804                break;
41805            }
41806        }
41807
41808        // Send our request to the key session
41809        session[api.release]();
41810    }
41811
41812    function setServerCertificate() /*serverCertificate*/{/* Not supported */}
41813    function loadKeySession() /*sessionID*/{/* Not supported */}
41814    function removeKeySession() /*sessionToken*/{/* Not supported */}
41815
41816    function createEventHandler() {
41817        return {
41818            handleEvent: function handleEvent(event) {
41819                switch (event.type) {
41820
41821                    case api.needkey:
41822                        if (event.initData) {
41823                            var initData = ArrayBuffer.isView(event.initData) ? event.initData.buffer : event.initData;
41824                            eventBus.trigger(events.NEED_KEY, { key: new _voNeedKey2['default'](initData, 'cenc') });
41825                        }
41826                        break;
41827                }
41828            }
41829        };
41830    }
41831
41832    // IE11 does not let you set MediaKeys until it has entered a certain
41833    // readyState, so we need this logic to ensure we don't set the keys
41834    // too early
41835    function setMediaKeys() {
41836        var boundDoSetKeys = null;
41837        var doSetKeys = function doSetKeys() {
41838            videoElement.removeEventListener('loadedmetadata', boundDoSetKeys);
41839            videoElement[api.setMediaKeys](mediaKeys);
41840            eventBus.trigger(events.VIDEO_ELEMENT_SELECTED);
41841        };
41842        if (videoElement.readyState >= 1) {
41843            doSetKeys();
41844        } else {
41845            boundDoSetKeys = doSetKeys.bind(this);
41846            videoElement.addEventListener('loadedmetadata', boundDoSetKeys);
41847        }
41848    }
41849
41850    // Function to create our session token objects which manage the EME
41851    // MediaKeySession and session-specific event handler
41852    function createSessionToken(keySession, initData) {
41853        return {
41854            // Implements SessionToken
41855            session: keySession,
41856            initData: initData,
41857
41858            getSessionID: function getSessionID() {
41859                return this.session.sessionId;
41860            },
41861
41862            getExpirationTime: function getExpirationTime() {
41863                return NaN;
41864            },
41865
41866            getSessionType: function getSessionType() {
41867                return 'temporary';
41868            },
41869            // This is our main event handler for all desired MediaKeySession events
41870            // These events are translated into our API-independent versions of the
41871            // same events
41872            handleEvent: function handleEvent(event) {
41873                switch (event.type) {
41874
41875                    case api.error:
41876                        var errorStr = 'KeyError'; // TODO: Make better string from event
41877                        eventBus.trigger(events.KEY_ERROR, { data: new _voKeyError2['default'](this, errorStr) });
41878                        break;
41879                    case api.message:
41880                        var message = ArrayBuffer.isView(event.message) ? event.message.buffer : event.message;
41881                        eventBus.trigger(events.INTERNAL_KEY_MESSAGE, { data: new _voKeyMessage2['default'](this, message, event.destinationURL) });
41882                        break;
41883                    case api.ready:
41884                        log('DRM: Key added.');
41885                        eventBus.trigger(events.KEY_ADDED);
41886                        break;
41887
41888                    case api.close:
41889                        log('DRM: Session closed.  SessionID = ' + this.get
41889SessionID());
41890                        eventBus.trigger(events.KEY_SESSION_CLOSED, { data: this.getSessionID() });
41891                        break;
41892                }
41893            }
41894        };
41895    }
41896
41897    instance = {
41898        getAllInitData: getAllInitData,
41899        requestKeySystemAccess: requestKeySystemAccess,
41900        getKeySystem: getKeySystem,
41901        selectKeySystem: selectKeySystem,
41902        setMediaElement: setMediaElement,
41903        createKeySession: createKeySession,
41904        updateKeySession: updateKeySession,
41905        closeKeySession: closeKeySession,
41906        setServerCertificate: setServerCertificate,
41907        loadKeySession: loadKeySession,
41908        removeKeySession: removeKeySession,
41909        reset: reset
41910    };
41911
41912    setup();
41913
41914    return instance;
41915}
41916
41917ProtectionModel_3Feb2014.__dashjs_factory_name = 'ProtectionModel_3Feb2014';
41918exports['default'] = dashjs.FactoryMaker.getClassFactory(ProtectionModel_3Feb2014);
41919/* jshint ignore:line */
41920module.exports = exports['default'];
41921
41922},{"150":150,"162":162,"163":163,"165":165,"166":166,"168":168}],157:[function(_dereq_,module,exports){
41923/**
41924 * The copyright in this software is being made available under the BSD License,
41925 * included below. This software may be subject to other third party and contributor
41926 * rights, including patent rights, and no such rights are granted under this license.
41927 *
41928 * Copyright (c) 2013, Dash Industry Forum.
41929 * All rights reserved.
41930 *
41931 * Redistribution and use in source and binary forms, with or without modification,
41932 * are permitted provided that the following conditions are met:
41933 *  * Redistributions of source code must retain the above copyright notice, this
41934 *  list of conditions and the following disclaimer.
41935 *  * Redistributions in binary form must reproduce the above copyright notice,
41936 *  this list of conditions and the following disclaimer in the documentation and/or
41937 *  other materials provided with the distribution.
41938 *  * Neither the name of Dash Industry Forum nor the names of its
41939 *  contributors may be used to endorse or promote products derived from this software
41940 *  without specific prior written permission.
41941 *
41942 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
41943 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
41944 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
41945 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
41946 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41947 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
41948 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
41949 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41950 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41951 *  POSSIBILITY OF SUCH DAMAGE.
41952 */
41953
41954/**
41955 * CableLabs ClearKey license server implementation
41956 *
41957 * For testing purposes and evaluating potential uses for ClearKey, we have developed
41958 * a dirt-simple API for requesting ClearKey licenses from a remote server.
41959 *
41960 * @implements LicenseServer
41961 * @class
41962 */
41963'use strict';
41964
41965Object.defineProperty(exports, '__esModule', {
41966    value: true
41967});
41968
41969function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
41970
41971var _voKeyPair = _dereq_(164);
41972
41973var _voKeyPair2 = _interopRequireDefault(_voKeyPair);
41974
41975var _voClearKeyKeySet = _dereq_(161);
41976
41977var _voClearKeyKeySet2 = _interopRequireDefault(_voClearKeyKeySet);
41978
41979function ClearKey() {
41980
41981    var instance = undefined;
41982
41983    function getServerURLFromMessage(url, message /*, messageType*/) {
41984        // Build ClearKey server query string
41985        var jsonMsg = JSON.parse(String.fromCharCode.apply(null, new Uint8Array(message)));
41986        url += '/?';
41987        for (var i = 0; i < jsonMsg.kids.length; i++) {
41988            url += jsonMsg.kids[i] + '&';
41989        }
41990        url = url.substring(0, url.length - 1);
41991        return url;
41992    }
41993
41994    function getHTTPMethod() /*messageType*/{
41995        return 'GET';
41996    }
41997
41998    function getResponseType() /*keySystemStr*/{
41999        return 'json';
42000    }
42001
42002    function getLicenseMessage(serverResponse /*, keySystemStr, messageType*/) {
42003        if (!serverResponse.hasOwnProperty('keys')) {
42004            return null;
42005        }
42006        var keyPairs = [];
42007        for (var i = 0; i < serverResponse.keys.length; i++) {
42008            var keypair = serverResponse.keys[i];
42009            var keyid = keypair.kid.replace(/=/g, '');
42010            var key = keypair.k.replace(/=/g, '');
42011
42012            keyPairs.push(new _voKeyPair2['default'](keyid, key));
42013        }
42014        return new _voClearKeyKeySet2['default'](keyPairs);
42015    }
42016
42017    function getErrorResponse(serverResponse /*, keySystemStr, messageType*/) {
42018        return String.fromCharCode.apply(null, new Uint8Array(serverResponse));
42019    }
42020
42021    instance = {
42022        getServerURLFromMessage: getServerURLFromMessage,
42023        getHTTPMethod: getHTTPMethod,
42024        getResponseType: getResponseType,
42025        getLicenseMessage: getLicenseMessage,
42026        getErrorResponse: getErrorResponse
42027    };
42028
42029    return instance;
42030}
42031
42032ClearKey.__dashjs_factory_name = 'ClearKey';
42033exports['default'] = dashjs.FactoryMaker.getSingletonFactory(ClearKey);
42034/* jshint ignore:line */
42035module.exports = exports['default'];
42036
42037},{"161":161,"164":164}],158:[function(_dereq_,module,exports){
42038/**
42039 * The copyright in this software is being made available under the BSD License,
42040 * included below. This software may be subject to other third party and contributor
42041 * rights, including patent rights, and no such rights are granted under this license.
42042 *
42043 * Copyright (c) 2013, Dash Industry Forum.
42044 * All rights reserved.
42045 *
42046 * Redistribution and use in source and binary forms, with or without modification,
42047 * are permitted provided that the following conditions are met:
42048 *  * Redistributions of source code must retain the above copyright notice, this
42049 *  list of conditions and the following disclaimer.
42050 *  * Redistributions in binary form must reproduce the above copyright notice,
42051 *  this list of conditions and the following disclaimer in the documentation and/or
42052 *  other materials provided with the distribution.
42053 *  * Neither the name of Dash Industry Forum nor the names of its
42054 *  contributors may be used to endorse or promote products derived from this software
42055 *  without specific prior written permission.
42056 *
42057 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
42058 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
42059 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
42060 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
42061 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
42061INCLUDING, BUT
42062 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
42063 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
42064 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42065 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42066 *  POSSIBILITY OF SUCH DAMAGE.
42067 */
42068
42069/**
42070 * CastLabs DRMToday License Server implementation
42071 *
42072 * @implements LicenseServer
42073 * @class
42074 */
42075
42076'use strict';
42077
42078Object.defineProperty(exports, '__esModule', {
42079    value: true
42080});
42081function DRMToday(config) {
42082
42083    var BASE64 = config.BASE64;
42084
42085    var keySystems = {
42086        'com.widevine.alpha': {
42087            responseType: 'json',
42088            getLicenseMessage: function getLicenseMessage(response) {
42089                return BASE64.decodeArray(response.license);
42090            },
42091            getErrorResponse: function getErrorResponse(response) {
42092                return response;
42093            }
42094        },
42095        'com.microsoft.playready': {
42096            responseType: 'arraybuffer',
42097            getLicenseMessage: function getLicenseMessage(response) {
42098                return response;
42099            },
42100            getErrorResponse: function getErrorResponse(response) {
42101                return String.fromCharCode.apply(null, new Uint8Array(response));
42102            }
42103        }
42104    };
42105
42106    var instance = undefined;
42107
42108    function checkConfig() {
42109        if (!BASE64 || !BASE64.hasOwnProperty('decodeArray')) {
42110            throw new Error('Missing config parameter(s)');
42111        }
42112    }
42113
42114    function getServerURLFromMessage(url /*, message, messageType*/) {
42115        return url;
42116    }
42117
42118    function getHTTPMethod() /*messageType*/{
42119        return 'POST';
42120    }
42121
42122    function getResponseType(keySystemStr /*, messageType*/) {
42123        return keySystems[keySystemStr].responseType;
42124    }
42125
42126    function getLicenseMessage(serverResponse, keySystemStr /*, messageType*/) {
42127        checkConfig();
42128        return keySystems[keySystemStr].getLicenseMessage(serverResponse);
42129    }
42130
42131    function getErrorResponse(serverResponse, keySystemStr /*, messageType*/) {
42132        return keySystems[keySystemStr].getErrorResponse(serverResponse);
42133    }
42134
42135    instance = {
42136        getServerURLFromMessage: getServerURLFromMessage,
42137        getHTTPMethod: getHTTPMethod,
42138        getResponseType: getResponseType,
42139        getLicenseMessage: getLicenseMessage,
42140        getErrorResponse: getErrorResponse
42141    };
42142
42143    return instance;
42144}
42145
42146DRMToday.__dashjs_factory_name = 'DRMToday';
42147exports['default'] = dashjs.FactoryMaker.getSingletonFactory(DRMToday);
42148/* jshint ignore:line */
42149module.exports = exports['default'];
42150
42151},{}],159:[function(_dereq_,module,exports){
42152/**
42153 * The copyright in this software is being made available under the BSD License,
42154 * included below. This software may be subject to other third party and contributor
42155 * rights, including patent rights, and no such rights are granted under this license.
42156 *
42157 * Copyright (c) 2013, Dash Industry Forum.
42158 * All rights reserved.
42159 *
42160 * Redistribution and use in source and binary forms, with or without modification,
42161 * are permitted provided that the following conditions are met:
42162 *  * Redistributions of source code must retain the above copyright notice, this
42163 *  list of conditions and the following disclaimer.
42164 *  * Redistributions in binary form must reproduce the above copyright notice,
42165 *  this list of conditions and the following disclaimer in the documentation and/or
42166 *  other materials provided with the distribution.
42167 *  * Neither the name of Dash Industry Forum nor the names of its
42168 *  contributors may be used to endorse or promote products derived from this software
42169 *  without specific prior written permission.
42170 *
42171 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
42172 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
42173 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
42174 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
42175 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
42175INCLUDING, BUT
42176 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
42177 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
42178 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42179 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42180 *  POSSIBILITY OF SUCH DAMAGE.
42181 */
42182
42183/* global escape: true */
42184
42185/**
42186 * Microsoft PlayReady Test License Server
42187 *
42188 * For testing content that uses the PlayReady test server at
42189 *
42190 * @implements LicenseServer
42191 * @class
42192 */
42193
42194'use strict';
42195
42196Object.defineProperty(exports, '__esModule', {
42197    value: true
42198});
42199function PlayReady() {
42200
42201    var instance = undefined;
42202
42203    var soap = 'http://schemas.xmlsoap.org/soap/envelope/';
42204
42205    function uintToString(arrayBuffer) {
42206        var encodedString = String.fromCharCode.apply(null, new Uint8Array(arrayBuffer));
42207        var decodedString = decodeURIComponent(escape(encodedString));
42208        return decodedString;
42209    }
42210
42211    function parseServerResponse(serverResponse) {
42212        if (window.DOMParser) {
42213            var stringResponse = uintToString(serverResponse);
42214            var parser = new window.DOMParser();
42215            var xmlDoc = parser.parseFromString(stringResponse, 'text/xml');
42216            var envelope = xmlDoc ? xmlDoc.getElementsByTagNameNS(soap, 'Envelope')[0] : null;
42217            var body = envelope ? envelope.getElementsByTagNameNS(soap, 'Body')[0] : null;
42218            var fault = body ? body.getElementsByTagNameNS(soap, 'Fault')[0] : null;
42219
42220            if (fault) {
42221                return null;
42222            }
42223        }
42224        return serverResponse;
42225    }
42226
42227    function parseErrorResponse(serverResponse) {
42228        var faultstring = '';
42229        var statusCode = '';
42230        var message = '';
42231        var idStart = -1;
42232        var idEnd = -1;
42233
42234        if (window.DOMParser) {
42235            var stringResponse = uintToString(serverResponse);
42236            var parser = new window.DOMParser();
42237            var xmlDoc = parser.parseFromString(stringResponse, 'text/xml');
42238            var envelope = xmlDoc ? xmlDoc.getElementsByTagNameNS(soap, 'Envelope')[0] : null;
42239            var body = envelope ? envelope.getElementsByTagNameNS(soap, 'Body')[0] : null;
42240            var fault = body ? body.getElementsByTagNameNS(soap, 'Fault')[0] : null;
42241            var detail = fault ? fault.getElementsByTagName('detail')[0] : null;
42242            var exception = detail ? detail.getElementsByTagName('Exception')[0] : null;
42243            var node = null;
42244
42245            if (fault === null) {
42246                return stringResponse;
42247            }
42248
42249            node = fault.getElementsByTagName('faultstring')[0].firstChild;
42250            faultstring = node ? node.nodeValue : null;
42251
42252            if (exception !== null) {
42253                node = exception.getElementsByTagName('StatusCode')[0];
42254                statusCode = node ? node.firstChild.nodeValue : null;
42255                node = exception.getElementsByTagName('Message')[0];
42256                message = node ? node.firstChild.nodeValue : null;
42257                idStart = message ? message.lastIndexOf('[') + 1 : -1;
42258                idEnd = message ? message.indexOf(']') : -1;
42259                message = message ? message.substring(idStart, idEnd) : '';
42260            }
42261        }
42262
42263        var errorString = 'code: ' + statusCode + ', name: ' + faultstring;
42264        if (message) {
42265            errorString += ', message: ' + message;
42266        }
42267
42268        return errorString;
42269    }
42270
42271    function getServerURLFromMessage(url /*, message, messageType*/) {
42272        return url;
42273    }
42274
42275    function getHTTPMethod() /*messageType*/{
42276        return 'POST';
42277    }
42278
42279    function getResponseType() /*keySystemStr, messageType*/{
42280        return 'arraybuffer';
42281    }
42282
42283    function getLicenseMessage(serverResponse /*, keySystemStr, messageType*/) {
42284        return parseServerResponse.call(this, serverResponse);
42285    }
42286
42287    function getErrorResponse(serverResponse /*, keySystemStr, messageType*/) {
42288        return parseErrorResponse.call(this, serverResponse);
42289    }
42290
42291    instance = {
42292        getServerURLFromMessage: getServerURLFromMessage,
42293        getHTTPMethod: getHTTPMethod,
42294        getResponseType: getResponseType,
42295        getLicenseMessage: getLicenseMessage,
42296        getErrorResponse: getErrorResponse
42297    };
42298
42299    return instance;
42300}
42301
42302PlayReady.__dashjs_factory_name = 'PlayReady';
42303exports['default'] = dashjs.FactoryMaker.getSingletonFactory(PlayReady);
42304/* jshint ignore:line */
42305module.exports = exports['default'];
42306
42307},{}],160:[function(_dereq_,module,exports){
42308/**
42309 * The copyright in this software is being made available under the BSD License,
42310 * included below. This software may be subject to other third party and contributor
42311 * rights, including patent rights, and no such rights are granted under this license.
42312 *
42313 * Copyright (c) 2013, Dash Industry Forum.
42314 * All rights reserved.
42315 *
42316 * Redistribution and use in source and binary forms, with or without modification,
42317 * are permitted provided that the following conditions are met:
42318 *  * Redistributions of source code must retain the above copyright notice, this
42319 *  list of conditions and the following disclaimer.
42320 *  * Redistributions in binary form must reproduce the above copyright notice,
42321 *  this list of conditions and the following disclaimer in the documentation and/or
42322 *  other materials provided with the distribution.
42323 *  * Neither the name of Dash Industry Forum nor the names of its
42324 *  contributors may be used to endorse or promote products derived from this software
42325 *  without specific prior written permission.
42326 *
42327 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
42328 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
42329 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
42330 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
42331 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42332 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
42333 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
42334 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42335 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42336 *  POSSIBILITY OF SUCH DAMAGE.
42337 */
42338
42339'use strict';
42340
42341Object.defineProperty(exports, '__esModule', {
42342    value: true
42343});
42344function Widevine() {
42345
42346    var instance = undefined;
42347
42348    function getServerURLFromMessage(url /*, message, messageType*/) {
42349        return url;
42350    }
42351
42352    function getHTTPMethod() /*messageType*/{
42353        return 'POST';
42354    }
42355
42356    function getResponseType() /*keySystemStr, messageType*/{
42357        return 'arraybuffer';
42358    }
42359
42360    function getLicenseMessage(serverResponse /*, keySystemStr, messageType*/) {
42361        return serverResponse;
42362    }
42363
42364    function getErrorResponse(serverResponse /*, keySystemStr, messageType*/) {
42365        return String.fromCharCode.apply(null, new Uint8Array(serverResponse));
42366    }
42367
42368    instance = {
42369        getServerURLFromMessage: getServerURLFromMessage,
42370        getHTTPMethod: getHTTPMethod,
42371        getResponseType: getResponseType,
42372        getLicenseMessage: getLicenseMessage,
42373        getErrorResponse: getErrorResponse
42374    };
42375
42376    return instance;
42377}
42378
42379Widevine.__dashjs_factory_name = 'Widevine';
42380exports['default'] = dashjs.FactoryMaker.getSingletonFactory(Widevine);
42381/* jshint ignore:line */
42382module.exports = exports['default'];
42383
42384},{}],161:[function(_dereq_,module,exports){
42385/**
42386 * The copyright in this software is being made available under the BSD License,
42387 * included below. This software may be subject to other third party and contributor
42388 * rights, including patent rights, and no such rights are granted under this license.
42389 *
42390 * Copyright (c) 2013, Dash Industry Forum.
42391 * All rights reserved.
42392 *
42393 * Redistribution and use in source and binary forms, with or without modification,
42394 * are permitted provided that the following conditions are met:
42395 *  * Redistributions of source code must retain the above copyright notice, this
42396 *  list of conditions and the following disclaimer.
42397 *  * Redistributions in binary form must reproduce the above copyright notice,
42398 *  this list of conditions and the following disclaimer in the documentation and/or
42399 *  other materials provided with the distribution.
42400 *  * Neither the name of Dash Industry Forum nor the names of its
42401 *  contributors may be used to endorse or promote products derived from this software
42402 *  without specific prior written permission.
42403 *
42404 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
42405 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
42406 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
42407 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
42408 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
42408INCLUDING, BUT
42409 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
42410 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
42411 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42412 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42413 *  POSSIBILITY OF SUCH DAMAGE.
42414 */
42415
42416/**
42417 * @classdesc A collection of ClearKey encryption keys with an (optional) associated
42418 *  type
42419 * @ignore
42420 */
42421'use strict';
42422
42423Object.defineProperty(exports, '__esModule', {
42424    value: true
42425});
42426
42427var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
42428
42429function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
42430
42431var ClearKeyKeySet = (function () {
42432    /**
42433     * @param {Array.<KeyPair>} keyPairs
42434     * @param {string} type the type of keys in this set.  One of either 'persistent'
42435     * or 'temporary'.  Can also be null or undefined.
42436     * @class
42437     * @ignore
42438     */
42439
42440    function ClearKeyKeySet(keyPairs, type) {
42441        _classCallCheck(this, ClearKeyKeySet);
42442
42443        if (type && type !== 'persistent' && type !== 'temporary') throw new Error('Invalid ClearKey key set type!  Must be one of \'persistent\' or \'temporary\'');
42444        this.keyPairs = keyPairs;
42445        this.type = type;
42446    }
42447
42448    /**
42449     * Convert this key set to its JSON Web Key (JWK) representation
42450     *
42451     * @return {ArrayBuffer} JWK object UTF-8 encoded as ArrayBuffer
42452     */
42453
42454    _createClass(ClearKeyKeySet, [{
42455        key: 'toJWK',
42456        value: function toJWK() {
42457            var i = undefined;
42458            var numKeys = this.keyPairs.length;
42459            var jwk = { keys: [] };
42460
42461            for (i = 0; i < numKeys; i++) {
42462                var key = {
42463                    kty: 'oct',
42464                    alg: 'A128KW',
42465                    kid: this.keyPairs[i].keyID,
42466                    k: this.keyPairs[i].key
42467                };
42468                jwk.keys.push(key);
42469            }
42470            if (this.type) {
42471                jwk.type = this.type;
42472            }
42473            var jwkString = JSON.stringify(jwk);
42474            var len = jwkString.length;
42475
42476            // Convert JSON string to ArrayBuffer
42477            var buf = new ArrayBuffer(len);
42478            var bView = new Uint8Array(buf);
42479            for (i = 0; i < len; i++) bView[i] = jwkString.charCodeAt(i);
42480            return buf;
42481        }
42482    }]);
42483
42484    return ClearKeyKeySet;
42485})();
42486
42487exports['default'] = ClearKeyKeySet;
42488module.exports = exports['default'];
42489
42490},{}],162:[function(_dereq_,module,exports){
42491/**
42492 * The copyright in this software is being made available under the BSD License,
42493 * included below. This software may be subject to other third party and contributor
42494 * rights, including patent rights, and no such rights are granted under this license.
42495 *
42496 * Copyright (c) 2013, Dash Industry Forum.
42497 * All rights reserved.
42498 *
42499 * Redistribution and use in source and binary forms, with or without modification,
42500 * are permitted provided that the following conditions are met:
42501 *  * Redistributions of source code must retain the above copyright notice, this
42502 *  list of conditions and the following disclaimer.
42503 *  * Redistributions in binary form must reproduce the above copyright notice,
42504 *  this list of conditions and the following disclaimer in the documentation and/or
42505 *  other materials provided with the distribution.
42506 *  * Neither the name of Dash Industry Forum nor the names of its
42507 *  contributors may be used to endorse or promote products derived from this software
42508 *  without specific prior written permission.
42509 *
42510 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
42511 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
42512 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
42513 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
42514 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
42514INCLUDING, BUT
42515 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
42516 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
42517 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42518 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42519 *  POSSIBILITY OF SUCH DAMAGE.
42520 */
42521
42522/**
42523 * @classdesc EME-independent KeyError
42524 * @ignore
42525 */
42526"use strict";
42527
42528Object.defineProperty(exports, "__esModule", {
42529  value: true
42530});
42531
42532function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
42533
42534var KeyError =
42535/**
42536 * @param {Object} sessionToken the key session to which this error is associated
42537 * @param {string} errorString an informational error message
42538 * @class
42539 * @deprecated Newest versions of EME APIs will not use this error object
42540 */
42541function KeyError(sessionToken, errorString) {
42542  _classCallCheck(this, KeyError);
42543
42544  this.sessionToken = sessionToken;
42545  this.error = errorString;
42546};
42547
42548exports["default"] = KeyError;
42549module.exports = exports["default"];
42550
42551},{}],163:[function(_dereq_,module,exports){
42552/**
42553 * The copyright in this software is being made available under the BSD License,
42554 * included below. This software may be subject to other third party and contributor
42555 * rights, including patent rights, and no such rights are granted under this license.
42556 *
42557 * Copyright (c) 2013, Dash Industry Forum.
42558 * All rights reserved.
42559 *
42560 * Redistribution and use in source and binary forms, with or without modification,
42561 * are permitted provided that the following conditions are met:
42562 *  * Redistributions of source code must retain the above copyright notice, this
42563 *  list of conditions and the following disclaimer.
42564 *  * Redistributions in binary form must reproduce the above copyright notice,
42565 *  this list of conditions and the following disclaimer in the documentation and/or
42566 *  other materials provided with the distribution.
42567 *  * Neither the name of Dash Industry Forum nor the names of its
42568 *  contributors may be used to endorse or promote products derived from this software
42569 *  without specific prior written permission.
42570 *
42571 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
42572 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
42573 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
42574 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
42575 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42576 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
42577 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
42578 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42579 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42580 *  POSSIBILITY OF SUCH DAMAGE.
42581 */
42582/**
42583 * @classdesc EME-independent KeyMessage
42584 * @ignore
42585 */
42586'use strict';
42587
42588Object.defineProperty(exports, '__esModule', {
42589  value: true
42590});
42591
42592function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
42593
42594var KeyMessage =
42595/**
42596 * @param {SessionToken} sessionToken the session
42597 * to which the key message is associated
42598 * @param {ArrayBuffer} message the key message
42599 * @param {string} defaultURL license acquisition URL provided by the CDM
42600 * @param {string} messageType Supported message types can be found
42601 * {@link https://w3c.github.io/encrypted-media/#idl-def-MediaKeyMessageType|here}.
42602 * @class
42603 */
42604function KeyMessage(sessionToken, message, defaultURL, messageType) {
42605  _classCallCheck(this, KeyMessage);
42606
42607  this.sessionToken = sessionToken;
42608  this.message = message;
42609  this.defaultURL = defaultURL;
42610  this.messageType = messageType ? messageType : 'license-request';
42611};
42612
42613exports['default'] = KeyMessage;
42614module.exports = exports['default'];
42615
42616},{}],164:[function(_dereq_,module,exports){
42617/**
42618 * The copyright in this software is being made available under the BSD License,
42619 * included below. This software may be subject to other third party and contributor
42620 * rights, including patent rights, and no such rights are granted under this license.
42621 *
42622 * Copyright (c) 2013, Dash Industry Forum.
42623 * All rights reserved.
42624 *
42625 * Redistribution and use in source and binary forms, with or without modification,
42626 * are permitted provided that the following conditions are met:
42627 *  * Redistributions of source code must retain the above copyright notice, this
42628 *  list of conditions and the following disclaimer.
42629 *  * Redistributions in binary form must reproduce the above copyright notice,
42630 *  this list of conditions and the following disclaimer in the documentation and/or
42631 *  other materials provided with the distribution.
42632 *  * Neither the name of Dash Industry Forum nor the names of its
42633 *  contributors may be used to endorse or promote products derived from this software
42634 *  without specific prior written permission.
42635 *
42636 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
42637 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
42638 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
42639 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
42640 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
42640INCLUDING, BUT
42641 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
42642 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
42643 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42644 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42645 *  POSSIBILITY OF SUCH DAMAGE.
42646 */
42647/**
42648 * @classdesc Represents a 128-bit keyID and 128-bit encryption key
42649 * @ignore
42650 */
42651"use strict";
42652
42653Object.defineProperty(exports, "__esModule", {
42654  value: true
42655});
42656
42657function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
42658
42659var KeyPair =
42660/**
42661 * @param {string} keyID 128-bit key ID, base64 encoded, with no padding
42662 * @param {string} key 128-bit encryption key, base64 encoded, with no padding
42663 * @class
42664 * @ignore
42665 */
42666function KeyPair(keyID, key) {
42667  _classCallCheck(this, KeyPair);
42668
42669  this.keyID = keyID;
42670  this.key = key;
42671};
42672
42673exports["default"] = KeyPair;
42674module.exports = exports["default"];
42675
42676},{}],165:[function(_dereq_,module,exports){
42677/**
42678 * The copyright in this software is being made available under the BSD License,
42679 * included below. This software may be subject to other third party and contributor
42680 * rights, including patent rights, and no such rights are granted under this license.
42681 *
42682 * Copyright (c) 2013, Dash Industry Forum.
42683 * All rights reserved.
42684 *
42685 * Redistribution and use in source and binary forms, with or without modification,
42686 * are permitted provided that the following conditions are met:
42687 *  * Redistributions of source code must retain the above copyright notice, this
42688 *  list of conditions and the following disclaimer.
42689 *  * Redistributions in binary form must reproduce the above copyright notice,
42690 *  this list of conditions and the following disclaimer in the documentation and/or
42691 *  other materials provided with the distribution.
42692 *  * Neither the name of Dash Industry Forum nor the names of its
42693 *  contributors may be used to endorse or promote products derived from this software
42694 *  without specific prior written permission.
42695 *
42696 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
42697 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
42698 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
42699 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
42700 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42701 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
42702 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
42703 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42704 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42705 *  POSSIBILITY OF SUCH DAMAGE.
42706 */
42707/**
42708 * @classdesc Creates a new key system access token.  Represents a valid key system for
42709 * given piece of content and key system requirements.  Used to initialize license
42710 * acquisition operations.
42711 * @ignore
42712 */
42713"use strict";
42714
42715Object.defineProperty(exports, "__esModule", {
42716  value: true
42717});
42718
42719function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
42720
42721var KeySystemAccess =
42722/**
42723 * @param {MediaPlayer.dependencies.protection.KeySystem} keySystem the key system
42724 * @param {KeySystemConfiguration} ksConfiguration the
42725 * subset of configurations passed to the key system access request that are supported
42726 * by this user agent
42727 * @class
42728 * @ignore
42729 */
42730function KeySystemAccess(keySystem, ksConfiguration) {
42731  _classCallCheck(this, KeySystemAccess);
42732
42733  this.keySystem = keySystem;
42734  this.ksConfiguration = ksConfiguration;
42735};
42736
42737exports["default"] = KeySystemAccess;
42738module.exports = exports["default"];
42739
42740},{}],166:[function(_dereq_,module,exports){
42741/**
42742 * The copyright in this software is being made available under the BSD License,
42743 * included below. This software may be subject to other third party and contributor
42744 * rights, including patent rights, and no such rights are granted under this license.
42745 *
42746 * Copyright (c) 2013, Dash Industry Forum.
42747 * All rights reserved.
42748 *
42749 * Redistribution and use in source and binary forms, with or without modification,
42750 * are permitted provided that the following conditions are met:
42751 *  * Redistributions of source code must retain the above copyright notice, this
42752 *  list of conditions and the following disclaimer.
42753 *  * Redistributions in binary form must reproduce the above copyright notice,
42754 *  this list of conditions and the following disclaimer in the documentation and/or
42755 *  other materials provided with the distribution.
42756 *  * Neither the name of Dash Industry Forum nor the names of its
42757 *  contributors may be used to endorse or promote products derived from this software
42758 *  without specific prior written permission.
42759 *
42760 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
42761 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
42762 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
42763 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
42764 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
42764INCLUDING, BUT
42765 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
42766 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
42767 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42768 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42769 *  POSSIBILITY OF SUCH DAMAGE.
42770 */
42771
42772/**
42773 * @classdesc Represents a set of configurations that describe the capabilities desired for
42774 *  support by a given CDM
42775 * @ignore
42776 */
42777'use strict';
42778
42779Object.defineProperty(exports, '__esModule', {
42780    value: true
42781});
42782
42783function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
42784
42785var KeySystemConfiguration =
42786/**
42787 * @param {Array.<MediaCapability>} audioCapabilities array of
42788 * desired audio capabilities.  Higher preference capabilities should be placed earlier
42789 * in the array.
42790 * @param {Array.<MediaCapability>} videoCapabilities array of
42791 * desired video capabilities.  Higher preference capabilities should be placed earlier
42792 * in the array.
42793 * @param {string} distinctiveIdentifier desired use of distinctive identifiers.
42794 * One of "required", "optional", or "not-allowed"
42795 * @param {string} persistentState desired support for persistent storage of
42796 * key systems.  One of "required", "optional", or "not-allowed"
42797 * @param {Array.<string>} sessionTypes List of session types that must
42798 * be supported by the key system
42799 * @class
42800 */
42801function KeySystemConfiguration(audioCapabilities, videoCapabilities, distinctiveIdentifier, persistentState, sessionTypes) {
42802    _classCallCheck(this, KeySystemConfiguration);
42803
42804    this.initDataTypes = ['cenc'];
42805    if (audioCapabilities && audioCapabilities.length) {
42806        this.audioCapabilities = audioCapabilities;
42807    }
42808    if (videoCapabilities && videoCapabilities.length) {
42809        this.videoCapabilities = videoCapabilities;
42810    }
42811    this.distinctiveIdentifier = distinctiveIdentifier;
42812    this.persistentState = persistentState;
42813    this.sessionTypes = sessionTypes;
42814};
42815
42816exports['default'] = KeySystemConfiguration;
42817module.exports = exports['default'];
42818
42819},{}],167:[function(_dereq_,module,exports){
42820/**
42821 * The copyright in this software is being made available under the BSD License,
42822 * included below. This software may be subject to other third party and contributor
42823 * rights, including patent rights, and no such rights are granted under this license.
42824 *
42825 * Copyright (c) 2013, Dash Industry Forum.
42826 * All rights reserved.
42827 *
42828 * Redistribution and use in source and binary forms, with or without modification,
42829 * are permitted provided that the following conditions are met:
42830 *  * Redistributions of source code must retain the above copyright notice, this
42831 *  list of conditions and the following disclaimer.
42832 *  * Redistributions in binary form must reproduce the above copyright notice,
42833 *  this list of conditions and the following disclaimer in the documentation and/or
42834 *  other materials provided with the distribution.
42835 *  * Neither the name of Dash Industry Forum nor the names of its
42836 *  contributors may be used to endorse or promote products derived from this software
42837 *  without specific prior written permission.
42838 *
42839 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
42840 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
42841 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
42842 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
42843 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42844 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
42845 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
42846 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42847 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42848 *  POSSIBILITY OF SUCH DAMAGE.
42849 */
42850/**
42851 * @classdesc A media capability
42852 * @ignore
42853 */
42854"use strict";
42855
42856Object.defineProperty(exports, "__esModule", {
42857  value: true
42858});
42859
42860function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
42861
42862var MediaCapability =
42863/**
42864 * @param {string} contentType MIME type and codecs (RFC6386)
42865 * @param {string} robustness
42866 * @class
42867 * @ignore
42868 */
42869function MediaCapability(contentType, robustness) {
42870  _classCallCheck(this, MediaCapability);
42871
42872  this.contentType = contentType;
42873  this.robustness = robustness;
42874};
42875
42876exports["default"] = MediaCapability;
42877module.exports = exports["default"];
42878
42879},{}],168:[function(_dereq_,module,exports){
42880/**
42881 * The copyright in this software is being made available under the BSD License,
42882 * included below. This software may be subject to other third party and contributor
42883 * rights, including patent rights, and no such rights are granted under this license.
42884 *
42885 * Copyright (c) 2013, Dash Industry Forum.
42886 * All rights reserved.
42887 *
42888 * Redistribution and use in source and binary forms, with or without modification,
42889 * are permitted provided that the following conditions are met:
42890 *  * Redistributions of source code must retain the above copyright notice, this
42891 *  list of conditions and the following disclaimer.
42892 *  * Redistributions in binary form must reproduce the above copyright notice,
42893 *  this list of conditions and the following disclaimer in the documentation and/or
42894 *  other materials provided with the distribution.
42895 *  * Neither the name of Dash Industry Forum nor the names of its
42896 *  contributors may be used to endorse or promote products derived from this software
42897 *  without specific prior written permission.
42898 *
42899 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
42900 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
42901 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
42902 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
42903 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
42903INCLUDING, BUT
42904 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
42905 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
42906 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42907 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42908 *  POSSIBILITY OF SUCH DAMAGE.
42909 */
42910/**
42911 * @classdesc NeedKey
42912 * @ignore
42913 */
42914"use strict";
42915
42916Object.defineProperty(exports, "__esModule", {
42917  value: true
42918});
42919
42920function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
42921
42922var NeedKey =
42923/**
42924 * @param {ArrayBuffer} initData the initialization data
42925 * @param {string} initDataType initialization data type
42926 * @class
42927 */
42928function NeedKey(initData, initDataType) {
42929  _classCallCheck(this, NeedKey);
42930
42931  this.initData = initData;
42932  this.initDataType = initDataType;
42933};
42934
42935exports["default"] = NeedKey;
42936module.exports = exports["default"];
42937
42938},{}],169:[function(_dereq_,module,exports){
42939'use strict';
42940
42941Object.defineProperty(exports, '__esModule', {
42942    value: true
42943});
42944
42945function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
42946
42947var _coreFactoryMakerJs = _dereq_(51);
42948
42949var _coreFactoryMakerJs2 = _interopRequireDefault(_coreFactoryMakerJs);
42950
42951function DroppedFramesHistory() {
42952
42953    var values = [];
42954    var lastDroppedFrames = 0;
42955    var lastTotalFrames = 0;
42956
42957    function push(index, playbackQuality) {
42958        var intervalDroppedFrames = playbackQuality.droppedVideoFrames - lastDroppedFrames;
42959        lastDroppedFrames = playbackQuality.droppedVideoFrames;
42960
42961        var intervalTotalFrames = playbackQuality.totalVideoFrames - lastTotalFrames;
42962        lastTotalFrames = playbackQuality.totalVideoFrames;
42963
42964        if (!isNaN(index)) {
42965            if (!values[index]) {
42966                values[index] = { droppedVideoFrames: intervalDroppedFrames, totalVideoFrames: intervalTotalFrames };
42967            } else {
42968                values[index].droppedVideoFrames += intervalDroppedFrames;
42969                values[index].totalVideoFrames += intervalTotalFrames;
42970            }
42971        }
42972    }
42973
42974    function getDroppedFrameHistory() {
42975        return values;
42976    }
42977
42978    function reset(playbackQuality) {
42979        values = [];
42980        lastDroppedFrames = playbackQuality.droppedVideoFrames;
42981        lastTotalFrames = playbackQuality.totalVideoFrames;
42982    }
42983
42984    return {
42985        push: push,
42986        getFrameHistory: getDroppedFrameHistory,
42987        reset: reset
42988    };
42989}
42990
42991DroppedFramesHistory.__dashjs_factory_name = 'DroppedFramesHistory';
42992var factory = _coreFactoryMakerJs2['default'].getClassFactory(DroppedFramesHistory);
42993exports['default'] = factory;
42994module.exports = exports['default'];
42995
42996},{"51":51}],170:[function(_dereq_,module,exports){
42997/**
42998 * The copyright in this software is being made available under the BSD License,
42999 * included below. This software may be subject to other third party and contributor
43000 * rights, including patent rights, and no such rights are granted under this license.
43001 *
43002 * Copyright (c) 2013, Dash Industry Forum.
43003 * All rights reserved.
43004 *
43005 * Redistribution and use in source and binary forms, with or without modification,
43006 * are permitted provided that the following conditions are met:
43007 *  * Redistributions of source code must retain the above copyright notice, this
43008 *  list of conditions and the following disclaimer.
43009 *  * Redistributions in binary form must reproduce the above copyright notice,
43010 *  this list of conditions and the following disclaimer in the documentation and/or
43011 *  other materials provided with the distribution.
43012 *  * Neither the name of Dash Industry Forum nor the names of its
43013 *  contributors may be used to endorse or promote products derived from this software
43014 *  without specific prior written permission.
43015 *
43016 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
43017 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
43018 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
43019 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
43020 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
43020INCLUDING, BUT
43021 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
43022 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
43023 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
43024 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43025 *  POSSIBILITY OF SUCH DAMAGE.
43026 */
43027
43028'use strict';
43029
43030Object.defineProperty(exports, '__esModule', {
43031    value: true
43032});
43033
43034function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
43035
43036var _coreFactoryMaker = _dereq_(51);
43037
43038var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
43039
43040function RulesContext(config) {
43041
43042    var instance = undefined;
43043    var abrController = config.abrController;
43044    var streamProcessor = config.streamProcessor;
43045    var representationInfo = config.streamProcessor.getCurrentRepresentationInfo();
43046    var switchHistory = config.switchHistory;
43047    var droppedFramesHistory = config.droppedFramesHistory;
43048    var currentRequest = config.currentRequest;
43049    var bufferOccupancyABR = config.useBufferOccupancyABR;
43050
43051    function getMediaType() {
43052        return representationInfo.mediaInfo.type;
43053    }
43054
43055    function getStreamInfo() {
43056        return representationInfo.mediaInfo.streamInfo;
43057    }
43058
43059    function getMediaInfo() {
43060        return representationInfo.mediaInfo;
43061    }
43062
43063    function getRepresentationInfo() {
43064        return representationInfo;
43065    }
43066
43067    function getStreamProcessor() {
43068        return streamProcessor;
43069    }
43070
43071    function getAbrController() {
43072        return abrController;
43073    }
43074
43075    function getSwitchHistory() {
43076        return switchHistory;
43077    }
43078
43079    function getDroppedFramesHistory() {
43080        return droppedFramesHistory;
43081    }
43082
43083    function getCurrentRequest() {
43084        return currentRequest;
43085    }
43086
43087    function useBufferOccupancyABR() {
43088        return bufferOccupancyABR;
43089    }
43090
43091    instance = {
43092        getMediaType: getMediaType,
43093        getMediaInfo: getMediaInfo,
43094        getDroppedFramesHistory: getDroppedFramesHistory,
43095        getCurrentRequest: getCurrentRequest,
43096        getSwitchHistory: getSwitchHistory,
43097        getStreamInfo: getStreamInfo,
43098        getStreamProcessor: getStreamProcessor,
43099        getAbrController: getAbrController,
43100        getRepresentationInfo: getRepresentationInfo,
43101        useBufferOccupancyABR: useBufferOccupancyABR
43102    };
43103
43104    return instance;
43105}
43106
43107RulesContext.__dashjs_factory_name = 'RulesContext';
43108exports['default'] = _coreFactoryMaker2['default'].getClassFactory(RulesContext);
43109module.exports = exports['default'];
43110
43111},{"51":51}],171:[function(_dereq_,module,exports){
43112/**
43113 * The copyright in this software is being made available under the BSD License,
43114 * included below. This software may be subject to other third party and contributor
43115 * rights, including patent rights, and no such rights are granted under this license.
43116 *
43117 * Copyright (c) 2013, Dash Industry Forum.
43118 * All rights reserved.
43119 *
43120 * Redistribution and use in source and binary forms, with or without modification,
43121 * are permitted provided that the following conditions are met:
43122 *  * Redistributions of source code must retain the above copyright notice, this
43123 *  list of conditions and the following disclaimer.
43124 *  * Redistributions in binary form must reproduce the above copyright notice,
43125 *  this list of conditions and the following disclaimer in the documentation and/or
43126 *  other materials provided with the distribution.
43127 *  * Neither the name of Dash Industry Forum nor the names of its
43128 *  contributors may be used to endorse or promote products derived from this software
43129 *  without specific prior written permission.
43130 *
43131 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
43132 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
43133 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
43134 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
43135 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
43135INCLUDING, BUT
43136 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
43137 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
43138 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
43139 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43140 *  POSSIBILITY OF SUCH DAMAGE.
43141 */
43142
43143'use strict';
43144
43145Object.defineProperty(exports, '__esModule', {
43146    value: true
43147});
43148
43149function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
43150
43151var _coreFactoryMaker = _dereq_(51);
43152
43153var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
43154
43155var NO_CHANGE = -1;
43156var PRIORITY = {
43157    DEFAULT: 0.5,
43158    STRONG: 1,
43159    WEAK: 0
43160};
43161
43162function SwitchRequest(q, r, p) {
43163    //TODO refactor all the calls to this to use config to be like everything else.
43164    var instance = undefined;
43165    var quality = undefined;
43166    var priority = undefined;
43167    var reason = undefined;
43168
43169    // check priority value
43170    function getPriority(p) {
43171        var ret = PRIORITY.DEFAULT;
43172
43173        // check that p is one of declared priority value
43174        if (p === PRIORITY.DEFAULT || p === PRIORITY.STRONG || p === PRIORITY.WEAK) {
43175            ret = p;
43176        }
43177        return ret;
43178    }
43179
43180    // init attributes
43181    quality = q === undefined ? NO_CHANGE : q;
43182    priority = getPriority(p);
43183    reason = r === undefined ? null : r;
43184
43185    instance = {
43186        quality: quality,
43187        reason: reason,
43188        priority: priority
43189    };
43190
43191    return instance;
43192}
43193
43194SwitchRequest.__dashjs_factory_name = 'SwitchRequest';
43195var factory = _coreFactoryMaker2['default'].getClassFactory(SwitchRequest);
43196factory.NO_CHANGE = NO_CHANGE;
43197factory.PRIORITY = PRIORITY;
43198_coreFactoryMaker2['default'].updateClassFactory(SwitchRequest.__dashjs_factory_name, factory);
43199
43200exports['default'] = factory;
43201module.exports = exports['default'];
43202
43203},{"51":51}],172:[function(_dereq_,module,exports){
43204/**
43205 * The copyright in this software is being made available under the BSD License,
43206 * included below. This software may be subject to other third party and contributor
43207 * rights, including patent rights, and no such rights are granted under this license.
43208 *
43209 * Copyright (c) 2013, Dash Industry Forum.
43210 * All rights reserved.
43211 *
43212 * Redistribution and use in source and binary forms, with or without modification,
43213 * are permitted provided that the following conditions are met:
43214 *  * Redistributions of source code must retain the above copyright notice, this
43215 *  list of conditions and the following disclaimer.
43216 *  * Redistributions in binary form must reproduce the above copyright notice,
43217 *  this list of conditions and the following disclaimer in the documentation and/or
43218 *  other materials provided with the distribution.
43219 *  * Neither the name of Dash Industry Forum nor the names of its
43220 *  contributors may be used to endorse or promote products derived from this software
43221 *  without specific prior written permission.
43222 *
43223 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
43224 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
43225 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
43226 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
43227 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
43228 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
43229 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
43230 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
43231 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43232 *  POSSIBILITY OF SUCH DAMAGE.
43233 */
43234
43235'use strict';
43236
43237Object.defineProperty(exports, '__esModule', {
43238    value: true
43239});
43240
43241function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
43242
43243var _coreFactoryMakerJs = _dereq_(51);
43244
43245var _coreFactoryMakerJs2 = _interopRequireDefault(_coreFactoryMakerJs);
43246
43247var _SwitchRequestJs = _dereq_(171);
43248
43249var _SwitchRequestJs2 = _interopRequireDefault(_SwitchRequestJs);
43250
43251var SWITCH_REQUEST_HISTORY_DEPTH = 8; // must be > SwitchHistoryRule SAMPLE_SIZE to enable rule
43252
43253function SwitchRequestHistory() {
43254    var switchRequests = []; // running total
43255    var srHistory = []; // history of each switch
43256
43257    function push(switchRequest) {
43258        if (switchRequest.newValue === _SwitchRequestJs2['default'].NO_CHANGE) {
43259            switchRequest.newValue = switchRequest.oldValue;
43260        }
43261        if (!switchRequests[switchRequest.oldValue]) {
43262            switchRequests[switchRequest.oldValue] = { noDrops: 0, drops: 0, dropSize: 0 };
43263        }
43264
43265        // Set switch details
43266        var indexDiff = switchRequest.newValue - switchRequest.oldValue;
43267        var drop = indexDiff < 0 ? 1 : 0;
43268        var dropSize = drop ? -indexDiff : 0;
43269        var noDrop = drop ? 0 : 1;
43270
43271        // Update running totals
43272        switchRequests[switchRequest.oldValue].drops += drop;
43273        switchRequests[switchRequest.oldValue].dropSize += dropSize;
43274        switchRequests[switchRequest.oldValue].noDrops += noDrop;
43275
43276        // Save to history
43277        srHistory.push({ idx: switchRequest.oldValue, noDrop: noDrop, drop: drop, dropSize: dropSize });
43278
43279        // Shift earliest switch off srHistory and readjust to keep depth of running totals constant
43280        if (srHistory.length > SWITCH_REQUEST_HISTORY_DEPTH) {
43281            var srHistoryFirst = srHistory.shift();
43282            switchRequests[srHistoryFirst.idx].drops -= srHistoryFirst.drop;
43283            switchRequests[srHistoryFirst.idx].dropSize -= srHistoryFirst.dropSize;
43284            switchRequests[srHistoryFirst.idx].noDrops -= srHistoryFirst.noDrop;
43285        }
43286    }
43287
43288    function getSwitchRequests() {
43289        return switchRequests;
43290    }
43291
43292    function reset() {
43293        switchRequests = [];
43294        srHistory = [];
43295    }
43296
43297    return {
43298        push: push,
43299        getSwitchRequests: getSwitchRequests,
43300        reset: reset
43301    };
43302}
43303
43304SwitchRequestHistory.__dashjs_factory_name = 'SwitchRequestHistory';
43305var factory = _coreFactoryMakerJs2['default'].getClassFactory(SwitchRequestHistory);
43306exports['default'] = factory;
43307module.exports = exports['default'];
43308
43309},{"171":171,"51":51}],173:[function(_dereq_,module,exports){
43310/**
43311 * The copyright in this software is being made available under the BSD License,
43312 * included below. This software may be subject to other third party and contributor
43313 * rights, including patent rights, and no such rights are granted under this license.
43314 *
43315 * Copyright (c) 2017, Dash Industry Forum.
43316 * All rights reserved.
43317 *
43318 * Redistribution and use in source and binary forms, with or without modification,
43319 * are permitted provided that the following conditions are met:
43320 *  * Redistributions of source code must retain the above copyright notice, this
43321 *  list of conditions and the following disclaimer.
43322 *  * Redistributions in binary form must reproduce the above copyright notice,
43323 *  this list of conditions and the following disclaimer in the documentation and/or
43324 *  other materials provided with the distribution.
43325 *  * Neither the name of Dash Industry Forum nor the names of its
43326 *  contributors may be used to endorse or promote products derived from this software
43327 *  without specific prior written permission.
43328 *
43329 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
43330 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
43331 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
43332 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
43333 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
43333INCLUDING, BUT
43334 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
43335 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
43336 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
43337 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43338 *  POSSIBILITY OF SUCH DAMAGE.
43339 */
43340
43341'use strict';
43342
43343Object.defineProperty(exports, '__esModule', {
43344    value: true
43345});
43346
43347function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
43348
43349var _constantsConstants = _dereq_(100);
43350
43351var _constantsConstants2 = _interopRequireDefault(_constantsConstants);
43352
43353var _coreFactoryMakerJs = _dereq_(51);
43354
43355var _coreFactoryMakerJs2 = _interopRequireDefault(_coreFactoryMakerJs);
43356
43357// throughput generally stored in kbit/s
43358// latency generally stored in ms
43359
43360function ThroughputHistory(config) {
43361
43362    // sliding window constants
43363    var MAX_MEASUREMENTS_TO_KEEP = 20;
43364    var AVERAGE_THROUGHPUT_SAMPLE_AMOUNT_LIVE = 3;
43365    var AVERAGE_THROUGHPUT_SAMPLE_AMOUNT_VOD = 4;
43366    var AVERAGE_LATENCY_SAMPLE_AMOUNT = 4;
43367    var THROUGHPUT_DECREASE_SCALE = 1.3;
43368    var THROUGHPUT_INCREASE_SCALE = 1.3;
43369
43370    // EWMA constants
43371    var EWMA_THROUGHPUT_SLOW_HALF_LIFE_SECONDS = 8;
43372    var EWMA_THROUGHPUT_FAST_HALF_LIFE_SECONDS = 3;
43373    var EWMA_LATENCY_SLOW_HALF_LIFE_COUNT = 2;
43374    var EWMA_LATENCY_FAST_HALF_LIFE_COUNT = 1;
43375
43376    var CACHE_LOAD_THRESHOLD_VIDEO = 50;
43377    var CACHE_LOAD_THRESHOLD_AUDIO = 5;
43378
43379    var mediaPlayerModel = config.mediaPlayerModel;
43380
43381    var throughputDict = undefined,
43382        latencyDict = undefined,
43383        ewmaThroughputDict = undefined,
43384        ewmaLatencyDict = undefined,
43385        ewmaHalfLife = undefined;
43386
43387    function setup() {
43388        ewmaHalfLife = {
43389            throughputHalfLife: { fast: EWMA_THROUGHPUT_FAST_HALF_LIFE_SECONDS, slow: EWMA_THROUGHPUT_SLOW_HALF_LIFE_SECONDS },
43390            latencyHalfLife: { fast: EWMA_LATENCY_FAST_HALF_LIFE_COUNT, slow: EWMA_LATENCY_SLOW_HALF_LIFE_COUNT }
43391        };
43392
43393        reset();
43394    }
43395
43396    function isCachedResponse(mediaType, latencyMs, downloadTimeMs) {
43397        if (mediaType === _constantsConstants2['default'].VIDEO) {
43398            return downloadTimeMs < CACHE_LOAD_THRESHOLD_VIDEO;
43399        } else if (mediaType === _constantsConstants2['default'].AUDIO) {
43400            return downloadTimeMs < CACHE_LOAD_THRESHOLD_AUDIO;
43401        }
43402    }
43403
43404    function push(mediaType, httpRequest, useDeadTimeLatency) {
43405        if (!httpRequest.trace || !httpRequest.trace.length) {
43406            return;
43407        }
43408
43409        var latencyTimeInMilliseconds = httpRequest.tresponse.getTime() - httpRequest.trequest.getTime() || 1;
43410        var downloadTimeInMilliseconds = httpRequest._tfinish.getTime() - httpRequest.tresponse.getTime() || 1; //Make sure never 0 we divide by this value. Avoid infinity!
43411        var downloadBytes = httpRequest.trace.reduce(function (a, b) {
43412            return a + b.b[0];
43413        }, 0);
43414        var throughputMeasureTime = useDeadTimeLatency ? downloadTimeInMilliseconds : latencyTimeInMilliseconds + downloadTimeInMilliseconds;
43415        var throughput = Math.round(8 * downloadBytes / throughputMeasureTime); // bits/ms = kbits/s
43416
43417        checkSettingsForMediaType(mediaType);
43418
43419        if (isCachedResponse(mediaType, latencyTimeInMilliseconds, downloadTimeInMilliseconds)) {
43420            if (throughputDict[mediaType].length > 0 && !throughputDict[mediaType].hasCachedEntries) {
43421                // already have some entries which are not cached entries
43422                // prevent cached fragment loads from skewing the average values
43423                return;
43424            } else {
43425                // have no entries || have cached entries
43426                // no uncached entries yet, rely on cached entries because ABR rules need something to go by
43427                throughputDict[mediaType].hasCachedEntries = true;
43428            }
43429        } else if (throughputDict[mediaType] && throughputDict[mediaType].hasCachedEntries) {
43430            // if we are here then we have some entries already, but they are cached, and now we have a new uncached entry
43431            clearSettingsForMediaType(mediaType);
43432        }
43433
43434        throughputDict[mediaType].push(throughput);
43435        if (throughputDict[mediaType].length > MAX_MEASUREMENTS_TO_KEEP) {
43436            throughputDict[mediaType].shift();
43437        }
43438
43439        latencyDict[mediaType].push(latencyTimeInMilliseconds);
43440        if (latencyDict[mediaType].length > MAX_MEASUREMENTS_TO_KEEP) {
43441            latencyDict[mediaType].shift();
43442        }
43443
43444        updateEwmaEstimate(ewmaThroughputDict[mediaType], throughput, 0.001 * downloadTimeInMilliseconds, ewmaHalfLife.throughputHalfLife);
43445        updateEwmaEstimate(ewmaLatencyDict[mediaType], latencyTimeInMilliseconds, 1, ewmaHalfLife.latencyHalfLife);
43446    }
43447
43448    function updateEwmaEstimate(ewmaObj, value, weight, halfLife) {
43449        // Note about startup:
43450        // Estimates start at 0, so early values are underestimated.
43451        // This effect is countered in getAverageEwma() by dividing the estimates by:
43452        //     1 - Math.pow(0.5, ewmaObj.totalWeight / halfLife)
43453
43454        var fastAlpha = Math.pow(0.5, weight / halfLife.fast);
43455        ewmaObj.fastEstimate = (1 - fastAlpha) * value + fastAlpha * ewmaObj.fastEstimate;
43456
43457        var slowAlpha = Math.pow(0.5, weight / halfLife.slow);
43458        ewmaObj.slowEstimate = (1 - slowAlpha) * value + slowAlpha * ewmaObj.slowEstimate;
43459
43460        ewmaObj.totalWeight += weight;
43461    }
43462
43463    function getSampleSize(isThroughput, mediaType, isLive) {
43464        var arr = undefined;
43465        var sampleSize = undefined;
43466
43467        if (isThroughput) {
43468            arr = throughputDict[mediaType];
43469            sampleSize = isLive ? AVERAGE_THROUGHPUT_SAMPLE_AMOUNT_LIVE : AVERAGE_THROUGHPUT_SAMPLE_AMOUNT_VOD;
43470        } else {
43471            arr = latencyDict[mediaType];
43472            sampleSize = AVERAGE_LATENCY_SAMPLE_AMOUNT;
43473        }
43474
43475        if (!arr) {
43476            sampleSize = 0;
43477        } else if (sampleSize >= arr.length) {
43478            sampleSize = arr.length;
43479        } else if (isThroughput) {
43480            // if throughput samples vary a lot, average over a wider sample
43481            for (var i = 1; i < sampleSize; ++i) {
43482                var ratio = arr[-i] / arr[-i - 1];
43483                if (ratio >= THROUGHPUT_INCREASE_SCALE || ratio <= 1 / THROUGHPUT_DECREASE_SCALE) {
43484                    sampleSize += 1;
43485                    if (sampleSize === arr.length) {
43486                        // cannot increase sampleSize beyond arr.length
43487                        break;
43488                    }
43489                }
43490            }
43491        }
43492
43493        return sampleSize;
43494    }
43495
43496    function getAverage(isThroughput, mediaType, isDynamic) {
43497        // only two moving average methods defined at the moment
43498        return mediaPlayerModel.getMovingAverageMethod() !== _constantsConstants2['default'].MOVING_AVERAGE_SLIDING_WINDOW ? getAverageEwma(isThroughput, mediaType) : getAverageSlidingWindow(isThroughput, mediaType, isDynamic);
43499    }
43500
43501    function getAverageSlidingWindow(isThroughput, mediaType, isDynamic) {
43502        var sampleSize = getSampleSize(isThroughput, mediaType, isDynamic);
43503        var dict = isThroughput ? throughputDict : latencyDict;
43504        var arr = dict[mediaType];
43505
43506        if (sampleSize === 0 || !arr || arr.length === 0) {
43507            return NaN;
43508        }
43509
43510        arr = arr.slice(-sampleSize); // still works if sampleSize too large
43511        // arr.length >= 1
43512        return arr.reduce(function (total, elem) {
43513            return total + elem;
43514        }) / arr.length;
43515    }
43516
43517    function getAverageEwma(isThroughput, mediaType) {
43518        var halfLife = isThroughput ? ewmaHalfLife.throughputHalfLife : ewmaHalfLife.latencyHalfLife;
43519        var ewmaObj = isThroughput ? ewmaThroughputDict[mediaType] : ewmaLatencyDict[mediaType];
43520
43521        if (!ewmaObj || ewmaObj.totalWeight <= 0) {
43522            return NaN;
43523        }
43524
43525        // to correct for startup, divide by zero factor = 1 - Math.pow(0.5, ewmaObj.totalWeight / halfLife)
43526        var fastEstimate = ewmaObj.fastEstimate / (1 - Math.pow(0.5, ewmaObj.totalWeight / halfLife.fast));
43527        var slowEstimate = ewmaObj.slowEstimate / (1 - Math.pow(0.5, ewmaObj.totalWeight / halfLife.slow));
43528        return isThroughput ? Math.min(fastEstimate, slowEstimate) : Math.max(fastEstimate, slowEstimate);
43529    }
43530
43531    function getAverageThroughput(mediaType, isDynamic) {
43532        return getAverage(true, mediaType, isDynamic);
43533    }
43534
43535    function getSafeAverageThroughput(mediaType, isDynamic) {
43536        var average = getAverageThroughput(mediaType, isDynamic);
43537        if (!isNaN(average)) {
43538            average *= mediaPlayerModel.getBandwidthSafetyFactor();
43539        }
43540        return average;
43541    }
43542
43543    function getAverageLatency(mediaType) {
43544        return getAverage(false, mediaType);
43545    }
43546
43547    function checkSettingsForMediaType(mediaType) {
43548        throughputDict[mediaType] = throughputDict[mediaType] || [];
43549        latencyDict[mediaType] = latencyDict[mediaType] || [];
43550        ewmaThroughputDict[mediaType] = ewmaThroughputDict[mediaType] || { fastEstimate: 0, slowEstimate: 0, totalWeight: 0 };
43551        ewmaLatencyDict[mediaType] = ewmaLatencyDict[mediaType] || { fastEstimate: 0, slowEstimate: 0, totalWeight: 0 };
43552    }
43553
43554    function clearSettingsForMediaType(mediaType) {
43555        delete throughputDict[mediaType];
43556        delete latencyDict[mediaType];
43557        delete ewmaThroughputDict[mediaType];
43558        delete ewmaLatencyDict[mediaType];
43559        checkSettingsForMediaType(mediaType);
43560    }
43561
43562    function reset() {
43563        throughputDict = {};
43564        latencyDict = {};
43565        ewmaThroughputDict = {};
43566        ewmaLatencyDict = {};
43567    }
43568
43569    var instance = {
43570        push: push,
43571        getAverageThroughput: getAverageThroughput,
43572        getSafeAverageThroughput: getSafeAverageThroughput,
43573        getAverageLatency: getAverageLatency,
43574        reset: reset
43575    };
43576
43577    setup();
43578    return instance;
43579}
43580
43581ThroughputHistory.__dashjs_factory_name = 'ThroughputHistory';
43582exports['default'] = _coreFactoryMakerJs2['default'].getClassFactory(ThroughputHistory);
43583module.exports = exports['default'];
43584
43585},{"100":100,"51":51}],174:[function(_dereq_,module,exports){
43586/**
43587 * The copyright in this software is being made available under the BSD License,
43588 * included below. This software may be subject to other third party and contributor
43589 * rights, including patent rights, and no such rights are granted under this license.
43590 *
43591 * Copyright (c) 2013, Dash Industry Forum.
43592 * All rights reserved.
43593 *
43594 * Redistribution and use in source and binary forms, with or without modification,
43595 * are permitted provided that the following conditions are met:
43596 *  * Redistributions of source code must retain the above copyright notice, this
43597 *  list of conditions and the following disclaimer.
43598 *  * Redistributions in binary form must reproduce the above copyright notice,
43599 *  this list of conditions and the following disclaimer in the documentation and/or
43600 *  other materials provided with the distribution.
43601 *  * Neither the name of Dash Industry Forum nor the names of its
43602 *  contributors may be used to endorse or promote products derived from this software
43603 *  without specific prior written permission.
43604 *
43605 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
43606 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
43607 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
43608 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
43609 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
43609INCLUDING, BUT
43610 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
43611 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
43612 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
43613 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43614 *  POSSIBILITY OF SUCH DAMAGE.
43615 */
43616'use strict';
43617
43618Object.defineProperty(exports, '__esModule', {
43619    value: true
43620});
43621
43622function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
43623
43624var _ThroughputRule = _dereq_(180);
43625
43626var _ThroughputRule2 = _interopRequireDefault(_ThroughputRule);
43627
43628var _InsufficientBufferRule = _dereq_(178);
43629
43630var _InsufficientBufferRule2 = _interopRequireDefault(_InsufficientBufferRule);
43631
43632var _AbandonRequestsRule = _dereq_(175);
43633
43634var _AbandonRequestsRule2 = _interopRequireDefault(_AbandonRequestsRule);
43635
43636var _DroppedFramesRuleJs = _dereq_(177);
43637
43638var _DroppedFramesRuleJs2 = _interopRequireDefault(_DroppedFramesRuleJs);
43639
43640var _SwitchHistoryRuleJs = _dereq_(179);
43641
43642var _SwitchHistoryRuleJs2 = _interopRequireDefault(_SwitchHistoryRuleJs);
43643
43644var _BolaRule = _dereq_(176);
43645
43646var _BolaRule2 = _interopRequireDefault(_BolaRule);
43647
43648var _coreFactoryMaker = _dereq_(51);
43649
43650var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
43651
43652var _SwitchRequestJs = _dereq_(171);
43653
43654var _SwitchRequestJs2 = _interopRequireDefault(_SwitchRequestJs);
43655
43656var QUALITY_SWITCH_RULES = 'qualitySwitchRules';
43657var ABANDON_FRAGMENT_RULES = 'abandonFragmentRules';
43658
43659function ABRRulesCollection(config) {
43660
43661    var context = this.context;
43662
43663    var mediaPlayerModel = config.mediaPlayerModel;
43664    var metricsModel = config.metricsModel;
43665    var dashMetrics = config.dashMetrics;
43666
43667    var instance = undefined,
43668        qualitySwitchRules = undefined,
43669        abandonFragmentRules = undefined;
43670
43671    function initialize() {
43672        qualitySwitchRules = [];
43673        abandonFragmentRules = [];
43674
43675        if (mediaPlayerModel.getUseDefaultABRRules()) {
43676
43677            // Only one of BolaRule and ThroughputRule will give a switchRequest.quality !== SwitchRequest.NO_CHANGE.
43678            // This is controlled by useBufferOccupancyABR mechanism in AbrController.
43679            qualitySwitchRules.push((0, _BolaRule2['default'])(context).create({
43680                metricsModel: metricsModel,
43681                dashMetrics: dashMetrics,
43682                mediaPlayerModel: mediaPlayerModel
43683            }));
43684            qualitySwitchRules.push((0, _ThroughputRule2['default'])(context).create({
43685                metricsModel: metricsModel,
43686                dashMetrics: dashMetrics
43687            }));
43688
43689            qualitySwitchRules.push((0, _InsufficientBufferRule2['default'])(context).create({
43690                metricsModel: metricsModel,
43691                dashMetrics: dashMetrics
43692            }));
43693            qualitySwitchRules.push((0, _SwitchHistoryRuleJs2['default'])(context).create());
43694            qualitySwitchRules.push((0, _DroppedFramesRuleJs2['default'])(context).create());
43695
43696            abandonFragmentRules.push((0, _AbandonRequestsRule2['default'])(context).create({
43697                metricsModel: metricsModel,
43698                dashMetrics: dashMetrics,
43699                mediaPlayerModel: mediaPlayerModel
43700            }));
43701        }
43702
43703        // add custom ABR rules if any
43704        var customRules = mediaPlayerModel.getABRCustomRules();
43705        customRules.forEach(function (rule) {
43706            if (rule.type === QUALITY_SWITCH_RULES) {
43707                qualitySwitchRules.push(rule.rule(context).create());
43708            }
43709
43710            if (rule.type === ABANDON_FRAGMENT_RULES) {
43711                abandonFragmentRules.push(rule.rule(context).create());
43712            }
43713        });
43714    }
43715
43716    function getActiveRules(srArray) {
43717        return srArray.filter(function (sr) {
43718            return sr.quality > _SwitchRequestJs2['default'].NO_CHANGE;
43719        });
43720    }
43721
43722    function getMinSwitchRequest(srArray) {
43723
43724        var values = {};
43725        var i = undefined,
43726            len = undefined,
43727            req = undefined,
43728            newQuality = undefined,
43729            quality = undefined;
43730
43731        if (srArray.length === 0) {
43732            return;
43733        }
43734
43735        values[_SwitchRequestJs2['default'].PRIORITY.STRONG] = _SwitchRequestJs2['default'].NO_CHANGE;
43736        values[_SwitchRequestJs2['default'].PRIORITY.WEAK] = _SwitchRequestJs2['default'].NO_CHANGE;
43737        values[_SwitchRequestJs2['default'].PRIORITY.DEFAULT] = _SwitchRequestJs2['default'].NO_CHANGE;
43738
43739        for (i = 0, len = srArray.length; i < len; i += 1) {
43740            req = srArray[i];
43741            if (req.quality !== _SwitchRequestJs2['default'].NO_CHANGE) {
43742                values[req.priority] = values[req.priority] > _SwitchRequestJs2['default'].NO_CHANGE ? Math.min(values[req.priority], req.quality) : req.quality;
43743            }
43744        }
43745
43746        if (values[_SwitchRequestJs2['default'].PRIORITY.WEAK] !== _SwitchRequestJs2['default'].NO_CHANGE) {
43747            newQuality = values[_SwitchRequestJs2['default'].PRIORITY.WEAK];
43748        }
43749
43750        if (values[_SwitchRequestJs2['default'].PRIORITY.DEFAULT] !== _SwitchRequestJs2['default'].NO_CHANGE) {
43751            newQuality = values[_SwitchRequestJs2['default'].PRIORITY.DEFAULT];
43752        }
43753
43754        if (values[_SwitchRequestJs2['default'].PRIORITY.STRONG] !== _SwitchRequestJs2['default'].NO_CHANGE) {
43755            newQuality = values[_SwitchRequestJs2['default'].PRIORITY.STRONG];
43756        }
43757
43758        if (newQuality !== _SwitchRequestJs2['default'].NO_CHANGE) {
43759            quality = newQuality;
43760        }
43761
43762        return (0, _SwitchRequestJs2['default'])(context).create(quality);
43763    }
43764
43765    function getMaxQuality(rulesContext) {
43766        var switchRequestArray = qualitySwitchRules.map(function (rule) {
43767            return rule.getMaxIndex(rulesContext);
43768        });
43769        var activeRules = getActiveRules(switchRequestArray);
43770        var maxQuality = getMinSwitchRequest(activeRules);
43771
43772        return maxQuality || (0, _SwitchRequestJs2['default'])(context).create();
43773    }
43774
43775    function shouldAbandonFragment(rulesContext) {
43776        var abandonRequestArray = abandonFragmentRules.map(function (rule) {
43777            return rule.shouldAbandon(rulesContext);
43778        });
43779        var activeRules = getActiveRules(abandonRequestArray);
43780        var shouldAbandon = getMinSwitchRequest(activeRules);
43781
43782        return shouldAbandon || (0, _SwitchRequestJs2['default'])(context).create();
43783    }
43784
43785    function reset() {
43786        [qualitySwitchRules, abandonFragmentRules].forEach(function (rules) {
43787            if (rules && rules.length) {
43788                rules.forEach(function (rule) {
43789                    return rule.reset && rule.reset();
43790                });
43791            }
43792        });
43793        qualitySwitchRules = [];
43794        abandonFragmentRules = [];
43795    }
43796
43797    instance = {
43798        initialize: initialize,
43799        reset: reset,
43800        getMaxQuality: getMaxQuality,
43801        shouldAbandonFragment: shouldAbandonFragment
43802    };
43803
43804    return instance;
43805}
43806
43807ABRRulesCollection.__dashjs_factory_name = 'ABRRulesCollection';
43808var factory = _coreFactoryMaker2['default'].getClassFactory(ABRRulesCollection);
43809factory.QUALITY_SWITCH_RULES = QUALITY_SWITCH_RULES;
43810factory.ABANDON_FRAGMENT_RULES = ABANDON_FRAGMENT_RULES;
43811_coreFactoryMaker2['default'].updateSingletonFactory(ABRRulesCollection.__dashjs_factory_name, factory);
43812
43813exports['default'] = factory;
43814module.exports = exports['default'];
43815
43816},{"171":171,"175":175,"176":176,"177":177,"178":178,"179":179,"180":180,"51":51}],175:[function(_dereq_,module,exports){
43817/**
43818 * The copyright in this software is being made available under the BSD License,
43819 * included below. This software may be subject to other third party and contributor
43820 * rights, including patent rights, and no such rights are granted under this license.
43821 *
43822 * Copyright (c) 2013, Dash Industry Forum.
43823 * All rights reserved.
43824 *
43825 * Redistribution and use in source and binary forms, with or without modification,
43826 * are permitted provided that the following conditions are met:
43827 *  * Redistributions of source code must retain the above copyright notice, this
43828 *  list of conditions and the following disclaimer.
43829 *  * Redistributions in binary form must reproduce the above copyright notice,
43830 *  this list of conditions and the following disclaimer in the documentation and/or
43831 *  other materials provided with the distribution.
43832 *  * Neither the name of Dash Industry Forum nor the names of its
43833 *  contributors may be used to endorse or promote products derived from this software
43834 *  without specific prior written permission.
43835 *
43836 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
43837 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
43838 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
43839 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
43840 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
43841 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
43842 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
43843 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
43844 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43845 *  POSSIBILITY OF SUCH DAMAGE.
43846 */
43847'use strict';
43848
43849Object.defineProperty(exports, '__esModule', {
43850    value: true
43851});
43852
43853function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
43854
43855var _SwitchRequest = _dereq_(171);
43856
43857var _SwitchRequest2 = _interopRequireDefault(_SwitchRequest);
43858
43859var _coreFactoryMaker = _dereq_(51);
43860
43861var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
43862
43863var _coreDebug = _dereq_(49);
43864
43865var _coreDebug2 = _interopRequireDefault(_coreDebug);
43866
43867function AbandonRequestsRule(config) {
43868
43869    var ABANDON_MULTIPLIER = 1.8;
43870    var GRACE_TIME_THRESHOLD = 500;
43871    var MIN_LENGTH_TO_AVERAGE = 5;
43872
43873    var context = this.context;
43874    var log = (0, _coreDebug2['default'])(context).getInstance().log;
43875
43876    var mediaPlayerModel = config.mediaPlayerModel;
43877    var metricsModel = config.metricsModel;
43878    var dashMetrics = config.dashMetrics;
43879
43880    var fragmentDict = undefined,
43881        abandonDict = undefined,
43882        throughputArray = undefined;
43883
43884    function setup() {
43885        reset();
43886    }
43887
43888    function setFragmentRequestDict(type, id) {
43889        fragmentDict[type] = fragmentDict[type] || {};
43890        fragmentDict[type][id] = fragmentDict[type][id] || {};
43891    }
43892
43893    function storeLastRequestThroughputByType(type, throughput) {
43894        throughputArray[type] = throughputArray[type] || [];
43895        throughputArray[type].push(throughput);
43896    }
43897
43898    function shouldAbandon(rulesContext) {
43899        var switchRequest = (0, _SwitchRequest2['default'])(context).create(_SwitchRequest2['default'].NO_CHANGE, { name: AbandonRequestsRule.__dashjs_factory_name });
43900
43901        if (!rulesContext || !rulesContext.hasOwnProperty('getMediaInfo') || !rulesContext.hasOwnProperty('getMediaType') || !rulesContext.hasOwnProperty('getCurrentRequest') || !rulesContext.hasOwnProperty('getTrackInfo') || !rulesContext.hasOwnProperty('getAbrController')) {
43902            return switchRequest;
43903        }
43904
43905        var mediaInfo = rulesContext.getMediaInfo();
43906        var mediaType = rulesContext.getMediaType();
43907        var req = rulesContext.getCurrentRequest();
43908
43909        if (!isNaN(req.index)) {
43910
43911            setFragmentRequestDict(mediaType, req.index);
43912
43913            var stableBufferTime = mediaPlayerModel.getStableBufferTime();
43914            var bufferLevel = dashMetrics.getCurrentBufferLevel(metricsModel.getReadOnlyMetricsF
vendor: 5,772 bytes, lines 43914-44019
43914or(mediaType));
43915            if (bufferLevel > stableBufferTime) {
43916                return switchRequest;
43917            }
43918
43919            var fragmentInfo = fragmentDict[mediaType][req.index];
43920            if (fragmentInfo === null || req.firstByteDate === null || abandonDict.hasOwnProperty(fragmentInfo.id)) {
43921                return switchRequest;
43922            }
43923
43924            //setup some init info based on first progress event
43925            if (fragmentInfo.firstByteTime === undefined) {
43926                throughputArray[mediaType] = [];
43927                fragmentInfo.firstByteTime = req.firstByteDate.getTime();
43928                fragmentInfo.segmentDuration = req.duration;
43929                fragmentInfo.bytesTotal = req.bytesTotal;
43930                fragmentInfo.id = req.index;
43931            }
43932            fragmentInfo.bytesLoaded = req.bytesLoaded;
43933            fragmentInfo.elapsedTime = new Date().getTime() - fragmentInfo.firstByteTime;
43934
43935            if (fragmentInfo.bytesLoaded > 0 && fragmentInfo.elapsedTime > 0) {
43936                storeLastRequestThroughputByType(mediaType, Math.round(fragmentInfo.bytesLoaded * 8 / fragmentInfo.elapsedTime));
43937            }
43938
43939            if (throughputArray[mediaType].length >= MIN_LENGTH_TO_AVERAGE && fragmentInfo.elapsedTime > GRACE_TIME_THRESHOLD && fragmentInfo.bytesLoaded < fragmentInfo.bytesTotal) {
43940
43941                var totalSampledValue = throughputArray[mediaType].reduce(function (a, b) {
43942                    return a + b;
43943                }, 0);
43944                fragmentInfo.measuredBandwidthInKbps = Math.round(totalSampledValue / throughputArray[mediaType].length);
43945                fragmentInfo.estimatedTimeOfDownload = +(fragmentInfo.bytesTotal * 8 / fragmentInfo.measuredBandwidthInKbps / 1000).toFixed(2);
43946                //log("id:",fragmentInfo.id, "kbps:", fragmentInfo.measuredBandwidthInKbps, "etd:",fragmentInfo.estimatedTimeOfDownload, fragmentInfo.bytesLoaded);
43947
43948                if (fragmentInfo.estimatedTimeOfDownload < fragmentInfo.segmentDuration * ABANDON_MULTIPLIER || rulesContext.getRepresentationInfo().quality === 0) {
43949                    return switchRequest;
43950                } else if (!abandonDict.hasOwnProperty(fragmentInfo.id)) {
43951
43952                    var abrController = rulesContext.getAbrController();
43953                    var bytesRemaining = fragmentInfo.bytesTotal - fragmentInfo.bytesLoaded;
43954                    var bitrateList = abrController.getBitrateList(mediaInfo);
43955                    var newQuality = abrController.getQualityForBitrate(mediaInfo, fragmentInfo.measuredBandwidthInKbps * mediaPlayerModel.getBandwidthSafetyFactor());
43956                    var estimateOtherBytesTotal = fragmentInfo.bytesTotal * bitrateList[newQuality].bitrate / bitrateList[abrController.getQualityFor(mediaType, mediaInfo.streamInfo)].bitrate;
43957
43958                    if (bytesRemaining > estimateOtherBytesTotal) {
43959                        switchRequest.quality = newQuality;
43960                        switchRequest.reason.throughput = fragmentInfo.measuredBandwidthInKbps;
43961                        switchRequest.reason.fragmentID = fragmentInfo.id;
43962                        abandonDict[fragmentInfo.id] = fragmentInfo;
43963                        log('AbandonRequestsRule ( ', mediaType, 'frag id', fragmentInfo.id, ') is asking to abandon and switch to quality to ', newQuality, ' measured bandwidth was', fragmentInfo.measuredBandwidthInKbps);
43964                        delete fragmentDict[mediaType][fragmentInfo.id];
43965                    }
43966                }
43967            } else if (fragmentInfo.bytesLoaded === fragmentInfo.bytesTotal) {
43968                delete fragmentDict[mediaType][fragmentInfo.id];
43969            }
43970        }
43971
43972        return switchRequest;
43973    }
43974
43975    function reset() {
43976        fragmentDict = {};
43977        abandonDict = {};
43978        throughputArray = [];
43979    }
43980
43981    var instance = {
43982        shouldAbandon: shouldAbandon,
43983        reset: reset
43984    };
43985
43986    setup();
43987
43988    return instance;
43989}
43990
43991AbandonRequestsRule.__dashjs_factory_name = 'AbandonRequestsRule';
43992exports['default'] = _coreFactoryMaker2['default'].getClassFactory(AbandonRequestsRule);
43993module.exports = exports['default'];
43994
43995},{"171":171,"49":49,"51":51}],176:[function(_dereq_,module,exports){
43996/**
43997 * The copyright in this software is being made available under the BSD License,
43998 * included below. This software may be subject to other third party and contributor
43999 * rights, including patent rights, and no such rights are granted under this license.
44000 *
44001 * Copyright (c) 2016, Dash Industry Forum.
44002 * All rights reserved.
44003 *
44004 * Redistribution and use in source and binary forms, with or without modification,
44005 * are permitted provided that the following conditions are met:
44006 *  * Redistributions of source code must retain the above copyright notice, this
44007 *  list of conditions and the following disclaimer.
44008 *  * Redistributions in binary form must reproduce the above copyright notice,
44009 *  this list of conditions and the following disclaimer in the documentation and/or
44010 *  other materials provided with the distribution.
44011 *  * Neither the name of Dash Industry Forum nor the names of its
44012 *  contributors may be used to endorse or promote products derived from this software
44013 *  without specific prior written permission.
44014 *
44015 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
44016 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
44017 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
44018 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
44019 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
44019INCLUDING, BUT
44020 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
44021 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44022 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
44023 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
44024 *  POSSIBILITY OF SUCH DAMAGE.
44025 */
44026
44027// For a description of the BOLA adaptive bitrate (ABR) algorithm, see http://arxiv.org/abs/1601.06748
44028
44029'use strict';
44030
44031Object.defineProperty(exports, '__esModule', {
44032    value: true
44033});
44034
44035function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
44036
44037var _constantsMetricsConstants = _dereq_(101);
44038
44039var _constantsMetricsConstants2 = _interopRequireDefault(_constantsMetricsConstants);
44040
44041var _SwitchRequest = _dereq_(171);
44042
44043var _SwitchRequest2 = _interopRequireDefault(_SwitchRequest);
44044
44045var _coreFactoryMaker = _dereq_(51);
44046
44047var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
44048
44049var _voMetricsHTTPRequest = _dereq_(224);
44050
44051var _coreEventBus = _dereq_(50);
44052
44053var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
44054
44055var _coreEventsEvents = _dereq_(54);
44056
44057var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
44058
44059var _coreDebug = _dereq_(49);
44060
44061var _coreDebug2 = _interopRequireDefault(_coreDebug);
44062
44063// BOLA_STATE_ONE_BITRATE   : If there is only one bitrate (or initialization failed), always return NO_CHANGE.
44064// BOLA_STATE_STARTUP       : Set placeholder buffer such that we download fragments at most recently measured throughput.
44065// BOLA_STATE_STEADY        : Buffer primed, we switch to steady operation.
44066// TODO: add BOLA_STATE_SEEK and tune BOLA behavior on seeking
44067var BOLA_STATE_ONE_BITRATE = 0;
44068var BOLA_STATE_STARTUP = 1;
44069var BOLA_STATE_STEADY = 2;
44070
44071var MINIMUM_BUFFER_S = 10; // BOLA should never add artificial delays if buffer is less than MINIMUM_BUFFER_S.
44072var MINIMUM_BUFFER_PER_BITRATE_LEVEL_S = 2;
44073// E.g. if there are 5 bitrates, BOLA switches to top bitrate at buffer = 10 + 5 * 2 = 20s.
44074// If Schedule Controller does not allow buffer to reach that level, it can be achieved through the placeholder buffer level.
44075
44076var PLACEHOLDER_BUFFER_DECAY = 0.99; // Make sure placeholder buffer does not stick around too long.
44077
44078function BolaRule(config) {
44079
44080    var context = this.context;
44081    var log = (0, _coreDebug2['default'])(context).getInstance().log;
44082    var dashMetrics = config.dashMetrics;
44083    var metricsModel = config.metricsModel;
44084    var mediaPlayerModel = config.mediaPlayerModel;
44085    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
44086
44087    var instance = undefined,
44088        bolaStateDict = undefined;
44089
44090    function setup() {
44091        resetInitialSettings();
44092
44093        eventBus.on(_coreEventsEvents2['default'].BUFFER_EMPTY, onBufferEmpty, instance);
44094        eventBus.on(_coreEventsEvents2['default'].PLAYBACK_SEEKING, onPlaybackSeeking, instance);
44095        eventBus.on(_coreEventsEvents2['default'].PERIOD_SWITCH_STARTED, onPeriodSwitchStarted, instance);
44096        eventBus.on(_coreEventsEvents2['default'].MEDIA_FRAGMENT_LOADED, onMediaFragmentLoaded, instance);
44097        eventBus.on(_coreEventsEvents2['default'].METRIC_ADDED, onMetricAdded, instance);
44098        eventBus.on(_coreEventsEvents2['default'].QUALITY_CHANGE_REQUESTED, onQualityChangeRequested, instance);
44099        eventBus.on(_coreEventsEvents2['default'].FRAGMENT_LOADING_ABANDONED, onFragmentLoadingAbandoned, instance);
44100    }
44101
44102    function utilitiesFromBitrates(bitrates) {
44103        return bitrates.map(function (b) {
44104            return Math.log(b);
44105        });
44106        // no need to worry about offset, utilities will be offset (uniformly) anyway later
44107    }
44108
44109    // NOTE: in live streaming, the real buffer level can drop below minimumBufferS, but bola should not stick to lowest bitrate by using a placeholder buffer level
44110    function calculateBolaParameters(stableBufferTime, bitrates, utilities) {
44111        var highestUtilityIndex = utilities.reduce(function (highestIndex, u, uIndex) {
44112            return u > utilities[highestIndex] ? uIndex : highestIndex;
44113        }, 0);
44114
44115        if (highestUtilityIndex === 0) {
44116            // if highestUtilityIndex === 0, then always use lowest bitrate
44117            return null;
44118        }
44119
44120        var bufferTime = Math.max(stableBufferTime, MINIMUM_BUFFER_S + MINIMUM_BUFFER_PER_BITRATE_LEVEL_S * bitrates.length);
44121
44122        // TODO: Investigate if following can be better if utilities are not the default Math.log utilities.
44123        // If using Math.log utilities, we can choose Vp and gp to always prefer bitrates[0] at minimumBufferS and bitrates[max] at bufferTarget.
44124        // (Vp * (utility + gp) - bufferLevel) / bitrate has the maxima described when:
44125        // Vp * (utilities[0] + gp - 1) === minimumBufferS and Vp * (utilities[max] + gp - 1) === bufferTarget
vendor: 11,827 bytes, lines 44126-44365
44126        // giving:
44127        var gp = (utilities[highestUtilityIndex] - 1) / (bufferTime / MINIMUM_BUFFER_S - 1);
44128        var Vp = MINIMUM_BUFFER_S / gp;
44129        // note that expressions for gp and Vp assume utilities[0] === 1, which is true because of normalization
44130
44131        return { gp: gp, Vp: Vp };
44132    }
44133
44134    function getInitialBolaState(rulesContext) {
44135        var initialState = {};
44136
44137        var mediaInfo = rulesContext.getMediaInfo();
44138        var bitrates = mediaInfo.bitrateList.map(function (b) {
44139            return b.bandwidth;
44140        });
44141        var utilities = utilitiesFromBitrates(bitrates);
44142        utilities = utilities.map(function (u) {
44143            return u - utilities[0] + 1;
44144        }); // normalize
44145        var stableBufferTime = mediaPlayerModel.getStableBufferTime();
44146        var params = calculateBolaParameters(stableBufferTime, bitrates, utilities);
44147
44148        if (!params) {
44149            // only happens when there is only one bitrate level
44150            initialState.state = BOLA_STATE_ONE_BITRATE;
44151        } else {
44152            initialState.state = BOLA_STATE_STARTUP;
44153
44154            initialState.bitrates = bitrates;
44155            initialState.utilities = utilities;
44156            initialState.stableBufferTime = stableBufferTime;
44157            initialState.Vp = params.Vp;
44158            initialState.gp = params.gp;
44159
44160            initialState.lastQuality = 0;
44161            clearBolaStateOnSeek(initialState);
44162        }
44163
44164        return initialState;
44165    }
44166
44167    function clearBolaStateOnSeek(bolaState) {
44168        bolaState.placeholderBuffer = 0;
44169        bolaState.mostAdvancedSegmentStart = NaN;
44170        bolaState.lastSegmentWasReplacement = false;
44171        bolaState.lastSegmentStart = NaN;
44172        bolaState.lastSegmentDurationS = NaN;
44173        bolaState.lastSegmentRequestTimeMs = NaN;
44174        bolaState.lastSegmentFinishTimeMs = NaN;
44175    }
44176
44177    // If the buffer target is changed (can this happen mid-stream?), then adjust BOLA parameters accordingly.
44178    function checkBolaStateStableBufferTime(bolaState, mediaType) {
44179        var stableBufferTime = mediaPlayerModel.getStableBufferTime();
44180        if (bolaState.stableBufferTime !== stableBufferTime) {
44181            var params = calculateBolaParameters(stableBufferTime, bolaState.bitrates, bolaState.utilities);
44182            if (params.Vp !== bolaState.Vp || params.gp !== bolaState.gp) {
44183                // correct placeholder buffer using two criteria:
44184                // 1. do not change effective buffer level at effectiveBufferLevel === MINIMUM_BUFFER_S ( === Vp * gp )
44185                // 2. scale placeholder buffer by Vp subject to offset indicated in 1.
44186
44187                var bufferLevel = dashMetrics.getCurrentBufferLevel(metricsModel.getReadOnlyMetricsFor(mediaType));
44188                var effectiveBufferLevel = bufferLevel + bolaState.placeholderBuffer;
44189
44190                effectiveBufferLevel -= MINIMUM_BUFFER_S;
44191                effectiveBufferLevel *= params.Vp / bolaState.Vp;
44192                effectiveBufferLevel += MINIMUM_BUFFER_S;
44193
44194                bolaState.stableBufferTime = stableBufferTime;
44195                bolaState.Vp = params.Vp;
44196                bolaState.gp = params.gp;
44197                bolaState.placeholderBuffer = Math.max(0, effectiveBufferLevel - bufferLevel);
44198            }
44199        }
44200    }
44201
44202    function getBolaState(rulesContext) {
44203        var mediaType = rulesContext.getMediaType();
44204        var bolaState = bolaStateDict[mediaType];
44205        if (!bolaState) {
44206            bolaState = getInitialBolaState(rulesContext);
44207            bolaStateDict[mediaType] = bolaState;
44208        } else if (bolaState.state !== BOLA_STATE_ONE_BITRATE) {
44209            checkBolaStateStableBufferTime(bolaState, mediaType);
44210        }
44211        return bolaState;
44212    }
44213
44214    // The core idea of BOLA.
44215    function getQualityFromBufferLevel(bolaState, bufferLevel) {
44216        var bitrateCount = bolaState.bitrates.length;
44217        var quality = NaN;
44218        var score = NaN;
44219        for (var i = 0; i < bitrateCount; ++i) {
44220            var s = (bolaState.Vp * (bolaState.utilities[i] + bolaState.gp) - bufferLevel) / bolaState.bitrates[i];
44221            if (isNaN(score) || s >= score) {
44222                score = s;
44223                quality = i;
44224            }
44225        }
44226        return quality;
44227    }
44228
44229    // maximum buffer level which prefers to download at quality rather than wait
44230    function maxBufferLevelForQuality(bolaState, quality) {
44231        return bolaState.Vp * (bolaState.utilities[quality] + bolaState.gp);
44232    }
44233
44234    // the minimum buffer level that would cause BOLA to choose quality rather than a lower bitrate
44235    function minBufferLevelForQuality(bolaState, quality) {
44236        var qBitrate = bolaState.bitrates[quality];
44237        var qUtility = bolaState.utilities[quality];
44238
44239        var min = 0;
44240        for (var i = quality - 1; i >= 0; --i) {
44241            // for each bitrate less than bitrates[quality], BOLA should prefer quality (unless other bitrate has higher utility)
44242            if (bolaState.utilities[i] < bolaState.utilities[quality]) {
44243                var iBitrate = bolaState.bitrates[i];
44244                var iUtility = bolaState.utilities[i];
44245
44246                var level = bolaState.Vp * (bolaState.gp + (qBitrate * iUtility - iBitrate * qUtility) / (qBitrate - iBitrate));
44247                min = Math.max(min, level); // we want min to be small but at least level(i) for all i
44248            }
44249        }
44250        return min;
44251    }
44252
44253    /*
44254     * The placeholder buffer increases the effective buffer that is used to calculate the bitrate.
44255     * There are two main reasons we might want to increase the placeholder buffer:
44256     *
44257     * 1. When a segment finishes downloading, we would expect to get a call on getMaxIndex() regarding the quality for
44258     *    the next segment. However, there might be a delay before the next call. E.g. when streaming live content, the
44259     *    next segment might not be available yet. If the call to getMaxIndex() does happens after a delay, we don't
44260     *    want the delay to change the BOLA decision - we only want to factor download time to decide on bitrate level.
44261     *
44262     * 2. It is possible to get a call to getMaxIndex() without having a segment download. The buffer target in dash.js
44263     *    is different for top-quality segments and lower-quality segments. If getMaxIndex() returns a lower-than-top
44264     *    quality, then the buffer controller might decide not to download a segment. When dash.js is ready for the next
44265     *    segment, getMaxIndex() will be called again. We don't want this extra delay to factor in the bitrate decision.
44266     */
44267    function updatePlaceholderBuffer(bolaState, mediaType) {
44268        var nowMs = Date.now();
44269
44270        if (!isNaN(bolaState.lastSegmentFinishTimeMs)) {
44271            // compensate for non-bandwidth-derived delays, e.g., live streaming availability, buffer controller
44272            var delay = 0.001 * (nowMs - bolaState.lastSegmentFinishTimeMs);
44273            bolaState.placeholderBuffer += Math.max(0, delay);
44274        } else if (!isNaN(bolaState.lastCallTimeMs)) {
44275            // no download after last call, compensate for delay between calls
44276            var delay = 0.001 * (nowMs - bolaState.lastCallTimeMs);
44277            bolaState.placeholderBuffer += Math.max(0, delay);
44278        }
44279
44280        bolaState.lastCallTimeMs = nowMs;
44281        bolaState.lastSegmentStart = NaN;
44282        bolaState.lastSegmentRequestTimeMs = NaN;
44283        bolaState.lastSegmentFinishTimeMs = NaN;
44284
44285        checkBolaStateStableBufferTime(bolaState, mediaType);
44286    }
44287
44288    function onBufferEmpty() {
44289        // if we rebuffer, we don't want the placeholder buffer to artificially raise BOLA quality
44290        for (var mediaType in bolaStateDict) {
44291            if (bolaStateDict.hasOwnProperty(mediaType) && bolaStateDict[mediaType].state === BOLA_STATE_STEADY) {
44292                bolaStateDict[mediaType].placeholderBuffer = 0;
44293            }
44294        }
44295    }
44296
44297    function onPlaybackSeeking() {
44298        // TODO: 1. Verify what happens if we seek mid-fragment.
44299        // TODO: 2. If e.g. we have 10s fragments and seek, we might want to download the first fragment at a lower quality to restart playback quickly.
44300        for (var mediaType in bolaStateDict) {
44301            if (bolaStateDict.hasOwnProperty(mediaType)) {
44302                var bolaState = bolaStateDict[mediaType];
44303                if (bolaState.state !== BOLA_STATE_ONE_BITRATE) {
44304                    bolaState.state = BOLA_STATE_STARTUP; // TODO: BOLA_STATE_SEEK?
44305                    clearBolaStateOnSeek(bolaState);
44306                }
44307            }
44308        }
44309    }
44310
44311    function onPeriodSwitchStarted() {
44312        // TODO: does this have to be handled here?
44313    }
44314
44315    function onMediaFragmentLoaded(e) {
44316        if (e && e.chunk && e.chunk.mediaInfo) {
44317            var bolaState = bolaStateDict[e.chunk.mediaInfo.type];
44318            if (bolaState && bolaState.state !== BOLA_STATE_ONE_BITRATE) {
44319                var start = e.chunk.start;
44320                if (isNaN(bolaState.mostAdvancedSegmentStart) || start > bolaState.mostAdvancedSegmentStart) {
44321                    bolaState.mostAdvancedSegmentStart = start;
44322                    bolaState.lastSegmentWasReplacement = false;
44323                } else {
44324                    bolaState.lastSegmentWasReplacement = true;
44325                }
44326
44327                bolaState.lastSegmentStart = start;
44328                bolaState.lastSegmentDurationS = e.chunk.duration;
44329                bolaState.lastQuality = e.chunk.quality;
44330
44331                checkNewSegment(bolaState, e.chunk.mediaInfo.type);
44332            }
44333        }
44334    }
44335
44336    function onMetricAdded(e) {
44337        if (e && e.metric === _constantsMetricsConstants2['default'].HTTP_REQUEST && e.value && e.value.type === _voMetricsHTTPRequest.HTTPRequest.MEDIA_SEGMENT_TYPE && e.value.trace && e.value.trace.length) {
44338            var bolaState = bolaStateDict[e.mediaType];
44339            if (bolaState && bolaState.state !== BOLA_STATE_ONE_BITRATE) {
44340                bolaState.lastSegmentRequestTimeMs = e.value.trequest.getTime();
44341                bolaState.lastSegmentFinishTimeMs = e.value._tfinish.getTime();
44342
44343                checkNewSegment(bolaState, e.mediaType);
44344            }
44345        }
44346    }
44347
44348    /*
44349     * When a new segment is downloaded, we get two notifications: onMediaFragmentLoaded() and onMetricAdded(). It is
44350     * possible that the quality for the downloaded segment was lower (not higher) than the quality indicated by BOLA.
44351     * This might happen because of other rules such as the DroppedFramesRule. When this happens, we trim the
44352     * placeholder buffer to make BOLA more stable. This mechanism also avoids inflating the buffer when BOLA itself
44353     * decides not to increase the quality to avoid oscillations.
44354     *
44355     * We should also check for replacement segments (fast switching). In this case, a segment is downloaded but does
44356     * not grow the actual buffer. Fast switching might cause the buffer to deplete, causing BOLA to drop the bitrate.
44357     * We avoid this by growing the placeholder buffer.
44358     */
44359    function checkNewSegment(bolaState, mediaType) {
44360        if (!isNaN(bolaState.lastSegmentStart) && !isNaN(bolaState.lastSegmentRequestTimeMs) && !isNaN(bolaState.placeholderBuffer)) {
44361            bolaState.placeholderBuffer *= PLACEHOLDER_BUFFER_DECAY;
44362
44363            // Find what maximum buffer corresponding to last segment was, and ensure placeholder is not relatively larger.
44364            if (!isNaN(bolaState.lastSegmentFinishTimeMs)) {
44365                var bufferLevel = dashMetrics.getCurrentBufferLevel(metricsModel.getReadOnlyMetricsF
44365or(mediaType));
44366                var bufferAtLastSegmentRequest = bufferLevel + 0.001 * (bolaState.lastSegmentFinishTimeMs - bolaState.lastSegmentRequestTimeMs); // estimate
44367                var maxEffectiveBufferForLastSegment = maxBufferLevelForQuality(bolaState, bolaState.lastQuality);
44368                var maxPlaceholderBuffer = Math.max(0, maxEffectiveBufferForLastSegment - bufferAtLastSegmentRequest);
44369                bolaState.placeholderBuffer = Math.min(maxPlaceholderBuffer, bolaState.placeholderBuffer);
44370            }
44371
44372            // then see if we should grow placeholder buffer
44373
44374            if (bolaState.lastSegmentWasReplacement && !isNaN(bolaState.lastSegmentDurationS)) {
44375                // compensate for segments that were downloaded but did not grow the buffer
44376                bolaState.placeholderBuffer += bolaState.lastSegmentDurationS;
44377            }
44378
44379            bolaState.lastSegmentStart = NaN;
44380            bolaState.lastSegmentRequestTimeMs = NaN;
44381        }
44382    }
44383
44384    function onQualityChangeRequested(e) {
44385        // Useful to store change requests when abandoning a download.
44386        if (e) {
44387            var bolaState = bolaStateDict[e.mediaType];
44388            if (bolaState && bolaState.state !== BOLA_STATE_ONE_BITRATE) {
44389                bolaState.abrQuality = e.newQuality;
44390            }
44391        }
44392    }
44393
44394    function onFragmentLoadingAbandoned(e) {
44395        if (e) {
44396            var bolaState = bolaStateDict[e.mediaType];
44397            if (bolaState && bolaState.state !== BOLA_STATE_ONE_BITRATE) {
44398                // deflate placeholderBuffer - note that we want to be conservative when abandoning
44399                var bufferLevel = dashMetrics.getCurrentBufferLevel(metricsModel.getReadOnlyMetricsFor(e.mediaType));
44400                var wantEffectiveBufferLevel = undefined;
44401                if (bolaState.abrQuality > 0) {
44402                    // deflate to point where BOLA just chooses newQuality over newQuality-1
44403                    wantEffectiveBufferLevel = minBufferLevelForQuality(bolaState, bolaState.abrQuality);
44404                } else {
44405                    wantEffectiveBufferLevel = MINIMUM_BUFFER_S;
44406                }
44407                var maxPlaceholderBuffer = Math.max(0, wantEffectiveBufferLevel - bufferLevel);
44408                bolaState.placeholderBuffer = Math.min(bolaState.placeholderBuffer, maxPlaceholderBuffer);
44409            }
44410        }
44411    }
44412
44413    function getMaxIndex(rulesContext) {
44414        var mediaInfo = rulesContext.getMediaInfo();
44415        var mediaType = rulesContext.getMediaType();
44416        var metrics = metricsModel.getReadOnlyMetricsFor(mediaType);
44417        var streamProcessor = rulesContext.getStreamProcessor();
44418        var streamInfo = rulesContext.getStreamInfo();
44419        var abrController = rulesContext.getAbrController();
44420        var throughputHistory = abrController.getThroughputHistory();
44421        var streamId = streamInfo ? streamInfo.id : null;
44422        var isDynamic = streamInfo && streamInfo.manifestInfo && streamInfo.manifestInfo.isDynamic;
44423        var useBufferOccupancyABR = rulesContext.useBufferOccupancyABR();
44424        var switchRequest = (0, _SwitchRequest2['default'])(context).create();
44425        switchRequest.reason = switchRequest.reason || {};
44426
44427        if (!useBufferOccupancyABR) {
44428            return switchRequest;
44429        }
44430
44431        streamProcessor.getScheduleController().setTimeToLoadDelay(0);
44432
44433        var bolaState = getBolaState(rulesContext);
44434
44435        if (bolaState.state === BOLA_STATE_ONE_BITRATE) {
44436            // shouldn't even have been called
44437            log('BOLA ABR rule invoked for media type \'' + mediaType + '\' with only one bitrate.');
44438            return switchRequest;
44439        }
44440
44441        var bufferLevel = dashMetrics.getCurrentBufferLevel(metrics);
44442        var throughput = throughputHistory.getAverageThroughput(mediaType, isDynamic);
44443        var safeThroughput = throughputHistory.getSafeAverageThroughput(mediaType, isDynamic);
44444        var latency = throughputHistory.getAverageLatency(mediaType);
44445        var quality = undefined;
44446
44447        switchRequest.reason.state = bolaState.state;
44448        switchRequest.reason.throughput = throughput;
44449        switchRequest.reason.latency = latency;
44450
44451        if (isNaN(throughput)) {
vendor: 4,205 bytes, lines 44452-44529
44452            // isNaN(throughput) === isNaN(safeThroughput) === isNaN(latency)
44453            // still starting up - not enough information
44454            return switchRequest;
44455        }
44456
44457        switch (bolaState.state) {
44458            case BOLA_STATE_STARTUP:
44459                quality = abrController.getQualityForBitrate(mediaInfo, safeThroughput, latency);
44460
44461                switchRequest.quality = quality;
44462                switchRequest.reason.throughput = safeThroughput;
44463
44464                bolaState.placeholderBuffer = Math.max(0, minBufferLevelForQuality(bolaState, quality) - bufferLevel);
44465                bolaState.lastQuality = quality;
44466
44467                if (!isNaN(bolaState.lastSegmentDurationS) && bufferLevel >= bolaState.lastSegmentDurationS) {
44468                    bolaState.state = BOLA_STATE_STEADY;
44469                }
44470
44471                break; // BOLA_STATE_STARTUP
44472
44473            case BOLA_STATE_STEADY:
44474
44475                // NB: The placeholder buffer is added to bufferLevel to come up with a bitrate.
44476                //     This might lead BOLA to be too optimistic and to choose a bitrate that would lead to rebuffering -
44477                //     if the real buffer bufferLevel runs out, the placeholder buffer cannot prevent rebuffering.
44478                //     However, the InsufficientBufferRule takes care of this scenario.
44479
44480                updatePlaceholderBuffer(bolaState, mediaType);
44481
44482                quality = getQualityFromBufferLevel(bolaState, bufferLevel + bolaState.placeholderBuffer);
44483
44484                // we want to avoid oscillations
44485                // We implement the "BOLA-O" variant: when network bandwidth lies between two encoded bitrate levels, stick to the lowest level.
44486                var qualityForThroughput = abrController.getQualityForBitrate(mediaInfo, safeThroughput, latency);
44487                if (quality > bolaState.lastQuality && quality > qualityForThroughput) {
44488                    // only intervene if we are trying to *increase* quality to an *unsustainable* level
44489                    // we are only avoid oscillations - do not drop below last quality
44490
44491                    quality = Math.max(qualityForThroughput, bolaState.lastQuality);
44492                }
44493
44494                // We do not want to overfill buffer with low quality chunks.
44495                // Note that there will be no delay if buffer level is below MINIMUM_BUFFER_S, probably even with some margin higher than MINIMUM_BUFFER_S.
44496                var delayS = Math.max(0, bufferLevel + bolaState.placeholderBuffer - maxBufferLevelForQuality(bolaState, quality));
44497
44498                // First reduce placeholder buffer, then tell schedule controller to pause.
44499                if (delayS <= bolaState.placeholderBuffer) {
44500                    bolaState.placeholderBuffer -= delayS;
44501                    delayS = 0;
44502                } else {
44503                    delayS -= bolaState.placeholderBuffer;
44504                    bolaState.placeholderBuffer = 0;
44505
44506                    if (quality < abrController.getTopQualityIndexFor(mediaType, streamId)) {
44507                        // At top quality, allow schedule controller to decide how far to fill buffer.
44508                        streamProcessor.getScheduleController().setTimeToLoadDelay(1000 * delayS);
44509                    } else {
44510                        delayS = 0;
44511                    }
44512                }
44513
44514                switchRequest.quality = quality;
44515                switchRequest.reason.throughput = throughput;
44516                switchRequest.reason.latency = latency;
44517                switchRequest.reason.bufferLevel = bufferLevel;
44518                switchRequest.reason.placeholderBuffer = bolaState.placeholderBuffer;
44519                switchRequest.reason.delay = delayS;
44520
44521                bolaState.lastQuality = quality;
44522                // keep bolaState.state === BOLA_STATE_STEADY
44523
44524                break; // BOLA_STATE_STEADY
44525
44526            default:
44527                log('BOLA ABR rule invoked in bad state.');
44528                // should not arrive here, try to recover
44529                switchRequest.quality = abrController.getQualityForBitrate(mediaInfo, safeThroughput, latency);
44530                switchRequest.reason.state = bolaState.state;
44531                switchRequest.reason.throughput = safeThroughput;
44532                switchRequest.reason.latency = latency;
44533                bolaState.state = BOLA_STATE_STARTUP;
44534                clearBolaStateOnSeek(bolaState);
44535        }
44536
44537        return switchRequest;
44538    }
44539
44540    function resetInitialSettings() {
44541        bolaStateDict = {};
44542    }
44543
44544    function reset() {
44545        resetInitialSettings();
44546
44547        eventBus.off(_coreEventsEvents2['default'].BUFFER_EMPTY, onBufferEmpty, instance);
44548        eventBus.off(_coreEventsEvents2['default'].PLAYBACK_SEEKING, onPlaybackSeeking, instance);
44549        eventBus.off(_coreEventsEvents2['default'].PERIOD_SWITCH_STARTED, onPeriodSwitchStarted, instance);
44550        eventBus.off(_coreEventsEvents2['default'].MEDIA_FRAGMENT_LOADED, onMediaFragmentLoaded, instance);
44551        eventBus.off(_coreEventsEvents2['default'].METRIC_ADDED, onMetricAdded, instance);
44552        eventBus.off(_coreEventsEvents2['default'].QUALITY_CHANGE_REQUESTED, onQualityChangeRequested, instance);
44553        eventBus.off(_coreEventsEvents2['default'].FRAGMENT_LOADING_ABANDONED, onFragmentLoadingAbandoned, instance);
44554    }
44555
44556    instance = {
44557        getMaxIndex: getMaxIndex,
44558        reset: reset
44559    };
44560
44561    setup();
44562    return instance;
44563}
44564
44565BolaRule.__dashjs_factory_name = 'BolaRule';
44566exports['default'] = _coreFactoryMaker2['default'].getClassFactory(BolaRule);
44567module.exports = exports['default'];
44568
44569},{"101":101,"171":171,"224":224,"49":49,"50":50,"51":51,"54":54}],177:[function(_dereq_,module,exports){
44570'use strict';
44571
44572Object.defineProperty(exports, '__esModule', {
44573    value: true
44574});
44575
44576function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
44577
44578var _coreFactoryMakerJs = _dereq_(51);
44579
44580var _coreFactoryMakerJs2 = _interopRequireDefault(_coreFactoryMakerJs);
44581
44582var _SwitchRequestJs = _dereq_(171);
44583
44584var _SwitchRequestJs2 = _interopRequireDefault(_SwitchRequestJs);
44585
44586var _coreDebug = _dereq_(49);
44587
44588var _coreDebug2 = _interopRequireDefault(_coreDebug);
44589
44590function DroppedFramesRule() {
44591    var context = this.context;
44592    var log = (0, _coreDebug2['default'])(context).getInstance().log;
44593
44594    var DROPPED_PERCENTAGE_FORBID = 0.15;
44595    var GOOD_SAMPLE_SIZE = 375; //Don't apply the rule until this many frames have been rendered(and counted under those indices).
44596
44597    function getMaxIndex(rulesContext) {
44598        var droppedFramesHistory = rulesContext.getDroppedFramesHistory();
44599        if (droppedFramesHistory) {
44600            var dfh = droppedFramesHistory.getFrameHistory();
44601            var droppedFrames = 0;
44602            var totalFrames = 0;
44603            var maxIndex = _SwitchRequestJs2['default'].NO_CHANGE;
44604            for (var i = 1; i < dfh.length; i++) {
44605                //No point in measuring dropped frames for the zeroeth index.
44606                if (dfh[i]) {
44607                    droppedFrames = dfh[i].droppedVideoFrames;
44608                    totalFrames = dfh[i].totalVideoFrames;
44609
44610                    if (totalFrames > GOOD_SAMPLE_SIZE && droppedFrames / totalFrames > DROPPED_PERCENTAGE_FORBID) {
44611                        maxIndex = i - 1;
44612                        log('DroppedFramesRule, index: ' + maxIndex + ' Dropped Frames: ' + droppedFrames + ' Total Frames: ' + totalFrames);
44613                        break;
44614                    }
44615                }
44616            }
44617            return (0, _SwitchRequestJs2['default'])(context).create(maxIndex, { droppedFrames: droppedFrames });
44618        }
44619
44620        return (0, _SwitchRequestJs2['default'])(context).create();
44621    }
44622
44623    return {
44624        getMaxIndex: getMaxIndex
44625    };
44626}
44627
44628DroppedFramesRule.__dashjs_factory_name = 'DroppedFramesRule';
44629var factory = _coreFactoryMakerJs2['default'].getClassFactory(DroppedFramesRule);
44630
44631exports['default'] = factory;
44632module.exports = exports['default'];
44633
44634},{"171":171,"49":49,"51":51}],178:[function(_dereq_,module,exports){
44635/**
44636 * The copyright in this software is being made available under the BSD License,
44637 * included below. This software may be subject to other third party and contributor
44638 * rights, including patent rights, and no such rights are granted under this license.
44639 *
44640 * Copyright (c) 2013, Dash Industry Forum.
44641 * All rights reserved.
44642 *
44643 * Redistribution and use in source and binary forms, with or without modification,
44644 * are permitted provided that the following conditions are met:
44645 *  * Redistributions of source code must retain the above copyright notice, this
44646 *  list of conditions and the following disclaimer.
44647 *  * Redistributions in binary form must reproduce the above copyright notice,
44648 *  this list of conditions and the following disclaimer in the documentation and/or
44649 *  other materials provided with the distribution.
44650 *  * Neither the name of Dash Industry Forum nor the names of its
44651 *  contributors may be used to endorse or promote products derived from this software
44652 *  without specific prior written permission.
44653 *
44654 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
44655 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
44656 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
44657 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
44658 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
44658INCLUDING, BUT
44659 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
44660 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44661 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
44662 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
44663 *  POSSIBILITY OF SUCH DAMAGE.
44664 */
44665'use strict';
44666
44667Object.defineProperty(exports, '__esModule', {
44668    value: true
44669});
44670
44671function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
44672
44673var _controllersBufferController = _dereq_(105);
44674
44675var _controllersBufferController2 = _interopRequireDefault(_controllersBufferController);
44676
44677var _coreEventBus = _dereq_(50);
44678
44679var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
44680
44681var _coreEventsEvents = _dereq_(54);
44682
44683var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
44684
44685var _coreFactoryMaker = _dereq_(51);
44686
44687var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
44688
44689var _coreDebug = _dereq_(49);
44690
44691var _coreDebug2 = _interopRequireDefault(_coreDebug);
44692
44693var _SwitchRequestJs = _dereq_(171);
44694
44695var _SwitchRequestJs2 = _interopRequireDefault(_SwitchRequestJs);
44696
44697function InsufficientBufferRule(config) {
44698
44699    var INSUFFICIENT_BUFFER_SAFETY_FACTOR = 0.5;
44700
44701    var context = this.context;
44702    var log = (0, _coreDebug2['default'])(context).getInstance().log;
44703    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
44704
44705    var metricsModel = config.metricsModel;
44706    var dashMetrics = config.dashMetrics;
44707
44708    var instance = undefined,
44709        bufferStateDict = undefined;
44710
44711    function setup() {
44712        resetInitialSettings();
44713        eventBus.on(_coreEventsEvents2['default'].PLAYBACK_SEEKING, onPlaybackSeeking, instance);
44714    }
44715
44716    function checkConfig() {
44717        if (!metricsModel || !metricsModel.hasOwnProperty('getReadOnlyMetricsFor') || !dashMetrics || !dashMetrics.hasOwnProperty('getCurrentBufferLevel')) {
44718            throw new Error('Missing config parameter(s)');
44719        }
44720    }
44721    /*
44722     * InsufficientBufferRule does not kick in before the first BUFFER_LOADED event happens. This is reset at every seek.
44723     *
44724     * If a BUFFER_EMPTY event happens, then InsufficientBufferRule returns switchRequest.quality=0 until BUFFER_LOADED happens.
44725     *
44726     * Otherwise InsufficientBufferRule gives a maximum bitrate depending on throughput and bufferLevel such that
44727     * a whole fragment can be downloaded before the buffer runs out, subject to a conservative safety factor of 0.5.
44728     * If the bufferLevel is low, then InsufficientBufferRule avoids rebuffering risk.
44729     * If the bufferLevel is high, then InsufficientBufferRule give a high MaxIndex allowing other rules to take over.
44730     */
44731    function getMaxIndex(rulesContext) {
44732        var switchRequest = (0, _SwitchRequestJs2['default'])(context).create();
44733
44734        if (!rulesContext || !rulesContext.hasOwnProperty('getMediaType')) {
44735            return switchRequest;
44736        }
44737
44738        checkConfig();
44739
44740        var mediaType = rulesContext.getMediaType();
44741        var metrics = metricsModel.getReadOnlyMetricsFor(mediaType);
44742        var lastBufferStateVO = metrics.BufferState.length > 0 ? metrics.BufferState[metrics.BufferState.length - 1] : null;
44743
44744        if (!lastBufferStateVO || !wasFirstBufferLoadedEventTriggered(mediaType, lastBufferStateVO)) {
44745            return switchRequest;
44746        }
44747
44748        if (lastBufferStateVO.state === _controllersBufferController2['default'].BUFFER_EMPTY) {
44749            log('Switch to index 0; buffer is empty.');
44750            switchRequest.quality = 0;
44751            switchRequest.reason = 'InsufficientBufferRule: Buffer is empty';
44752        } else {
44753            var mediaInfo = rulesContext.getMediaInfo();
44754            var abrController = rulesContext.getAbrController();
44755            var throughputHistory = abrController.getThroughputHistory();
44756            var representationInfo = rulesContext.getRepresentationInfo();
44757            var fragmentDuration = representationInfo.fragmentDuration;
44758
44759            var bufferLevel = dashMetrics.getCurrentBufferLevel(metrics);
44760
44761            var throughput = throughputHistory.getAverageThroughput(mediaType);
44762            var latency = throughputHistory.getAverageLatency(mediaType);
44763
44764            var bitrate = throughput * (bufferLevel / fragmentDuration) * INSUFFICIENT_BUFFER_SAFETY_FACTOR;
44765
44766            switchRequest.quality = abrController.getQualityForBitrate(mediaInfo, bitrate, latency);
44767            switchRequest.reason = 'InsufficientBufferRule: being conservative to avoid immediate rebuffering';
44768        }
44769
44770        return switchRequest;
44771    }
44772
44773    function wasFirstBufferLoadedEventTriggered(mediaType, currentBufferState) {
44774        bufferStateDict[mediaType] = bufferStateDict[mediaType] || {};
44775
44776        var wasTriggered = false;
44777        if (bufferStateDict[mediaType].firstBufferLoadedEvent) {
44778            wasTriggered = true;
44779        } else if (currentBufferState && currentBufferState.state === _controllersBufferController2['default'].BUFFER_LOADED) {
44780            bufferStateDict[mediaType].firstBufferLoadedEvent = true;
44781            wasTriggered = true;
44782        }
44783        return wasTriggered;
44784    }
44785
44786    function resetInitialSettings() {
44787        bufferStateDict = {};
44788    }
44789
44790    function onPlaybackSeeking() {
44791        resetInitialSettings();
44792    }
44793
44794    function reset() {
44795        resetInitialSettings();
44796        eventBus.off(_coreEventsEvents2['default'].PLAYBACK_SEEKING, onPlaybackSeeking, instance);
44797    }
44798
44799    instance = {
44800        getMaxIndex: getMaxIndex,
44801        reset: reset
44802    };
44803
44804    setup();
44805
44806    return instance;
44807}
44808
44809InsufficientBufferRule.__dashjs_factory_name = 'InsufficientBufferRule';
44810exports['default'] = _coreFactoryMaker2['default'].getClassFactory(InsufficientBufferRule);
44811module.exports = exports['default'];
44812
44813},{"105":105,"171":171,"49":49,"50":50,"51":51,"54":54}],179:[function(_dereq_,module,exports){
44814'use strict';
44815
44816Object.defineProperty(exports, '__esModule', {
44817    value: true
44818});
44819
44820function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
44821
44822var _coreFactoryMakerJs = _dereq_(51);
44823
44824var _coreFactoryMakerJs2 = _interopRequireDefault(_coreFactoryMakerJs);
44825
44826var _coreDebug = _dereq_(49);
44827
44828var _coreDebug2 = _interopRequireDefault(_coreDebug);
44829
44830var _SwitchRequestJs = _dereq_(171);
44831
44832var _SwitchRequestJs2 = _interopRequireDefault(_SwitchRequestJs);
44833
44834function SwitchHistoryRule() {
44835    var context = this.context;
44836    var log = (0, _coreDebug2['default'])(context).getInstance().log;
44837
44838    //MAX_SWITCH is the number of drops made. It doesn't consider the size of the drop.
44839    var MAX_SWITCH = 0.075;
44840
44841    //Before this number of switch requests(no switch or actual), don't apply the rule.
44842    //must be < SwitchRequestHistory SWITCH_REQUEST_HISTORY_DEPTH to enable rule
44843    var SAMPLE_SIZE = 6;
44844
44845    function getMaxIndex(rulesContext) {
44846        var switchRequestHistory = rulesContext ? rulesContext.getSwitchHistory() : null;
44847        var switchRequests = switchRequestHistory ? switchRequestHistory.getSwitchRequests() : [];
44848        var drops = 0;
44849        var noDrops = 0;
44850        var dropSize = 0;
44851        var switchRequest = (0, _SwitchRequestJs2['default'])(context).create();
44852
44853        for (var i = 0; i < switchRequests.length; i++) {
44854            if (switchRequests[i] !== undefined) {
44855                drops += switchRequests[i].drops;
44856                noDrops += switchRequests[i].noDrops;
44857                dropSize += switchRequests[i].dropSize;
44858
44859                if (drops + noDrops >= SAMPLE_SIZE && drops / noDrops > MAX_SWITCH) {
44860                    switchRequest.quality = i > 0 && switchRequests[i].drops > 0 ? i - 1 : i;
44861                    switchRequest.reason = { index: switchRequest.quality, drops: drops, noDrops: noDrops, dropSize: dropSize };
44862                    log('Switch history rule index: ' + switchRequest.quality + ' samples: ' + (drops + noDrops) + ' drops: ' + drops);
44863                    break;
44864                }
44865            }
44866        }
44867
44868        return switchRequest;
44869    }
44870
44871    return {
44872        getMaxIndex: getMaxIndex
44873    };
44874}
44875
44876SwitchHistoryRule.__dashjs_factory_name = 'SwitchHistoryRule';
44877var factory = _coreFactoryMakerJs2['default'].getClassFactory(SwitchHistoryRule);
44878
44879exports['default'] = factory;
44880module.exports = exports['default'];
44881
44882},{"171":171,"49":49,"51":51}],180:[function(_dereq_,module,exports){
44883/**
44884 * The copyright in this software is being made available under the BSD License,
44885 * included below. This software may be subject to other third party and contributor
44886 * rights, including patent rights, and no such rights are granted under this license.
44887 *
44888 * Copyright (c) 2013, Dash Industry Forum.
44889 * All rights reserved.
44890 *
44891 * Redistribution and use in source and binary forms, with or without modification,
44892 * are permitted provided that the following conditions are met:
44893 *  * Redistributions of source code must retain the above copyright notice, this
44894 *  list of conditions and the following disclaimer.
44895 *  * Redistributions in binary form must reproduce the above copyright notice,
44896 *  this list of conditions and the following disclaimer in the documentation and/or
44897 *  other materials provided with the distribution.
44898 *  * Neither the name of Dash Industry Forum nor the names of its
44899 *  contributors may be used to endorse or promote products derived from this software
44900 *  without specific prior written permission.
44901 *
44902 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
44903 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
44904 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
44905 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
44906 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
44906INCLUDING, BUT
44907 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
44908 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44909 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
44910 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
44911 *  POSSIBILITY OF SUCH DAMAGE.
44912 */
44913'use strict';
44914
44915Object.defineProperty(exports, '__esModule', {
44916    value: true
44917});
44918
44919function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
44920
44921var _controllersBufferController = _dereq_(105);
44922
44923var _controllersBufferController2 = _interopRequireDefault(_controllersBufferController);
44924
44925var _controllersAbrController = _dereq_(102);
44926
44927var _controllersAbrController2 = _interopRequireDefault(_controllersAbrController);
44928
44929var _coreFactoryMaker = _dereq_(51);
44930
44931var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
44932
44933var _coreDebug = _dereq_(49);
44934
44935var _coreDebug2 = _interopRequireDefault(_coreDebug);
44936
44937var _SwitchRequestJs = _dereq_(171);
44938
44939var _SwitchRequestJs2 = _interopRequireDefault(_SwitchRequestJs);
44940
44941function ThroughputRule(config) {
44942
44943    var context = this.context;
44944    var log = (0, _coreDebug2['default'])(context).getInstance().log;
44945    var metricsModel = config.metricsModel;
44946
44947    function checkConfig() {
44948        if (!metricsModel || !metricsModel.hasOwnProperty('getReadOnlyMetricsFor')) {
44949            throw new Error('Missing config parameter(s)');
44950        }
44951    }
44952
44953    function getMaxIndex(rulesContext) {
44954        var switchRequest = (0, _SwitchRequestJs2['default'])(context).create();
44955
44956        if (!rulesContext || !rulesContext.hasOwnProperty('getMediaInfo') || !rulesContext.hasOwnProperty('getMediaType') || !rulesContext.hasOwnProperty('useBufferOccupancyABR') || !rulesContext.hasOwnProperty('getAbrController') || !rulesContext.hasOwnProperty('getStreamProcessor')) {
44957            return switchRequest;
44958        }
44959
44960        checkConfig();
44961
44962        var mediaInfo = rulesContext.getMediaInfo();
44963        var mediaType = rulesContext.getMediaType();
44964        var metrics = metricsModel.getReadOnlyMetricsFor(mediaType);
44965        var streamProcessor = rulesContext.getStreamProcessor();
44966        var abrController = rulesContext.getAbrController();
44967        var streamInfo = rulesContext.getStreamInfo();
44968        var isDynamic = streamInfo && streamInfo.manifestInfo ? streamInfo.manifestInfo.isDynamic : null;
44969        var throughputHistory = abrController.getThroughputHistory();
44970        var throughput = throughputHistory.getSafeAverageThroughput(mediaType, isDynamic);
44971        var latency = throughputHistory.getAverageLatency(mediaType);
44972        var bufferStateVO = metrics.BufferState.length > 0 ? metrics.BufferState[metrics.BufferState.length - 1] : null;
44973        var useBufferOccupancyABR = rulesContext.useBufferOccupancyABR();
44974
44975        if (!metrics || isNaN(throughput) || !bufferStateVO || useBufferOccupancyABR) {
44976            return switchRequest;
44977        }
44978
44979        if (abrController.getAbandonmentStateFor(mediaType) !== _controllersAbrController2['default'].ABANDON_LOAD) {
44980
44981            if (bufferStateVO.state === _controllersBufferController2['default'].BUFFER_LOADED || isDynamic) {
44982                switchRequest.quality = abrController.getQualityForBitrate(mediaInfo, throughput, latency);
44983                streamProcessor.getScheduleController().setTimeToLoadDelay(0);
44984                log('ThroughputRule requesting switch to index: ', switchRequest.quality, 'type: ', mediaType, 'Average throughput', Math.round(throughput), 'kbps');
44985                switchRequest.reason = { throughput: throughput, latency: latency };
44986            }
44987        }
44988
44989        return switchRequest;
44990    }
44991
44992    function reset() {
44993        // no persistent information to reset
44994    }
44995
44996    var instance = {
44997        getMaxIndex: getMaxIndex,
44998        reset: reset
44999    };
45000
45001    return instance;
45002}
45003
45004ThroughputRule.__dashjs_factory_name = 'ThroughputRule';
45005exports['default'] = _coreFactoryMaker2['default'].getClassFactory(ThroughputRule);
45006module.exports = exports['default'];
45007
45008},{"102":102,"105":105,"171":171,"49":49,"51":51}],181:[function(_dereq_,module,exports){
45009/**
45010 * The copyright in this software is being made available under the BSD License,
45011 * included below. This software may be subject to other third party and contributor
45012 * rights, including patent rights, and no such rights are granted under this license.
45013 *
45014 * Copyright (c) 2013, Dash Industry Forum.
45015 * All rights reserved.
45016 *
45017 * Redistribution and use in source and binary forms, with or without modification,
45018 * are permitted provided that the following conditions are met:
45019 *  * Redistributions of source code must retain the above copyright notice, this
45020 *  list of conditions and the following disclaimer.
45021 *  * Redistributions in binary form must reproduce the above copyright notice,
45022 *  this list of conditions and the following disclaimer in the documentation and/or
45023 *  other materials provided with the distribution.
45024 *  * Neither the name of Dash Industry Forum nor the names of its
45025 *  contributors may be used to endorse or promote products derived from this software
45026 *  without specific prior written permission.
45027 *
45028 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
45029 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
45030 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
45031 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
45032 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
45032INCLUDING, BUT
45033 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
45034 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
45035 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45036 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
45037 *  POSSIBILITY OF SUCH DAMAGE.
45038 */
45039'use strict';
45040
45041Object.defineProperty(exports, '__esModule', {
45042    value: true
45043});
45044
45045function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
45046
45047var _constantsConstants = _dereq_(100);
45048
45049var _constantsConstants2 = _interopRequireDefault(_constantsConstants);
45050
45051var _coreFactoryMaker = _dereq_(51);
45052
45053var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
45054
45055function BufferLevelRule(config) {
45056
45057    var dashMetrics = config.dashMetrics;
45058    var metricsModel = config.metricsModel;
45059    var mediaPlayerModel = config.mediaPlayerModel;
45060    var textController = config.textController;
45061    var abrController = config.abrController;
45062
45063    function setup() {}
45064
45065    function execute(streamProcessor, type, videoTrackPresent) {
45066        var bufferLevel = dashMetrics.getCurrentBufferLevel(metricsModel.getReadOnlyMetricsFor(type));
45067        return bufferLevel < getBufferTarget(streamProcessor, type, videoTrackPresent);
45068    }
45069
45070    function getBufferTarget(streamProcessor, type, videoTrackPresent) {
45071        var bufferTarget = NaN;
45072        var representationInfo = streamProcessor.getCurrentRepresentationInfo();
45073        if (type === _constantsConstants2['default'].FRAGMENTED_TEXT) {
45074            bufferTarget = textController.getAllTracksAreDisabled() ? 0 : representationInfo.fragmentDuration;
45075        } else if (type === _constantsConstants2['default'].AUDIO && videoTrackPresent) {
45076            var videoBufferLevel = dashMetrics.getCurrentBufferLevel(metricsModel.getReadOnlyMetricsFor(_constantsConstants2['default'].VIDEO));
45077            if (isNaN(representationInfo.fragmentDuration)) {
45078                bufferTarget = videoBufferLevel;
45079            } else {
45080                bufferTarget = Math.max(videoBufferLevel, representationInfo.fragmentDuration);
45081            }
45082            // console.log('videoBufferLevel  - ' + videoBufferLevel + ' target : ' + bufferTarget);
45083        } else {
45084                var streamInfo = representationInfo.mediaInfo.streamInfo;
45085                if (abrController.isPlayingAtTopQuality(streamInfo)) {
45086                    var isLongFormContent = streamInfo.manifestInfo.duration >= mediaPlayerModel.getLongFormContentDurationThreshold();
45087                    bufferTarget = isLongFormContent ? mediaPlayerModel.getBufferTimeAtTopQualityLongForm() : mediaPlayerModel.getBufferTimeAtTopQuality();
45088                } else {
45089                    bufferTarget = mediaPlayerModel.getStableBufferTime();
45090                }
45091            }
45092
45093        return bufferTarget;
45094    }
45095
45096    var instance = {
45097        execute: execute,
45098        getBufferTarget: getBufferTarget
45099    };
45100
45101    setup();
45102    return instance;
45103}
45104
45105BufferLevelRule.__dashjs_factory_name = 'BufferLevelRule';
45106exports['default'] = _coreFactoryMaker2['default'].getClassFactory(BufferLevelRule);
45107module.exports = exports['default'];
45108
45109},{"100":100,"51":51}],182:[function(_dereq_,module,exports){
45110/**
45111 * The copyright in this software is being made available under the BSD License,
45112 * included below. This software may be subject to other third party and contributor
45113 * rights, including patent rights, and no such rights are granted under this license.
45114 *
45115 * Copyright (c) 2013, Dash Industry Forum.
45116 * All rights reserved.
45117 *
45118 * Redistribution and use in source and binary forms, with or without modification,
45119 * are permitted provided that the following conditions are met:
45120 *  * Redistributions of source code must retain the above copyright notice, this
45121 *  list of conditions and the following disclaimer.
45122 *  * Redistributions in binary form must reproduce the above copyright notice,
45123 *  this list of conditions and the following disclaimer in the documentation and/or
45124 *  other materials provided with the distribution.
45125 *  * Neither the name of Dash Industry Forum nor the names of its
45126 *  contributors may be used to endorse or promote products derived from this software
45127 *  without specific prior written permission.
45128 *
45129 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
45130 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
45131 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
45132 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
45133 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
45133INCLUDING, BUT
45134 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
45135 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
45136 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45137 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
45138 *  POSSIBILITY OF SUCH DAMAGE.
45139 */
45140'use strict';
45141
45142Object.defineProperty(exports, '__esModule', {
45143    value: true
45144});
45145
45146function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
45147
45148var _constantsConstants = _dereq_(100);
45149
45150var _constantsConstants2 = _interopRequireDefault(_constantsConstants);
45151
45152var _coreDebug = _dereq_(49);
45153
45154var _coreDebug2 = _interopRequireDefault(_coreDebug);
45155
45156var _coreFactoryMaker = _dereq_(51);
45157
45158var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
45159
45160function NextFragmentRequestRule(config) {
45161
45162    var context = this.context;
45163    var log = (0, _coreDebug2['default'])(context).getInstance().log;
45164    var adapter = config.adapter;
45165    var sourceBufferController = config.sourceBufferController;
45166    var textController = config.textController;
45167
45168    function execute(streamProcessor, requestToReplace) {
45169
45170        var representationInfo = streamProcessor.getCurrentRepresentationInfo();
45171        var mediaInfo = representationInfo.mediaInfo;
45172        var mediaType = mediaInfo.type;
45173        var scheduleController = streamProcessor.getScheduleController();
45174        var seekTarget = scheduleController.getSeekTarget();
45175        var hasSeekTarget = !isNaN(seekTarget);
45176        var buffer = streamProcessor.getBuffer();
45177
45178        var time = hasSeekTarget ? seekTarget : adapter.getIndexHandlerTime(streamProcessor);
45179
45180        if (isNaN(time) || mediaType === _constantsConstants2['default'].FRAGMENTED_TEXT && textController.getAllTracksAreDisabled()) {
45181            return null;
45182        }
45183
45184        if (hasSeekTarget) {
45185            scheduleController.setSeekTarget(NaN);
45186        }
45187
45188        /**
45189         * This is critical for IE/Safari/EDGE
45190         * */
45191        if (buffer) {
45192            var range = sourceBufferController.getBufferRange(buffer, time);
45193            if (range !== null) {
45194                log('Prior to making a request for time, NextFragmentRequestRule is aligning index handler\'s currentTime with bufferedRange.end.', time, ' was changed to ', range.end);
45195                time = range.end;
45196            }
45197        }
45198
45199        var request = undefined;
45200        if (requestToReplace) {
45201            // log('requestToReplace :' + requestToReplace.url);
45202            time = requestToReplace.startTime + requestToReplace.duration / 2;
45203            request = adapter.getFragmentRequestForTime(streamProcessor, representationInfo, time, {
45204                timeThreshold: 0,
45205                ignoreIsFinished: true
45206            });
45207        } else {
45208            request = adapter.getFragmentRequestForTime(streamProcessor, representationInfo, time, {
45209                keepIdx: !hasSeekTarget
45210            });
45211            while (streamProcessor.getFragmentModel().isFragmentLoaded(request)) {
45212                // loop until we found not loaded fragment, or no fragment
45213                request = adapter.getNextFragmentRequest(streamProcessor, representationInfo);
45214            }
45215            if (request) {
45216                adapter.setIndexHandlerTime(streamProcessor, request.startTime + request.duration);
45217                request.delayLoadingTime = new Date().getTime() + scheduleController.getTimeToLoadDelay();
45218                scheduleController.setTimeToLoadDelay(0);
45219            }
45220        }
45221
45222        /*
45223        if (request) {
45224            log('Return request :' + request.url);
45225        } else {
45226            log('no request');
45227        }*/
45228
45229        return request;
45230    }
45231
45232    var instance = {
45233        execute: execute
45234    };
45235
45236    return instance;
45237}
45238
45239NextFragmentRequestRule.__dashjs_factory_name = 'NextFragmentRequestRule';
45240exports['default'] = _coreFactoryMaker2['default'].getClassFactory(NextFragmentRequestRule);
45241module.exports = exports['default'];
45242
45243},{"100":100,"49":49,"51":51}],183:[function(_dereq_,module,exports){
45244/**
45245 * The copyright in this software is being made available under the BSD License,
45246 * included below. This software may be subject to other third party and contributor
45247 * rights, including patent rights, and no such rights are granted under this license.
45248 *
45249 * Copyright (c) 2013, Dash Industry Forum.
45250 * All rights reserved.
45251 *
45252 * Redistribution and use in source and binary forms, with or without modification,
45253 * are permitted provided that the following conditions are met:
45254 *  * Redistributions of source code must retain the above copyright notice, this
45255 *  list of conditions and the following disclaimer.
45256 *  * Redistributions in binary form must reproduce the above copyright notice,
45257 *  this list of conditions and the following disclaimer in the documentation and/or
45258 *  other materials provided with the distribution.
45259 *  * Neither the name of Dash Industry Forum nor the names of its
45260 *  contributors may be used to endorse or promote products derived from this software
45261 *  without specific prior written permission.
45262 *
45263 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
45264 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
45265 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
45266 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
45267 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
vendor: 14,910 bytes, lines 45267-45606
45267INCLUDING, BUT
45268 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
45269 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
45270 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45271 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
45272 *  POSSIBILITY OF SUCH DAMAGE.
45273 */
45274'use strict';
45275
45276Object.defineProperty(exports, '__esModule', {
45277    value: true
45278});
45279
45280function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
45281
45282var _coreFactoryMaker = _dereq_(51);
45283
45284var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
45285
45286function EmbeddedTextHtmlRender() {
45287
45288    var captionId = 0;
45289    var instance = undefined;
45290
45291    /* HTML Rendering functions */
45292    function checkIndent(chars) {
45293        var line = '';
45294
45295        for (var c = 0; c < chars.length; ++c) {
45296            var uc = chars[c];
45297            line += uc.uchar;
45298        }
45299
45300        var l = line.length;
45301        var ll = line.replace(/^\s+/, '').length;
45302        return l - ll;
45303    }
45304
45305    function getRegionProperties(region) {
45306        return 'left: ' + region.x * 3.125 + '%; top: ' + region.y1 * 6.66 + '%; width: ' + (100 - region.x * 3.125) + '%; height: ' + Math.max(region.y2 - 1 - region.y1, 1) * 6.66 + '%; align-items: flex-start; overflow: visible; -webkit-writing-mode: horizontal-tb;';
45307    }
45308
45309    function createRGB(color) {
45310        if (color === 'red') {
45311            return 'rgb(255, 0, 0)';
45312        } else if (color === 'green') {
45313            return 'rgb(0, 255, 0)';
45314        } else if (color === 'blue') {
45315            return 'rgb(0, 0, 255)';
45316        } else if (color === 'cyan') {
45317            return 'rgb(0, 255, 255)';
45318        } else if (color === 'magenta') {
45319            return 'rgb(255, 0, 255)';
45320        } else if (color === 'yellow') {
45321            return 'rgb(255, 255, 0)';
45322        } else if (color === 'white') {
45323            return 'rgb(255, 255, 255)';
45324        } else if (color === 'black') {
45325            return 'rgb(0, 0, 0)';
45326        }
45327        return color;
45328    }
45329
45330    function getStyle(videoElement, style) {
45331        var fontSize = videoElement.videoHeight / 15.0;
45332        if (style) {
45333            return 'font-size: ' + fontSize + 'px; font-family: Menlo, Consolas, \'Cutive Mono\', monospace; color: ' + (style.foreground ? createRGB(style.foreground) : 'rgb(255, 255, 255)') + '; font-style: ' + (style.italics ? 'italic' : 'normal') + '; text-decoration: ' + (style.underline ? 'underline' : 'none') + '; white-space: pre; background-color: ' + (style.background ? createRGB(style.background) : 'transparent') + ';';
45334        } else {
45335            return 'font-size: ' + fontSize + 'px; font-family: Menlo, Consolas, \'Cutive Mono\', monospace; justify-content: flex-start; text-align: left; color: rgb(255, 255, 255); font-style: normal; white-space: pre; line-height: normal; font-weight: normal; text-decoration: none; width: 100%; display: flex;';
45336        }
45337    }
45338
45339    function ltrim(s) {
45340        var trimmed = s.replace(/^\s+/g, '');
45341        return trimmed;
45342    }
45343    function rtrim(s) {
45344        var trimmed = s.replace(/\s+$/g, '');
45345        return trimmed;
45346    }
45347
45348    function createHTMLCaptionsFromScreen(videoElement, startTime, endTime, captionScreen) {
45349
45350        var currRegion = null;
45351        var existingRegion = null;
45352        var lastRowHasText = false;
45353        var lastRowIndentL = -1;
45354        var currP = { start: startTime, end: endTime, spans: [] };
45355        var currentStyle = 'style_cea608_white_black';
45356        var seenRegions = {};
45357        var styleStates = {};
45358        var regions = [];
45359        var r = undefined,
45360            s = undefined;
45361
45362        for (r = 0; r < 15; ++r) {
45363            var row = captionScreen.rows[r];
45364            var line = '';
45365            var prevPenState = null;
45366
45367            if (false === row.isEmpty()) {
45368                /* Row is not empty */
45369
45370                /* Get indentation of this row */
45371                var rowIndent = checkIndent(row.chars);
45372
45373                /* Create a new region is there is none */
45374                if (currRegion === null) {
45375                    currRegion = { x: rowIndent, y1: r, y2: r + 1, p: [] };
45376                }
45377
45378                /* Check if indentation has changed and we had text of last row */
45379                if (rowIndent !== lastRowIndentL && lastRowHasText) {
45380                    currRegion.p.push(currP);
45381                    currP = { start: startTime, end: endTime, spans: [] };
45382                    currRegion.y2 = r;
45383                    currRegion.name = 'region_' + currRegion.x + '_' + currRegion.y1 + '_' + currRegion.y2;
45384                    if (false === seenRegions.hasOwnProperty(currRegion.name)) {
45385                        regions.push(currRegion);
45386                        seenRegions[currRegion.name] = currRegion;
45387                    } else {
45388                        existingRegion = seenRegions[currRegion.name];
45389                        existingRegion.p.contat(currRegion.p);
45390                    }
45391
45392                    currRegion = { x: rowIndent, y1: r, y2: r + 1, p: [] };
45393                }
45394
45395                for (var c = 0; c < row.chars.length; ++c) {
45396                    var uc = row.chars[c];
45397                    var currPenState = uc.penState;
45398                    if (prevPenState === null || !currPenState.equals(prevPenState)) {
45399                        if (line.trim().length > 0) {
45400                            currP.spans.push({ name: currentStyle, line: line, row: r });
45401                            line = '';
45402                        }
45403
45404                        var currPenStateString = 'style_cea608_' + currPenState.foreground + '_' + currPenState.background;
45405                        if (currPenState.underline) {
45406                            currPenStateString += '_underline';
45407                        }
45408                        if (currPenState.italics) {
45409                            currPenStateString += '_italics';
45410                        }
45411
45412                        if (!styleStates.hasOwnProperty(currPenStateString)) {
45413                            styleStates[currPenStateString] = JSON.parse(JSON.stringify(currPenState));
45414                        }
45415
45416                        prevPenState = currPenState;
45417
45418                        currentStyle = currPenStateString;
45419                    }
45420
45421                    line += uc.uchar;
45422                }
45423
45424                if (line.trim().length > 0) {
45425                    currP.spans.push({ name: currentStyle, line: line, row: r });
45426                }
45427
45428                lastRowHasText = true;
45429                lastRowIndentL = rowIndent;
45430            } else {
45431                /* Row is empty */
45432                lastRowHasText = false;
45433                lastRowIndentL = -1;
45434
45435                if (currRegion) {
45436                    currRegion.p.push(currP);
45437                    currP = { start: startTime, end: endTime, spans: [] };
45438                    currRegion.y2 = r;
45439                    currRegion.name = 'region_' + currRegion.x + '_' + currRegion.y1 + '_' + currRegion.y2;
45440                    if (false === seenRegions.hasOwnProperty(currRegion.name)) {
45441                        regions.push(currRegion);
45442                        seenRegions[currRegion.name] = currRegion;
45443                    } else {
45444                        existingRegion = seenRegions[currRegion.name];
45445                        existingRegion.p.contat(currRegion.p);
45446                    }
45447
45448                    currRegion = null;
45449                }
45450            }
45451        }
45452
45453        if (currRegion) {
45454            currRegion.p.push(currP);
45455            currRegion.y2 = r + 1;
45456            currRegion.name = 'region_' + currRegion.x + '_' + currRegion.y1 + '_' + currRegion.y2;
45457            if (false === seenRegions.hasOwnProperty(currRegion.name)) {
45458                regions.push(currRegion);
45459                seenRegions[currRegion.name] = currRegion;
45460            } else {
45461                existingRegion = seenRegions[currRegion.name];
45462                existingRegion.p.contat(currRegion.p);
45463            }
45464
45465            currRegion = null;
45466        }
45467
45468        //log(styleStates);
45469        //log(regions);
45470
45471        var captionsArray = [];
45472
45473        /* Loop thru regions */
45474        for (r = 0; r < regions.length; ++r) {
45475            var region = regions[r];
45476
45477            var cueID = 'sub_cea608_' + captionId++;
45478            var finalDiv = document.createElement('div');
45479            finalDiv.id = cueID;
45480            var cueRegionProperties = getRegionProperties(region);
45481            finalDiv.style.cssText = 'position: absolute; margin: 0; display: flex; box-sizing: border-box; pointer-events: none;' + cueRegionProperties;
45482
45483            var bodyDiv = document.createElement('div');
45484            bodyDiv.className = 'paragraph bodyStyle';
45485            bodyDiv.style.cssText = getStyle(videoElement);
45486
45487            var cueUniWrapper = document.createElement('div');
45488            cueUniWrapper.className = 'cueUniWrapper';
45489            cueUniWrapper.style.cssText = 'unicode-bidi: normal; direction: ltr;';
45490
45491            for (var p = 0; p < region.p.length; ++p) {
45492                var ptag = region.p[p];
45493                var lastSpanRow = 0;
45494                for (s = 0; s < ptag.spans.length; ++s) {
45495                    var span = ptag.spans[s];
45496                    if (span.line.length > 0) {
45497                        if (s !== 0 && lastSpanRow != span.row) {
45498                            var brElement = document.createElement('br');
45499                            brElement.className = 'lineBreak';
45500                            cueUniWrapper.appendChild(brElement);
45501                        }
45502                        var sameRow = false;
45503                        if (lastSpanRow === span.row) {
45504                            sameRow = true;
45505                        }
45506                        lastSpanRow = span.row;
45507                        var spanStyle = styleStates[span.name];
45508                        var spanElement = document.createElement('span');
45509                        spanElement.className = 'spanPadding ' + span.name + ' customSpanColor';
45510                        spanElement.style.cssText = getStyle(videoElement, spanStyle);
45511                        /* If this is not the first span, and it's on the same
45512                         * row as the last one */
45513                        if (s !== 0 && sameRow) {
45514                            /* and it's the last span on this row */
45515                            if (s === ptag.spans.length - 1) {
45516                                /* trim only the right side */
45517                                spanElement.textContent = rtrim(span.line);
45518                            } else {
45519                                /* don't trim at all */
45520                                spanElement.textContent = span.line;
45521                            }
45522                        } else {
45523                            /* if there is more than 1 span and this isn't the last span */
45524                            if (ptag.spans.length > 1 && s < ptag.spans.length - 1) {
45525                                /* Check if next text is on same row */
45526                                if (span.row === ptag.spans[s + 1].row) {
45527                                    /* Next element on same row, trim start */
45528                                    spanElement.textContent = ltrim(span.line);
45529                                } else {
45530                                    /* Different rows, trim both */
45531                                    spanElement.textContent = span.line.trim();
45532                                }
45533                            } else {
45534                                spanElement.textContent = span.line.trim();
45535                            }
45536                        }
45537                        cueUniWrapper.appendChild(spanElement);
45538                    }
45539                }
45540            }
45541
45542            bodyDiv.appendChild(cueUniWrapper);
45543
45544            finalDiv.appendChild(bodyDiv);
45545
45546            var fontSize = { 'bodyStyle': ['%', 90] };
45547            for (s in styleStates) {
45548                if (styleStates.hasOwnProperty(s)) {
45549                    fontSize[s] = ['%', 90];
45550                }
45551            }
45552
45553            captionsArray.push({ type: 'html',
45554                start: startTime,
45555                end: endTime,
45556                cueHTMLElement: finalDiv,
45557                cueID: cueID,
45558                cellResolution: [32, 15],
45559                isFromCEA608: true,
45560                regions: regions,
45561                regionID: region.name,
45562                videoHeight: videoElement.videoHeight,
45563                videoWidth: videoElement.videoWidth,
45564                fontSize: fontSize,
45565                lineHeight: {},
45566                linePadding: {}
45567            });
45568        }
45569        return captionsArray;
45570    }
45571
45572    instance = {
45573        createHTMLCaptionsFromScreen: createHTMLCaptionsFromScreen
45574    };
45575    return instance;
45576}
45577
45578EmbeddedTextHtmlRender.__dashjs_factory_name = 'EmbeddedTextHtmlRender';
45579exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(EmbeddedTextHtmlRender);
45580module.exports = exports['default'];
45581
45582},{"51":51}],184:[function(_dereq_,module,exports){
45583/**
45584 * The copyright in this software is being made available under the BSD License,
45585 * included below. This software may be subject to other third party and contributor
45586 * rights, including patent rights, and no such rights are granted under this license.
45587 *
45588 * Copyright (c) 2013, Dash Industry Forum.
45589 * All rights reserved.
45590 *
45591 * Redistribution and use in source and binary forms, with or without modification,
45592 * are permitted provided that the following conditions are met:
45593 *  * Redistributions of source code must retain the above copyright notice, this
45594 *  list of conditions and the following disclaimer.
45595 *  * Redistributions in binary form must reproduce the above copyright notice,
45596 *  this list of conditions and the following disclaimer in the documentation and/or
45597 *  other materials provided with the distribution.
45598 *  * Neither the name of Dash Industry Forum nor the names of its
45599 *  contributors may be used to endorse or promote products derived from this software
45600 *  without specific prior written permission.
45601 *
45602 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
45603 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
45604 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
45605 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
45606 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
45606INCLUDING, BUT
45607 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
45608 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
45609 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45610 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
45611 *  POSSIBILITY OF SUCH DAMAGE.
45612 */
45613'use strict';
45614
45615Object.defineProperty(exports, '__esModule', {
45616    value: true
45617});
45618
45619function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
45620
45621var _constantsConstants = _dereq_(100);
45622
45623var _constantsConstants2 = _interopRequireDefault(_constantsConstants);
45624
45625var _coreEventBus = _dereq_(50);
45626
45627var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
45628
45629var _coreEventsEvents = _dereq_(54);
45630
45631var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
45632
45633var _coreFactoryMaker = _dereq_(51);
45634
45635var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
45636
45637var _utilsInitCache = _dereq_(196);
45638
45639var _utilsInitCache2 = _interopRequireDefault(_utilsInitCache);
45640
45641var BUFFER_CONTROLLER_TYPE = 'NotFragmentedTextBufferController';
45642function NotFragmentedTextBufferController(config) {
45643
45644    var context = this.context;
45645    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
45646
45647    var sourceBufferController = config.sourceBufferController;
45648    var errHandler = config.errHandler;
45649    var type = config.type;
45650    var streamProcessor = config.streamProcessor;
45651
45652    var instance = undefined,
45653        isBufferingCompleted = undefined,
45654        initialized = undefined,
45655        mediaSource = undefined,
45656        buffer = undefined,
45657        seekStartTime = undefined,
45658        representationController = undefined,
45659        initCache = undefined;
45660
45661    function setup() {
45662
45663        initialized = false;
45664        mediaSource = null;
45665        buffer = null;
45666        representationController = null;
45667        isBufferingCompleted = false;
45668
45669        eventBus.on(_coreEventsEvents2['default'].DATA_UPDATE_COMPLETED, onDataUpdateCompleted, this);
45670        eventBus.on(_coreEventsEvents2['default'].INIT_FRAGMENT_LOADED, onInitFragmentLoaded, this);
45671    }
45672
45673    function getBufferControllerType() {
45674        return BUFFER_CONTROLLER_TYPE;
45675    }
45676
45677    function initialize(source) {
45678        setMediaSource(source);
45679        representationController = streamProcessor.getRepresentationController();
45680        initCache = (0, _utilsInitCache2['default'])(context).getInstance();
45681    }
45682
45683    /**
45684     * @param {MediaInfo }mediaInfo
45685     * @returns {Object} SourceBuffer object
45686     * @memberof BufferController#
45687     */
45688    function createBuffer(mediaInfo) {
45689        try {
45690            buffer = sourceBufferController.createSourceBuffer(mediaSource, mediaInfo);
45691
45692            if (!initialized) {
45693                if (buffer.hasOwnProperty(_constantsConstants2['default'].INITIALIZE)) {
45694                    buffer.initialize(type, streamProcessor);
45695                }
45696                initialized = true;
45697            }
45698        } catch (e) {
45699            errHandler.mediaSourceError('Error creating ' + type + ' source buffer.');
45700        }
45701
45702        return buffer;
45703    }
45704
45705    function getType() {
45706        return type;
45707    }
45708
45709    function getBuffer() {
45710        return buffer;
45711    }
45712
45713    function setBuffer(value) {
45714        buffer = value;
45715    }
45716
45717    function setMediaSource(value) {
45718        mediaSource = value;
45719    }
45720
45721    function getMediaSource() {
45722        return mediaSource;
45723    }
45724
45725    function getStreamProcessor() {
45726        return streamProcessor;
45727    }
45728
45729    function setSeekStartTime(value) {
45730        seekStartTime = value;
45731    }
45732
45733    function getSeekStartTime() {
45734        return seekStartTime;
45735    }
45736
45737    function getBufferLevel() {
45738        return 0;
45739    }
45740
45741    function getIsBufferingCompleted() {
45742        return isBufferingCompleted;
45743    }
45744
45745    function reset(errored) {
45746
45747        eventBus.off(_coreEventsEvents2['default'].DATA_UPDATE_COMPLETED, onDataUpdateCompleted, this);
45748        eventBus.off(_coreEventsEvents2['default'].INIT_FRAGMENT_LOADED, onInitFragmentLoaded, this);
45749
45750        if (!errored) {
45751            sourceBufferController.abort(mediaSource, buffer);
45752            sourceBufferController.removeSourceBuffer(mediaSource, buffer);
45753        }
45754    }
45755
45756    function onDataUpdateCompleted(e) {
45757        if (e.sender.getStreamProcessor() !== streamProcessor) {
45758            return;
45759        }
45760
45761        eventBus.trigger(_coreEventsEvents2['default'].TIMED_TEXT_REQUESTED, {
45762            index: 0,
45763            sender: e.sender
45764        }); //TODO make index dynamic if referring to MP?
45765    }
45766
45767    function onInitFragmentLoaded(e) {
45768        if (e.fragmentModel !== streamProcessor.getFragmentModel() || !e.chunk.bytes) {
45769            return;
45770        }
45771        initCache.save(e.chunk);
45772        sourceBufferController.append(buffer, e.chunk);
45773    }
45774
45775    function switchInitData(streamId, representationId) {
45776        var chunk = initCache.extract(streamId, representationId);
45777        if (chunk) {
45778            sourceBufferController.append(buffer, chunk);
45779        } else {
45780            eventBus.trigger(_coreEventsEvents2['default'].INIT_REQUESTED, {
45781                sender: instance
45782            });
45783        }
45784    }
45785
45786    instance = {
45787        getBufferControllerType: getBufferControllerType,
45788        initialize: initialize,
45789        createBuffer: createBuffer,
45790        getType: getType,
45791        getStreamProcessor: getStreamProcessor,
45792        setSeekStartTime: setSeekStartTime,
45793        getSeekStartTime: getSeekStartTime,
45794        getBuffer: getBuffer,
45795        setBuffer: setBuffer,
45796        getBufferLevel: getBufferLevel,
45797        setMediaSource: setMediaSource,
45798        getMediaSource: getMediaSource,
45799        getIsBufferingCompleted: getIsBufferingCompleted,
45800        switchInitData: switchInitData,
45801        reset: reset
45802    };
45803
45804    setup();
45805
45806    return instance;
45807}
45808
45809NotFragmentedTextBufferController.__dashjs_factory_name = BUFFER_CONTROLLER_TYPE;
45810exports['default'] = _coreFactoryMaker2['default'].getClassFactory(NotFragmentedTextBufferController);
45811module.exports = exports['default'];
45812
45813},{"100":100,"196":196,"50":50,"51":51,"54":54}],185:[function(_dereq_,module,exports){
45814/**
45815 * The copyright in this software is being made available under the BSD License,
45816 * included below. This software may be subject to other third party and contributor
45817 * rights, including patent rights, and no such rights are granted under this license.
45818 *
45819 * Copyright (c) 2013, Dash Industry Forum.
45820 * All rights reserved.
45821 *
45822 * Redistribution and use in source and binary forms, with or without modification,
45823 * are permitted provided that the following conditions are met:
45824 *  * Redistributions of source code must retain the above copyright notice, this
45825 *  list of conditions and the following disclaimer.
45826 *  * Redistributions in binary form must reproduce the above copyright notice,
45827 *  this list of conditions and the following disclaimer in the documentation and/or
45828 *  other materials provided with the distribution.
45829 *  * Neither the name of Dash Industry Forum nor the names of its
45830 *  contributors may be used to endorse or promote products derived from this software
45831 *  without specific prior written permission.
45832 *
45833 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
45834 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
45835 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
45836 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
45837 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
45837INCLUDING, BUT
45838 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
45839 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
45840 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45841 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
45842 *  POSSIBILITY OF SUCH DAMAGE.
45843 */
45844'use strict';
45845
45846Object.defineProperty(exports, '__esModule', {
45847    value: true
45848});
45849
45850function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
45851
45852var _constantsConstants = _dereq_(100);
45853
45854var _constantsConstants2 = _interopRequireDefault(_constantsConstants);
45855
45856var _coreFactoryMaker = _dereq_(51);
45857
45858var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
45859
45860var _controllersBufferController = _dereq_(105);
45861
45862var _controllersBufferController2 = _interopRequireDefault(_controllersBufferController);
45863
45864var _NotFragmentedTextBufferController = _dereq_(184);
45865
45866var _NotFragmentedTextBufferController2 = _interopRequireDefault(_NotFragmentedTextBufferController);
45867
45868function TextBufferController(config) {
45869
45870    var context = this.context;
45871
45872    var _BufferControllerImpl = undefined;
45873
45874    var instance = undefined;
45875
45876    function setup() {
45877
45878        // according to text type, we create corresponding buffer controller
45879        if (config.type === _constantsConstants2['default'].FRAGMENTED_TEXT) {
45880
45881            // in this case, internal buffer ocntroller is a classical BufferController object
45882            _BufferControllerImpl = (0, _controllersBufferController2['default'])(context).create({
45883                type: config.type,
45884                metricsModel: config.metricsModel,
45885                mediaPlayerModel: config.mediaPlayerModel,
45886                manifestModel: config.manifestModel,
45887                sourceBufferController: config.sourceBufferController,
45888                errHandler: config.errHandler,
45889                streamController: config.streamController,
45890                mediaController: config.mediaController,
45891                adapter: config.adapter,
45892                textController: config.textController,
45893                abrController: config.abrController,
45894                playbackController: config.playbackController,
45895                streamProcessor: config.streamProcessor
45896            });
45897        } else {
45898
45899            // in this case, internal buffer controller is a not fragmented text controller object
45900            _BufferControllerImpl = (0, _NotFragmentedTextBufferController2['default'])(context).create({
45901                type: config.type,
45902                errHandler: config.errHandler,
45903                sourceBufferController: config.sourceBufferController,
45904                streamProcessor: config.streamProcessor
45905            });
45906        }
45907    }
45908
45909    function getBufferControllerType() {
45910        return _BufferControllerImpl.getBufferControllerType();
45911    }
45912
45913    function initialize(source, StreamProcessor) {
45914        return _BufferControllerImpl.initialize(source, StreamProcessor);
45915    }
45916
45917    /**
45918     * @param {MediaInfo }mediaInfo
45919     * @returns {Object} SourceBuffer object
45920     * @memberof BufferController#
45921     */
45922    function createBuffer(mediaInfo) {
45923        return _BufferControllerImpl.createBuffer(mediaInfo);
45924    }
45925
45926    function getType() {
45927        return _BufferControllerImpl.getType();
45928    }
45929
45930    function getBuffer() {
45931        return _BufferControllerImpl.getBuffer();
45932    }
45933
45934    function setBuffer(value) {
45935        _BufferControllerImpl.setBuffer(value);
45936    }
45937
45938    function getMediaSource() {
45939        return _BufferControllerImpl.getMediaSource();
45940    }
45941
45942    function setMediaSource(value) {
45943        _BufferControllerImpl.setMediaSource(value);
45944    }
45945
45946    function getStreamProcessor() {
45947        _BufferControllerImpl.getStreamProcessor();
45948    }
45949
45950    function setSeekStartTime(value) {
45951        _BufferControllerImpl.setSeekStartTime(value);
45952    }
45953
45954    function getBufferLevel() {
45955        return _BufferControllerImpl.getBufferLevel();
45956    }
45957
45958    function reset(errored) {
45959        _BufferControllerImpl.reset(errored);
45960    }
45961
45962    function getIsBufferingCompleted() {
45963        return _BufferControllerImpl.getIsBufferingCompleted();
45964    }
45965
45966    function switchInitData(streamId, representationId) {
45967        _BufferControllerImpl.switchInitData(streamId, representationId);
45968    }
45969
45970    instance = {
45971        getBufferControllerType: getBufferControllerType,
45972        initialize: initialize,
45973        createBuffer: createBuffer,
45974        getType: getType,
45975        getStreamProcessor: getStreamProcessor,
45976        setSeekStartTime: setSeekStartTime,
45977        getBuffer: getBuffer,
45978        setBuffer: setBuffer,
45979        getBufferLevel: getBufferLevel,
45980        setMediaSource: setMediaSource,
45981        getMediaSource: getMediaSource,
45982        getIsBufferingCompleted: getIsBufferingCompleted,
45983        switchInitData: switchInitData,
45984        reset: reset
45985    };
45986
45987    setup();
45988
45989    return instance;
45990}
45991
45992TextBufferController.__dashjs_factory_name = 'TextBufferController';
45993exports['default'] = _coreFactoryMaker2['default'].getClassFactory(TextBufferController);
45994module.exports = exports['default'];
45995
45996},{"100":100,"105":105,"184":184,"51":51}],186:[function(_dereq_,module,exports){
45997/**
45998 * The copyright in this software is being made available under the BSD License,
45999 * included below. This software may be subject to other third party and contributor
46000 * rights, including patent rights, and no such rights are granted under this license.
46001 *
46002 * Copyright (c) 2013, Dash Industry Forum.
46003 * All rights reserved.
46004 *
46005 * Redistribution and use in source and binary forms, with or without modification,
46006 * are permitted provided that the following conditions are met:
46007 *  * Redistributions of source code must retain the above copyright notice, this
46008 *  list of conditions and the following disclaimer.
46009 *  * Redistributions in binary form must reproduce the above copyright notice,
46010 *  this list of conditions and the following disclaimer in the documentation and/or
46011 *  other materials provided with the distribution.
46012 *  * Neither the name of Dash Industry Forum nor the names of its
46013 *  contributors may be used to endorse or promote products derived from this software
46014 *  without specific prior written permission.
46015 *
46016 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
46017 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
46018 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
46019 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
46020 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
46020INCLUDING, BUT
46021 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
46022 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
46023 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46024 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46025 *  POSSIBILITY OF SUCH DAMAGE.
46026 */
46027'use strict';
46028
46029Object.defineProperty(exports, '__esModule', {
46030    value: true
46031});
46032
46033function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
46034
46035var _constantsConstants = _dereq_(100);
46036
46037var _constantsConstants2 = _interopRequireDefault(_constantsConstants);
46038
46039var _coreFactoryMaker = _dereq_(51);
46040
46041var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
46042
46043var _TextSourceBuffer = _dereq_(187);
46044
46045var _TextSourceBuffer2 = _interopRequireDefault(_TextSourceBuffer);
46046
46047var _TextTracks = _dereq_(188);
46048
46049var _TextTracks2 = _interopRequireDefault(_TextTracks);
46050
46051var _utilsVTTParser = _dereq_(203);
46052
46053var _utilsVTTParser2 = _interopRequireDefault(_utilsVTTParser);
46054
46055var _utilsTTMLParser = _dereq_(201);
46056
46057var _utilsTTMLParser2 = _interopRequireDefault(_utilsTTMLParser);
46058
46059function TextController() {
46060
46061    var context = this.context;
46062    var instance = undefined;
46063    var textSourceBuffer = undefined;
46064
46065    var allTracksAreDisabled = undefined,
46066        errHandler = undefined,
46067        dashManifestModel = undefined,
46068        manifestModel = undefined,
46069        mediaController = undefined,
46070        videoModel = undefined,
46071        streamController = undefined,
46072        textTracks = undefined,
46073        vttParser = undefined,
46074        ttmlParser = undefined;
46075
46076    function setup() {
46077
46078        textTracks = (0, _TextTracks2['default'])(context).getInstance();
46079        vttParser = (0, _utilsVTTParser2['default'])(context).getInstance();
46080        ttmlParser = (0, _utilsTTMLParser2['default'])(context).getInstance();
46081        textSourceBuffer = (0, _TextSourceBuffer2['default'])(context).getInstance();
46082
46083        textTracks.initialize();
46084
46085        resetInitialSettings();
46086    }
46087
46088    function setConfig(config) {
46089        if (!config) {
46090            return;
46091        }
46092        if (config.errHandler) {
46093            errHandler = config.errHandler;
46094        }
46095        if (config.dashManifestModel) {
46096            dashManifestModel = config.dashManifestModel;
46097        }
46098        if (config.manifestModel) {
46099            manifestModel = config.manifestModel;
46100        }
46101        if (config.mediaController) {
46102            mediaController = config.mediaController;
46103        }
46104        if (config.videoModel) {
46105            videoModel = config.videoModel;
46106        }
46107        if (config.streamController) {
46108            streamController = config.streamController;
46109        }
46110        if (config.textTracks) {
46111            textTracks = config.textTracks;
46112        }
46113        if (config.vttParser) {
46114            vttParser = config.vttParser;
46115        }
46116        if (config.ttmlParser) {
46117            ttmlParser = config.ttmlParser;
46118        }
46119
46120        // create config for source buffer
46121        textSourceBuffer.setConfig({
46122            errHandler: errHandler,
46123            dashManifestModel: dashManifestModel,
46124            manifestModel: manifestModel,
46125            mediaController: mediaController,
46126            videoModel: videoModel,
46127            streamController: streamController,
46128            textTracks: textTracks,
46129            vttParser: vttParser,
46130            ttmlParser: ttmlParser
46131        });
46132    }
46133
46134    function getTextSourceBuffer() {
46135        return textSourceBuffer;
46136    }
46137
46138    function getAllTracksAreDisabled() {
46139        return allTracksAreDisabled;
46140    }
46141
46142    function addEmbeddedTrack(mediaInfo) {
46143        textSourceBuffer.addEmbeddedTrack(mediaInfo);
46144    }
46145
46146    function setTextTrack(idx) {
46147        //For external time text file,  the only action needed to change a track is marking the track mode to showing.
46148        // Fragmented text tracks need the additional step of calling TextController.setTextTrack();
46149
46150        var config = textSourceBuffer.getConfig();
46151        var fragmentModel = config.fragmentModel;
46152        var fragmentedTracks = config.fragmentedTracks;
46153
46154        var oldTrackIdx = textTracks.getCurrentTrackIdx();
46155        if (oldTrackIdx !== idx) {
46156            textTracks.setModeForTrackIdx(oldTrackIdx, _constantsConstants2['default'].TEXT_HIDDEN);
46157            textTracks.setCurrentTrackIdx(idx);
46158            textTracks.setModeForTrackIdx(idx, _constantsConstants2['default'].TEXT_SHOWING);
46159
46160            var currentTrackInfo = textTracks.getCurrentTrackInfo();
46161
46162            if (currentTrackInfo && currentTrackInfo.isFragmented && !currentTrackInfo.isEmbedded) {
46163                for (var i = 0; i < fragmentedTracks.length; i++) {
46164                    var mediaInfo = fragmentedTracks[i];
46165                    if (currentTrackInfo.lang === mediaInfo.lang && currentTrackInfo.index === mediaInfo.index && (currentTrackInfo.label ? currentTrackInfo.label === mediaInfo.id : true)) {
46166                        var currentFragTrack = mediaController.getCurrentTrackFor(_constantsConstants2['default'].FRAGMENTED_TEXT, streamController.getActiveStreamInfo());
46167                        if (mediaInfo !== currentFragTrack) {
46168                            fragmentModel.abortRequests();
46169                            textTracks.deleteCuesFromTrackIdx(oldTrackIdx);
46170                            mediaController.setTrack(mediaInfo);
46171                            textSourceBuffer.setCurrentFragmentedTrackIdx(i);
46172                        }
46173                    }
46174                }
46175            }
46176        }
46177
46178        allTracksAreDisabled = idx === -1 ? true : false;
46179    }
46180
46181    function getCurrentTrackIdx() {
46182        var textTracks = textSourceBuffer.getConfig().textTracks;
46183        return textTracks.getCurrentTrackIdx();
46184    }
46185
46186    function resetInitialSettings() {
46187        allTracksAreDisabled = false;
46188    }
46189
46190    function reset() {
46191        resetInitialSettings();
46192        textSourceBuffer.resetEmbedded();
46193    }
46194
46195    instance = {
46196        setConfig: setConfig,
46197        getTextSourceBuffer: getTextSourceBuffer,
46198        getAllTracksAreDisabled: getAllTracksAreDisabled,
46199        addEmbeddedTrack: addEmbeddedTrack,
46200        setTextTrack: setTextTrack,
46201        getCurrentTrackIdx: getCurrentTrackIdx,
46202        reset: reset
46203    };
46204    setup();
46205    return instance;
46206}
46207
46208TextController.__dashjs_factory_name = 'TextController';
46209exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(TextController);
46210module.exports = exports['default'];
46211
46212},{"100":100,"187":187,"188":188,"201":201,"203":203,"51":51}],187:[function(_dereq_,module,exports){
46213/**
46214 * The copyright in this software is being made available under the BSD License,
46215 * included below. This software may be subject to other third party and contributor
46216 * rights, including patent rights, and no such rights are granted under this license.
46217 *
46218 * Copyright (c) 2013, Dash Industry Forum.
46219 * All rights reserved.
46220 *
46221 * Redistribution and use in source and binary forms, with or without modification,
46222 * are permitted provided that the following conditions are met:
46223 *  * Redistributions of source code must retain the above copyright notice, this
46224 *  list of conditions and the following disclaimer.
46225 *  * Redistributions in binary form must reproduce the above copyright notice,
46226 *  this list of conditions and the following disclaimer in the documentation and/or
46227 *  other materials provided with the distribution.
46228 *  * Neither the name of Dash Industry Forum nor the names of its
46229 *  contributors may be used to endorse or promote products derived from this software
46230 *  without specific prior written permission.
46231 *
46232 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
46233 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
46234 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
46235 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
46236 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46237 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
46238 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
46239 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46240 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46241 *  POSSIBILITY OF SUCH DAMAGE.
46242 */
46243'use strict';
46244
46245Object.defineProperty(exports, '__esModule', {
46246    value: true
46247});
46248
46249function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
46250
46251var _constantsConstants = _dereq_(100);
46252
46253var _constantsConstants2 = _interopRequireDefault(_constantsConstants);
46254
46255var _voMetricsHTTPRequest = _dereq_(224);
46256
46257var _voTextTrackInfo = _dereq_(218);
46258
46259var _voTextTrackInfo2 = _interopRequireDefault(_voTextTrackInfo);
46260
46261var _dashUtilsFragmentedTextBoxParser = _dereq_(74);
46262
46263var _dashUtilsFragmentedTextBoxParser2 = _interopRequireDefault(_dashUtilsFragmentedTextBoxParser);
46264
46265var _utilsBoxParser = _dereq_(190);
46266
46267var _utilsBoxParser2 = _interopRequireDefault(_utilsBoxParser);
46268
46269var _utilsCustomTimeRanges = _dereq_(192);
46270
46271var _utilsCustomTimeRanges2 = _interopRequireDefault(_utilsCustomTimeRanges);
46272
46273var _coreFactoryMaker = _dereq_(51);
46274
46275var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
46276
46277var _coreDebug = _dereq_(49);
46278
46279var _coreDebug2 = _interopRequireDefault(_coreDebug);
46280
46281var _TextTracks = _dereq_(188);
46282
46283var _TextTracks2 = _interopRequireDefault(_TextTracks);
46284
46285var _EmbeddedTextHtmlRender = _dereq_(183);
46286
46287var _EmbeddedTextHtmlRender2 = _interopRequireDefault(_EmbeddedTextHtmlRender);
46288
46289var _codemIsoboxer = _dereq_(11);
46290
46291var _codemIsoboxer2 = _interopRequireDefault(_codemIsoboxer);
46292
46293var _externalsCea608Parser = _dereq_(2);
46294
46295var _externalsCea608Parser2 = _interopRequireDefault(_externalsCea608Parser);
46296
46297var _coreEventBus = _dereq_(50);
46298
46299var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
46300
46301var _coreEventsEvents = _dereq_(54);
46302
46303var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
46304
46305function TextSourceBuffer() {
46306
46307    var context = this.context;
46308    var log = (0, _coreDebug2['default'])(context).getInstance().log;
46309    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
46310    var embeddedInitialized = false;
46311
46312    var instance = undefined,
46313        boxParser = undefined,
46314        errHandler = undefined,
46315        dashManifestModel = undefined,
46316        manifestModel = undefined,
46317        mediaController = undefined,
46318        parser = undefined,
46319        vttParser = undefined,
46320        ttmlParser = undefined,
46321        fragmentedTextBoxParser = undefined,
46322        mediaInfos = undefined,
46323        textTracks = undefined,
46324        isFragmented = undefined,
46325        fragmentModel = undefined,
46326        initializationSegmentReceived = undefined,
46327        timescale = undefined,
46328        fragmentedTracks = undefined,
46329        videoModel = undefined,
46330        streamController = undefined,
46331        firstSubtitleStart = undefined,
46332        currFragmentedTrackIdx = undefined,
46333        embeddedTracks = undefined,
46334        embeddedInitializationSegmentReceived = undefined,
46335        embeddedTimescale = undefined,
46336        embeddedLastSequenceNumber = undefined,
46337        embeddedSequenceNumbers = undefined,
46338        embeddedCea608FieldParsers = undefined,
46339        embeddedTextHtmlRender = undefined;
46340
46341    function initialize(type, streamProcessor) {
46342        parser = null;
46343        fragmentModel = null;
46344        initializationSegmentReceived = false;
46345        timescale = NaN;
46346        fragmentedTracks = [];
46347        firstSubtitleStart = null;
46348
46349        if (!embeddedInitialized) {
46350            initEmbedded();
46351        }
46352
46353        mediaInfos = streamProcessor.getMediaInfoArr();
46354        textTracks.setConfig({
46355            videoModel: videoModel
46356        });
46357        textTracks.initialize();
46358        isFragmented = !dashManifestModel.getIsTextTrack(type);
46359        boxParser = (0, _utilsBoxParser2['default'])(context).getInstance();
46360        fragmentedTextBoxParser = (0, _dashUtilsFragmentedTextBoxParser2['default'])(context).getInstance();
46361        fragmentedTextBoxParser.setConfig({
46362            boxParser: boxParser
46363        });
46364
46365        if (isFragmented) {
46366            fragmentModel = streamProcessor.getFragmentModel();
46367            this.buffered = (0, _utilsCustomTimeRanges2['default'])(context).create();
46368            fragmentedTracks = mediaController.getTracksFor(_constantsConstants2['default'].FRAGMENTED_TEXT, streamController.getActiveStreamInfo());
46369            var currFragTrack = mediaController.getCurrentTrackFor(_constantsConstants2['default'].FRAGMENTED_TEXT, streamController.getActiveStreamInfo());
46370            for (var i = 0; i < fragmentedTracks.length; i++) {
46371                if (fragmentedTracks[i] === currFragTrack) {
46372                    currFragmentedTrackIdx = i;
46373                    break;
46374                }
46375            }
46376        }
46377    }
46378
46379    function abort() {
46380        textTracks.deleteAllTextTracks();
46381        parser = null;
46382        fragmentedTextBoxParser = null;
46383        mediaInfos = null;
46384        textTracks = null;
46385        isFragmented = false;
46386        fragmentModel = null;
46387        initializationSegmentReceived = false;
46388        timescale = NaN;
46389        fragmentedTracks = [];
46390        videoModel = null;
46391        streamController = null;
46392        embeddedInitialized = false;
46393        embeddedTracks = null;
46394    }
46395
46396    function onVideoChunkReceived(e) {
46397        var chunk = e.chunk;
46398
46399        if (chunk.mediaInfo.embeddedCaptions) {
46400            append(chunk.bytes, chunk);
46401        }
46402    }
46403
46404    function initEmbedded() {
46405        embeddedTracks = [];
46406        mediaInfos = [];
46407        textTracks = (0, _TextTracks2['default'])(context).getInstance();
46408        textTracks.setConfig({
46409            videoModel: videoModel
46410        });
46411        textTracks.initialize();
46412        boxParser = (0, _utilsBoxParser2['default'])(context).getInstance();
46413        fragmentedTextBoxParser = (0, _dashUtilsFragmentedTextBoxParser2['default'])(context).getInstance();
46414        fragmentedTextBoxParser.setConfig({
46415            boxParser: boxParser
46416        });
46417        isFragmented = false;
46418        currFragmentedTrackIdx = null;
46419        embeddedInitializationSegmentReceived = false;
46420        embeddedTimescale = 0;
46421        embeddedCea608FieldParsers = [];
46422        embeddedSequenceNumbers = [];
46423        embeddedLastSequenceNumber = null;
46424        embeddedInitialized = true;
46425        embeddedTextHtmlRender = (0, _EmbeddedTextHtmlRender2['default'])(context).getInstance();
46426
46427        eventBus.on(_coreEventsEvents2['default'].VIDEO_CHUNK_RECEIVED, onVideoChunkReceived, this);
46428    }
46429
46430    function resetEmbedded() {
46431        eventBus.off(_coreEventsEvents2['default'].VIDEO_CHUNK_RECEIVED, onVideoChunkReceived, this);
46432        if (textTracks) {
46433            textTracks.deleteAllTextTracks();
46434        }
46435        embeddedInitialized = false;
46436        embeddedTracks = [];
46437        embeddedCea608FieldParsers = [null, null];
46438        embeddedSequenceNumbers = [];
46439        embeddedLastSequenceNumber = null;
46440    }
46441
46442    function addEmbeddedTrack(mediaInfo) {
46443        if (!embeddedInitialized) {
46444            initEmbedded();
46445        }
46446        if (mediaInfo.id === _constantsConstants2['default'].CC1 || mediaInfo.id === _constantsConstants2['default'].CC3) {
46447            embeddedTracks.push(mediaInfo);
46448        } else {
46449            log('Warning: Embedded track ' + mediaInfo.id + ' not supported!');
46450        }
46451    }
46452
46453    function setConfig(config) {
46454        if (!config) {
46455            return;
46456        }
46457        if (config.errHandler) {
46458            errHandler = config.errHandler;
46459        }
46460        if (config.dashManifestModel) {
46461            dashManifestModel = config.dashManifestModel;
46462        }
46463        if (config.manifestModel) {
46464            manifestModel = config.manifestModel;
46465        }
46466        if (config.mediaController) {
46467            mediaController = config.mediaController;
46468        }
46469        if (config.videoModel) {
46470            videoModel = config.videoModel;
46471        }
46472        if (config.streamController) {
46473            streamController = config.streamController;
46474        }
46475        if (config.textTracks) {
46476            textTracks = config.textTracks;
46477        }
46478        if (config.vttParser) {
46479            vttParser = config.vttParser;
46480        }
46481        if (config.ttmlParser) {
46482            ttmlParser = config.ttmlParser;
46483        }
46484    }
46485
46486    function getConfig() {
46487        var config = {
46488            errHandler: errHandler,
46489            dashManifestModel: dashManifestModel,
46490            mediaController: mediaController,
46491            videoModel: videoModel,
46492            fragmentModel: fragmentModel,
46493            streamController: streamController,
46494            textTracks: textTracks,
46495            isFragmented: isFragmented,
46496            embeddedTracks: embeddedTracks,
46497            fragmentedTracks: fragmentedTracks
46498        };
46499
46500        return config;
46501    }
46502
46503    function setCurrentFragmentedTrackIdx(idx) {
46504        currFragmentedTrackIdx = idx;
46505    }
46506
46507    function append(bytes, chunk) {
46508        var result = undefined,
46509            sampleList = undefined,
46510            i = undefined,
46511            j = undefined,
46512            k = undefined,
46513            samplesInfo = undefined,
46514            ccContent = undefined;
46515        var mediaInfo = chunk.mediaInfo;
46516        var mediaType = mediaInfo.type;
46517        var mimeType = mediaInfo.mimeType;
46518        var codecType = mediaInfo.codec || mimeType;
46519        if (!codecType) {
46520            log('No text type defined');
46521            return;
46522        }
46523
46524        function createTextTrackFromMediaInfo(captionData, mediaInfo) {
46525            var textTrackInfo = new _voTextTrackInfo2['default']();
46526            var trackKindMap = { subtitle: 'subtitles', caption: 'captions' }; //Dash Spec has no "s" on end of KIND but HTML needs plural.
46527            var getKind = function getKind() {
46528                var kind = mediaInfo.roles.length > 0 ? trackKindMap[mediaInfo.roles[0]] : trackKindMap.caption;
46529                kind = kind === trackKindMap.caption || kind === trackKindMap.subtitle ? kind : trackKindMap.caption;
46530                return kind;
46531            };
46532
46533            var checkTTML = function checkTTML() {
46534                var ttml = false;
46535                if (mediaInfo.codec && mediaInfo.codec.search(_constantsConstants2['default'].STPP) >= 0) {
46536                    ttml = true;
46537                }
46538                if (mediaInfo.mimeType && mediaInfo.mimeType.search(_constantsConstants2['default'].TTML) >= 0) {
46539                    ttml = true;
46540                }
46541                return ttml;
46542            };
46543
46544            textTrackInfo.captionData = captionData;
46545            textTrackInfo.lang = mediaInfo.lang;
46546            textTrackInfo.label = mediaInfo.id; // AdaptationSet id (an unsigned int)
46547            textTrackInfo.index = mediaInfo.index; // AdaptationSet index in manifest
46548            textTrackInfo.isTTML = checkTTML();
46549            textTrackInfo.defaultTrack = getIsDefault(mediaInfo);
46550            textTrackInfo.isFragmented = isFragmented;
46551            textTrackInfo.isEmbedded = mediaInfo.isEmbedded ? true : false;
46552            textTrackInfo.kind = getKind();
46553            textTrackInfo.roles = mediaInfo.roles;
46554            var totalNrTracks = (mediaInfos ? mediaInfos.length : 0) + embeddedTracks.length;
46555            textTracks.addTextTrack(textTrackInfo, totalNrTracks);
46556        }
46557
46558        if (mediaType === _constantsConstants2['default'].FRAGMENTED_TEXT) {
46559            if (!initializationSegmentReceived) {
46560                initializationSegmentReceived = true;
46561                for (i = 0; i < mediaInfos.length; i++) {
46562                    createTextTrackFromMediaInfo(null, mediaInfos[i]);
46563                }
46564                timescale = fragmentedTextBoxParser.getMediaTimescaleFromMoov(bytes);
46565            } else {
46566                samplesInfo = fragmentedTextBoxParser.getSamplesInfo(bytes);
46567                sampleList = samplesInfo.sampleList;
46568                if (!firstSubtitleStart && sampleList.length > 0) {
46569                    firstSubtitleStart = sampleList[0].cts - chunk.start * timescale;
46570                }
46571                if (codecType.search(_constantsConstants2['default'].STPP) >= 0) {
46572                    parser = parser !== null ? parser : getParser(codecType);
46573                    for (i = 0; i < sampleList.length; i++) {
46574                        var sample = sampleList[i];
46575                        var sampleStart = sample.cts;
46576                        var sampleRelStart = sampleStart - firstSubtitleStart;
46577                        this.buffered.add(sampleRelStart / timescale, (sampleRelStart + sample.duration) / timescale);
46578                        var dataView = new DataView(bytes, sample.offset, sample.subSizes[0]);
46579                        ccContent = _codemIsoboxer2['default'].Utils.dataViewToString(dataView, _constantsConstants2['default'].UTF8);
46580                        var images = [];
46581                        var subOffset = sample.offset + sample.subSizes[0];
46582                        for (j = 1; j < sample.subSizes.length; j++) {
46583                            var inData = new Uint8Array(bytes, subOffset, sample.subSizes[j]);
46584                            var raw = String.fromCharCode.apply(null, inData);
46585                            images.push(raw);
46586                            subOffset += sample.subSizes[j];
46587                        }
46588                        try {
46589                            // Only used for Miscrosoft Smooth Streaming support - caption time is relative to sample time. In this case, we apply an offset.
46590                            var manifest = manifestModel.getValue();
46591                            var offsetTime = manifest.ttmlTimeIsRelative ? sampleStart / timescale : 0;
46592                            result = parser.parse(ccContent, offsetTime, sampleStart / timescale, (sampleStart + sample.duration) / timescale, images);
46593                            textTracks.addCaptions(currFragmentedTrackIdx, firstSubtitleStart / timescale, result);
46594                        } catch (e) {
46595                            log('TTML parser error: ' + e.message);
46596                        }
46597                    }
46598                } else {
46599                    // WebVTT case
46600                    var captionArray = [];
46601                    for (i = 0; i < sampleList.length; i++) {
46602                        var sample = sampleList[i];
46603                        sample.cts -= firstSubtitleStart;
46604                        this.buffered.add(sample.cts / timescale, (sample.cts + sample.duration) / timescale);
46605                        var sampleData = bytes.slice(sample.offset, sample.offset + sample.size);
46606                        // There are boxes inside the sampleData, so we need a ISOBoxer to get at it.
46607                        var sampleBoxes = _codemIsoboxer2['default'].parseBuffer(sampleData);
46608
46609                        for (j = 0; j < sampleBoxes.boxes.length; j++) {
46610                            var box1 = sampleBoxes.boxes[j];
46611                            log('VTT box1: ' + box1.type);
46612                            if (box1.type === 'vtte') {
46613                                continue; //Empty box
46614                            }
46615                            if (box1.type === 'vttc') {
46616                                log('VTT vttc boxes.length = ' + box1.boxes.length);
46617                                for (k = 0; k < box1.boxes.length; k++) {
46618                                    var box2 = box1.boxes[k];
46619                                    log('VTT box2: ' + box2.type);
46620                                    if (box2.type === 'payl') {
46621                                        var cue_text = box2.cue_text;
46622                                        log('VTT cue_text = ' + cue_text);
46623                                        var start_time = sample.cts / timescale;
46624                                        var end_time = (sample.cts + sample.duration) / timescale;
46625                                        captionArray.push({
46626                                            start: start_time,
46627                                            end: end_time,
46628                                            data: cue_text,
46629                                            styles: {}
46630                                        });
46631                                        log('VTT ' + start_time + '-' + end_time + ' : ' + cue_text);
46632                                    }
46633                                }
46634                            }
46635                        }
46636                    }
46637                    if (captionArray.length > 0) {
46638                        textTracks.addCaptions(currFragmentedTrackIdx, 0, captionArray);
46639                    }
46640                }
46641            }
46642        } else if (mediaType === _constantsConstants2['default'].TEXT) {
46643            var dataView = new DataView(bytes, 0, bytes.byteLength);
46644            ccContent = _codemIsoboxer2['default'].Utils.dataViewToString(dataView, _constantsConstants2['default'].UTF8);
46645
46646            try {
46647                result = getParser(codecType).parse(ccContent, 0);
46648                createTextTrackFromMediaInfo(result, mediaInfo);
46649            } catch (e) {
46650                errHandler.timedTextError(e, 'parse', ccContent);
46651            }
46652        } else if (mediaType === _constantsConstants2['default'].VIDEO) {
46653            //embedded text
46654            if (chunk.segmentType === _voMetricsHTTPRequest.HTTPRequest.INIT_SEGMENT_TYPE) {
46655                if (embeddedTimescale === 0) {
46656                    embeddedTimescale = fragmentedTextBoxParser.getMediaTimescaleFromMoov(bytes);
46657                    for (i = 0; i < embeddedTracks.length; i++) {
46658                        createTextTrackFromMediaInfo(null, embeddedTracks[i]);
46659                    }
46660                }
46661            } else {
46662                // MediaSegment
46663                if (embeddedTimescale === 0) {
46664                    log('CEA-608: No timescale for embeddedTextTrack yet');
46665                    return;
46666                }
46667                var makeCueAdderForIndex = function makeCueAdderForIndex(self, trackIndex) {
46668                    function newCue(startTime, endTime, captionScreen) {
46669                        var captionsArray = null;
46670                        if (videoModel.getTTMLRenderingDiv()) {
46671                            captionsArray = embeddedTextHtmlRender.createHTMLCaptionsFromScreen(videoModel.getElement(), startTime, endTime, captionScreen);
46672                        } else {
46673                            var text = captionScreen.getDisplayText();
46674                            //log("CEA text: " + startTime + "-" + endTime + "  '" + text + "'");
46675                            captionsArray = [{
46676                                start: startTime,
46677                                end: endTime,
46678                                data: text,
46679                                styles: {}
46680                            }];
46681                        }
46682                        if (captionsArray) {
46683                            textTracks.addCaptions(trackIndex, 0, captionsArray);
46684                        }
46685                    }
46686                    return newCue;
46687                };
46688
46689                samplesInfo = fragmentedTextBoxParser.getSamplesInfo(bytes);
46690
46691                var sequenceNumber = samplesInfo.lastSequenceNumber;
46692
46693                if (!embeddedCea608FieldParsers[0] && !embeddedCea608FieldParsers[1]) {
46694                    // Time to setup the CEA-608 parsing
46695                    var field = undefined,
46696                        handler = undefined,
46697                        trackIdx = undefined;
46698                    for (i = 0; i < embeddedTracks.length; i++) {
46699                        if (embeddedTracks[i].id === _constantsConstants2['default'].CC1) {
46700                            field = 0;
46701                            trackIdx = textTracks.getTrackIdxForId(_constantsConstants2['default'].CC1);
46702                        } else if (embeddedTracks[i].id === _constantsConstants2['default'].CC3) {
46703                            field = 1;
46704                            trackIdx = textTracks.getTrackIdxForId(_constantsConstants2['default'].CC3);
46705                        }
46706                        if (trackIdx === -1) {
46707                            log('CEA-608: data before track is ready.');
46708                            return;
46709                        }
46710                        handler = makeCueAdderForIndex(this, trackIdx);
46711                        embeddedCea608FieldParsers[i] = new _externalsCea608Parser2['default'].Cea608Parser(i, {
46712                            'newCue': handler
46713                        }, null);
46714                    }
46715                }
46716
46717                if (embeddedTimescale && embeddedSequenceNumbers.indexOf(sequenceNumber) == -1) {
46718                    if (embeddedLastSequenceNumber !== null && sequenceNumber !== embeddedLastSequenceNumber + samplesInfo.numSequences) {
46719                        for (i = 0; i < embeddedCea608FieldParsers.length; i++) {
46720                            if (embeddedCea608FieldParsers[i]) {
46721                                embeddedCea608FieldParsers[i].reset();
46722                            }
46723                        }
46724                    }
46725
46726                    var allCcData = extractCea608Data(bytes, samplesInfo.sampleList);
46727
46728                    for (var fieldNr = 0; fieldNr < embeddedCea608FieldParsers.length; fieldNr++) {
46729                        var ccData = allCcData.fields[fieldNr];
46730                        var fieldParser = embeddedCea608FieldParsers[fieldNr];
46731                        if (fieldParser) {
46732                            /*if (ccData.length > 0 ) {
46733                                log("CEA-608 adding Data to field " + fieldNr + " " + ccData.length + "bytes");
46734                            }*/
46735                            for (i = 0; i < ccData.length; i++) {
46736                                fieldParser.addData(ccData[i][0] / embeddedTimescale, ccData[i][1]);
46737                            }
46738                        }
46739                    }
46740                    embeddedLastSequenceNumber = sequenceNumber;
46741                    embeddedSequenceNumbers.push(sequenceNumber);
46742                }
46743            }
46744        }
46745    }
46746    /**
46747     * Extract CEA-608 data from a buffer of data.
46748     * @param {ArrayBuffer} data
46749     * @param {Array} samples cue information
46750     * @returns {Object|null} ccData corresponding to one segment.
46751     */
46752    function extractCea608Data(data, samples) {
46753
46754        if (samples.length === 0) {
46755            return null;
46756        }
46757
46758        var allCcData = {
46759            splits: [],
46760            fields: [[], []]
46761        };
46762        var raw = new DataView(data);
46763        for (var i = 0; i < samples.length; i++) {
46764            var sample = samples[i];
46765            var cea608Ranges = _externalsCea608Parser2['default'].findCea608Nalus(raw, sample.offset, sample.
46765size);
46766            var lastSampleTime = null;
46767            var idx = 0;
46768            for (var j = 0; j < cea608Ranges.length; j++) {
46769                var ccData = _externalsCea608Parser2['default'].extractCea608DataFromRange(raw, cea608Ranges[j]);
46770                for (var k = 0; k < 2; k++) {
46771                    if (ccData[k].length > 0) {
46772                        if (sample.cts !== lastSampleTime) {
46773                            idx = 0;
46774                        } else {
46775                            idx += 1;
46776                        }
46777                        allCcData.fields[k].push([sample.cts, ccData[k], idx]);
46778                        lastSampleTime = sample.cts;
46779                    }
46780                }
46781            }
46782        }
46783
46784        // Sort by sampleTime ascending order
46785        // If two packets have the same sampleTime, use them in the order
46786        // they were received
46787        allCcData.fields.forEach(function sortField(field) {
46788            field.sort(function (a, b) {
46789                if (a[0] === b[0]) {
46790                    return a[2] - b[2];
46791                }
46792                return a[0] - b[0];
46793            });
46794        });
46795
46796        return allCcData;
46797    }
46798
46799    function getIsDefault(mediaInfo) {
46800        //TODO How to tag default. currently same order as listed in manifest.
46801        // Is there a way to mark a text adaptation set as the default one? DASHIF meeting talk about using role which is being used for track KIND
46802        // Eg subtitles etc. You can have multiple role tags per adaptation Not defined in the spec yet.
46803        var isDefault = false;
46804        if (embeddedTracks.length > 1 && mediaInfo.isEmbedded) {
46805            isDefault = mediaInfo.id && mediaInfo.id === _constantsConstants2['default'].CC1; // CC1 if both CC1 and CC3 exist
46806        } else if (embeddedTracks.length === 1) {
46807                if (mediaInfo.id && mediaInfo.id.substring(0, 2) === 'CC') {
46808                    // Either CC1 or CC3
46809                    isDefault = true;
46810                }
46811            } else if (embeddedTracks.length === 0) {
46812                isDefault = mediaInfo.index === mediaInfos[0].index;
46813            }
46814        return isDefault;
46815    }
46816
46817    function getParser(codecType) {
46818        var parser = undefined;
46819        if (codecType.search(_constantsConstants2['default'].VTT) >= 0) {
46820            parser = vttParser;
46821        } else if (codecType.search(_constantsConstants2['default'].TTML) >= 0 || codecType.search(_constantsConstants2['default'].STPP) >= 0) {
46822            parser = ttmlParser;
46823        }
46824        return parser;
46825    }
46826
46827    instance = {
46828        initialize: initialize,
46829        append: append,
46830        abort: abort,
46831        addEmbeddedTrack: addEmbeddedTrack,
46832        resetEmbedded: resetEmbedded,
46833        setConfig: setConfig,
46834        getConfig: getConfig,
46835        setCurrentFragmentedTrackIdx: setCurrentFragmentedTrackIdx
46836    };
46837
46838    return instance;
46839}
46840
46841TextSourceBuffer.__dashjs_factory_name = 'TextSourceBuffer';
46842exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(TextSourceBuffer);
46843module.exports = exports['default'];
46844
46845},{"100":100,"11":11,"183":183,"188":188,"190":190,"192":192,"2":2,"218":218,"224":224,"49":49,"50":50,"51":51,"54":54,"74":74}],188:[function(_dereq_,module,exports){
46846/**
46847 * The copyright in this software is being made available under the BSD License,
46848 * included below. This software may be subject to other third party and contributor
46849 * rights, including patent rights, and no such rights are granted under this license.
46850 *
46851 * Copyright (c) 2013, Dash Industry Forum.
46852 * All rights reserved.
46853 *
46854 * Redistribution and use in source and binary forms, with or without modification,
46855 * are permitted provided that the following conditions are met:
46856 *  * Redistributions of source code must retain the above copyright notice, this
46857 *  list of conditions and the following disclaimer.
46858 *  * Redistributions in binary form must reproduce the above copyright notice,
46859 *  this list of conditions and the following disclaimer in the documentation and/or
46860 *  other materials provided with the distribution.
46861 *  * Neither the name of Dash Industry Forum nor the names of its
46862 *  contributors may be used to endorse or promote products derived from this software
46863 *  without specific prior written permission.
46864 *
46865 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
46866 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
46867 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
46868 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
46869 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
46869INCLUDING, BUT
46870 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
46871 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
46872 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46873 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46874 *  POSSIBILITY OF SUCH DAMAGE.
46875 */
46876'use strict';
46877
46878Object.defineProperty(exports, '__esModule', {
46879    value: true
46880});
46881
46882function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
46883
46884var _constantsConstants = _dereq_(100);
46885
46886var _constantsConstants2 = _interopRequireDefault(_constantsConstants);
46887
46888var _coreEventBus = _dereq_(50);
46889
46890var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
46891
46892var _coreEventsEvents = _dereq_(54);
46893
46894var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
46895
46896var _coreFactoryMaker = _dereq_(51);
46897
46898var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
46899
46900var _coreDebug = _dereq_(49);
46901
46902var _coreDebug2 = _interopRequireDefault(_coreDebug);
46903
46904var _imsc = _dereq_(21);
46905
46906function TextTracks() {
46907
46908    var context = this.context;
46909    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
46910    var log = (0, _coreDebug2['default'])(context).getInstance().log;
46911
46912    var instance = undefined,
46913        Cue = undefined,
46914        videoModel = undefined,
46915        textTrackQueue = undefined,
46916        trackElementArr = undefined,
46917        currentTrackIdx = undefined,
46918        actualVideoLeft = undefined,
46919        actualVideoTop = undefined,
46920        actualVideoWidth = undefined,
46921        actualVideoHeight = undefined,
46922        captionContainer = undefined,
46923        videoSizeCheckInterval = undefined,
46924        isChrome = undefined,
46925        fullscreenAttribute = undefined,
46926        displayCCOnTop = undefined,
46927        topZIndex = undefined;
46928
46929    function initialize() {
46930        if (typeof window === 'undefined' || typeof navigator === 'undefined') {
46931            return;
46932        }
46933
46934        Cue = window.VTTCue || window.TextTrackCue;
46935        textTrackQueue = [];
46936        trackElementArr = [];
46937        currentTrackIdx = -1;
46938        actualVideoLeft = 0;
46939        actualVideoTop = 0;
46940        actualVideoWidth = 0;
46941        actualVideoHeight = 0;
46942        captionContainer = null;
46943        videoSizeCheckInterval = null;
46944        displayCCOnTop = false;
46945        topZIndex = 2147483647;
46946
46947        //TODO Check if IE has resolved issues: Then revert to not using the addTextTrack API for all browsers.
46948        // https://connect.microsoft.com/IE/feedbackdetail/view/1660701/text-tracks-do-not-fire-change-addtrack-or-removetrack-events
46949        // https://connect.microsoft.com/IE/feedback/details/1573380/htmltrackelement-track-addcue-throws-invalidstateerror-when-adding-new-cue
46950        // Same issue with Firefox.
46951        //isIE11orEdge = !!navigator.userAgent.match(/Trident.*rv[ :]*11\./) || navigator.userAgent.match(/Edge/);
46952        //isFirefox = !!navigator.userAgent.match(/Firefox/);
46953        isChrome = !!navigator.userAgent.match(/Chrome/) && !navigator.userAgent.match(/Edge/);
46954        if (document.fullscreenElement !== undefined) {
46955            fullscreenAttribute = 'fullscreenElement'; // Standard and Edge
46956        } else if (document.webkitIsFullScreen !== undefined) {
46957                fullscreenAttribute = 'webkitIsFullScreen'; // Chrome and Safari (and Edge)
46958            } else if (document.msFullscreenElement) {
46959                    // IE11
46960                    fullscreenAttribute = 'msFullscreenElement';
46961                } else if (document.mozFullScreen) {
46962                    // Firefox
46963                    fullscreenAttribute = 'mozFullScreen';
46964                }
46965    }
46966
46967    function createTrackForUserAgent(i) {
46968        var kind = textTrackQueue[i].kind;
46969        var label = textTrackQueue[i].label !== undefined ? textTrackQueue[i].label : textTrackQueue[i].lang;
46970        var lang = textTrackQueue[i].lang;
46971        var track = isChrome ? document.createElement('track') : videoModel.addTextTrack(kind, label, lang);
46972
46973        if (isChrome) {
46974            track.kind = kind;
46975            track.label = label;
46976            track.srclang = lang;
46977        }
46978
46979        return track;
46980    }
46981
46982    function displayCConTop(value) {
46983        displayCCOnTop = value;
46984        if (!captionContainer || document[fullscreenAttribute]) {
46985            return;
46986        }
46987        captionContainer.style.zIndex = value ? topZIndex : null;
46988    }
46989
46990    function addTextTrack(textTrackInfoVO, totalTextTracks) {
46991        if (textTrackQueue.length === totalTextTracks) {
46992            log('Trying to add too many tracks.');
46993            return;
46994        }
46995
46996        textTrackQueue.push(textTrackInfoVO);
46997
46998        if (textTrackQueue.length === totalTextTracks) {
46999            textTrackQueue.sort(function (a, b) {
47000                //Sort in same order as in manifest
47001                return a.index - b.index;
47002            });
47003            captionContainer = videoModel.getTTMLRenderingDiv();
47004            var defaultIndex = -1;
47005            for (var i = 0; i < textTrackQueue.length; i++) {
47006                var track = createTrackForUserAgent.call(this, i);
47007                trackElementArr.push(track); //used to remove tracks from video element when added manually
47008
47009                if (textTrackQueue[i].defaultTrack) {
47010                    // track.default is an object property identifier that is a reserved word
47011                    // The following jshint directive is used to suppressed the warning "Expected an identifier and instead saw 'default' (a reserved word)"
47012                    /*jshint -W024 */
47013                    track['default'] = true;
47014                    defaultIndex = i;
47015                }
47016                if (isChrome) {
47017                    videoModel.appendChild(track);
47018                }
47019
47020                var textTrack = getTrackByIdx(i);
47021                if (textTrack) {
47022                    //each time a track is created, its mode should be showing by default
47023                    //sometime, it's not on Chrome
47024                    textTrack.mode = _constantsConstants2['default'].TEXT_SHOWING;
47025                    if (captionContainer && (textTrackQueue[i].isTTML || textTrackQueue[i].isEmbedded)) {
47026                        textTrack.renderingType = 'html';
47027                    } else {
47028                        textTrack.renderingType = 'default';
47029                    }
47030                }
47031                this.addCaptions(i, 0, textTrackQueue[i].captionData);
47032                eventBus.trigger(_coreEventsEvents2['default'].TEXT_TRACK_ADDED);
47033            }
47034
47035            //set current track index in textTrackQueue array
47036            setCurrentTrackIdx.call(this, defaultIndex);
47037
47038            if (defaultIndex >= 0) {
47039                for (var idx = 0; idx < textTrackQueue.length; idx++) {
47040                    var videoTextTrack = getTrackByIdx(idx);
47041                    if (videoTextTrack) {
47042                        videoTextTrack.mode = idx === defaultIndex ? _constantsConstants2['default'].TEXT_SHOWING : _constantsConstants2['default'].TEXT_HIDDEN;
47043                    }
47044                }
47045            }
47046
47047            eventBus.trigger(_coreEventsEvents2['default'].TEXT_TRACKS_ADDED, {
47048                index: currentTrackIdx,
47049                tracks: textTrackQueue
47050            }); //send default idx.
47051        }
47052    }
47053
47054    function getVideoVisibleVideoSize(viewWidth, viewHeight, videoWidth, videoHeight, aspectRatio, use80Percent) {
47055        var viewAspectRatio = viewWidth / viewHeight;
47056        var videoAspectRatio = videoWidth / videoHeight;
47057
47058        var videoPictureWidth = 0;
47059        var videoPictureHeight = 0;
47060
47061        if (viewAspectRatio > videoAspectRatio) {
47062            videoPictureHeight = viewHeight;
47063            videoPictureWidth = videoPictureHeight / videoHeight * videoWidth;
47064        } else {
47065            videoPictureWidth = viewWidth;
47066            videoPictureHeight = videoPictureWidth / videoWidth * videoHeight;
47067        }
47068
47069        var videoPictureXAspect = 0;
47070        var videoPictureYAspect = 0;
47071        var videoPictureWidthAspect = 0;
47072        var videoPictureHeightAspect = 0;
47073        var videoPictureAspect = videoPictureWidth / videoPictureHeight;
47074
47075        if (videoPictureAspect > aspectRatio) {
47076            videoPictureHeightAspect = videoPictureHeight;
47077            videoPictureWidthAspect = videoPictureHeight / (1 / aspectRatio);
47078            videoPictureXAspect = (viewWidth - videoPictureWidthAspect) / 2;
47079            videoPictureYAspect = 0;
47080        } else {
47081            videoPictureWidthAspect = videoPictureWidth;
47082            videoPictureHeightAspect = videoPictureWidth / aspectRatio;
47083            videoPictureXAspect = 0;
47084            videoPictureYAspect = (viewHeight - videoPictureHeightAspect) / 2;
47085        }
47086
47087        if (use80Percent) {
47088            return {
47089                x: videoPictureXAspect + videoPictureWidthAspect * 0.1,
47090                y: videoPictureYAspect + videoPictureHeightAspect * 0.1,
47091                w: videoPictureWidthAspect * 0.8,
47092                h: videoPictureHeightAspect * 0.8
47093            }; /* Maximal picture size in videos aspect ratio */
47094        } else {
47095                return {
47096                    x: videoPictureXAspect,
47097                    y: videoPictureYAspect,
47098                    w: videoPictureWidthAspect,
47099                    h: videoPictureHeightAspect
47100                }; /* Maximal picture size in videos aspect ratio */
47101            }
47102    }
47103
47104    function checkVideoSize(track) {
47105        var clientWidth = videoModel.getClientWidth();
47106        var clientHeight = videoModel.getClientHeight();
47107        var videoWidth = videoModel.getVideoWidth();
47108        var videoHeight = videoModel.getVideoHeight();
47109        var aspectRatio = clientWidth / clientHeight;
47110        var use80Percent = false;
47111        if (track.isFromCEA608) {
47112            // If this is CEA608 then use predefined aspect ratio
47113            aspectRatio = 3.5 / 3.0;
47114            use80Percent = true;
47115        }
47116
47117        var realVideoSize = getVideoVisibleVideoSize.call(this, clientWidth, clientHeight, videoWidth, videoHeight, aspectRatio, use80Percent);
47118
47119        var newVideoWidth = realVideoSize.w;
47120        var newVideoHeight = realVideoSize.h;
47121
47122        if (newVideoWidth != actualVideoWidth || newVideoHeight != actualVideoHeight) {
47123            actualVideoLeft = realVideoSize.x;
47124            actualVideoTop = realVideoSize.y;
47125            actualVideoWidth = newVideoWidth;
47126            actualVideoHeight = newVideoHeight;
47127            captionContainer.style.left = actualVideoLeft + 'px';
47128            captionContainer.style.top = actualVideoTop + 'px';
47129            captionContainer.style.width = actualVideoWidth + 'px';
47130            captionContainer.style.height = actualVideoHeight + 'px';
47131
47132            // Video view has changed size, so resize any active cues
47133            for (var i = 0; track.activeCues && i < track.activeCues.length; ++i) {
47134                var cue = track.activeCues[i];
47135                cue.scaleCue(cue);
47136            }
47137
47138            if (fullscreenAttribute && document[fullscreenAttribute] || displayCCOnTop) {
47139                captionContainer.style.zIndex = topZIndex;
47140            } else {
47141                captionContainer.style.zIndex = null;
47142            }
47143        }
47144    }
47145
47146    function scaleCue(activeCue) {
47147        var videoWidth = actualVideoWidth;
47148        var videoHeight = actualVideoHeight;
47149        var key = undefined,
47150            replaceValue = undefined,
47151            valueFontSize = undefined,
47152            valueLineHeight = undefined,
47153            elements = undefined;
47154
47155        if (activeCue.cellResolution) {
47156            var cellUnit = [videoWidth / activeCue.cellResolution[0], videoHeight / activeCue.cellResolution[1]];
47157            if (activeCue.linePadding) {
47158                for (key in activeCue.linePadding) {
47159                    if (activeCue.linePadding.hasOwnProperty(key)) {
47160                        var valueLinePadding = activeCue.linePadding[key];
47161                        replaceValue = (valueLinePadding * cellUnit[0]).toString();
47162                        // Compute the CellResolution unit in order to process properties using sizing (fontSize, linePadding, etc).
47163                        var elementsSpan = document.getElementsByClassName('spanPadding');
47164                        for (var i = 0; i < elementsSpan.length; i++) {
47165                            elementsSpan[i].style.cssText = elementsSpan[i].style.cssText.replace(/(padding-left\s*:\s*)[\d.,]+(?=\s*px)/gi, '$1' + replaceValue);
47166                            elementsSpan[i].style.cssText = elementsSpan[i].style.cssText.replace(/(padding-right\s*:\s*)[\d.,]+(?=\s*px)/gi, '$1' + replaceValue);
47167                        }
47168                    }
47169                }
47170            }
47171
47172            if (activeCue.fontSize) {
47173                for (key in activeCue.fontSize) {
47174                    if (activeCue.fontSize.hasOwnProperty(key)) {
47175                        if (activeCue.fontSize[key][0] === '%') {
47176                            valueFontSize = activeCue.fontSize[key][1] / 100;
47177                        } else if (activeCue.fontSize[key][0] === 'c') {
47178                            valueFontSize = activeCue.fontSize[key][1];
47179                        }
47180
47181                        replaceValue = (valueFontSize * cellUnit[1]).toString();
47182
47183                        if (key !== 'defaultFontSize') {
47184                            elements = document.getElementsByClassName(key);
47185                        } else {
47186                            elements = document.getElementsByClassName('paragraph');
47187                        }
47188
47189                        for (var j = 0; j < elements.length; j++) {
47190                            elements[j].style.cssText = elements[j].style.cssText.replace(/(font-size\s*:\s*)[\d.,]+(?=\s*px)/gi, '$1' + replaceValue);
47191                        }
47192                    }
47193                }
47194
47195                if (activeCue.lineHeight) {
47196                    for (key in activeCue.lineHeight) {
47197                        if (activeCue.lineHeight.hasOwnProperty(key)) {
47198                            if (activeCue.lineHeight[key][0] === '%') {
47199                                valueLineHeight = activeCue.lineHeight[key][1] / 100;
47200                            } else if (activeCue.fontSize[key][0] === 'c') {
47201                                valueLineHeight = activeCue.lineHeight[key][1];
47202                            }
47203
47204                            replaceValue = (valueLineHeight * cellUnit[1]).toString();
47205                            elements = document.getElementsByClassName(key);
47206                            for (var k = 0; k < elements.length; k++) {
47207                                elements[k].style.cssText = elements[k].style.cssText.replace(/(line-height\s*:\s*)[\d.,]+(?=\s*px)/gi, '$1' + replaceValue);
47208                            }
47209                        }
47210                    }
47211                }
47212            }
47213        }
47214    }
47215
47216    /*
47217     * Add captions to track, store for later adding, or add captions added before
47218     */
47219    function addCaptions(trackIdx, timeOffset, captionData) {
47220        var track = getTrackByIdx(trackIdx);
47221        var self = this;
47222
47223        if (!track) {
47224            return;
47225        }
47226
47227        if (!captionData || captionData.length === 0) {
47228            return;
47229        }
47230
47231        var _loop = function (item) {
47232            var cue = undefined;
47233            var currentItem = captionData[item];
47234
47235            track.cellResolution = currentItem.cellResolution;
47236            track.isFromCEA608 = currentItem.isFromCEA608;
47237
47238            if (currentItem.type === 'html') {
47239                cue = new Cue(currentItem.start - timeOffset, currentItem.end - timeOffset, '');
47240                cue.cueHTMLElement = currentItem.cueHTMLElement;
47241                cue.isd = currentItem.isd;
47242                cue.images = currentItem.images;
47243                cue.embeddedImages = currentItem.embeddedImages;
47244                cue.cueID = currentItem.cueID;
47245                cue.scaleCue = scaleCue.bind(self);
47246                //useful parameters for cea608 subtitles, not for TTML one.
47247                cue.cellResolution = currentItem.cellResolution;
47248                cue.lineHeight = currentItem.lineHeight;
47249                cue.linePadding = currentItem.linePadding;
47250                cue.fontSize = currentItem.fontSize;
47251
47252                captionContainer.style.left = actualVideoLeft + 'px';
47253                captionContainer.style.top = actualVideoTop + 'px';
47254                captionContainer.style.width = actualVideoWidth + 'px';
47255                captionContainer.style.height = actualVideoHeight + 'px';
47256
47257                cue.onenter = function () {
47258                    if (track.mode === _constantsConstants2['default'].TEXT_SHOWING) {
47259                        if (this.isd) {
47260                            var finalCue = document.createElement('div');
47261                            log('Cue enter id:' + this.cueID);
47262                            captionContainer.appendChild(finalCue);
47263                            (0, _imsc.renderHTML)(this.isd, finalCue, function (uri) {
47264                                var imsc1ImgUrnTester = /^(urn:)(mpeg:[a-z0-9][a-z0-9-]{0,31}:)(subs:)([0-9])$/;
47265                                var smpteImgUrnTester = /^#(.*)$/;
47266                                if (imsc1ImgUrnTester.test(uri)) {
47267                                    var match = imsc1ImgUrnTester.exec(uri);
47268                                    var imageId = parseInt(match[4], 10) - 1;
47269                                    var imageData = btoa(cue.images[imageId]);
47270                                    var dataUrl = 'data:image/png;base64,' + imageData;
47271                                    return dataUrl;
47272                                } else if (smpteImgUrnTester.test(uri)) {
47273                                    var match = smpteImgUrnTester.exec(uri);
47274                                    var imageId = match[1];
47275                                    var dataUrl = 'data:image/png;base64,' + cue.embeddedImages[imageId];
47276                                    return dataUrl;
47277                                } else {
47278                                    return null;
47279                                }
47280                            }, captionContainer.clientHeight, captionContainer.clientWidth);
47281                            finalCue.id = this.cueID;
47282                        } else {
47283                            captionContainer.appendChild(this.cueHTMLElement);
47284                            scaleCue.call(self, this);
47285                        }
47286                    }
47287                };
47288
47289                cue.onexit = function () {
47290                    var divs = captionContainer.childNodes;
47291                    for (var i = 0; i < divs.length; ++i) {
47292                        if (divs[i].id === this.cueID) {
47293                            log('Cue exit id:' + divs[i].id);
47294                            captionContainer.removeChild(divs[i]);
47295                        }
47296                    }
47297                };
47298            } else {
47299                cue = new Cue(currentItem.start - timeOffset, currentItem.end - timeOffset, currentItem.data);
47300                if (currentItem.styles) {
47301                    if (currentItem.styles.align !== undefined && 'align' in cue) {
47302                        cue.align = currentItem.styles.align;
47303                    }
47304                    if (currentItem.styles.line !== undefined && 'line' in cue) {
47305                        cue.line = currentItem.styles.line;
47306                    }
47307                    if (currentItem.styles.position !== undefined && 'position' in cue) {
47308                        cue.position = currentItem.styles.position;
47309                    }
47310                    if (currentItem.styles.size !== undefined && 'size' in cue) {
47311                        cue.size = currentItem.styles.size;
47312                    }
47313                }
47314            }
47315
47316            track.addCue(cue);
47317        };
47318
47319        for (var item in captionData) {
47320            _loop(item);
47321        }
47322    }
47323
47324    function getTrackByIdx(idx) {
47325        return idx >= 0 && textTrackQueue[idx] ? videoModel.getTextTrack(textTrackQueue[idx].kind, textTrackQueue[idx].label, textTrackQueue[idx].lang) : null;
47326    }
47327
47328    function getCurrentTrackIdx() {
47329        return currentTrackIdx;
47330    }
47331
47332    function getTrackIdxForId(trackId) {
47333        var idx = -1;
47334        for (var i = 0; i < textTrackQueue.length; i++) {
47335            if (textTrackQueue[i].label === trackId) {
47336                idx = i;
47337                break;
47338            }
47339        }
47340
47341        return idx;
47342    }
47343
47344    function setCurrentTrackIdx(idx) {
47345        if (idx === currentTrackIdx) {
47346            return;
47347        }
47348        currentTrackIdx = idx;
47349        var track = getTrackByIdx(currentTrackIdx);
47350        setCueStyleOnTrack.call(this, track);
47351
47352        if (videoSizeCheckInterval) {
47353            clearInterval(videoSizeCheckInterval);
47354            videoSizeCheckInterval = null;
47355        }
47356
47357        if (track && track.renderingType === 'html') {
47358            checkVideoSize.call(this, track);
47359            videoSizeCheckInterval = setInterval(checkVideoSize.bind(this, track), 500);
47360        }
47361    }
47362
47363    function setCueStyleOnTrack(track) {
47364        clearCaptionContainer.call(this);
47365        if (track) {
47366            if (track.renderingType === 'html') {
47367                setNativeCueStyle.call(this);
47368            } else {
47369                removeNativeCueStyle.call(this);
47370            }
47371        } else {
47372            removeNativeCueStyle.call(this);
47373        }
47374    }
47375
47376    function deleteTrackCues(track) {
47377        if (track.cues) {
47378            var cues = track.cues;
47379            var lastIdx = cues.length - 1;
47380
47381            for (var r = lastIdx; r >= 0; r--) {
47382                track.removeCue(cues[r]);
47383            }
47384        }
47385    }
47386
47387    function deleteCuesFromTrackIdx(trackIdx) {
47388        var track = getTrackByIdx(trackIdx);
47389        if (track) {
47390            deleteTrackCues(track);
47391        }
47392    }
47393
47394    function deleteAllTextTracks() {
47395        var ln = trackElementArr ? trackElementArr.length : 0;
47396        for (var i = 0; i < ln; i++) {
47397            if (isChrome) {
47398                videoModel.removeChild(trackElementArr[i]);
47399            } else {
47400                var track = getTrackByIdx(i);
47401                if (track) {
47402                    deleteTrackCues.call(this, track);
47403                    track.mode = 'disabled';
47404                }
47405            }
47406        }
47407        trackElementArr = [];
47408        textTrackQueue = [];
47409        if (videoSizeCheckInterval) {
47410            clearInterval(videoSizeCheckInterval);
47411            videoSizeCheckInterval = null;
47412        }
47413        currentTrackIdx = -1;
47414        clearCaptionContainer.call(this);
47415    }
47416
47417    function deleteTextTrack(idx) {
47418        videoModel.removeChild(trackElementArr[idx]);
47419        trackElementArr.splice(idx, 1);
47420    }
47421
47422    /* Set native cue style to transparent background to avoid it being displayed. */
47423    function setNativeCueStyle() {
47424        if (!isChrome) {
47425            return;
47426        }
47427        var styleElement = document.getElementById('native-cue-style');
47428        if (styleElement) {
47429            return; //Already set
47430        }
47431
47432        styleElement = document.createElement('style');
47433        styleElement.id = 'native-cue-style';
47434        document.head.appendChild(styleElement);
47435        var stylesheet = styleElement.sheet;
47436        var video = videoModel.getElement();
47437        if (video) {
47438            if (video.id) {
47439                stylesheet.insertRule('#' + video.id + '::cue {background: transparent}', 0);
47440            } else if (video.classList.length !== 0) {
47441                stylesheet.insertRule('.' + video.className + '::cue {background: transparent}', 0);
47442            } else {
47443                stylesheet.insertRule('video::cue {background: transparent}', 0);
47444            }
47445        }
47446    }
47447
47448    /* Remove the extra cue style with transparent background for native cues. */
47449    function removeNativeCueStyle() {
47450        if (!isChrome) {
47451            return;
47452        }
47453        var styleElement = document.getElementById('native-cue-style');
47454        if (styleElement) {
47455            document.head.removeChild(styleElement);
47456        }
47457    }
47458
47459    function clearCaptionContainer() {
47460        if (captionContainer) {
47461            while (captionContainer.firstChild) {
47462                captionContainer.removeChild(captionContainer.firstChild);
47463            }
47464        }
47465    }
47466
47467    function setConfig(config) {
47468        if (!config) {
47469            return;
47470        }
47471        if (config.videoModel) {
47472            videoModel = config.videoModel;
47473        }
47474    }
47475
47476    function setModeForTrackIdx(idx, mode) {
47477        var track = getTrackByIdx(idx);
47478        if (track && track.mode !== mode) {
47479            track.mode = mode;
47480        }
47481    }
47482
47483    function getCurrentTrackInfo() {
47484        return textTrackQueue[currentTrackIdx];
47485    }
47486
47487    instance = {
47488        initialize: initialize,
47489        displayCConTop: displayCConTop,
47490        addTextTrack: addTextTrack,
47491        addCaptions: addCaptions,
47492        getCurrentTrackIdx: getCurrentTrackIdx,
47493        setCurrentTrackIdx: setCurrentTrackIdx,
47494        getTrackIdxForId: getTrackIdxForId,
47495        getCurrentTrackInfo: getCurrentTrackInfo,
47496        setModeForTrackIdx: setModeForTrackIdx,
47497        deleteCuesFromTrackIdx: deleteCuesFromTrackIdx,
47498        deleteAllTextTracks: deleteAllTextTracks,
47499        deleteTextTrack: deleteTextTrack,
47500        setConfig: setConfig
47501    };
47502
47503    return instance;
47504}
47505
47506TextTracks.__dashjs_factory_name = 'TextTracks';
47507exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(TextTracks);
47508module.exports = exports['default'];
47509
47510},{"100":100,"21":21,"49":49,"50":50,"51":51,"54":54}],189:[function(_dereq_,module,exports){
47511/**
47512 * The copyright in this software is being made available under the BSD License,
47513 * included below. This software may be subject to other third party and contributor
47514 * rights, including patent rights, and no such rights are granted under this license.
47515 *
47516 * Copyright (c) 2013, Dash Industry Forum.
47517 * All rights reserved.
47518 *
47519 * Redistribution and use in source and binary forms, with or without modification,
47520 * are permitted provided that the following conditions are met:
47521 *  * Redistributions of source code must retain the above copyright notice, this
47522 *  list of conditions and the following disclaimer.
47523 *  * Redistributions in binary form must reproduce the above copyright notice,
47524 *  this list of conditions and the following disclaimer in the documentation and/or
47525 *  other materials provided with the distribution.
47526 *  * Neither the name of Dash Industry Forum nor the names of its
47527 *  contributors may be used to endorse or promote products derived from this software
47528 *  without specific prior written permission.
47529 *
47530 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
47531 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
47532 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
47533 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
47534 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
47534INCLUDING, BUT
47535 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
47536 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
47537 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
47538 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
47539 *  POSSIBILITY OF SUCH DAMAGE.
47540 */
47541
47542'use strict';
47543
47544Object.defineProperty(exports, '__esModule', {
47545    value: true
47546});
47547
47548function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
47549
47550var _coreEventBus = _dereq_(50);
47551
47552var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
47553
47554var _coreEventsEvents = _dereq_(54);
47555
47556var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
47557
47558var _controllersBlacklistController = _dereq_(104);
47559
47560var _controllersBlacklistController2 = _interopRequireDefault(_controllersBlacklistController);
47561
47562var _baseUrlResolutionDVBSelector = _dereq_(205);
47563
47564var _baseUrlResolutionDVBSelector2 = _interopRequireDefault(_baseUrlResolutionDVBSelector);
47565
47566var _baseUrlResolutionBasicSelector = _dereq_(204);
47567
47568var _baseUrlResolutionBasicSelector2 = _interopRequireDefault(_baseUrlResolutionBasicSelector);
47569
47570var _coreFactoryMaker = _dereq_(51);
47571
47572var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
47573
47574var URL_RESOLUTION_FAILED_GENERIC_ERROR_CODE = 1;
47575var URL_RESOLUTION_FAILED_GENERIC_ERROR_MESSAGE = 'Failed to resolve a valid URL';
47576
47577function BaseURLSelector() {
47578
47579    var context = this.context;
47580    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
47581    var dashManifestModel = undefined;
47582
47583    var instance = undefined,
47584        serviceLocationBlacklistController = undefined,
47585        basicSelector = undefined,
47586        dvbSelector = undefined,
47587        selector = undefined;
47588
47589    function setup() {
47590        serviceLocationBlacklistController = (0, _controllersBlacklistController2['default'])(context).create({
47591            updateEventName: _coreEventsEvents2['default'].SERVICE_LOCATION_BLACKLIST_CHANGED,
47592            addBlacklistEventName: _coreEventsEvents2['default'].SERVICE_LOCATION_BLACKLIST_ADD
47593        });
47594
47595        basicSelector = (0, _baseUrlResolutionBasicSelector2['default'])(context).create({
47596            blacklistController: serviceLocationBlacklistController
47597        });
47598
47599        dvbSelector = (0, _baseUrlResolutionDVBSelector2['default'])(context).create({
47600            blacklistController: serviceLocationBlacklistController
47601        });
47602
47603        selector = basicSelector;
47604    }
47605
47606    function setConfig(config) {
47607        if (config.selector) {
47608            selector = config.selector;
47609        }
47610        if (config.dashManifestModel) {
47611            dashManifestModel = config.dashManifestModel;
47612        }
47613    }
47614
47615    function checkConfig() {
47616        if (!dashManifestModel || !dashManifestModel.hasOwnProperty('getIsDVB')) {
47617            throw new Error('Missing config parameter(s)');
47618        }
47619    }
47620
47621    function chooseSelectorFromManifest(manifest) {
47622        checkConfig();
47623        if (dashManifestModel.getIsDVB(manifest)) {
47624            selector = dvbSelector;
47625        } else {
47626            selector = basicSelector;
47627        }
47628    }
47629
47630    function select(data) {
47631        var baseUrls = data.baseUrls;
47632        var selectedIdx = data.selectedIdx;
47633
47634        // Once a random selection has been carried out amongst a group of BaseURLs with the same
47635        // @priority attribute value, then that choice should be re-used if the selection needs to be made again
47636        // unless the blacklist has been modified or the available BaseURLs have changed.
47637        if (!isNaN(selectedIdx)) {
47638            return baseUrls[selectedIdx];
47639        }
47640
47641        var selectedBaseUrl = selector.select(baseUrls);
47642
47643        if (!selectedBaseUrl) {
47644            eventBus.trigger(_coreEventsEvents2['default'].URL_RESOLUTION_FAILED, {
47645                error: new Error(URL_RESOLUTION_FAILED_GENERIC_ERROR_CODE, URL_RESOLUTION_FAILED_GENERIC_ERROR_MESSAGE)
47646            });
47647
47648            return;
47649        }
47650
47651        data.selectedIdx = baseUrls.indexOf(selectedBaseUrl);
47652
47653        return selectedBaseUrl;
47654    }
47655
47656    function reset() {
47657        serviceLocationBlacklistController.reset();
47658    }
47659
47660    instance = {
47661        chooseSelectorFromManifest: chooseSelectorFromManifest,
47662        select: select,
47663        reset: reset,
47664        setConfig: setConfig
47665    };
47666
47667    setup();
47668
47669    return instance;
47670}
47671
47672BaseURLSelector.__dashjs_factory_name = 'BaseURLSelector';
47673var factory = _coreFactoryMaker2['default'].getClassFactory(BaseURLSelector);
47674factory.URL_RESOLUTION_FAILED_GENERIC_ERROR_CODE = URL_RESOLUTION_FAILED_GENERIC_ERROR_CODE;
47675factory.URL_RESOLUTION_FAILED_GENERIC_ERROR_MESSAGE = URL_RESOLUTION_FAILED_GENERIC_ERROR_MESSAGE;
47676_coreFactoryMaker2['default'].updateClassFactory(BaseURLSelector.__dashjs_factory_name, factory);
47677exports['default'] = factory;
47678module.exports = exports['default'];
47679
47680},{"104":104,"204":204,"205":205,"50":50,"51":51,"54":54}],190:[function(_dereq_,module,exports){
47681/**
47682 * The copyright in this software is being made available under the BSD License,
47683 * included below. This software may be subject to other third party and contributor
47684 * rights, including patent rights, and no such rights are granted under this license.
47685 *
47686 * Copyright (c) 2013, Dash Industry Forum.
47687 * All rights reserved.
47688 *
47689 * Redistribution and use in source and binary forms, with or without modification,
47690 * are permitted provided that the following conditions are met:
47691 *  * Redistributions of source code must retain the above copyright notice, this
47692 *  list of conditions and the following disclaimer.
47693 *  * Redistributions in binary form must reproduce the above copyright notice,
47694 *  this list of conditions and the following disclaimer in the documentation and/or
47695 *  other materials provided with the distribution.
47696 *  * Neither the name of Dash Industry Forum nor the names of its
47697 *  contributors may be used to endorse or promote products derived from this software
47698 *  without specific prior written permission.
47699 *
47700 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
47701 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
47702 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
47703 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
47704 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
47704INCLUDING, BUT
47705 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
47706 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
47707 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
47708 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
47709 *  POSSIBILITY OF SUCH DAMAGE.
47710 */
47711
47712'use strict';
47713
47714Object.defineProperty(exports, '__esModule', {
47715    value: true
47716});
47717
47718function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
47719
47720var _IsoFile = _dereq_(197);
47721
47722var _IsoFile2 = _interopRequireDefault(_IsoFile);
47723
47724var _coreFactoryMaker = _dereq_(51);
47725
47726var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
47727
47728var _codemIsoboxer = _dereq_(11);
47729
47730var _codemIsoboxer2 = _interopRequireDefault(_codemIsoboxer);
47731
47732function BoxParser() /*config*/{
47733
47734    var instance = undefined;
47735    var context = this.context;
47736
47737    /**
47738     * @param {ArrayBuffer} data
47739     * @returns {IsoFile|null}
47740     * @memberof BoxParser#
47741     */
47742    function parse(data) {
47743        if (!data) return null;
47744
47745        if (data.fileStart === undefined) {
47746            data.fileStart = 0;
47747        }
47748
47749        var parsedFile = _codemIsoboxer2['default'].parseBuffer(data);
47750        var dashIsoFile = (0, _IsoFile2['default'])(context).create();
47751
47752        dashIsoFile.setData(parsedFile);
47753
47754        return dashIsoFile;
47755    }
47756
47757    instance = {
47758        parse: parse
47759    };
47760
47761    return instance;
47762}
47763BoxParser.__dashjs_factory_name = 'BoxParser';
47764exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(BoxParser);
47765module.exports = exports['default'];
47766
47767},{"11":11,"197":197,"51":51}],191:[function(_dereq_,module,exports){
47768/**
47769 * The copyright in this software is being made available under the BSD License,
47770 * included below. This software may be subject to other third party and contributor
47771 * rights, including patent rights, and no such rights are granted under this license.
47772 *
47773 * Copyright (c) 2013, Dash Industry Forum.
47774 * All rights reserved.
47775 *
47776 * Redistribution and use in source and binary forms, with or without modification,
47777 * are permitted provided that the following conditions are met:
47778 *  * Redistributions of source code must retain the above copyright notice, this
47779 *  list of conditions and the following disclaimer.
47780 *  * Redistributions in binary form must reproduce the above copyright notice,
47781 *  this list of conditions and the following disclaimer in the documentation and/or
47782 *  other materials provided with the distribution.
47783 *  * Neither the name of Dash Industry Forum nor the names of its
47784 *  contributors may be used to endorse or promote products derived from this software
47785 *  without specific prior written permission.
47786 *
47787 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
47788 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
47789 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
47790 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
47791 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47792 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
47793 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
47794 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
47795 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
47796 *  POSSIBILITY OF SUCH DAMAGE.
47797 */
47798'use strict';
47799
47800Object.defineProperty(exports, '__esModule', {
47801    value: true
47802});
47803
47804function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
47805
47806var _coreFactoryMaker = _dereq_(51);
47807
47808var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
47809
47810function Capabilities() {
47811
47812    var instance = undefined,
47813        encryptedMediaSupported = undefined;
47814
47815    function setup() {
47816        encryptedMediaSupported = false;
47817    }
47818
47819    function supportsMediaSource() {
47820        var hasWebKit = ('WebKitMediaSource' in window);
47821        var hasMediaSource = ('MediaSource' in window);
47822
47823        return hasWebKit || hasMediaSource;
47824    }
47825
47826    /**
47827     * Returns whether Encrypted Media Extensions are supported on this
47828     * user agent
47829     *
47830     * @return {boolean} true if EME is supported, false otherwise
47831     */
47832    function supportsEncryptedMedia() {
47833        return encryptedMediaSupported;
47834    }
47835
47836    function setEncryptedMediaSupported(value) {
47837        encryptedMediaSupported = value;
47838    }
47839
47840    function supportsCodec(codec) {
vendor: 9,886 bytes, lines 47841-48070
47841        if ('MediaSource' in window && MediaSource.isTypeSupported(codec)) {
47842            return true;
47843        }
47844
47845        if ('WebKitMediaSource' in window && WebKitMediaSource.isTypeSupported(codec)) {
47846            return true;
47847        }
47848
47849        return false;
47850    }
47851
47852    instance = {
47853        supportsMediaSource: supportsMediaSource,
47854        supportsEncryptedMedia: supportsEncryptedMedia,
47855        supportsCodec: supportsCodec,
47856        setEncryptedMediaSupported: setEncryptedMediaSupported
47857    };
47858
47859    setup();
47860
47861    return instance;
47862}
47863Capabilities.__dashjs_factory_name = 'Capabilities';
47864exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(Capabilities);
47865module.exports = exports['default'];
47866
47867},{"51":51}],192:[function(_dereq_,module,exports){
47868/**
47869* The copyright in this software is being made available under the BSD License,
47870* included below. This software may be subject to other third party and contributor
47871* rights, including patent rights, and no such rights are granted under this license.
47872*
47873* Copyright (c) 2013, Dash Industry Forum.
47874* All rights reserved.
47875*
47876* Redistribution and use in source and binary forms, with or without modification,
47877* are permitted provided that the following conditions are met:
47878*  * Redistributions of source code must retain the above copyright notice, this
47879*  list of conditions and the following disclaimer.
47880*  * Redistributions in binary form must reproduce the above copyright notice,
47881*  this list of conditions and the following disclaimer in the documentation and/or
47882*  other materials provided with the distribution.
47883*  * Neither the name of Dash Industry Forum nor the names of its
47884*  contributors may be used to endorse or promote products derived from this software
47885*  without specific prior written permission.
47886*
47887*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
47888*  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
47889*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
47890*  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
47891*  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47892*  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
47893*  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
47894*  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
47895*  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
47896*  POSSIBILITY OF SUCH DAMAGE.
47897*/
47898'use strict';
47899
47900Object.defineProperty(exports, '__esModule', {
47901    value: true
47902});
47903
47904function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
47905
47906var _coreFactoryMaker = _dereq_(51);
47907
47908var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
47909
47910function CustomTimeRanges() /*config*/{
47911    var customTimeRangeArray = [];
47912    var length = 0;
47913
47914    function add(start, end) {
47915        var i = 0;
47916
47917        for (i = 0; i < this.customTimeRangeArray.length && start > this.customTimeRangeArray[i].start; i++);
47918
47919        this.customTimeRangeArray.splice(i, 0, { start: start, end: end });
47920
47921        for (i = 0; i < this.customTimeRangeArray.length - 1; i++) {
47922            if (this.mergeRanges(i, i + 1)) {
47923                i--;
47924            }
47925        }
47926        this.length = this.customTimeRangeArray.length;
47927    }
47928
47929    function clear() {
47930        this.customTimeRangeArray = [];
47931        this.length = 0;
47932    }
47933
47934    function remove(start, end) {
47935        for (var i = 0; i < this.customTimeRangeArray.length; i++) {
47936            if (start <= this.customTimeRangeArray[i].start && end >= this.customTimeRangeArray[i].end) {
47937                //      |--------------Range i-------|
47938                //|---------------Range to remove ---------------|
47939                //    or
47940                //|--------------Range i-------|
47941                //|--------------Range to remove ---------------|
47942                //    or
47943                //                 |--------------Range i-------|
47944                //|--------------Range to remove ---------------|
47945                this.customTimeRangeArray.splice(i, 1);
47946                i--;
47947            } else if (start > this.customTimeRangeArray[i].start && end < this.customTimeRangeArray[i].end) {
47948                //|-----------------Range i----------------|
47949                //        |-------Range to remove -----|
47950                this.customTimeRangeArray.splice(i + 1, 0, { start: end, end: this.customTimeRangeArray[i].end });
47951                this.customTimeRangeArray[i].end = start;
47952                break;
47953            } else if (start > this.customTimeRangeArray[i].start && start < this.customTimeRangeArray[i].end) {
47954                //|-----------Range i----------|
47955                //                    |---------Range to remove --------|
47956                //    or
47957                //|-----------------Range i----------------|
47958                //            |-------Range to remove -----|
47959                this.customTimeRangeArray[i].end = start;
47960            } else if (end > this.customTimeRangeArray[i].start && end < this.customTimeRangeArray[i].end) {
47961                //                     |-----------Range i----------|
47962                //|---------Range to remove --------|
47963                //            or
47964                //|-----------------Range i----------------|
47965                //|-------Range to remove -----|
47966                this.customTimeRangeArray[i].start = end;
47967            }
47968        }
47969
47970        this.length = this.customTimeRangeArray.length;
47971    }
47972
47973    function mergeRanges(rangeIndex1, rangeIndex2) {
47974        var range1 = this.customTimeRangeArray[rangeIndex1];
47975        var range2 = this.customTimeRangeArray[rangeIndex2];
47976
47977        if (range1.start <= range2.start && range2.start <= range1.end && range1.end <= range2.end) {
47978            //|-----------Range1----------|
47979            //                    |-----------Range2----------|
47980            range1.end = range2.end;
47981            this.customTimeRangeArray.splice(rangeIndex2, 1);
47982            return true;
47983        } else if (range2.start <= range1.start && range1.start <= range2.end && range2.end <= range1.end) {
47984            //                |-----------Range1----------|
47985            //|-----------Range2----------|
47986            range1.start = range2.start;
47987            this.customTimeRangeArray.splice(rangeIndex2, 1);
47988            return true;
47989        } else if (range2.start <= range1.start && range1.start <= range2.end && range1.end <= range2.end) {
47990            //      |--------Range1-------|
47991            //|---------------Range2--------------|
47992            this.customTimeRangeArray.splice(rangeIndex1, 1);
47993            return true;
47994        } else if (range1.start <= range2.start && range2.start <= range1.end && range2.end <= range1.end) {
47995            //|-----------------Range1--------------|
47996            //        |-----------Range2----------|
47997            this.customTimeRangeArray.splice(rangeIndex2, 1);
47998            return true;
47999        }
48000        return false;
48001    }
48002
48003    function checkIndex(index) {
48004        var isInt = index !== null && !isNaN(index) && index % 1 === 0;
48005
48006        if (!isInt) {
48007            throw new Error('index argument is not an integer');
48008        }
48009    }
48010
48011    function start(index) {
48012        checkIndex(index);
48013
48014        if (index >= this.customTimeRangeArray.length || index < 0) {
48015            return NaN;
48016        }
48017
48018        return this.customTimeRangeArray[index].start;
48019    }
48020
48021    function end(index) {
48022        checkIndex(index);
48023
48024        if (index >= this.customTimeRangeArray.length || index < 0) {
48025            return NaN;
48026        }
48027
48028        return this.customTimeRangeArray[index].end;
48029    }
48030
48031    return {
48032        customTimeRangeArray: customTimeRangeArray,
48033        length: length,
48034        add: add,
48035        clear: clear,
48036        remove: remove,
48037        mergeRanges: mergeRanges,
48038        start: start,
48039        end: end
48040    };
48041}
48042CustomTimeRanges.__dashjs_factory_name = 'CustomTimeRanges';
48043exports['default'] = _coreFactoryMaker2['default'].getClassFactory(CustomTimeRanges);
48044module.exports = exports['default'];
48045
48046},{"51":51}],193:[function(_dereq_,module,exports){
48047/**
48048 * The copyright in this software is being made available under the BSD License,
48049 * included below. This software may be subject to other third party and contributor
48050 * rights, including patent rights, and no such rights are granted under this license.
48051 *
48052 * Copyright (c) 2013, Dash Industry Forum.
48053 * All rights reserved.
48054 *
48055 * Redistribution and use in source and binary forms, with or without modification,
48056 * are permitted provided that the following conditions are met:
48057 *  * Redistributions of source code must retain the above copyright notice, this
48058 *  list of conditions and the following disclaimer.
48059 *  * Redistributions in binary form must reproduce the above copyright notice,
48060 *  this list of conditions and the following disclaimer in the documentation and/or
48061 *  other materials provided with the distribution.
48062 *  * Neither the name of Dash Industry Forum nor the names of its
48063 *  contributors may be used to endorse or promote products derived from this software
48064 *  without specific prior written permission.
48065 *
48066 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
48067 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
48068 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
48069 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
48070 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
48070INCLUDING, BUT
48071 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
48072 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
48073 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48074 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
48075 *  POSSIBILITY OF SUCH DAMAGE.
48076 */
48077'use strict';
48078
48079Object.defineProperty(exports, '__esModule', {
48080    value: true
48081});
48082
48083function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
48084
48085var _coreFactoryMaker = _dereq_(51);
48086
48087var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
48088
48089var _coreDebug = _dereq_(49);
48090
48091var _coreDebug2 = _interopRequireDefault(_coreDebug);
48092
48093var legacyKeysAndReplacements = [{ oldKey: 'dashjs_vbitrate', newKey: 'dashjs_video_bitrate' }, { oldKey: 'dashjs_abitrate', newKey: 'dashjs_audio_bitrate' }, { oldKey: 'dashjs_vsettings', newKey: 'dashjs_video_settings' }, { oldKey: 'dashjs_asettings', newKey: 'dashjs_audio_settings' }];
48094
48095var LOCAL_STORAGE_BITRATE_KEY_TEMPLATE = 'dashjs_?_bitrate';
48096var LOCAL_STORAGE_SETTINGS_KEY_TEMPLATE = 'dashjs_?_settings';
48097
48098var STORAGE_TYPE_LOCAL = 'localStorage';
48099var STORAGE_TYPE_SESSION = 'sessionStorage';
48100var LAST_BITRATE = 'LastBitrate';
48101var LAST_MEDIA_SETTINGS = 'LastMediaSettings';
48102
48103function DOMStorage(config) {
48104
48105    var context = this.context;
48106    var log = (0, _coreDebug2['default'])(context).getInstance().log;
48107    var mediaPlayerModel = config.mediaPlayerModel;
48108
48109    var instance = undefined,
48110        supported = undefined;
48111
48112    //type can be local, session
48113    function isSupported(type) {
48114        if (supported !== undefined) return supported;
48115
48116        supported = false;
48117
48118        var testKey = '1';
48119        var testValue = '1';
48120        var storage = undefined;
48121
48122        try {
48123            if (typeof window !== 'undefined') {
48124                storage = window[type];
48125            }
48126        } catch (error) {
48127            log('Warning: DOMStorage access denied: ' + error.message);
48128            return supported;
48129        }
48130
48131        if (!storage || type !== STORAGE_TYPE_LOCAL && type !== STORAGE_TYPE_SESSION) {
48132            return supported;
48133        }
48134
48135        /* When Safari (OS X or iOS) is in private browsing mode, it appears as though localStorage is available, but trying to call setItem throws an exception.
48136         http://stackoverflow.com/questions/14555347/html5-localstorage-error-with-safari-quota-exceeded-err-dom-exception-22-an
48137          Check if the storage can be used
48138         */
48139        try {
48140            storage.setItem(testKey, testValue);
48141            storage.removeItem(testKey);
48142            supported = true;
48143        } catch (error) {
48144            log('Warning: DOMStorage is supported, but cannot be used: ' + error.message);
48145        }
48146
48147        return supported;
48148    }
48149
48150    function translateLegacyKeys() {
48151        if (isSupported(STORAGE_TYPE_LOCAL)) {
48152            legacyKeysAndReplacements.forEach(function (entry) {
48153                var value = localStorage.getItem(entry.oldKey);
48154
48155                if (value) {
48156                    localStorage.removeItem(entry.oldKey);
48157
48158                    try {
48159                        localStorage.setItem(entry.newKey, value);
48160                    } catch (e) {
48161                        log(e.message);
48162                    }
48163                }
48164            });
48165        }
48166    }
48167
48168    function setup() {
48169        translateLegacyKeys();
48170    }
48171
48172    // Return current epoch time, ms, rounded to the nearest 10m to avoid fingerprinting user
48173    function getTimestamp() {
48174        var ten_minutes_ms = 60 * 1000 * 10;
48175        return Math.round(new Date().getTime() / ten_minutes_ms) * ten_minutes_ms;
48176    }
48177
48178    function canStore(storageType, key) {
48179        return isSupported(storageType) && mediaPlayerModel['get' + key + 'CachingInfo']().enabled;
48180    }
48181
48182    function checkConfig() {
48183        if (!mediaPlayerModel || !mediaPlayerModel.hasOwnProperty('getLastMediaSettingsCachingInfo')) {
48184            throw new Error('Missing config parameter(s)');
48185        }
48186    }
48187
48188    function getSavedMediaSettings(type) {
48189        checkConfig();
48190        //Checks local storage to see if there is valid, non-expired media settings
48191        if (!canStore(STORAGE_TYPE_LOCAL, LAST_MEDIA_SETTINGS)) return null;
48192
48193        var settings = null;
48194        var key = LOCAL_STORAGE_SETTINGS_KEY_TEMPLATE.replace(/\?/, type);
48195        try {
48196            var obj = JSON.parse(localStorage.getItem(key)) || {};
48197            var isExpired = new Date().getTime() - parseInt(obj.timestamp, 10) >= mediaPlayerModel.getLastMediaSettingsCachingInfo().ttl || false;
48198            settings = obj.settings;
48199
48200            if (isExpired) {
48201                localStorage.removeItem(key);
48202                settings = null;
48203            }
48204        } catch (e) {
48205            return null;
48206        }
48207        return settings;
48208    }
48209
48210    function getSavedBitrateSettings(type) {
48211        var savedBitrate = NaN;
48212
48213        checkConfig();
48214
48215        //Checks local storage to see if there is valid, non-expired bit rate
48216        //hinting from the last play session to use as a starting bit rate.
48217        if (canStore(STORAGE_TYPE_LOCAL, LAST_BITRATE)) {
48218            var key = LOCAL_STORAGE_BITRATE_KEY_TEMPLATE.replace(/\?/, type);
48219            try {
48220                var obj = JSON.parse(localStorage.getItem(key)) || {};
48221                var isExpired = new Date().getTime() - parseInt(obj.timestamp, 10) >= mediaPlayerModel.getLastMediaSettingsCachingInfo().ttl || false;
48222                var bitrate = parseFloat(obj.bitrate);
48223
48224                if (!isNaN(bitrate) && !isExpired) {
48225                    savedBitrate = bitrate;
48226                    log('Last saved bitrate for ' + type + ' was ' + bitrate);
48227                } else if (isExpired) {
48228                    localStorage.removeItem(key);
48229                }
48230            } catch (e) {
48231                return null;
48232            }
48233        }
48234        return savedBitrate;
48235    }
48236
48237    function setSavedMediaSettings(type, value) {
48238        if (canStore(STORAGE_TYPE_LOCAL, LAST_MEDIA_SETTINGS)) {
48239            var key = LOCAL_STORAGE_SETTINGS_KEY_TEMPLATE.replace(/\?/, type);
48240            try {
48241                localStorage.setItem(key, JSON.stringify({ settings: value, timestamp: getTimestamp() }));
48242            } catch (e) {
48243                log(e.message);
48244            }
48245        }
48246    }
48247
48248    function setSavedBitrateSettings(type, bitrate) {
48249        if (canStore(STORAGE_TYPE_LOCAL, LAST_BITRATE) && bitrate) {
48250            var key = LOCAL_STORAGE_BITRATE_KEY_TEMPLATE.replace(/\?/, type);
48251            try {
48252                localStorage.setItem(key, JSON.stringify({ bitrate: bitrate.toFixed(3), timestamp: getTimestamp() }));
48253            } catch (e) {
48254                log(e.message);
48255            }
48256        }
48257    }
48258
48259    instance = {
48260        getSavedBitrateSettings: getSavedBitrateSettings,
48261        setSavedBitrateSettings: setSavedBitrateSettings,
48262        getSavedMediaSettings: getSavedMediaSettings,
48263        setSavedMediaSettings: setSavedMediaSettings
48264    };
48265
48266    setup();
48267    return instance;
48268}
48269
48270DOMStorage.__dashjs_factory_name = 'DOMStorage';
48271var factory = _coreFactoryMaker2['default'].getSingletonFactory(DOMStorage);
48272exports['default'] = factory;
48273module.exports = exports['default'];
48274
48275},{"49":49,"51":51}],194:[function(_dereq_,module,exports){
48276'use strict';
48277
48278Object.defineProperty(exports, '__esModule', {
48279    value: true
48280});
48281
48282function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
48283
48284var _coreFactoryMaker = _dereq_(51);
48285
48286var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
48287
48288/**
48289 * Creates an instance of an EBMLParser class which implements a large subset
48290 * of the functionality required to parse Matroska EBML
48291 *
48292 * @param {Object} config object with data member which is the buffer to parse
48293 */
48294function EBMLParser(config) {
48295
48296    var instance = undefined;
48297
48298    var data = new DataView(config.data);
48299    var pos = 0;
48300
48301    function getPos() {
48302        return pos;
48303    }
48304
48305    function setPos(value) {
48306        pos = value;
48307    }
48308
48309    /**
48310     * Consumes an EBML tag from the data stream.
48311     *
48312     * @param {Object} tag to parse, A tag is an object with at least a {number} tag and
48313     * {boolean} required flag.
48314     * @param {boolean} test whether or not the function should throw if a required
48315     * tag is not found
48316     * @return {boolean} whether or not the tag was found
48317     * @throws will throw an exception if a required tag is not found and test
48318     * param is false or undefined, or if the stream is malformed.
48319     * @memberof EBMLParser
48320     */
48321    function consumeTag(tag, test) {
48322        var found = true;
48323        var bytesConsumed = 0;
48324        var p1 = undefined,
48325            p2 = undefined;
48326
48327        if (test === undefined) {
48328            test = false;
48329        }
48330
48331        if (tag.tag > 0xFFFFFF) {
48332            if (data.getUint32(pos) !== tag.tag) {
48333                found = false;
48334            }
48335            bytesConsumed = 4;
48336        } else if (tag.tag > 0xFFFF) {
48337            // 3 bytes
48338            p1 = data.getUint16(pos);
48339            p2 = data.getUint8(pos + 2);
48340
48341            // shift p1 over a byte and add p2
48342            if (p1 * 256 + p2 !== tag.tag) {
48343                found = false;
48344            }
48345            bytesConsumed = 3;
48346        } else if (tag.tag > 0xFF) {
48347            if (data.getUint16(pos) !== tag.tag) {
48348                found = false;
48349            }
48350            bytesConsumed = 2;
48351        } else {
48352            if (data.getUint8(pos) !== tag.tag) {
48353                found = false;
48354            }
48355            bytesConsumed = 1;
48356        }
48357
48358        if (!found && tag.required && !test) {
48359            throw new Error('required tag not found');
48360        }
48361
48362        if (found) {
48363            pos += bytesConsumed;
48364        }
48365
48366        return found;
48367    }
48368
48369    /**
48370     * Consumes an EBML tag from the data stream.   If the tag is found then this
48371     * function will also remove the size field which follows the tag from the
48372     * data stream.
48373     *
48374     * @param {Object} tag to parse, A tag is an object with at least a {number} tag and
48375     * {boolean} required flag.
48376     * @param {boolean} test whether or not the function should throw if a required
48377     * tag is not found
48378     * @return {boolean} whether or not the tag was found
48379     * @throws will throw an exception if a required tag is not found and test
48380     * param is false or undefined, or if the stream is malformedata.
48381     * @memberof EBMLParser
48382     */
48383    function consumeTagAndSize(tag, test) {
48384        var found = consumeTag(tag, test);
48385
48386        if (found) {
48387            getMatroskaCodedNum();
48388        }
48389
48390        return found;
48391    }
48392
48393    /**
48394     * Consumes an EBML tag from the data stream.   If the tag is found then this
48395     * function will also remove the size field which follows the tag from the
48396     * data stream.  It will use the value of the size field to parse a binary
48397     * field, using a parser defined in the tag itself
48398     *
48399     * @param {Object} tag to parse, A tag is an object with at least a {number} tag,
48400     * {boolean} required flag, and a parse function which takes a size parameter
48401     * @return {boolean} whether or not the tag was found
48402     * @throws will throw an exception if a required tag is not found,
48403     * or if the stream is malformed
48404     * @memberof EBMLParser
48405     */
48406    function parseTag(tag) {
48407        var size = undefined;
48408
48409        consumeTag(tag);
48410        size = getMatroskaCodedNum();
48411        return instance[tag.parse](size);
48412    }
48413
48414    /**
48415     * Consumes an EBML tag from the data stream.   If the tag is found then this
48416     * function will also remove the size field which follows the tag from the
48417     * data stream.  It will use the value of the size field to skip over the
48418     * entire section of EBML encapsulated by the tag.
48419     *
48420     * @param {Object} tag to parse, A tag is an object with at least a {number} tag, and
48421     * {boolean} required flag
48422     * @param {boolean} test a flag to indicate if an exception should be thrown
48423     * if a required tag is not found
48424     * @return {boolean} whether or not the tag was found
48425     * @throws will throw an exception if a required tag is not found and test is
48426     * false or undefined or if the stream is malformed
48427     * @memberof EBMLParser
48428     */
48429    function skipOverElement(tag, test) {
48430        var found = consumeTag(tag, test);
48431        var headerSize = undefined;
48432
48433        if (found) {
48434            headerSize = getMatroskaCodedNum();
48435            pos += headerSize;
48436        }
48437
48438        return found;
48439    }
48440
48441    /**
48442     * Returns and consumes a number encoded according to the Matroska EBML
48443     * specification from the bitstream.
48444     *
48445     * @param {boolean} retainMSB whether or not to retain the Most Significant Bit (the
48446     * first 1). this is usually true when reading Tag IDs.
48447     * @return {number} the decoded number
48448     * @throws will throw an exception if the bit stream is malformed or there is
48449     * not enough data
48450     * @memberof EBMLParser
48451     */
48452    function getMatroskaCodedNum(retainMSB) {
48453        var bytesUsed = 1;
48454        var mask = 0x80;
48455        var maxBytes = 8;
48456        var extraBytes = -1;
48457        var num = 0;
48458        var ch = data.getUint8(pos);
48459        var i = 0;
48460
48461        for (i = 0; i < maxBytes; i += 1) {
48462            if ((ch & mask) === mask) {
48463                num = retainMSB === undefined ? ch & ~mask : ch;
48464                extraBytes = i;
48465                break;
48466            }
48467            mask >>= 1;
48468        }
48469
48470        for (i = 0; i < extraBytes; i += 1, bytesUsed += 1) {
48471            num = num << 8 | 0xff & data.getUint8(pos + bytesUsed);
48472        }
48473
48474        pos += bytesUsed;
48475
48476        return num;
48477    }
48478
48479    /**
48480     * Returns and consumes a float from the bitstream.
48481     *
48482     * @param {number} size 4 or 8 byte floats are supported
48483     * @return {number} the decoded number
48484     * @throws will throw an exception if the bit stream is malformed or there is
48485     * not enough data
48486     * @memberof EBMLParser
48487     */
48488    function getMatroskaFloat(size) {
48489        var outFloat = undefined;
48490
48491        switch (size) {
48492            case 4:
48493                outFloat = data.getFloat32(pos);
48494                pos += 4;
48495                break;
48496            case 8:
48497                outFloat = data.getFloat64(pos);
48498                pos += 8;
48499                break;
48500        }
48501        return outFloat;
48502    }
48503
48504    /**
48505     * Consumes and returns an unsigned int from the bitstream.
48506     *
48507     * @param {number} size 1 to 8 bytes
48508     * @return {number} the decoded number
48509     * @throws will throw an exception if the bit stream is malformed or there is
48510     * not enough data
48511     * @memberof EBMLParser
48512     */
48513    function getMatroskaUint(size) {
48514        var val = 0;
48515
48516        for (var i = 0; i < size; i += 1) {
48517            val <<= 8;
48518            val |= data.getUint8(pos + i) & 0xff;
48519        }
48520
48521        pos += size;
48522        return val;
48523    }
48524
48525    /**
48526     * Tests whether there is more data in the bitstream for parsing
48527     *
48528     * @return {boolean} whether there is more data to parse
48529     * @memberof EBMLParser
48530     */
48531    function moreData() {
48532        return pos < data.byteLength;
48533    }
48534
48535    instance = {
48536        getPos: getPos,
48537        setPos: setPos,
48538        consumeTag: consumeTag,
48539        consumeTagAndSize: consumeTagAndSize,
48540        parseTag: parseTag,
48541        skipOverElement: skipOverElement,
48542        getMatroskaCodedNum: getMatroskaCodedNum,
48543        getMatroskaFloat: getMatroskaFloat,
48544        getMatroskaUint: getMatroskaUint,
48545        moreData: moreData
48546    };
48547
48548    return instance;
48549}
48550
48551EBMLParser.__dashjs_factory_name = 'EBMLParser';
48552exports['default'] = _coreFactoryMaker2['default'].getClassFactory(EBMLParser);
48553module.exports = exports['default'];
48554
48555},{"51":51}],195:[function(_dereq_,module,exports){
48556/**
48557 * The copyright in this software is being made available under the BSD License,
48558 * included below. This software may be subject to other third party and contributor
48559 * rights, including patent rights, and no such rights are granted under this license.
48560 *
48561 * Copyright (c) 2013, Dash Industry Forum.
48562 * All rights reserved.
48563 *
48564 * Redistribution and use in source and binary forms, with or without modification,
48565 * are permitted provided that the following conditions are met:
48566 *  * Redistributions of source code must retain the above copyright notice, this
48567 *  list of conditions and the following disclaimer.
48568 *  * Redistributions in binary form must reproduce the above copyright notice,
48569 *  this list of conditions and the following disclaimer in the documentation and/or
48570 *  other materials provided with the distribution.
48571 *  * Neither the name of Dash Industry Forum nor the names of its
48572 *  contributors may be used to endorse or promote products derived from this software
48573 *  without specific prior written permission.
48574 *
48575 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
48576 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
48577 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
48578 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
48579 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
48580 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
48581 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
48582 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48583 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
48584 *  POSSIBILITY OF SUCH DAMAGE.
48585 */
48586'use strict';
48587
48588Object.defineProperty(exports, '__esModule', {
48589    value: true
48590});
48591
48592function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
48593
48594var _coreEventBus = _dereq_(50);
48595
48596var _coreEventBus2 = _interopRequireDefault(_coreEventBus);
48597
48598var _coreEventsEvents = _dereq_(54);
48599
48600var _coreEventsEvents2 = _interopRequireDefault(_coreEventsEvents);
48601
48602var _coreFactoryMaker = _dereq_(51);
48603
48604var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
48605
48606var CAPABILITY_ERROR_MEDIASOURCE = 'mediasource';
48607var CAPABILITY_ERROR_MEDIAKEYS = 'mediakeys';
48608
48609var DOWNLOAD_ERROR_ID_MANIFEST = 'manifest';
48610var DOWNLOAD_ERROR_ID_SIDX = 'SIDX';
48611var DOWNLOAD_ERROR_ID_CONTENT = 'content';
48612var DOWNLOAD_ERROR_ID_INITIALIZATION = 'initialization';
48613var DOWNLOAD_ERROR_ID_XLINK = 'xlink';
48614
48615var MANIFEST_ERROR_ID_CODEC = 'codec';
48616var MANIFEST_ERROR_ID_PARSE = 'parse';
48617var MANIFEST_ERROR_ID_NOSTREAMS = 'nostreams';
48618
48619var TIMED_TEXT_ERROR_ID_PARSE = 'parse';
48620
48621function ErrorHandler() {
48622
48623    var instance = undefined;
48624    var context = this.context;
48625    var eventBus = (0, _coreEventBus2['default'])(context).getInstance();
48626
48627    // "mediasource"|"mediakeys"
48628    function capabilityError(err) {
48629        eventBus.trigger(_coreEventsEvents2['default'].ERROR, { error: 'capability', event: err });
48630    }
48631
48632    // {id: "manifest"|"SIDX"|"content"|"initialization"|"xlink", url: "", request: {XMLHttpRequest instance}}
48633    function downloadError(id, url, request) {
48634        eventBus.trigger(_coreEventsEvents2['default'].ERROR, { error: 'download', event: { id: id, url: url, request: request } });
48635    }
48636
48637    // {message: "", id: "codec"|"parse"|"nostreams", manifest: {parsed manifest}}
48638    function manifestError(message, id, manifest, err) {
48639        eventBus.trigger(_coreEventsEvents2['default'].ERROR, { error: 'manifestError', event: { message: message, id: id, manifest: manifest, event: err } });
48640    }
48641
48642    // {message: '', id: 'parse', cc: ''}
48643    function timedTextError(message, id, ccContent) {
48644        eventBus.trigger(_coreEventsEvents2['default'].ERROR, { error: 'cc', event: { message: message, id: id, cc: ccContent } });
48645    }
48646
48647    function mediaSourceError(err) {
48648        eventBus.trigger(_coreEventsEvents2['default'].ERROR, { error: 'mediasource', event: err });
48649    }
48650
48651    function mediaKeySessionError(err) {
48652        eventBus.trigger(_coreEventsEvents2['default'].ERROR, { error: 'key_session', event: err });
48653    }
48654
48655    function mediaKeyMessageError(err) {
48656        eventBus.trigger(_coreEventsEvents2['default'].ERROR, { error: 'key_message', event: err });
48657    }
48658
48659    instance = {
48660        capabilityError: capabilityError,
48661        downloadError: downloadError,
48662        manifestError: manifestError,
48663        timedTextError: timedTextError,
48664        mediaSourceError: mediaSourceError,
48665        mediaKeySessionError: mediaKeySessionError,
48666        mediaKeyMessageError: mediaKeyMessageError
48667    };
48668
48669    return instance;
48670}
48671
48672ErrorHandler.__dashjs_factory_name = 'ErrorHandler';
48673
48674var factory = _coreFactoryMaker2['default'].getSingletonFactory(ErrorHandler);
48675
48676factory.CAPABILITY_ERROR_MEDIASOURCE = CAPABILITY_ERROR_MEDIASOURCE;
48677factory.CAPABILITY_ERROR_MEDIAKEYS = CAPABILITY_ERROR_MEDIAKEYS;
48678factory.DOWNLOAD_ERROR_ID_MANIFEST = DOWNLOAD_ERROR_ID_MANIFEST;
48679factory.DOWNLOAD_ERROR_ID_SIDX = DOWNLOAD_ERROR_ID_SIDX;
48680factory.DOWNLOAD_ERROR_ID_CONTENT = DOWNLOAD_ERROR_ID_CONTENT;
48681factory.DOWNLOAD_ERROR_ID_INITIALIZATION = DOWNLOAD_ERROR_ID_INITIALIZATION;
48682factory.DOWNLOAD_ERROR_ID_XLINK = DOWNLOAD_ERROR_ID_XLINK;
48683factory.MANIFEST_ERROR_ID_CODEC = MANIFEST_ERROR_ID_CODEC;
48684factory.MANIFEST_ERROR_ID_PARSE = MANIFEST_ERROR_ID_PARSE;
48685factory.MANIFEST_ERROR_ID_NOSTREAMS = MANIFEST_ERROR_ID_NOSTREAMS;
48686factory.TIMED_TEXT_ERROR_ID_PARSE = TIMED_TEXT_ERROR_ID_PARSE;
48687
48688_coreFactoryMaker2['default'].updateSingletonFactory(ErrorHandler.__dashjs_factory_name, factory);
48689
48690exports['default'] = factory;
48691module.exports = exports['default'];
48692
48693},{"50":50,"51":51,"54":54}],196:[function(_dereq_,module,exports){
48694/**
48695 * The copyright in this software is being made available under the BSD License,
48696 * included below. This software may be subject to other third party and contributor
48697 * rights, including patent rights, and no such rights are granted under this license.
48698 *
48699 * Copyright (c) 2013, Dash Industry Forum.
48700 * All rights reserved.
48701 *
48702 * Redistribution and use in source and binary forms, with or without modification,
48703 * are permitted provided that the following conditions are met:
48704 *  * Redistributions of source code must retain the above copyright notice, this
48705 *  list of conditions and the following disclaimer.
48706 *  * Redistributions in binary form must reproduce the above copyright notice,
48707 *  this list of conditions and the following disclaimer in the documentation and/or
48708 *  other materials provided with the distribution.
48709 *  * Neither the name of Dash Industry Forum nor the names of its
48710 *  contributors may be used to endorse or promote products derived from this software
48711 *  without specific prior written permission.
48712 *
48713 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
48714 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
48715 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
48716 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
48717 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
48717INCLUDING, BUT
48718 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
48719 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
48720 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48721 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
48722 *  POSSIBILITY OF SUCH DAMAGE.
48723 */
48724
48725/**
48726 * Represents data structure to keep and drive {DataChunk}
48727 */
48728
48729'use strict';
48730
48731Object.defineProperty(exports, '__esModule', {
48732    value: true
48733});
48734
48735function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
48736
48737var _coreFactoryMaker = _dereq_(51);
48738
48739var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
48740
48741function InitCache() {
48742
48743    var data = {};
48744
48745    function save(chunk) {
48746        var id = chunk.streamId;
48747        var representationId = chunk.representationId;
48748
48749        data[id] = data[id] || {};
48750        data[id][representationId] = chunk;
48751    }
48752
48753    function extract(streamId, representationId) {
48754        if (data && data[streamId] && data[streamId][representationId]) {
48755            return data[streamId][representationId];
48756        } else {
48757            return null;
48758        }
48759    }
48760
48761    function reset() {
48762        data = {};
48763    }
48764
48765    var instance = {
48766        save: save,
48767        extract: extract,
48768        reset: reset
48769    };
48770
48771    return instance;
48772}
48773
48774InitCache.__dashjs_factory_name = 'InitCache';
48775exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(InitCache);
48776module.exports = exports['default'];
48777
48778},{"51":51}],197:[function(_dereq_,module,exports){
48779/**
48780 * The copyright in this software is being made available under the BSD License,
48781 * included below. This software may be subject to other third party and contributor
48782 * rights, including patent rights, and no such rights are granted under this license.
48783 *
48784 * Copyright (c) 2013, Dash Industry Forum.
48785 * All rights reserved.
48786 *
48787 * Redistribution and use in source and binary forms, with or without modification,
48788 * are permitted provided that the following conditions are met:
48789 *  * Redistributions of source code must retain the above copyright notice, this
48790 *  list of conditions and the following disclaimer.
48791 *  * Redistributions in binary form must reproduce the above copyright notice,
48792 *  this list of conditions and the following disclaimer in the documentation and/or
48793 *  other materials provided with the distribution.
48794 *  * Neither the name of Dash Industry Forum nor the names of its
48795 *  contributors may be used to endorse or promote products derived from this software
48796 *  without specific prior written permission.
48797 *
48798 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
48799 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
48800 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
48801 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
48802 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
48803 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
48804 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
48805 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48806 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
48807 *  POSSIBILITY OF SUCH DAMAGE.
48808 */
48809
48810'use strict';
48811
48812Object.defineProperty(exports, '__esModule', {
48813    value: true
48814});
48815
48816function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
48817
48818var _voIsoBox = _dereq_(211);
48819
48820var _voIsoBox2 = _interopRequireDefault(_voIsoBox);
48821
48822var _coreFactoryMaker = _dereq_(51);
48823
48824var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
48825
48826function IsoFile() {
48827
48828    var instance = undefined,
48829        parsedIsoFile = undefined;
48830
48831    /**
48832    * @param {string} type
48833    * @returns {IsoBox|null}
48834    * @memberof IsoFile#
48835    */
48836    function getBox(type) {
48837        if (!type || !parsedIsoFile || !parsedIsoFile.boxes || parsedIsoFile.boxes.length === 0 || typeof parsedIsoFile.fetch !== 'function') return null;
48838
48839        return convertToDashIsoBox(parsedIsoFile.fetch(type));
48840    }
48841
48842    /**
48843    * @param {string} type
48844    * @returns {Array|null} array of {@link IsoBox}
48845    * @memberof IsoFile#
48846    */
48847    function getBoxes(type) {
48848        var boxes = [];
48849
48850        if (!type || !parsedIsoFile || typeof parsedIsoFile.fetchAll !== 'function') {
48851            return boxes;
48852        }
48853
48854        var boxData = parsedIsoFile.fetchAll(type);
48855        var box = undefined;
48856
48857        for (var i = 0, ln = boxData.length; i < ln; i++) {
48858            box = convertToDashIsoBox(boxData[i]);
48859
48860            if (box) {
48861                boxes.push(box);
48862            }
48863        }
48864
48865        return boxes;
48866    }
48867
48868    /**
48869    * @param {string} value
48870    * @memberof IsoFile#
48871    */
48872    function setData(value) {
48873        parsedIsoFile = value;
48874    }
48875
48876    /**
48877    * @returns {IsoBox|null}
48878    * @memberof IsoFile#
48879    */
48880    function getLastBox() {
48881        if (!parsedIsoFile || !parsedIsoFile.boxes || !parsedIsoFile.boxes.length) return null;
48882
48883        var type = parsedIsoFile.boxes[parsedIsoFile.boxes.length - 1].type;
48884        var boxes = getBoxes(type);
48885
48886        return boxes.length > 0 ? boxes[boxes.length - 1] : null;
48887    }
48888
48889    function convertToDashIsoBox(boxData) {
48890        if (!boxData) return null;
48891
48892        var box = new _voIsoBox2['default'](boxData);
48893
48894        if (boxData.hasOwnProperty('_incomplete')) {
48895            box.isComplete = !boxData._incomplete;
48896        }
48897
48898        return box;
48899    }
48900
48901    instance = {
48902        getBox: getBox,
48903        getBoxes: getBoxes,
48904        setData: setData,
48905        getLastBox: getLastBox
48906    };
48907
48908    return instance;
48909}
48910IsoFile.__dashjs_factory_name = 'IsoFile';
48911exports['default'] = _coreFactoryMaker2['default'].getClassFactory(IsoFile);
48912module.exports = exports['default'];
48913
48914},{"211":211,"51":51}],198:[function(_dereq_,module,exports){
48915/**
48916 * The copyright in this software is being made available under the BSD License,
48917 * included below. This software may be subject to other third party and contributor
48918 * rights, including patent rights, and no such rights are granted under this license.
48919 *
48920 * Copyright (c) 2013, Dash Industry Forum.
48921 * All rights reserved.
48922 *
48923 * Redistribution and use in source and binary forms, with or without modification,
48924 * are permitted provided that the following conditions are met:
48925 *  * Redistributions of source code must retain the above copyright notice, this
48926 *  list of conditions and the following disclaimer.
48927 *  * Redistributions in binary form must reproduce the above copyright notice,
48928 *  this list of conditions and the following disclaimer in the documentation and/or
48929 *  other materials provided with the distribution.
48930 *  * Neither the name of Dash Industry Forum nor the names of its
48931 *  contributors may be used to endorse or promote products derived from this software
48932 *  without specific prior written permission.
48933 *
48934 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
48935 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
48936 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
48937 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
48938 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
48938INCLUDING, BUT
48939 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
48940 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
48941 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48942 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
48943 *  POSSIBILITY OF SUCH DAMAGE.
48944 */
48945'use strict';
48946
48947Object.defineProperty(exports, '__esModule', {
48948    value: true
48949});
48950
48951function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
48952
48953var _coreFactoryMaker = _dereq_(51);
48954
48955var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
48956
48957/**
48958 * @param {Object} config
48959 * @returns {{initialize: initialize, getLiveEdge: getLiveEdge, reset: reset}|*}
48960 * @constructor
48961 */
48962function LiveEdgeFinder(config) {
48963
48964    var instance = undefined;
48965    var timelineConverter = config.timelineConverter;
48966    var streamProcessor = config.streamProcessor;
48967
48968    function checkConfig() {
48969        if (!timelineConverter || !timelineConverter.hasOwnProperty('getExpectedLiveEdge') || !streamProcessor || !streamProcessor.hasOwnProperty('getCurrentRepresentationInfo')) {
48970            throw new Error('Missing config parameter(s)');
48971        }
48972    }
48973
48974    function getLiveEdge() {
48975        checkConfig();
48976        var representationInfo = streamProcessor.getCurrentRepresentationInfo();
48977        var liveEdge = representationInfo.DVRWindow.end;
48978        if (representationInfo.useCalculatedLiveEdgeTime) {
48979            liveEdge = timelineConverter.getExpectedLiveEdge();
48980            timelineConverter.setClientTimeOffset(liveEdge - representationInfo.DVRWindow.end);
48981        }
48982        return liveEdge;
48983    }
48984
48985    function reset() {
48986        timelineConverter = null;
48987        streamProcessor = null;
48988    }
48989
48990    instance = {
48991        getLiveEdge: getLiveEdge,
48992        reset: reset
48993    };
48994
48995    return instance;
48996}
48997
48998LiveEdgeFinder.__dashjs_factory_name = 'LiveEdgeFinder';
48999exports['default'] = _coreFactoryMaker2['default'].getClassFactory(LiveEdgeFinder);
49000module.exports = exports['default'];
49001
49002},{"51":51}],199:[function(_dereq_,module,exports){
49003/**
49004 * The copyright in this software is being made available under the BSD License,
49005 * included below. This software may be subject to other third party and contributor
49006 * rights, including patent rights, and no such rights are granted under this license.
49007 *
49008 * Copyright (c) 2013, Dash Industry Forum.
49009 * All rights reserved.
49010 *
49011 * Redistribution and use in source and binary forms, with or without modification,
49012 * are permitted provided that the following conditions are met:
49013 *  * Redistributions of source code must retain the above copyright notice, this
49014 *  list of conditions and the following disclaimer.
49015 *  * Redistributions in binary form must reproduce the above copyright notice,
49016 *  this list of conditions and the following disclaimer in the documentation and/or
49017 *  other materials provided with the distribution.
49018 *  * Neither the name of Dash Industry Forum nor the names of its
49019 *  contributors may be used to endorse or promote products derived from this software
49020 *  without specific prior written permission.
49021 *
49022 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
49023 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
49024 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49025 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
49026 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
49027 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
49028 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
49029 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49030 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49031 *  POSSIBILITY OF SUCH DAMAGE.
49032 */
49033
49034'use strict';
49035
49036Object.defineProperty(exports, '__esModule', {
49037  value: true
49038});
49039
49040function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
49041
49042var _coreFactoryMaker = _dereq_(51);
49043
49044var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
49045
49046var _deepEqual = _dereq_(13);
49047
49048var _deepEqual2 = _interopRequireDefault(_deepEqual);
49049
49050/**
49051 * @module ObjectUtils
49052 * @description Provides utility functions for objects
49053 */
49054function ObjectUtils() {
49055
49056  var instance = undefined;
49057
49058  /**
49059   * Returns true if objects are equal
49060   * @return {boolean}
49061   * @param {object} obj1
49062   * @param {object} obj2
49063   * @memberof module:ObjectUtils
49064   * @instance
49065   */
49066  function areEqual(obj1, obj2) {
49067    return (0, _deepEqual2['default'])(obj1, obj2);
49068  }
49069
49070  instance = {
49071    areEqual: areEqual
49072  };
49073
49074  return instance;
49075}
49076
49077ObjectUtils.__dashjs_factory_name = 'ObjectUtils';
49078exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(ObjectUtils);
49079module.exports = exports['default'];
49080
49081},{"13":13,"51":51}],200:[function(_dereq_,module,exports){
49082/**
49083 * The copyright in this software is being made available under the BSD License,
49084 * included below. This software may be subject to other third party and contributor
49085 * rights, including patent rights, and no such rights are granted under this license.
49086 *
49087 * Copyright (c) 2013, Dash Industry Forum.
49088 * All rights reserved.
49089 *
49090 * Redistribution and use in source and binary forms, with or without modification,
49091 * are permitted provided that the following conditions are met:
49092 *  * Redistributions of source code must retain the above copyright notice, this
49093 *  list of conditions and the following disclaimer.
49094 *  * Redistributions in binary form must reproduce the above copyright notice,
49095 *  this list of conditions and the following disclaimer in the documentation and/or
49096 *  other materials provided with the distribution.
49097 *  * Neither the name of Dash Industry Forum nor the names of its
49098 *  contributors may be used to endorse or promote products derived from this software
49099 *  without specific prior written permission.
49100 *
49101 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
49102 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
49103 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49104 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
49105 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
49106 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
49107 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
49108 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49109 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49110 *  POSSIBILITY OF SUCH DAMAGE.
49111 */
49112
49113'use strict';
49114
49115Object.defineProperty(exports, '__esModule', {
49116    value: true
49117});
49118
49119function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
49120
49121var _coreFactoryMaker = _dereq_(51);
49122
49123var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
49124
49125function RequestModifier() {
49126
49127    var instance = undefined;
49128
49129    function modifyRequestURL(url) {
49130        return url;
49131    }
49132
49133    function modifyRequestHeader(request) {
49134        return request;
49135    }
49136
49137    instance = {
49138        modifyRequestURL: modifyRequestURL,
49139        modifyRequestHeader: modifyRequestHeader
49140    };
49141
49142    return instance;
49143}
49144
49145RequestModifier.__dashjs_factory_name = 'RequestModifier';
49146exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(RequestModifier);
49147module.exports = exports['default'];
49148
49149},{"51":51}],201:[function(_dereq_,module,exports){
49150/**
49151 * The copyright in this software is being made available under the BSD License,
49152 * included below. This software may be subject to other third party and contributor
49153 * rights, including patent rights, and no such rights are granted under this license.
49154 *
49155 * Copyright (c) 2013, Dash Industry Forum.
49156 * All rights reserved.
49157 *
49158 * Redistribution and use in source and binary forms, with or without modification,
49159 * are permitted provided that the following conditions are met:
49160 *  * Redistributions of source code must retain the above copyright notice, this
49161 *  list of conditions and the following disclaimer.
49162 *  * Redistributions in binary form must reproduce the above copyright notice,
49163 *  this list of conditions and the following disclaimer in the documentation and/or
49164 *  other materials provided with the distribution.
49165 *  * Neither the name of Dash Industry Forum nor the names of its
49166 *  contributors may be used to endorse or promote products derived from this software
49167 *  without specific prior written permission.
49168 *
49169 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
49170 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
49171 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49172 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
49173 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
49173INCLUDING, BUT
49174 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
49175 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
49176 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49177 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49178 *  POSSIBILITY OF SUCH DAMAGE.
49179 */
49180'use strict';
49181
49182Object.defineProperty(exports, '__esModule', {
49183    value: true
49184});
49185
49186function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
49187
49188var _coreFactoryMaker = _dereq_(51);
49189
49190var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
49191
49192var _coreDebug = _dereq_(49);
49193
49194var _coreDebug2 = _interopRequireDefault(_coreDebug);
49195
49196var _imsc = _dereq_(21);
49197
49198function TTMLParser() {
49199
49200    var context = this.context;
49201    var log = (0, _coreDebug2['default'])(context).getInstance().log;
49202
49203    /*
49204     * This TTML parser follows "EBU-TT-D SUBTITLING DISTRIBUTION FORMAT - tech3380" spec - https://tech.ebu.ch/docs/tech/tech3380.pdf.
49205     * */
49206    var instance = undefined;
49207
49208    var cueCounter = 0; // Used to give every cue a unique ID.
49209
49210    function getCueID() {
49211        var id = 'cue_TTML_' + cueCounter;
49212        cueCounter++;
49213        return id;
49214    }
49215
49216    /**
49217     * Parse the raw data and process it to return the HTML element representing the cue.
49218     * Return the region to be processed and controlled (hide/show) by the caption controller.
49219     * @param {string} data - raw data received from the TextSourceBuffer
49220     * @param {number} offsetTime - offset time to apply to cue time
49221     * @param {integer} startTimeSegment - startTime for the current segment
49222     * @param {integer} endTimeSegment - endTime for the current segment
49223     * @param {Array} images - images array referenced by subs MP4 box
49224     */
49225    function parse(data, offsetTime, startTimeSegment, endTimeSegment, images) {
49226        var i = undefined,
49227            j = undefined;
49228
49229        var errorMsg = '';
49230        var captionArray = [];
49231        var startTime = undefined,
49232            endTime = undefined;
49233
49234        var embeddedImages = {};
49235        var currentImageId = '';
49236        var accumulated_image_data = '';
49237        var metadataHandler = {
49238
49239            onOpenTag: function onOpenTag(ns, name, attrs) {
49240                if (name === 'image' && ns === 'http://www.smpte-ra.org/schemas/2052-1/2010/smpte-tt') {
49241                    if (!attrs[' imagetype'] || attrs[' imagetype'].value !== 'PNG') {
49242                        log('Warning: smpte-tt imagetype != PNG. Discarded');
49243                        return;
49244                    }
49245                    currentImageId = attrs['http://www.w3.org/XML/1998/namespace id'].value;
49246                }
49247            },
49248
49249            onCloseTag: function onCloseTag() {
49250                if (currentImageId) {
49251                    embeddedImages[currentImageId] = accumulated_image_data.trim();
49252                }
49253                accumulated_image_data = '';
49254                currentImageId = '';
49255            },
49256
49257            onText: function onText(contents) {
49258                if (currentImageId) {
49259                    accumulated_image_data = accumulated_image_data + contents;
49260                }
49261            }
49262        };
49263
49264        if (!data) {
49265            errorMsg = 'no ttml data to parse';
49266            throw new Error(errorMsg);
49267        }
49268
49269        var imsc1doc = (0, _imsc.fromXML)(data, function (msg) {
49270            errorMsg = msg;
49271        }, metadataHandler);
49272        var mediaTimeEvents = imsc1doc.getMediaTimeEvents();
49273
49274        for (i = 0; i < mediaTimeEvents.length; i++) {
49275            var isd = (0, _imsc.generateISD)(imsc1doc, mediaTimeEvents[i], function (error) {
49276                errorMsg = error;
49277            });
49278            for (j = 0; j < isd.contents.length; j++) {
49279                if (isd.contents[j].contents.length >= 1) {
49280                    //be sure that mediaTimeEvents values are in the mp4 segment time ranges.
49281                    startTime = mediaTimeEvents[i] + offsetTime < startTimeSegment ? startTimeSegment : mediaTimeEvents[i] + offsetTime;
49282                    endTime = mediaTimeEvents[i + 1] + offsetTime > endTimeSegment ? endTimeSegment : mediaTimeEvents[i + 1] + offsetTime;
49283
49284                    captionArray.push({
49285                        start: startTime,
49286                        end: endTime,
49287                        type: 'html',
49288                        cueID: getCueID(),
49289                        isd: isd,
49290                        images: images,
49291                        embeddedImages: embeddedImages
49292                    });
49293                }
49294            }
49295        }
49296
49297        if (errorMsg !== '') {
49298            log(errorMsg);
49299        }
49300
49301        if (captionArray.length > 0) {
49302            return captionArray;
49303        } else {
49304            // This seems too strong given that there are segments with no TTML subtitles
49305            throw new Error(errorMsg);
49306        }
49307    }
49308
49309    function setup() {}
49310
49311    instance = {
49312        parse: parse
49313    };
49314
49315    setup();
49316    return instance;
49317}
49318TTMLParser.__dashjs_factory_name = 'TTMLParser';
49319exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(TTMLParser);
49320module.exports = exports['default'];
49321
49322},{"21":21,"49":49,"51":51}],202:[function(_dereq_,module,exports){
49323/**
49324 * The copyright in this software is being made available under the BSD License,
49325 * included below. This software may be subject to other third party and contributor
49326 * rights, including patent rights, and no such rights are granted under this license.
49327 *
49328 * Copyright (c) 2013, Dash Industry Forum.
49329 * All rights reserved.
49330 *
49331 * Redistribution and use in source and binary forms, with or without modification,
49332 * are permitted provided that the following conditions are met:
49333 *  * Redistributions of source code must retain the above copyright notice, this
49334 *  list of conditions and the following disclaimer.
49335 *  * Redistributions in binary form must reproduce the above copyright notice,
49336 *  this list of conditions and the following disclaimer in the documentation and/or
49337 *  other materials provided with the distribution.
49338 *  * Neither the name of Dash Industry Forum nor the names of its
49339 *  contributors may be used to endorse or promote products derived from this software
49340 *  without specific prior written permission.
49341 *
49342 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
49343 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
49344 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49345 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
49346 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
49346INCLUDING, BUT
49347 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
49348 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
49349 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49350 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49351 *  POSSIBILITY OF SUCH DAMAGE.
49352 */
49353
49354'use strict';
49355
49356Object.defineProperty(exports, '__esModule', {
49357    value: true
49358});
49359
49360function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
49361
49362var _coreFactoryMaker = _dereq_(51);
49363
49364var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
49365
49366/**
49367 * @module URLUtils
49368 * @description Provides utility functions for operating on URLs.
49369 * Initially this is simply a method to determine the Base URL of a URL, but
49370 * should probably include other things provided all over the place such as
49371 * determining whether a URL is relative/absolute, resolving two paths etc.
49372 */
49373function URLUtils() {
49374
49375    var resolveFunction = undefined;
49376
49377    var schemeRegex = /^[a-z][a-z0-9+\-.]*:/i;
49378    var httpUrlRegex = /^https?:\/\//i;
49379    var originRegex = /^([a-z][a-z0-9+\-.]*:\/\/[^\/]+)\/?/i;
49380
49381    /**
49382     * Resolves a url given an optional base url
49383     * Uses window.URL to do the resolution.
49384     *
49385     * @param {string} url
49386     * @param {string} [baseUrl]
49387     * @return {string}
49388     * @memberof module:URLUtils
49389     * @instance
49390     * @private
49391     */
49392    var nativeURLResolver = function nativeURLResolver(url, baseUrl) {
49393        try {
49394            // this will throw if baseurl is undefined, invalid etc
49395            return new window.URL(url, baseUrl).toString();
49396        } catch (e) {
49397            return url;
49398        }
49399    };
49400
49401    /**
49402     * Resolves a url given an optional base url
49403     * Does not resolve ./, ../ etc but will do enough to construct something
49404     * which will satisfy XHR etc when window.URL is not available ie
49405     * IE11/node etc.
49406     *
49407     * @param {string} url
49408     * @param {string} [baseUrl]
49409     * @return {string}
49410     * @memberof module:URLUtils
49411     * @instance
49412     * @private
49413     */
49414    var dumbURLResolver = function dumbURLResolver(url, baseUrl) {
49415        var baseUrlParseFunc = parseBaseUrl;
49416
49417        if (!baseUrl) {
49418            return url;
49419        }
49420
49421        if (!isRelative(url)) {
49422            return url;
49423        }
49424
49425        if (isPathAbsolute(url)) {
49426            baseUrlParseFunc = parseOrigin;
49427        }
49428
49429        if (isSchemeRelative(url)) {
49430            baseUrlParseFunc = parseScheme;
49431        }
49432
49433        var base = baseUrlParseFunc(baseUrl);
49434        var joinChar = base.charAt(base.length - 1) !== '/' && url.charAt(0) !== '/' ? '/' : '';
49435
49436        return [base, url].join(joinChar);
49437    };
49438
49439    function setup() {
49440        try {
49441            var u = new window.URL('x', 'http://y'); //jshint ignore:line
49442            resolveFunction = nativeURLResolver;
49443        } catch (e) {
49444            // must be IE11/Node etc
49445        } finally {
49446            resolveFunction = resolveFunction || dumbURLResolver;
49447        }
49448    }
49449
49450    /**
49451     * Returns a string that contains the Base URL of a URL, if determinable.
49452     * @param {string} url - full url
49453     * @return {string}
49454     * @memberof module:URLUtils
49455     * @instance
49456     */
49457    function parseBaseUrl(url) {
49458        var slashIndex = url.indexOf('/');
49459        var lastSlashIndex = url.lastIndexOf('/');
49460
49461        if (slashIndex !== -1) {
49462            // if there is only '//'
49463            if (lastSlashIndex === slashIndex + 1) {
49464                return url;
49465            }
49466
49467            if (url.indexOf('?') !== -1) {
49468                url = url.substring(0, url.indexOf('?'));
49469            }
49470
49471            return url.substring(0, lastSlashIndex + 1);
49472        }
49473
49474        return '';
49475    }
49476
49477    /**
49478     * Returns a string that contains the scheme and origin of a URL,
49479     * if determinable.
49480     * @param {string} url - full url
49481     * @return {string}
49482     * @memberof module:URLUtils
49483     * @instance
49484     */
49485    function parseOrigin(url) {
49486        var matches = url.match(originRegex);
49487
49488        if (matches) {
49489            return matches[1];
49490        }
49491
49492        return '';
49493    }
49494
49495    /**
49496     * Returns a string that contains the scheme of a URL, if determinable.
49497     * @param {string} url - full url
49498     * @return {string}
49499     * @memberof module:URLUtils
49500     * @instance
49501     */
49502    function parseScheme(url) {
49503        var matches = url.match(schemeRegex);
49504
49505        if (matches) {
49506            return matches[0];
49507        }
49508
49509        return '';
49510    }
49511
49512    /**
49513     * Determines whether the url is relative.
49514     * @return {bool}
49515     * @param {string} url
49516     * @memberof module:URLUtils
49517     * @instance
49518     */
49519    function isRelative(url) {
49520        return !schemeRegex.test(url);
49521    }
49522
49523    /**
49524     * Determines whether the url is path-absolute.
49525     * @return {bool}
49526     * @param {string} url
49527     * @memberof module:URLUtils
49528     * @instance
49529     */
49530    function isPathAbsolute(url) {
49531        return isRelative(url) && url.charAt(0) === '/';
49532    }
49533
49534    /**
49535     * Determines whether the url is scheme-relative.
49536     * @return {bool}
49537     * @param {string} url
49538     * @memberof module:URLUtils
49539     * @instance
49540     */
49541    function isSchemeRelative(url) {
49542        return url.indexOf('//') === 0;
49543    }
49544
49545    /**
49546     * Determines whether the url is an HTTP-URL as defined in ISO/IEC
49547     * 23009-1:2014 3.1.15. ie URL with a fixed scheme of http or https
49548     * @return {bool}
49549     * @param {string} url
49550     * @memberof module:URLUtils
49551     * @instance
49552     */
49553    function isHTTPURL(url) {
49554        return httpUrlRegex.test(url);
49555    }
49556
49557    /**
49558     * Resolves a url given an optional base url
49559     * @return {string}
49560     * @param {string} url
49561     * @param {string} [baseUrl]
49562     * @memberof module:URLUtils
49563     * @instance
49564     */
49565    function resolve(url, baseUrl) {
49566        return resolveFunction(url, baseUrl);
49567    }
49568
49569    setup();
49570
49571    var instance = {
49572        parseBaseUrl: parseBaseUrl,
49573        parseOrigin: parseOrigin,
49574        parseScheme: parseScheme,
49575        isRelative: isRelative,
49576        isPathAbsolute: isPathAbsolute,
49577        isSchemeRelative: isSchemeRelative,
49578        isHTTPURL: isHTTPURL,
49579        resolve: resolve
49580    };
49581
49582    return instance;
49583}
49584
49585URLUtils.__dashjs_factory_name = 'URLUtils';
49586exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(URLUtils);
49587module.exports = exports['default'];
49588
49589},{"51":51}],203:[function(_dereq_,module,exports){
49590/**
49591 * The copyright in this software is being made available under the BSD License,
49592 * included below. This software may be subject to other third party and contributor
49593 * rights, including patent rights, and no such rights are granted under this license.
49594 *
49595 * Copyright (c) 2013, Dash Industry Forum.
49596 * All rights reserved.
49597 *
49598 * Redistribution and use in source and binary forms, with or without modification,
49599 * are permitted provided that the following conditions are met:
49600 *  * Redistributions of source code must retain the above copyright notice, this
49601 *  list of conditions and the following disclaimer.
49602 *  * Redistributions in binary form must reproduce the above copyright notice,
49603 *  this list of conditions and the following disclaimer in the documentation and/or
49604 *  other materials provided with the distribution.
49605 *  * Neither the name of Dash Industry Forum nor the names of its
49606 *  contributors may be used to endorse or promote products derived from this software
49607 *  without specific prior written permission.
49608 *
49609 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
49610 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
49611 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49612 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
49613 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
49613INCLUDING, BUT
49614 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
49615 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
49616 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49617 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49618 *  POSSIBILITY OF SUCH DAMAGE.
49619 */
49620'use strict';
49621
49622Object.defineProperty(exports, '__esModule', {
49623    value: true
49624});
49625
49626function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
49627
49628var _coreFactoryMaker = _dereq_(51);
49629
49630var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
49631
49632var _coreDebug = _dereq_(49);
49633
49634var _coreDebug2 = _interopRequireDefault(_coreDebug);
49635
49636var WEBVTT = 'WEBVTT';
49637
49638function VTTParser() {
49639    var context = this.context;
49640    var log = (0, _coreDebug2['default'])(context).getInstance().log;
49641
49642    var instance = undefined,
49643        regExNewLine = undefined,
49644        regExToken = undefined,
49645        regExWhiteSpace = undefined,
49646        regExWhiteSpaceWordBoundary = undefined;
49647
49648    function setup() {
49649        regExNewLine = /(?:\r\n|\r|\n)/gm;
49650        regExToken = /-->/;
49651        regExWhiteSpace = /(^[\s]+|[\s]+$)/g;
49652        regExWhiteSpaceWordBoundary = /\s\b/g;
49653    }
49654
49655    function parse(data) {
49656        var captionArray = [];
49657        var len = undefined,
49658            lastStartTime = undefined;
49659
49660        if (!data) {
49661            return captionArray;
49662        }
49663
49664        data = data.split(regExNewLine);
49665        len = data.length;
49666        lastStartTime = -1;
49667
49668        for (var i = 0; i < len; i++) {
49669            var item = data[i];
49670
49671            if (item.length > 0 && item !== WEBVTT) {
49672                if (item.match(regExToken)) {
49673                    var attributes = parseItemAttributes(item);
49674                    var cuePoints = attributes.cuePoints;
49675                    var styles = attributes.styles;
49676                    var text = getSublines(data, i + 1);
49677                    var startTime = convertCuePointTimes(cuePoints[0].replace(regExWhiteSpace, ''));
49678                    var endTime = convertCuePointTimes(cuePoints[1].replace(regExWhiteSpace, ''));
49679
49680                    if (!isNaN(startTime) && !isNaN(endTime) && startTime >= lastStartTime && endTime > startTime) {
49681                        if (text !== '') {
49682                            lastStartTime = startTime;
49683                            //TODO Make VO external so other parsers can use.
49684                            captionArray.push({
49685                                start: startTime,
49686                                end: endTime,
49687                                data: text,
49688                                styles: styles
49689                            });
49690                        } else {
49691                            log('Skipping cue due to empty/malformed cue text');
49692                        }
49693                    } else {
49694                        log('Skipping cue due to incorrect cue timing');
49695                    }
49696                }
49697            }
49698        }
49699
49700        return captionArray;
49701    }
49702
49703    function convertCuePointTimes(time) {
49704        var timeArray = time.split(':');
49705        var len = timeArray.length - 1;
49706
49707        time = parseInt(timeArray[len - 1], 10) * 60 + parseFloat(timeArray[len]);
49708
49709        if (len === 2) {
49710            time += parseInt(timeArray[0], 10) * 3600;
49711        }
49712
49713        return time;
49714    }
49715
49716    function parseItemAttributes(data) {
49717        var vttCuePoints = data.split(regExToken);
49718        var arr = vttCuePoints[1].split(regExWhiteSpaceWordBoundary);
49719        arr.shift(); //remove first array index it is empty...
49720        vttCuePoints[1] = arr[0];
49721        arr.shift();
49722        return { cuePoints: vttCuePoints, styles: getCaptionStyles(arr) };
49723    }
49724
49725    function getCaptionStyles(arr) {
49726        var styleObject = {};
49727        arr.forEach(function (element) {
49728            if (element.split(/:/).length > 1) {
49729                var val = element.split(/:/)[1];
49730                if (val && val.search(/%/) != -1) {
49731                    val = parseInt(val.replace(/%/, ''), 10);
49732                }
49733                if (element.match(/align/) || element.match(/A/)) {
49734                    styleObject.align = val;
49735                }
49736                if (element.match(/line/) || element.match(/L/)) {
49737                    styleObject.line = val;
49738                }
49739                if (element.match(/position/) || element.match(/P/)) {
49740                    styleObject.position = val;
49741                }
49742                if (element.match(/size/) || element.match(/S/)) {
49743                    styleObject.size = val;
49744                }
49745            }
49746        });
49747
49748        return styleObject;
49749    }
49750
49751    /*
49752    * VTT can have multiple lines to display per cuepoint.
49753    */
49754    function getSublines(data, idx) {
49755        var i = idx;
49756
49757        var subline = '';
49758        var lineData = '';
49759        var lineCount = undefined;
49760
49761        while (data[i] !== '' && i < data.length) {
49762            i++;
49763        }
49764
49765        lineCount = i - idx;
49766        if (lineCount > 1) {
49767            for (var j = 0; j < lineCount; j++) {
49768                lineData = data[idx + j];
49769                if (!lineData.match(regExToken)) {
49770                    subline += lineData;
49771                    if (j !== lineCount - 1) {
49772                        subline += '\n';
49773                    }
49774                } else {
49775                    // caption text should not have '-->' in it
49776                    subline = '';
49777                    break;
49778                }
49779            }
49780        } else {
49781            lineData = data[idx];
49782            if (!lineData.match(regExToken)) subline = lineData;
49783        }
49784        return subline;
49785    }
49786
49787    instance = {
49788        parse: parse
49789    };
49790
49791    setup();
49792    return instance;
49793}
49794VTTParser.__dashjs_factory_name = 'VTTParser';
49795exports['default'] = _coreFactoryMaker2['default'].getSingletonFactory(VTTParser);
49796module.exports = exports['default'];
49797
49798},{"49":49,"51":51}],204:[function(_dereq_,module,exports){
49799/**
49800 * The copyright in this software is being made available under the BSD License,
49801 * included below. This software may be subject to other third party and contributor
49802 * rights, including patent rights, and no such rights are granted under this license.
49803 *
49804 * Copyright (c) 2013, Dash Industry Forum.
49805 * All rights reserved.
49806 *
49807 * Redistribution and use in source and binary forms, with or without modification,
49808 * are permitted provided that the following conditions are met:
49809 *  * Redistributions of source code must retain the above copyright notice, this
49810 *  list of conditions and the following disclaimer.
49811 *  * Redistributions in binary form must reproduce the above copyright notice,
49812 *  this list of conditions and the following disclaimer in the documentation and/or
49813 *  other materials provided with the distribution.
49814 *  * Neither the name of Dash Industry Forum nor the names of its
49815 *  contributors may be used to endorse or promote products derived from this software
49816 *  without specific prior written permission.
49817 *
49818 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
49819 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
49820 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49821 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
49822 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
49822INCLUDING, BUT
49823 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
49824 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
49825 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49826 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49827 *  POSSIBILITY OF SUCH DAMAGE.
49828 */
49829
49830'use strict';
49831
49832Object.defineProperty(exports, '__esModule', {
49833    value: true
49834});
49835
49836function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
49837
49838var _coreFactoryMaker = _dereq_(51);
49839
49840var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
49841
49842function BasicSelector(config) {
49843
49844    var instance = undefined;
49845
49846    var blacklistController = config.blacklistController;
49847
49848    function select(baseUrls) {
49849        var index = 0;
49850        var selectedBaseUrl = undefined;
49851
49852        if (baseUrls && baseUrls.some(function (baseUrl, idx) {
49853            index = idx;
49854
49855            return !blacklistController.contains(baseUrl.serviceLocation);
49856        })) {
49857            selectedBaseUrl = baseUrls[index];
49858        }
49859
49860        return selectedBaseUrl;
49861    }
49862
49863    instance = {
49864        select: select
49865    };
49866
49867    return instance;
49868}
49869
49870BasicSelector.__dashjs_factory_name = 'BasicSelector';
49871exports['default'] = _coreFactoryMaker2['default'].getClassFactory(BasicSelector);
49872module.exports = exports['default'];
49873
49874},{"51":51}],205:[function(_dereq_,module,exports){
49875/**
49876 * The copyright in this software is being made available under the BSD License,
49877 * included below. This software may be subject to other third party and contributor
49878 * rights, including patent rights, and no such rights are granted under this license.
49879 *
49880 * Copyright (c) 2013, Dash Industry Forum.
49881 * All rights reserved.
49882 *
49883 * Redistribution and use in source and binary forms, with or without modification,
49884 * are permitted provided that the following conditions are met:
49885 *  * Redistributions of source code must retain the above copyright notice, this
49886 *  list of conditions and the following disclaimer.
49887 *  * Redistributions in binary form must reproduce the above copyright notice,
49888 *  this list of conditions and the following disclaimer in the documentation and/or
49889 *  other materials provided with the distribution.
49890 *  * Neither the name of Dash Industry Forum nor the names of its
49891 *  contributors may be used to endorse or promote products derived from this software
49892 *  without specific prior written permission.
49893 *
49894 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
49895 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
49896 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49897 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
49898 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
49899 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
49900 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
49901 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49902 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49903 *  POSSIBILITY OF SUCH DAMAGE.
49904 */
49905'use strict';
49906
49907Object.defineProperty(exports, '__esModule', {
49908    value: true
49909});
49910
49911function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
49912
49913var _coreFactoryMaker = _dereq_(51);
49914
49915var _coreFactoryMaker2 = _interopRequireDefault(_coreFactoryMaker);
49916
49917function DVBSelector(config) {
49918
49919    var instance = undefined;
49920
49921    var blacklistController = config.blacklistController;
49922
49923    function getNonBlacklistedBaseUrls(urls) {
49924        var removedPriorities = [];
49925
49926        var samePrioritiesFilter = function samePrioritiesFilter(el) {
49927            if (removedPriorities.length) {
49928                if (el.dvb_priority && removedPriorities.indexOf(el.dvb_priority) !== -1) {
49929                    return false;
49930                }
49931            }
49932
49933            return true;
49934        };
49935
49936        var serviceLocationFilter = function serviceLocationFilter(baseUrl) {
49937            if (blacklistController.contains(baseUrl.serviceLocation)) {
49938                // whenever a BaseURL is removed from the available list of
49939                // BaseURLs, any other BaseURL with the same @priority
49940                // value as the BaseURL being removed shall also be removed
49941                if (baseUrl.dvb_priority) {
49942                    removedPriorities.push(baseUrl.dvb_priority);
49943                }
49944
49945                // all URLs in the list which have a @serviceLocation
vendor: 4,500 bytes, lines 49946-50050
49946                // attribute matching an entry in the blacklist shall be
49947                // removed from the available list of BaseURLs
49948                return false;
49949            }
49950
49951            return true;
49952        };
49953
49954        return urls.filter(serviceLocationFilter).filter(samePrioritiesFilter);
49955    }
49956
49957    function selectByWeight(availableUrls) {
49958        var prioritySorter = function prioritySorter(a, b) {
49959            var diff = a.dvb_priority - b.dvb_priority;
49960            return isNaN(diff) ? 0 : diff;
49961        };
49962
49963        var topPriorityFilter = function topPriorityFilter(baseUrl, idx, arr) {
49964            return !idx || arr[0].dvb_priority && baseUrl.dvb_priority && arr[0].dvb_priority === baseUrl.dvb_priority;
49965        };
49966
49967        var totalWeight = 0;
49968        var cumulWeights = [];
49969        var idx = 0;
49970        var rn = undefined,
49971            urls = undefined;
49972
49973        // It shall begin by taking the set of resolved BaseURLs present or inherited at the current
49974        // position in the MPD, resolved and filtered as described in 10.8.2.1, that have the lowest
49975        // @priority attribute value.
49976        urls = availableUrls.sort(prioritySorter).filter(topPriorityFilter);
49977
49978        if (urls.length) {
49979            if (urls.length > 1) {
49980                // If there is more than one BaseURL with this lowest @priority attribute value then the Player
49981                // shall select one of them at random such that the probability of each BaseURL being chosen
49982                // is proportional to the value of its @weight attribute. The method described in RFC 2782
49983                // [26] or picking from a number of weighted entries is suitable for this, but there may be other
49984                // algorithms which achieve the same effect.
49985
49986                // add all the weights together, storing the accumulated weight per entry
49987                urls.forEach(function (baseUrl) {
49988                    totalWeight += baseUrl.dvb_weight;
49989                    cumulWeights.push(totalWeight);
49990                });
49991
49992                // pick a random number between zero and totalWeight
49993                rn = Math.floor(Math.random() * (totalWeight - 1));
49994
49995                // select the index for the range rn falls within
49996                cumulWeights.every(function (limit, index) {
49997                    idx = index;
49998
49999                    if (rn < limit) {
50000                        return false;
50001                    }
50002
50003                    return true;
50004                });
50005            }
50006
50007            return urls[idx];
50008        }
50009    }
50010
50011    function select(baseUrls) {
50012        return baseUrls && selectByWeight(getNonBlacklistedBaseUrls(baseUrls));
50013    }
50014
50015    instance = {
50016        select: select
50017    };
50018
50019    return instance;
50020}
50021
50022DVBSelector.__dashjs_factory_name = 'DVBSelector';
50023exports['default'] = _coreFactoryMaker2['default'].getClassFactory(DVBSelector);
50024module.exports = exports['default'];
50025
50026},{"51":51}],206:[function(_dereq_,module,exports){
50027/**
50028 * The copyright in this software is being made available under the BSD License,
50029 * included below. This software may be subject to other third party and contributor
50030 * rights, including patent rights, and no such rights are granted under this license.
50031 *
50032 * Copyright (c) 2013, Dash Industry Forum.
50033 * All rights reserved.
50034 *
50035 * Redistribution and use in source and binary forms, with or without modification,
50036 * are permitted provided that the following conditions are met:
50037 *  * Redistributions of source code must retain the above copyright notice, this
50038 *  list of conditions and the following disclaimer.
50039 *  * Redistributions in binary form must reproduce the above copyright notice,
50040 *  this list of conditions and the following disclaimer in the documentation and/or
50041 *  other materials provided with the distribution.
50042 *  * Neither the name of Dash Industry Forum nor the names of its
50043 *  contributors may be used to endorse or promote products derived from this software
50044 *  without specific prior written permission.
50045 *
50046 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
50047 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
50048 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
50049 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
50050 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
50050INCLUDING, BUT
50051 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
50052 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
50053 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50054 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
50055 *  POSSIBILITY OF SUCH DAMAGE.
50056 */
50057/**
50058 * @class
50059 * @ignore
50060 */
50061"use strict";
50062
50063Object.defineProperty(exports, "__esModule", {
50064  value: true
50065});
50066
50067function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
50068
50069var BitrateInfo = function BitrateInfo() {
50070  _classCallCheck(this, BitrateInfo);
50071
50072  this.mediaType = null;
50073  this.bitrate = null;
50074  this.width = null;
50075  this.height = null;
50076  this.scanType = null;
50077  this.qualityIndex = NaN;
50078};
50079
50080exports["default"] = BitrateInfo;
50081module.exports = exports["default"];
50082
50083},{}],207:[function(_dereq_,module,exports){
50084/**
50085 * The copyright in this software is being made available under the BSD License,
50086 * included below. This software may be subject to other third party and contributor
50087 * rights, including patent rights, and no such rights are granted under this license.
50088 *
50089 * Copyright (c) 2013, Dash Industry Forum.
50090 * All rights reserved.
50091 *
50092 * Redistribution and use in source and binary forms, with or without modification,
50093 * are permitted provided that the following conditions are met:
50094 *  * Redistributions of source code must retain the above copyright notice, this
50095 *  list of conditions and the following disclaimer.
50096 *  * Redistributions in binary form must reproduce the above copyright notice,
50097 *  this list of conditions and the following disclaimer in the documentation and/or
50098 *  other materials provided with the distribution.
50099 *  * Neither the name of Dash Industry Forum nor the names of its
50100 *  contributors may be used to endorse or promote products derived from this software
50101 *  without specific prior written permission.
50102 *
50103 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
50104 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
50105 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
50106 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
50107 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
50108 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
50109 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
50110 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50111 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
50112 *  POSSIBILITY OF SUCH DAMAGE.
50113 */
50114/**
50115 * @class
50116 * @ignore
50117 */
50118"use strict";
50119
50120Object.defineProperty(exports, "__esModule", {
50121  value: true
50122});
50123
50124function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
50125
50126var DashJSError = function DashJSError(code, message, data) {
50127  _classCallCheck(this, DashJSError);
50128
50129  this.code = code || null;
50130  this.message = message || null;
50131  this.data = data || null;
50132};
50133
50134exports["default"] = DashJSError;
50135module.exports = exports["default"];
50136
50137},{}],208:[function(_dereq_,module,exports){
50138/**
50139 * The copyright in this software is being made available under the BSD License,
50140 * included below. This software may be subject to other third party and contributor
50141 * rights, including patent rights, and no such rights are granted under this license.
50142 *
50143 * Copyright (c) 2013, Dash Industry Forum.
50144 * All rights reserved.
50145 *
50146 * Redistribution and use in source and binary forms, with or without modification,
50147 * are permitted provided that the following conditions are met:
50148 *  * Redistributions of source code must retain the above copyright notice, this
50149 *  list of conditions and the following disclaimer.
50150 *  * Redistributions in binary form must reproduce the above copyright notice,
50151 *  this list of conditions and the following disclaimer in the documentation and/or
50152 *  other materials provided with the distribution.
50153 *  * Neither the name of Dash Industry Forum nor the names of its
50154 *  contributors may be used to endorse or promote products derived from this software
50155 *  without specific prior written permission.
50156 *
50157 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
50158 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
50159 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
50160 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
50161 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
50161INCLUDING, BUT
50162 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
50163 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
50164 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50165 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
50166 *  POSSIBILITY OF SUCH DAMAGE.
50167 */
50168
50169/**
50170 * @class
50171 * @ignore
50172 */
50173"use strict";
50174
50175Object.defineProperty(exports, "__esModule", {
50176  value: true
50177});
50178
50179function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
50180
50181var DataChunk =
50182//Represents a data structure that keep all the necessary info about a single init/media segment
50183function DataChunk() {
50184  _classCallCheck(this, DataChunk);
50185
50186  this.streamId = null;
50187  this.mediaInfo = null;
50188  this.segmentType = null;
50189  this.quality = NaN;
50190  this.index = NaN;
50191  this.bytes = null;
50192  this.start = NaN;
50193  this.end = NaN;
50194  this.duration = NaN;
50195  this.representationId = null;
50196};
50197
50198exports["default"] = DataChunk;
50199module.exports = exports["default"];
50200
50201},{}],209:[function(_dereq_,module,exports){
50202/**
50203 * The copyright in this software is being made available under the BSD License,
50204 * included below. This software may be subject to other third party and contributor
50205 * rights, including patent rights, and no such rights are granted under this license.
50206 *
50207 * Copyright (c) 2013, Dash Industry Forum.
50208 * All rights reserved.
50209 *
50210 * Redistribution and use in source and binary forms, with or without modification,
50211 * are permitted provided that the following conditions are met:
50212 *  * Redistributions of source code must retain the above copyright notice, this
50213 *  list of conditions and the following disclaimer.
50214 *  * Redistributions in binary form must reproduce the above copyright notice,
50215 *  this list of conditions and the following disclaimer in the documentation and/or
50216 *  other materials provided with the distribution.
50217 *  * Neither the name of Dash Industry Forum nor the names of its
50218 *  contributors may be used to endorse or promote products derived from this software
50219 *  without specific prior written permission.
50220 *
50221 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
50222 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
50223 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
50224 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
50225 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
50226 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
50227 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
50228 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50229 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
50230 *  POSSIBILITY OF SUCH DAMAGE.
50231 */
50232/**
50233 * @class
50234 * @ignore
50235 */
50236'use strict';
50237
50238Object.defineProperty(exports, '__esModule', {
50239  value: true
50240});
50241
50242function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
50243
50244var FragmentRequest = function FragmentRequest() {
50245  _classCallCheck(this, FragmentRequest);
50246
50247  this.action = FragmentRequest.ACTION_DOWNLOAD;
50248  this.startTime = NaN;
50249  this.mediaType = null;
50250  this.mediaInfo = null;
50251  this.type = null;
50252  this.duration = NaN;
50253  this.timescale = NaN;
50254  this.range = null;
50255  this.url = null;
50256  this.serviceLocation = null;
50257  this.requestStartDate = null;
50258  this.firstByteDate = null;
50259  this.requestEndDate = null;
50260  this.quality = NaN;
50261  this.index = NaN;
50262  this.availabilityStartTime = null;
50263  this.availabilityEndTime = null;
50264  this.wallStartTime = null;
50265  this.bytesLoaded = NaN;
50266  this.bytesTotal = NaN;
50267  this.delayLoadingTime = NaN;
50268  this.responseType = 'arraybuffer';
50269  this.representationId = null;
50270};
50271
50272FragmentRequest.ACTION_DOWNLOAD = 'download';
50273FragmentRequest.ACTION_COMPLETE = 'complete';
50274
50275exports['default'] = FragmentRequest;
50276module.exports = exports['default'];
50277
50278},{}],210:[function(_dereq_,module,exports){
50279/**
50280 * The copyright in this software is being made available under the BSD License,
50281 * included below. This software may be subject to other third party and contributor
50282 * rights, including patent rights, and no such rights are granted under this license.
50283 *
50284 * Copyright (c) 2013, Dash Industry Forum.
50285 * All rights reserved.
50286 *
50287 * Redistribution and use in source and binary forms, with or without modification,
50288 * are permitted provided that the following conditions are met:
50289 *  * Redistributions of source code must retain the above copyright notice, this
50290 *  list of conditions and the following disclaimer.
50291 *  * Redistributions in binary form must reproduce the above copyright notice,
50292 *  this list of conditions and the following disclaimer in the documentation and/or
50293 *  other materials provided with the distribution.
50294 *  * Neither the name of Dash Industry Forum nor the names of its
50295 *  contributors may be used to endorse or promote products derived from this software
50296 *  without specific prior written permission.
50297 *
50298 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
50299 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
50300 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
50301 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
50302 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
50302INCLUDING, BUT
50303 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
50304 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
50305 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50306 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
50307 *  POSSIBILITY OF SUCH DAMAGE.
50308 */
50309/**
50310 * @class
50311 * @ignore
50312 */
50313'use strict';
50314
50315Object.defineProperty(exports, '__esModule', {
50316  value: true
50317});
50318
50319var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
50320
50321function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
50322
50323function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
50324
50325function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
50326
50327var _FragmentRequest2 = _dereq_(209);
50328
50329var _FragmentRequest3 = _interopRequireDefault(_FragmentRequest2);
50330
50331var HeadRequest = (function (_FragmentRequest) {
50332  _inherits(HeadRequest, _FragmentRequest);
50333
50334  function HeadRequest(url) {
50335    _classCallCheck(this, HeadRequest);
50336
50337    _get(Object.getPrototypeOf(HeadRequest.prototype), 'constructor', this).call(this);
50338    this.url = url || null;
50339    this.checkForExistenceOnly = true;
50340  }
50341
50342  return HeadRequest;
50343})(_FragmentRequest3['default']);
50344
50345exports['default'] = HeadRequest;
50346module.exports = exports['default'];
50347
50348},{"209":209}],211:[function(_dereq_,module,exports){
50349/**
50350 * The copyright in this software is being made available under the BSD License,
50351 * included below. This software may be subject to other third party and contributor
50352 * rights, including patent rights, and no such rights are granted under this license.
50353 *
50354 * Copyright (c) 2013, Dash Industry Forum.
50355 * All rights reserved.
50356 *
50357 * Redistribution and use in source and binary forms, with or without modification,
50358 * are permitted provided that the following conditions are met:
50359 *  * Redistributions of source code must retain the above copyright notice, this
50360 *  list of conditions and the following disclaimer.
50361 *  * Redistributions in binary form must reproduce the above copyright notice,
50362 *  this list of conditions and the following disclaimer in the documentation and/or
50363 *  other materials provided with the distribution.
50364 *  * Neither the name of Dash Industry Forum nor the names of its
50365 *  contributors may be used to endorse or promote products derived from this software
50366 *  without specific prior written permission.
50367 *
50368 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
50369 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
50370 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
50371 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
50372 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
50373 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
50374 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
50375 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50376 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
50377 *  POSSIBILITY OF SUCH DAMAGE.
50378 */
50379/**
50380 * @class
50381 * @ignore
50382 */
50383'use strict';
50384
50385Object.defineProperty(exports, '__esModule', {
50386    value: true
50387});
50388
50389var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
vendor: 4,258 bytes, lines 50390-50484
50390
50391function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
50392
50393var IsoBox = (function () {
50394    function IsoBox(boxData) {
50395        _classCallCheck(this, IsoBox);
50396
50397        this.offset = boxData._offset;
50398        this.type = boxData.type;
50399        this.size = boxData.size;
50400        this.boxes = [];
50401        if (boxData.boxes) {
50402            for (var i = 0; i < boxData.boxes.length; i++) {
50403                this.boxes.push(new IsoBox(boxData.boxes[i]));
50404            }
50405        }
50406        this.isComplete = true;
50407
50408        switch (boxData.type) {
50409            case 'sidx':
50410                this.timescale = boxData.timescale;
50411                this.earliest_presentation_time = boxData.earliest_presentation_time;
50412                this.first_offset = boxData.first_offset;
50413                this.references = boxData.references;
50414                if (boxData.references) {
50415                    this.references = [];
50416                    for (var i = 0; i < boxData.references.length; i++) {
50417                        var reference = {
50418                            reference_type: boxData.references[i].reference_type,
50419                            referenced_size: boxData.references[i].referenced_size,
50420                            subsegment_duration: boxData.references[i].subsegment_duration
50421                        };
50422                        this.references.push(reference);
50423                    }
50424                }
50425                break;
50426            case 'emsg':
50427                this.id = boxData.id;
50428                this.value = boxData.value;
50429                this.timescale = boxData.timescale;
50430                this.scheme_id_uri = boxData.scheme_id_uri;
50431                this.presentation_time_delta = boxData.presentation_time_delta;
50432                this.event_duration = boxData.event_duration;
50433                this.message_data = boxData.message_data;
50434                break;
50435            case 'mdhd':
50436                this.timescale = boxData.timescale;
50437                break;
50438            case 'mfhd':
50439                this.sequence_number = boxData.sequence_number;
50440                break;
50441            case 'subs':
50442                this.entry_count = boxData.entry_count;
50443                this.entries = boxData.entries;
50444                break;
50445            case 'tfhd':
50446                this.base_data_offset = boxData.base_data_offset;
50447                this.sample_description_index = boxData.sample_description_index;
50448                this.default_sample_duration = boxData.default_sample_duration;
50449                this.default_sample_size = boxData.default_sample_size;
50450                this.default_sample_flags = boxData.default_sample_flags;
50451                this.flags = boxData.flags;
50452                break;
50453            case 'tfdt':
50454                this.version = boxData.version;
50455                this.baseMediaDecodeTime = boxData.baseMediaDecodeTime;
50456                this.flags = boxData.flags;
50457                break;
50458            case 'trun':
50459                this.sample_count = boxData.sample_count;
50460                this.first_sample_flags = boxData.first_sample_flags;
50461                this.data_offset = boxData.data_offset;
50462                this.flags = boxData.flags;
50463                this.samples = boxData.samples;
50464                if (boxData.samples) {
50465                    this.samples = [];
50466                    for (var i = 0, ln = boxData.samples.length; i < ln; i++) {
50467                        var sample = {
50468                            sample_size: boxData.samples[i].sample_size,
50469                            sample_duration: boxData.samples[i].sample_duration,
50470                            sample_composition_time_offset: boxData.samples[i].sample_composition_time_offset
50471                        };
50472                        this.samples.push(sample);
50473                    }
50474                }
50475                break;
50476        }
50477    }
50478
50479    _createClass(IsoBox, [{
50480        key: 'getChildBox',
50481        value: function getChildBox(type) {
50482            for (var i = 0; i < this.boxes.length; i++) {
50483                if (this.boxes[i].type === type) {
50484                    return this.boxes[i];
50485                }
50486            }
50487        }
50488    }, {
50489        key: 'getChildBoxes',
50490        value: function getChildBoxes(type) {
50491            var boxes = [];
50492            for (var i = 0; i < this.boxes.length; i++) {
50493                if (this.boxes[i].type === type) {
50494                    boxes.push(this.boxes[i]);
50495                }
50496            }
50497            return boxes;
50498        }
50499    }]);
50500
50501    return IsoBox;
50502})();
50503
50504exports['default'] = IsoBox;
50505module.exports = exports['default'];
50506
50507},{}],212:[function(_dereq_,module,exports){
50508/**
50509 * The copyright in this software is being made available under the BSD License,
50510 * included below. This software may be subject to other third party and contributor
50511 * rights, including patent rights, and no such rights are granted under this license.
50512 *
50513 * Copyright (c) 2013, Dash Industry Forum.
50514 * All rights reserved.
50515 *
50516 * Redistribution and use in source and binary forms, with or without modification,
50517 * are permitted provided that the following conditions are met:
50518 *  * Redistributions of source code must retain the above copyright notice, this
50519 *  list of conditions and the following disclaimer.
50520 *  * Redistributions in binary form must reproduce the above copyright notice,
50521 *  this list of conditions and the following disclaimer in the documentation and/or
50522 *  other materials provided with the distribution.
50523 *  * Neither the name of Dash Industry Forum nor the names of its
50524 *  contributors may be used to endorse or promote products derived from this software
50525 *  without specific prior written permission.
50526 *
50527 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
50528 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
50529 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
50530 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
50531 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
50532 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
50533 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
50534 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50535 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
50536 *  POSSIBILITY OF SUCH DAMAGE.
50537 */
50538/**
50539 * @class
50540 * @ignore
50541 */
50542"use strict";
50543
50544Object.defineProperty(exports, "__esModule", {
50545  value: true
50546});
50547
50548function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
50549
50550var ManifestInfo = function ManifestInfo() {
50551  _classCallCheck(this, ManifestInfo);
50552
50553  this.DVRWindowSize = NaN;
50554  this.loadedTime = null;
50555  this.availableFrom = null;
50556  this.minBufferTime = NaN;
50557  this.duration = NaN;
50558  this.isDynamic = false;
50559  this.maxFragmentDuration = null;
50560};
50561
50562exports["default"] = ManifestInfo;
50563module.exports = exports["default"];
50564
50565},{}],213:[function(_dereq_,module,exports){
50566/**
50567 * The copyright in this software is being made available under the BSD License,
50568 * included below. This software may be subject to other third party and contributor
50569 * rights, including patent rights, and no such rights are granted under this license.
50570 *
50571 * Copyright (c) 2013, Dash Industry Forum.
50572 * All rights reserved.
50573 *
50574 * Redistribution and use in source and binary forms, with or without modification,
50575 * are permitted provided that the following conditions are met:
50576 *  * Redistributions of source code must retain the above copyright notice, this
50577 *  list of conditions and the following disclaimer.
50578 *  * Redistributions in binary form must reproduce the above copyright notice,
50579 *  this list of conditions and the following disclaimer in the documentation and/or
50580 *  other materials provided with the distribution.
50581 *  * Neither the name of Dash Industry Forum nor the names of its
50582 *  contributors may be used to endorse or promote products derived from this software
50583 *  without specific prior written permission.
50584 *
50585 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
50586 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
50587 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
50588 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
50589 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
50589INCLUDING, BUT
50590 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
50591 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
50592 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50593 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
50594 *  POSSIBILITY OF SUCH DAMAGE.
50595 */
50596/**
50597 * @class
50598 * @ignore
50599 */
50600"use strict";
50601
50602Object.defineProperty(exports, "__esModule", {
50603  value: true
50604});
50605
50606function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
50607
50608var MediaInfo = function MediaInfo() {
50609  _classCallCheck(this, MediaInfo);
50610
50611  this.id = null;
50612  this.index = null;
50613  this.type = null;
50614  this.streamInfo = null;
50615  this.representationCount = 0;
50616  this.lang = null;
50617  this.viewpoint = null;
50618  this.accessibility = null;
50619  this.audioChannelConfiguration = null;
50620  this.roles = null;
50621  this.codec = null;
50622  this.mimeType = null;
50623  this.contentProtection = null;
50624  this.isText = false;
50625  this.KID = null;
50626  this.bitrateList = null;
50627};
50628
50629exports["default"] = MediaInfo;
50630module.exports = exports["default"];
50631
50632},{}],214:[function(_dereq_,module,exports){
50633/**
50634 * The copyright in this software is being made available under the BSD License,
50635 * included below. This software may be subject to other third party and contributor
50636 * rights, including patent rights, and no such rights are granted under this license.
50637 *
50638 * Copyright (c) 2013, Dash Industry Forum.
50639 * All rights reserved.
50640 *
50641 * Redistribution and use in source and binary forms, with or without modification,
50642 * are permitted provided that the following conditions are met:
50643 *  * Redistributions of source code must retain the above copyright notice, this
50644 *  list of conditions and the following disclaimer.
50645 *  * Redistributions in binary form must reproduce the above copyright notice,
50646 *  this list of conditions and the following disclaimer in the documentation and/or
50647 *  other materials provided with the distribution.
50648 *  * Neither the name of Dash Industry Forum nor the names of its
50649 *  contributors may be used to endorse or promote products derived from this software
50650 *  without specific prior written permission.
50651 *
50652 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
50653 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
50654 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
50655 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
50656 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
50657 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
50658 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
50659 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50660 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
50661 *  POSSIBILITY OF SUCH DAMAGE.
50662 */
50663/**
50664 * @class
50665 * @ignore
50666 */
50667"use strict";
50668
50669Object.defineProperty(exports, "__esModule", {
50670  value: true
50671});
50672
50673function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
50674
50675var MetricsList = function MetricsList() {
50676  _classCallCheck(this, MetricsList);
50677
50678  this.TcpList = [];
50679  this.HttpList = [];
50680  this.RepSwitchList = [];
50681  this.BufferLevel = [];
50682  this.BufferState = [];
50683  this.PlayList = [];
50684  this.DroppedFrames = [];
50685  this.SchedulingInfo = [];
50686  this.DVRInfo = [];
50687  this.ManifestUpdate = [];
50688  this.RequestsQueue = null;
50689  this.DVBErrors = [];
50690};
50691
50692exports["default"] = MetricsList;
50693module.exports = exports["default"];
50694
50695},{}],215:[function(_dereq_,module,exports){
50696/**
50697 * The copyright in this software is being made available under the BSD License,
50698 * included below. This software may be subject to other third party and contributor
50699 * rights, including patent rights, and no such rights are granted under this license.
50700 *
50701 * Copyright (c) 2013, Dash Industry Forum.
50702 * All rights reserved.
50703 *
50704 * Redistribution and use in source and binary forms, with or without modification,
50705 * are permitted provided that the following conditions are met:
50706 *  * Redistributions of source code must retain the above copyright notice, this
50707 *  list of conditions and the following disclaimer.
50708 *  * Redistributions in binary form must reproduce the above copyright notice,
50709 *  this list of conditions and the following disclaimer in the documentation and/or
50710 *  other materials provided with the distribution.
50711 *  * Neither the name of Dash Industry Forum nor the names of its
50712 *  contributors may be used to endorse or promote products derived from this software
50713 *  without specific prior written permission.
50714 *
50715 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
50716 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
50717 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
50718 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
50719 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
50719INCLUDING, BUT
50720 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
50721 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
50722 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50723 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
50724 *  POSSIBILITY OF SUCH DAMAGE.
50725 */
50726/**
50727 * @class
50728 * @ignore
50729 */
50730"use strict";
50731
50732Object.defineProperty(exports, "__esModule", {
50733  value: true
50734});
50735
50736function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
50737
50738var RepresentationInfo = function RepresentationInfo() {
50739  _classCallCheck(this, RepresentationInfo);
50740
50741  this.id = null;
50742  this.quality = null;
50743  this.DVRWindow = null;
50744  this.fragmentDuration = null;
50745  this.mediaInfo = null;
50746  this.MSETimeOffset = null;
50747};
50748
50749exports["default"] = RepresentationInfo;
50750module.exports = exports["default"];
50751
50752},{}],216:[function(_dereq_,module,exports){
50753/**
50754 * The copyright in this software is being made available under the BSD License,
50755 * included below. This software may be subject to other third party and contributor
50756 * rights, including patent rights, and no such rights are granted under this license.
50757 *
50758 * Copyright (c) 2013, Dash Industry Forum.
50759 * All rights reserved.
50760 *
50761 * Redistribution and use in source and binary forms, with or without modification,
50762 * are permitted provided that the following conditions are met:
50763 *  * Redistributions of source code must retain the above copyright notice, this
50764 *  list of conditions and the following disclaimer.
50765 *  * Redistributions in binary form must reproduce the above copyright notice,
50766 *  this list of conditions and the following disclaimer in the documentation and/or
50767 *  other materials provided with the distribution.
50768 *  * Neither the name of Dash Industry Forum nor the names of its
50769 *  contributors may be used to endorse or promote products derived from this software
50770 *  without specific prior written permission.
50771 *
50772 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
50773 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
50774 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
50775 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
50776 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
50777 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
50778 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
50779 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50780 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
50781 *  POSSIBILITY OF SUCH DAMAGE.
50782 */
50783/**
50784 * @class
50785 * @ignore
50786 */
50787"use strict";
50788
50789Object.defineProperty(exports, "__esModule", {
50790  value: true
50791});
50792
50793function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
50794
50795var StreamInfo = function StreamInfo() {
50796  _classCallCheck(this, StreamInfo);
50797
50798  this.id = null;
50799  this.index = null;
50800  this.start = NaN;
50801  this.duration = NaN;
50802  this.manifestInfo = null;
50803  this.isLast = true;
50804};
50805
50806exports["default"] = StreamInfo;
50807module.exports = exports["default"];
50808
50809},{}],217:[function(_dereq_,module,exports){
50810/**
50811 * The copyright in this software is being made available under the BSD License,
50812 * included below. This software may be subject to other third party and contributor
50813 * rights, including patent rights, and no such rights are granted under this license.
50814 *
50815 * Copyright (c) 2013, Dash Industry Forum.
50816 * All rights reserved.
50817 *
50818 * Redistribution and use in source and binary forms, with or without modification,
50819 * are permitted provided that the following conditions are met:
50820 *  * Redistributions of source code must retain the above copyright notice, this
50821 *  list of conditions and the following disclaimer.
50822 *  * Redistributions in binary form must reproduce the above copyright notice,
50823 *  this list of conditions and the following disclaimer in the documentation and/or
50824 *  other materials provided with the distribution.
50825 *  * Neither the name of Dash Industry Forum nor the names of its
50826 *  contributors may be used to endorse or promote products derived from this software
50827 *  without specific prior written permission.
50828 *
50829 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
50830 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
50831 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
50832 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
50833 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
50833INCLUDING, BUT
50834 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
50835 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
50836 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50837 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
50838 *  POSSIBILITY OF SUCH DAMAGE.
50839 */
50840/**
50841 * @class
50842 * @ignore
50843 */
50844'use strict';
50845
50846Object.defineProperty(exports, '__esModule', {
50847  value: true
50848});
50849
50850var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
50851
50852function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
50853
50854function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
50855
50856function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
50857
50858var _constantsConstants = _dereq_(100);
50859
50860var _constantsConstants2 = _interopRequireDefault(_constantsConstants);
50861
50862var _FragmentRequest2 = _dereq_(209);
50863
50864var _FragmentRequest3 = _interopRequireDefault(_FragmentRequest2);
50865
50866var TextRequest = (function (_FragmentRequest) {
50867  _inherits(TextRequest, _FragmentRequest);
50868
50869  function TextRequest(url, type) {
50870    _classCallCheck(this, TextRequest);
50871
50872    _get(Object.getPrototypeOf(TextRequest.prototype), 'constructor', this).call(this);
50873    this.url = url || null;
50874    this.type = type || null;
50875    this.mediaType = _constantsConstants2['default'].STREAM;
50876    this.responseType = _constantsConstants2['default'].TEXT;
50877  }
50878
50879  return TextRequest;
50880})(_FragmentRequest3['default']);
50881
50882exports['default'] = TextRequest;
50883module.exports = exports['default'];
50884
50885},{"100":100,"209":209}],218:[function(_dereq_,module,exports){
50886/**
50887 * The copyright in this software is being made available under the BSD License,
50888 * included below. This software may be subject to other third party and contributor
50889 * rights, including patent rights, and no such rights are granted under this license.
50890 *
50891 * Copyright (c) 2013, Dash Industry Forum.
50892 * All rights reserved.
50893 *
50894 * Redistribution and use in source and binary forms, with or without modification,
50895 * are permitted provided that the following conditions are met:
50896 *  * Redistributions of source code must retain the above copyright notice, this
50897 *  list of conditions and the following disclaimer.
50898 *  * Redistributions in binary form must reproduce the above copyright notice,
50899 *  this list of conditions and the following disclaimer in the documentation and/or
50900 *  other materials provided with the distribution.
50901 *  * Neither the name of Dash Industry Forum nor the names of its
50902 *  contributors may be used to endorse or promote products derived from this software
50903 *  without specific prior written permission.
50904 *
50905 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
50906 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
50907 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
50908 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
50909 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
50909INCLUDING, BUT
50910 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
50911 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
50912 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50913 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
50914 *  POSSIBILITY OF SUCH DAMAGE.
50915 */
50916/**
50917 * @class
50918 * @ignore
50919 */
50920"use strict";
50921
50922Object.defineProperty(exports, "__esModule", {
50923  value: true
50924});
50925
50926function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
50927
50928var TextTrackInfo = function TextTrackInfo() {
50929  _classCallCheck(this, TextTrackInfo);
50930
50931  this.captionData = null;
50932  this.label = null;
50933  this.lang = null;
50934  this.defaultTrack = false;
50935  this.kind = null;
50936  this.isFragmented = false;
50937  this.isEmbedded = false;
50938};
50939
50940exports["default"] = TextTrackInfo;
50941module.exports = exports["default"];
50942
50943},{}],219:[function(_dereq_,module,exports){
50944/**
50945 * The copyright in this software is being made available under the BSD License,
50946 * included below. This software may be subject to other third party and contributor
50947 * rights, including patent rights, and no such rights are granted under this license.
50948 *
50949 * Copyright (c) 2013, Dash Industry Forum.
50950 * All rights reserved.
50951 *
50952 * Redistribution and use in source and binary forms, with or without modification,
50953 * are permitted provided that the following conditions are met:
50954 *  * Redistributions of source code must retain the above copyright notice, this
50955 *  list of conditions and the following disclaimer.
50956 *  * Redistributions in binary form must reproduce the above copyright notice,
50957 *  this list of conditions and the following disclaimer in the documentation and/or
50958 *  other materials provided with the distribution.
50959 *  * Neither the name of Dash Industry Forum nor the names of its
50960 *  contributors may be used to endorse or promote products derived from this software
50961 *  without specific prior written permission.
50962 *
50963 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
50964 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
50965 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
50966 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
50967 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
50968 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
50969 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
50970 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50971 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
50972 *  POSSIBILITY OF SUCH DAMAGE.
50973 */
50974/**
50975 * @class
50976 * @ignore
50977 */
50978"use strict";
50979
50980Object.defineProperty(exports, "__esModule", {
50981    value: true
50982});
50983
50984function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
50985
50986var URIFragmentData = function URIFragmentData() {
50987    _classCallCheck(this, URIFragmentData);
50988
50989    this.t = null;
50990    this.xywh = null;
50991    this.track = null;
50992    this.id = null;
50993    this.s = null;
50994};
50995
50996exports["default"] = URIFragmentData;
50997
50998/*
50999    From Spec http://www.w3.org/TR/media-frags/
51000
51001    temporal (t)     - This dimension denotes a specific time range in the original media, such as "starting at second 10, continuing until second 20";
51002    spatial  (xywh)  - this dimension denotes a specific range of pixels in the original media, such as "a rectangle with size (100,100) with its top-left at coordinate (10,10)";
51003                       Media fragments support also addressing the media along two additional dimensions (in the advanced version defined in Media Fragments 1.0 URI (advanced)):
51004    track    (track) - this dimension denotes one or more tracks in the original media, such as "the english audio and the video track";
51005    id       (id)    - this dimension denotes a named temporal fragment within the original media, such as "chapter 2", and can be seen as a convenient way of specifying a temporal fragment.
51006
51007
51008    ## Note
51009    Akamai is purposing to add #s=X to the ISO standard.
51010        - (X) Value would be a start time to seek to at startup instead of starting at 0 or live edge
51011        - Allows for seeking back before the start time unlike a temporal clipping.
51012*/
51013module.exports = exports["default"];
51014
51015},{}],220:[function(_dereq_,module,exports){
51016/**
51017 * The copyright in this software is being made available under the BSD License,
51018 * included below. This software may be subject to other third party and contributor
51019 * rights, including patent rights, and no such rights are granted under this license.
51020 *
51021 * Copyright (c) 2013, Dash Industry Forum.
51022 * All rights reserved.
51023 *
51024 * Redistribution and use in source and binary forms, with or without modification,
51025 * are permitted provided that the following conditions are met:
51026 *  * Redistributions of source code must retain the above copyright notice, this
51027 *  list of conditions and the following disclaimer.
51028 *  * Redistributions in binary form must reproduce the above copyright notice,
51029 *  this list of conditions and the following disclaimer in the documentation and/or
51030 *  other materials provided with the distribution.
51031 *  * Neither the name of Dash Industry Forum nor the names of its
51032 *  contributors may be used to endorse or promote products derived from this software
51033 *  without specific prior written permission.
51034 *
51035 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
51036 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
51037 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
51038 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
51039 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
51039INCLUDING, BUT
51040 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
51041 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
51042 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51043 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
51044 *  POSSIBILITY OF SUCH DAMAGE.
51045 */
51046
51047/**
51048 * @class
51049 */
51050"use strict";
51051
51052Object.defineProperty(exports, "__esModule", {
51053  value: true
51054});
51055
51056function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
51057
51058var BufferLevel =
51059/**
51060 * @description This Object holds reference to the current buffer level and the time it was recorded.
51061 */
51062function BufferLevel() {
51063  _classCallCheck(this, BufferLevel);
51064
51065  /**
51066   * Real-Time | Time of the measurement of the buffer level.
51067   * @public
51068   */
51069  this.t = null;
51070  /**
51071   * Level of the buffer in milliseconds. Indicates the playout duration for which
51072   * media data of all active media components is available starting from the
51073   * current playout time.
51074   * @public
51075   */
51076  this.level = null;
51077};
51078
51079exports["default"] = BufferLevel;
51080module.exports = exports["default"];
51081
51082},{}],221:[function(_dereq_,module,exports){
51083/**
51084 * The copyright in this software is being made available under the BSD License,
51085 * included below. This software may be subject to other third party and contributor
51086 * rights, including patent rights, and no such rights are granted under this license.
51087 *
51088 * Copyright (c) 2013, Dash Industry Forum.
51089 * All rights reserved.
51090 *
51091 * Redistribution and use in source and binary forms, with or without modification,
51092 * are permitted provided that the following conditions are met:
51093 *  * Redistributions of source code must retain the above copyright notice, this
51094 *  list of conditions and the following disclaimer.
51095 *  * Redistributions in binary form must reproduce the above copyright notice,
51096 *  this list of conditions and the following disclaimer in the documentation and/or
51097 *  other materials provided with the distribution.
51098 *  * Neither the name of Dash Industry Forum nor the names of its
51099 *  contributors may be used to endorse or promote products derived from this software
51100 *  without specific prior written permission.
51101 *
51102 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
51103 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
51104 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
51105 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
51106 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
51107 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
51108 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
51109 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51110 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
51111 *  POSSIBILITY OF SUCH DAMAGE.
51112 */
51113'use strict';
51114
51115Object.defineProperty(exports, '__esModule', {
51116  value: true
51117});
51118
51119function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
51120
51121function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
51122
51123var _controllersBufferController = _dereq_(105);
51124
51125var _controllersBufferController2 = _interopRequireDefault(_controllersBufferController);
51126
51127/**
51128 * @class
51129 */
51130
51131var BufferState =
51132/**
51133 * @description This Object holds reference to the current buffer state of the video element.
51134 */
51135function BufferState() {
51136  _classCallCheck(this, BufferState);
51137
51138  /**
51139   * The Buffer Level Target determined by the BufferLevelRule.
51140   * @public
51141   */
51142  this.target = null;
51143  /**
51144   * Current buffer state. Will be BufferController.BUFFER_EMPTY or BufferController.BUFFER_LOADED.
51145   * @public
51146   */
51147  this.state = _controllersBufferController2['default'].BUFFER_EMPTY;
51148};
51149
51150exports['default'] = BufferState;
51151module.exports = exports['default'];
51152
51153},{"105":105}],222:[function(_dereq_,module,exports){
51154/**
51155 * The copyright in this software is being made available under the BSD License,
51156 * included below. This software may be subject to other third party and contributor
51157 * rights, including patent rights, and no such rights are granted under this license.
51158 *
51159 * Copyright (c) 2013, Dash Industry Forum.
51160 * All rights reserved.
51161 *
51162 * Redistribution and use in source and binary forms, with or without modification,
51163 * are permitted provided that the following conditions are met:
51164 *  * Redistributions of source code must retain the above copyright notice, this
51165 *  list of conditions and the following disclaimer.
51166 *  * Redistributions in binary form must reproduce the above copyright notice,
51167 *  this list of conditions and the following disclaimer in the documentation and/or
51168 *  other materials provided with the distribution.
51169 *  * Neither the name of Dash Industry Forum nor the names of its
51170 *  contributors may be used to endorse or promote products derived from this software
51171 *  without specific prior written permission.
51172 *
51173 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
51174 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
51175 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
51176 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
51177 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
51177INCLUDING, BUT
51178 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
51179 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
51180 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51181 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
51182 *  POSSIBILITY OF SUCH DAMAGE.
51183 */
51184/**
51185 * @class
51186 */
51187"use strict";
51188
51189Object.defineProperty(exports, "__esModule", {
51190  value: true
51191});
51192
51193function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
51194
51195var DVRInfo =
51196/**
51197 * @description This Object holds reference to DVR availability window information.
51198 */
51199function DVRInfo() {
51200  _classCallCheck(this, DVRInfo);
51201
51202  /**
51203   * The current time of the video element when this was created.
51204   * @public
51205   */
51206  this.time = null;
51207  /**
51208   * The current Segment Availability Range as an object with start and end properties.
51209   * It's delta defined by the timeShiftBufferDepth MPD attribute.
51210   * @public
51211   */
51212  this.range = null;
51213  /**
51214   * Reference to the internal ManifestInfo.js VO.
51215   * @public
51216   */
51217  this.manifestInfo = null;
51218};
51219
51220exports["default"] = DVRInfo;
51221module.exports = exports["default"];
51222
51223},{}],223:[function(_dereq_,module,exports){
51224/**
51225 * The copyright in this software is being made available under the BSD License,
51226 * included below. This software may be subject to other third party and contributor
51227 * rights, including patent rights, and no such rights are granted under this license.
51228 *
51229 * Copyright (c) 2013, Dash Industry Forum.
51230 * All rights reserved.
51231 *
51232 * Redistribution and use in source and binary forms, with or without modification,
51233 * are permitted provided that the following conditions are met:
51234 *  * Redistributions of source code must retain the above copyright notice, this
51235 *  list of conditions and the following disclaimer.
51236 *  * Redistributions in binary form must reproduce the above copyright notice,
51237 *  this list of conditions and the following disclaimer in the documentation and/or
51238 *  other materials provided with the distribution.
51239 *  * Neither the name of Dash Industry Forum nor the names of its
51240 *  contributors may be used to endorse or promote products derived from this software
51241 *  without specific prior written permission.
51242 *
51243 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
51244 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
51245 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
51246 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
51247 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
51248 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
51249 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
51250 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51251 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
51252 *  POSSIBILITY OF SUCH DAMAGE.
51253 */
51254/**
51255 * @class
51256 */
51257"use strict";
51258
51259Object.defineProperty(exports, "__esModule", {
51260  value: true
51261});
51262
51263function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
51264
51265var DroppedFrames =
51266/**
51267 * @description This Object holds reference to DroppedFrames count and the time it was recorded.
51268 */
51269function DroppedFrames() {
51270  _classCallCheck(this, DroppedFrames);
51271
51272  /**
51273   * Real-Time | Time of the measurement of the dropped frames.
51274   * @public
51275   */
51276  this.time = null;
51277  /**
51278   * Number of dropped frames
51279   * @public
51280   */
51281  this.droppedFrames = null;
51282};
51283
51284exports["default"] = DroppedFrames;
51285module.exports = exports["default"];
51286
51287},{}],224:[function(_dereq_,module,exports){
51288/**
51289 * The copyright in this software is being made available under the BSD License,
51290 * included below. This software may be subject to other third party and contributor
51291 * rights, including patent rights, and no such rights are granted under this license.
51292 *
51293 * Copyright (c) 2013, Dash Industry Forum.
51294 * All rights reserved.
51295 *
51296 * Redistribution and use in source and binary forms, with or without modification,
51297 * are permitted provided that the following conditions are met:
51298 *  * Redistributions of source code must retain the above copyright notice, this
51299 *  list of conditions and the following disclaimer.
51300 *  * Redistributions in binary form must reproduce the above copyright notice,
51301 *  this list of conditions and the following disclaimer in the documentation and/or
51302 *  other materials provided with the distribution.
51303 *  * Neither the name of Dash Industry Forum nor the names of its
51304 *  contributors may be used to endorse or promote products derived from this software
51305 *  without specific prior written permission.
51306 *
51307 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
51308 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
51309 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
51310 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
51311 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
51311INCLUDING, BUT
51312 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
51313 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
51314 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51315 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
51316 *  POSSIBILITY OF SUCH DAMAGE.
51317 */
51318/**
51319 * @classdesc This Object holds reference to the HTTPRequest for manifest, fragment and xlink loading.
51320 * Members which are not defined in ISO23009-1 Annex D should be prefixed by a _ so that they are ignored
51321 * by Metrics Reporting code.
51322 */
51323'use strict';
51324
51325Object.defineProperty(exports, '__esModule', {
51326  value: true
51327});
51328
51329function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
51330
51331var HTTPRequest =
51332/**
51333 * @class
51334 */
51335function HTTPRequest() {
51336  _classCallCheck(this, HTTPRequest);
51337
51338  /**
51339   * Identifier of the TCP connection on which the HTTP request was sent.
51340   * @public
51341   */
51342  this.tcpid = null;
51343  /**
51344   * This is an optional parameter and should not be included in HTTP request/response transactions for progressive download.
51345   * The type of the request:
51346   * - MPD
51347   * - XLink expansion
51348   * - Initialization Fragment
51349   * - Index Fragment
51350   * - Media Fragment
51351   * - Bitstream Switching Fragment
51352   * - other
51353   * @public
51354   */
51355  this.type = null;
51356  /**
51357   * The original URL (before any redirects or failures)
51358   * @public
51359   */
51360  this.url = null;
51361  /**
51362   * The actual URL requested, if different from above
51363   * @public
51364   */
51365  this.actualurl = null;
51366  /**
51367   * The contents of the byte-range-spec part of the HTTP Range header.
51368   * @public
51369   */
51370  this.range = null;
51371  /**
51372   * Real-Time | The real time at which the request was sent.
51373   * @public
51374   */
51375  this.trequest = null;
51376  /**
51377   * Real-Time | The real time at which the first byte of the response was received.
51378   * @public
51379   */
51380  this.tresponse = null;
51381  /**
51382   * The HTTP response code.
51383   * @public
51384   */
51385  this.responsecode = null;
51386  /**
51387   * The duration of the throughput trace intervals (ms), for successful requests only.
51388   * @public
51389   */
51390  this.interval = null;
51391  /**
51392   * Throughput traces, for successful requests only.
51393   * @public
51394   */
51395  this.trace = [];
51396
51397  /**
51398   * Type of stream ("audio" | "video" etc..)
51399   * @public
51400   */
51401  this._stream = null;
51402  /**
51403   * Real-Time | The real time at which the request finished.
51404   * @public
51405   */
51406  this._tfinish = null;
51407  /**
51408   * The duration of the media requests, if available, in milliseconds.
51409   * @public
51410   */
51411  this._mediaduration = null;
51412  /**
51413   * all the response headers from request.
51414   * @public
51415   */
51416  this._responseHeaders = null;
51417  /**
51418   * The selected service location for the request. string.
51419   * @public
51420   */
51421  this._serviceLocation = null;
51422}
51423
51424/**
51425 * @classdesc This Object holds reference to the progress of the HTTPRequest.
51426 */
51427;
51428
51429var HTTPRequestTrace =
51430/**
51431* @class
51432*/
51433function HTTPRequestTrace() {
51434  _classCallCheck(this, HTTPRequestTrace);
51435
51436  /**
51437   * Real-Time | Measurement stream start.
51438   * @public
51439   */
51440  this.s = null;
51441  /**
51442   * Measurement stream duration (ms).
51443   * @public
51444   */
51445  this.d = null;
51446  /**
51447   * List of integers counting the bytes received in each trace interval within the measurement stream.
51448   * @public
51449   */
51450  this.b = [];
51451};
51452
51453HTTPRequest.GET = 'GET';
51454HTTPRequest.HEAD = 'HEAD';
51455HTTPRequest.MPD_TYPE = 'MPD';
51456HTTPRequest.XLINK_EXPANSION_TYPE = 'XLinkExpansion';
51457HTTPRequest.INIT_SEGMENT_TYPE = 'InitializationSegment';
51458HTTPRequest.INDEX_SEGMENT_TYPE = 'IndexSegment';
51459HTTPRequest.MEDIA_SEGMENT_TYPE = 'MediaSegment';
51460HTTPRequest.BITSTREAM_SWITCHING_SEGMENT_TYPE = 'BitstreamSwitchingSegment';
51461HTTPRequest.OTHER_TYPE = 'other';
51462
51463exports.HTTPRequest = HTTPRequest;
51464exports.HTTPRequestTrace = HTTPRequestTrace;
51465
51466},{}],225:[function(_dereq_,module,exports){
51467/**
51468 * The copyright in this software is being made available under the BSD License,
51469 * included below. This software may be subject to other third party and contributor
51470 * rights, including patent rights, and no such rights are granted under this license.
51471 *
51472 * Copyright (c) 2013, Dash Industry Forum.
51473 * All rights reserved.
51474 *
51475 * Redistribution and use in source and binary forms, with or without modification,
51476 * are permitted provided that the following conditions are met:
51477 *  * Redistributions of source code must retain the above copyright notice, this
51478 *  list of conditions and the following disclaimer.
51479 *  * Redistributions in binary form must reproduce the above copyright notice,
51480 *  this list of conditions and the following disclaimer in the documentation and/or
51481 *  other materials provided with the distribution.
51482 *  * Neither the name of Dash Industry Forum nor the names of its
51483 *  contributors may be used to endorse or promote products derived from this software
51484 *  without specific prior written permission.
51485 *
51486 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
51487 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
51488 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
51489 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
51490 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
51490INCLUDING, BUT
51491 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
51492 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
51493 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51494 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
51495 *  POSSIBILITY OF SUCH DAMAGE.
51496 */
51497/**
51498 * @classdesc This Object holds reference to the manifest update information.
51499 */
51500"use strict";
51501
51502Object.defineProperty(exports, "__esModule", {
51503  value: true
51504});
51505
51506function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
51507
51508var ManifestUpdate =
51509/**
51510 * @class
51511 */
51512function ManifestUpdate() {
51513  _classCallCheck(this, ManifestUpdate);
51514
51515  /**
51516   * Media Type Video | Audio | FragmentedText
51517   * @public
51518   */
51519  this.mediaType = null;
51520  /**
51521   * MPD Type static | dynamic
51522   * @public
51523   */
51524  this.type = null;
51525  /**
51526   * When this manifest update was requested
51527   * @public
51528   */
51529  this.requestTime = null;
51530  /**
51531   * When this manifest update was received
51532   * @public
51533   */
51534  this.fetchTime = null;
51535  /**
51536   * Calculated Availability Start time of the stream.
51537   * @public
51538   */
51539  this.availabilityStartTime = null;
51540  /**
51541   * the seek point (liveEdge for dynamic, Stream[0].startTime for static)
51542   * @public
51543   */
51544  this.presentationStartTime = 0;
51545  /**
51546   * The calculated difference between the server and client wall clock time
51547   * @public
51548   */
51549  this.clientTimeOffset = 0;
51550  /**
51551   * Actual element.currentTime
51552   * @public
51553   */
51554  this.currentTime = null;
51555  /**
51556   * Actual element.ranges
51557   * @public
51558   */
51559  this.buffered = null;
51560  /**
51561   * Static is fixed value of zero. dynamic should be ((Now-@availabilityStartTime) - elementCurrentTime)
51562   * @public
51563   */
51564  this.latency = 0;
51565  /**
51566   * Array holding list of StreamInfo VO Objects
51567   * @public
51568   */
51569  this.streamInfo = [];
51570  /**
51571   * Array holding list of RepresentationInfo VO Objects
51572   * @public
51573   */
51574  this.representationInfo = [];
51575}
51576
51577/**
51578 * @classdesc This Object holds reference to the current period's stream information when the manifest was updated.
51579 */
51580;
51581
51582var ManifestUpdateStreamInfo =
51583/**
51584 * @class
51585 */
51586function ManifestUpdateStreamInfo() {
51587  _classCallCheck(this, ManifestUpdateStreamInfo);
51588
51589  /**
51590   * Stream@id
51591   * @public
51592   */
51593  this.id = null;
51594  /**
51595   * Period Index
51596   * @public
51597   */
51598  this.index = null;
51599  /**
51600   * Stream@start
51601   * @public
51602   */
51603  this.start = null;
51604  /**
51605   * Stream@duration
51606   * @public
51607   */
51608  this.duration = null;
51609}
51610
51611/**
51612 * @classdesc This Object holds reference to the current representation's info when the manifest was updated.
51613 */
51614;
51615
51616var ManifestUpdateRepresentationInfo =
51617/**
51618 * @class
51619 */
51620function ManifestUpdateRepresentationInfo() {
51621  _classCallCheck(this, ManifestUpdateRepresentationInfo);
51622
51623  /**
51624   * Track@id
51625   * @public
51626   */
51627  this.id = null;
51628  /**
51629   * Representation Index
51630   * @public
51631   */
51632  this.index = null;
51633  /**
51634   * Media Type Video | Audio | FragmentedText
51635   * @public
51636   */
51637  this.mediaType = null;
51638  /**
51639   * Which representation
51640   * @public
51641   */
51642  this.streamIndex = null;
51643  /**
51644   * Holds reference to @presentationTimeOffset
51645   * @public
51646   */
51647  this.presentationTimeOffset = null;
51648  /**
51649   * Holds reference to @startNumber
51650   * @public
51651   */
51652  this.startNumber = null;
51653  /**
51654   * list|template|timeline
51655   * @public
51656   */
51657  this.fragmentInfoType = null;
51658};
51659
51660exports.ManifestUpdate = ManifestUpdate;
51661exports.ManifestUpdateStreamInfo = ManifestUpdateStreamInfo;
51662exports.ManifestUpdateRepresentationInfo = ManifestUpdateRepresentationInfo;
51663
51664},{}],226:[function(_dereq_,module,exports){
51665/**
51666 * The copyright in this software is being made available under the BSD License,
51667 * included below. This software may be subject to other third party and contributor
51668 * rights, including patent rights, and no such rights are granted under this license.
51669 *
51670 * Copyright (c) 2013, Dash Industry Forum.
51671 * All rights reserved.
51672 *
51673 * Redistribution and use in source and binary forms, with or without modification,
51674 * are permitted provided that the following conditions are met:
51675 *  * Redistributions of source code must retain the above copyright notice, this
51676 *  list of conditions and the following disclaimer.
51677 *  * Redistributions in binary form must reproduce the above copyright notice,
51678 *  this list of conditions and the following disclaimer in the documentation and/or
51679 *  other materials provided with the distribution.
51680 *  * Neither the name of Dash Industry Forum nor the names of its
51681 *  contributors may be used to endorse or promote products derived from this software
51682 *  without specific prior written permission.
51683 *
51684 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
51685 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
51686 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
51687 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
51688 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
51688INCLUDING, BUT
51689 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
51690 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
51691 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51692 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
51693 *  POSSIBILITY OF SUCH DAMAGE.
51694 */
51695/**
51696 * @classdesc a PlayList from ISO23009-1 Annex D, this Object holds reference to the playback session information
51697 */
51698'use strict';
51699
51700Object.defineProperty(exports, '__esModule', {
51701  value: true
51702});
51703
51704function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
51705
51706var PlayList =
51707/**
51708 * @class
51709 */
51710function PlayList() {
51711  _classCallCheck(this, PlayList);
51712
51713  /**
51714   * Timestamp of the user action that starts the playback stream...
51715   * @public
51716   */
51717  this.start = null;
51718  /**
51719   * Presentation time at which playout was requested by the user...
51720   * @public
51721   */
51722  this.mstart = null;
51723  /**
51724   * Type of user action which triggered playout
51725   * - New playout request (e.g. initial playout or seeking)
51726   * - Resume from pause
51727   * - Other user request (e.g. user-requested quality change)
51728   * - Start of a metrics collection stream (hence earlier entries in the play list not collected)
51729   * @public
51730   */
51731  this.starttype = null;
51732
51733  /**
51734   * List of streams of continuous rendering of decoded samples.
51735   * @public
51736   */
51737  this.trace = [];
51738}
51739
51740/* Public Static Constants */
51741;
51742
51743PlayList.INITIAL_PLAYOUT_START_REASON = 'initial_playout';
51744PlayList.SEEK_START_REASON = 'seek';
51745PlayList.RESUME_FROM_PAUSE_START_REASON = 'resume';
51746PlayList.METRICS_COLLECTION_START_REASON = 'metrics_collection_start';
51747
51748/**
51749 * @classdesc a PlayList.Trace from ISO23009-1 Annex D
51750 */
51751
51752var PlayListTrace =
51753/**
51754 * @class
51755 */
51756function PlayListTrace() {
51757  _classCallCheck(this, PlayListTrace);
51758
51759  /**
51760   * The value of the Representation@id of the Representation from which the samples were taken.
51761   * @type {string}
51762   * @public
51763   */
51764  this.representationid = null;
51765  /**
51766   * If not present, this metrics concerns the Representation as a whole.
51767   * If present, subreplevel indicates the greatest value of any
51768   * Subrepresentation@level being rendered.
51769   * @type {number}
51770   * @public
51771   */
51772  this.subreplevel = null;
51773  /**
51774   * The time at which the first sample was rendered
51775   * @type {number}
51776   * @public
51777   */
51778  this.start = null;
51779  /**
51780   * The presentation time of the first sample rendered.
51781   * @type {number}
51782   * @public
51783   */
51784  this.mstart = null;
51785  /**
51786   * The duration of the continuously presented samples (which is the same in real time and media time). "Continuously presented" means that the media clock continued to advance at the playout speed throughout the interval. NOTE: the spec does not call out the units, but all other durations etc are in ms, and we use ms too.
51787   * @type {number}
51788   * @public
51789   */
51790  this.duration = null;
51791  /**
51792   * The playback speed relative to normal playback speed (i.e.normal forward playback speed is 1.0).
51793   * @type {number}
51794   * @public
51795   */
51796  this.playbackspeed = null;
51797  /**
51798   * The reason why continuous presentation of this Representation was stopped.
51799   * representation switch
51800   * rebuffering
51801   * user request
51802   * end of Period
51803   * end of Stream
51804   * end of content
51805   * end of a metrics collection period
51806   *
51807   * @type {string}
51808   * @public
51809   */
51810  this.stopreason = null;
51811};
51812
51813PlayListTrace.REPRESENTATION_SWITCH_STOP_REASON = 'representation_switch';
51814PlayListTrace.REBUFFERING_REASON = 'rebuffering';
51815PlayListTrace.USER_REQUEST_STOP_REASON = 'user_request';
51816PlayListTrace.END_OF_PERIOD_STOP_REASON = 'end_of_period';
51817PlayListTrace.END_OF_CONTENT_STOP_REASON = 'end_of_content';
51818PlayListTrace.METRICS_COLLECTION_STOP_REASON = 'metrics_collection_end';
51819PlayListTrace.FAILURE_STOP_REASON = 'failure';
51820
51821exports.PlayList = PlayList;
51822exports.PlayListTrace = PlayListTrace;
51823
51824},{}],227:[function(_dereq_,module,exports){
51825/**
51826 * The copyright in this software is being made available under the BSD License,
51827 * included below. This software may be subject to other third party and contributor
51828 * rights, including patent rights, and no such rights are granted under this license.
51829 *
51830 * Copyright (c) 2013, Dash Industry Forum.
51831 * All rights reserved.
51832 *
51833 * Redistribution and use in source and binary forms, with or without modification,
51834 * are permitted provided that the following conditions are met:
51835 *  * Redistributions of source code must retain the above copyright notice, this
51836 *  list of conditions and the following disclaimer.
51837 *  * Redistributions in binary form must reproduce the above copyright notice,
51838 *  this list of conditions and the following disclaimer in the documentation and/or
51839 *  other materials provided with the distribution.
51840 *  * Neither the name of Dash Industry Forum nor the names of its
51841 *  contributors may be used to endorse or promote products derived from this software
51842 *  without specific prior written permission.
51843 *
51844 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
51845 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
51846 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
51847 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
51848 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
51848INCLUDING, BUT
51849 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
51850 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
51851 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51852 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
51853 *  POSSIBILITY OF SUCH DAMAGE.
51854 */
51855/**
51856 * @class
51857 */
51858"use strict";
51859
51860Object.defineProperty(exports, "__esModule", {
51861  value: true
51862});
51863
51864function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
51865
51866var RepresentationSwitch =
51867/**
51868 * @description This Object holds reference to the info at quality switch between two representations.
51869 */
51870function RepresentationSwitch() {
51871  _classCallCheck(this, RepresentationSwitch);
51872
51873  /**
51874   * Time of the switch event.
51875   * @public
51876   */
51877  this.t = null;
51878  /**
51879   * The media presentation time of the earliest access unit
51880   * (out of all media content components) played out from
51881   * the Representation.
51882   *
51883   * @public
51884   */
51885  this.mt = null;
51886  /**
51887   * Value of Representation@id identifying the switch-to Representation.
51888   * @public
51889   */
51890  this.to = null;
51891  /**
51892   * If not present, this metrics concerns the Representation as a whole.
51893   * If present, lto indicates the value of SubRepresentation@level within
51894   * Representation identifying the switch-to level of the Representation.
51895   *
51896   * @public
51897   */
51898  this.lto = null;
51899};
51900
51901exports["default"] = RepresentationSwitch;
51902module.exports = exports["default"];
51903
51904},{}],228:[function(_dereq_,module,exports){
51905/**
51906 * The copyright in this software is being made available under the BSD License,
51907 * included below. This software may be subject to other third party and contributor
51908 * rights, including patent rights, and no such rights are granted under this license.
51909 *
51910 * Copyright (c) 2013, Dash Industry Forum.
51911 * All rights reserved.
51912 *
51913 * Redistribution and use in source and binary forms, with or without modification,
51914 * are permitted provided that the following conditions are met:
51915 *  * Redistributions of source code must retain the above copyright notice, this
51916 *  list of conditions and the following disclaimer.
51917 *  * Redistributions in binary form must reproduce the above copyright notice,
51918 *  this list of conditions and the following disclaimer in the documentation and/or
51919 *  other materials provided with the distribution.
51920 *  * Neither the name of Dash Industry Forum nor the names of its
51921 *  contributors may be used to endorse or promote products derived from this software
51922 *  without specific prior written permission.
51923 *
51924 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
51925 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
51926 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
51927 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
51928 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
51929 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
51930 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
51931 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51932 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
51933 *  POSSIBILITY OF SUCH DAMAGE.
51934 */
51935/**
51936 * @class
51937 */
51938"use strict";
51939
51940Object.defineProperty(exports, "__esModule", {
51941  value: true
51942});
51943
51944function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
51945
51946var RequestsQueue =
51947/**
51948 * @description This Object holds reference to Fragment Model's request queues
51949 */
51950function RequestsQueue() {
51951  _classCallCheck(this, RequestsQueue);
51952
51953  /**
51954   * Array of all of the requests that have begun to load
51955   * This request may not make it into the executed queue if it is abandon due to ABR rules for example.
51956   * @public
51957   */
51958  this.loadingRequests = [];
51959  /**
51960   * Array of the The requests that have completed
51961   * @public
51962   */
51963  this.executedRequests = [];
51964};
51965
51966exports["default"] = RequestsQueue;
51967module.exports = exports["default"];
51968
51969},{}],229:[function(_dereq_,module,exports){
51970/**
51971 * The copyright in this software is being made available under the BSD License,
51972 * included below. This software may be subject to other third party and contributor
51973 * rights, including patent rights, and no such rights are granted under this license.
51974 *
51975 * Copyright (c) 2013, Dash Industry Forum.
51976 * All rights reserved.
51977 *
51978 * Redistribution and use in source and binary forms, with or without modification,
51979 * are permitted provided that the following conditions are met:
51980 *  * Redistributions of source code must retain the above copyright notice, this
51981 *  list of conditions and the following disclaimer.
51982 *  * Redistributions in binary form must reproduce the above copyright notice,
51983 *  this list of conditions and the following disclaimer in the documentation and/or
51984 *  other materials provided with the distribution.
51985 *  * Neither the name of Dash Industry Forum nor the names of its
51986 *  contributors may be used to endorse or promote products derived from this software
51987 *  without specific prior written permission.
51988 *
51989 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
51990 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
51991 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
51992 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
51993 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
51993INCLUDING, BUT
51994 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
51995 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
51996 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51997 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
51998 *  POSSIBILITY OF SUCH DAMAGE.
51999 */
52000/**
52001 * @class
52002 */
52003"use strict";
52004
52005Object.defineProperty(exports, "__esModule", {
52006  value: true
52007});
52008
52009function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
52010
52011var SchedulingInfo =
52012/**
52013 * @description This Object holds reference to the index handling of the current fragment being loaded or executed.
52014 */
52015function SchedulingInfo() {
52016  _classCallCheck(this, SchedulingInfo);
52017
52018  /**
52019   * Type of stream Audio | Video | FragmentedText
52020   * @public
52021   */
52022  this.mediaType = null;
52023  /**
52024   * Time of the scheduling event.
52025   * @public
52026   */
52027  this.t = null;
52028
52029  /**
52030   * Type of fragment (initialization | media)
52031   * @public
52032   */
52033  this.type = null;
52034  /**
52035   * Presentation start time of fragment
52036   * @public
52037   */
52038  this.startTime = null;
52039  /**
52040   * Availability start time of fragment
52041   * @public
52042   */
52043  this.availabilityStartTime = null;
52044  /**
52045   * Duration of fragment
52046   * @public
52047   */
52048  this.duration = null;
52049  /**
52050   * Bit Rate Quality of fragment
52051   * @public
52052   */
52053  this.quality = null;
52054  /**
52055   * Range of fragment
52056   * @public
52057   */
52058  this.range = null;
52059
52060  /**
52061   * Current state of fragment
52062   * @public
52063   */
52064  this.state = null;
52065};
52066
52067exports["default"] = SchedulingInfo;
52068module.exports = exports["default"];
52069
52070},{}],230:[function(_dereq_,module,exports){
52071/**
52072 * The copyright in this software is being made available under the BSD License,
52073 * included below. This software may be subject to other third party and contributor
52074 * rights, including patent rights, and no such rights are granted under this license.
52075 *
52076 * Copyright (c) 2013, Dash Industry Forum.
52077 * All rights reserved.
52078 *
52079 * Redistribution and use in source and binary forms, with or without modification,
52080 * are permitted provided that the following conditions are met:
52081 *  * Redistributions of source code must retain the above copyright notice, this
52082 *  list of conditions and the following disclaimer.
52083 *  * Redistributions in binary form must reproduce the above copyright notice,
52084 *  this list of conditions and the following disclaimer in the documentation and/or
52085 *  other materials provided with the distribution.
52086 *  * Neither the name of Dash Industry Forum nor the names of its
52087 *  contributors may be used to endorse or promote products derived from this software
52088 *  without specific prior written permission.
52089 *
52090 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
52091 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
52092 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
52093 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
52094 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
52095 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
52096 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
52097 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
52098 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
52099 *  POSSIBILITY OF SUCH DAMAGE.
52100 */
52101/**
52102 * @class
52103 */
52104"use strict";
52105
52106Object.defineProperty(exports, "__esModule", {
52107  value: true
52108});
52109
52110function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
52111
52112var TCPConnection =
52113/**
52114 * @description This Object holds reference to the current tcp connection
52115 */
52116function TCPConnection() {
52117  _classCallCheck(this, TCPConnection);
52118
52119  /**
52120   * Identifier of the TCP connection on which the HTTP request was sent.
52121   * @public
52122   */
52123  this.tcpid = null;
52124  /**
52125   * IP Address of the interface over which the client is receiving the TCP data.
52126   * @public
52127   */
52128  this.dest = null;
52129  /**
52130   * Real-Time | The time at which the connection was opened (sending time of the initial SYN or connect socket operation).
52131   * @public
52132   */
52133  this.topen = null;
52134  /**
52135   * Real-Time | The time at which the connection was closed (sending or reception time of FIN or RST or close socket operation).
52136   * @public
52137   */
52138  this.tclose = null;
52139  /**
52140   * Connect time in ms (time from sending the initial SYN to receiving the ACK or completion of the connect socket operation).
52141   * @public
52142   */
52143  this.tconnect = null;
52144};
52145
52146exports["default"] = TCPConnection;
52147module.exports = exports["default"];
52148
52149},{}]},{},[5])
52150//# sourceMappingURL=dash.all.debug.js.map

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.