1(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.flvjs = f()}})(function(){var define,module,exports;return (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(function (process,global){ 3/*! 4 * @overview es6-promise - a tiny implementation of Promises/A+. 5 * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) 6 * @license Licensed under MIT license 7 * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE 8 * @version v4.2.5+7f2b526d 9 */ 10 11(function (global, factory) { 12 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 13 typeof define === 'function' && define.amd ? define(factory) : 14 (global.ES6Promise = factory()); 15}(this, (function () { 'use strict'; 16 17function objectOrFunction(x) { 18 var type = typeof x; 19 return x !== null && (type === 'object' || type === 'function'); 20} 21 22function isFunction(x) { 23 return typeof x === 'function'; 24} 25 26 27 28var _isArray = void 0; 29if (Array.isArray) { 30 _isArray = Array.isArray; 31} else { 32 _isArray = function (x) { 33 return Object.prototype.toString.call(x) === '[object Array]'; 34 }; 35} 36 37var isArray = _isArray; 38 39var len = 0; 40var vertxNext = void 0; 41var customSchedulerFn = void 0; 42 43var asap = function asap(callback, arg) { 44 queue[len] = callback; 45 queue[len + 1] = arg; 46 len += 2; 47 if (len === 2) { 48 // If len is 2, that means that we need to schedule an async flush. 49 // If additional callbacks are queued before the queue is flushed, they 50 // will be processed by this flush that we are scheduling. 51 if (customSchedulerFn) { 52 customSchedulerFn(flush); 53 } else { 54 scheduleFlush(); 55 } 56 } 57}; 58 59function setScheduler(scheduleFn) { 60 customSchedulerFn = scheduleFn; 61} 62 63function setAsap(asapFn) { 64 asap = asapFn; 65} 66 67var browserWindow = typeof window !== 'undefined' ? window : undefined; 68var browserGlobal = browserWindow || {}; 69var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver; 70var isNode = typeof self === 'undefined' && typeof process !== 'undefined' && {}.toString.call(process) === '[object process]'; 71 72// test for web worker but not in IE10 73var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined'; 74 75// node 76function useNextTick() { 77 // node version 0.10.x displays a deprecation warning when nextTick is used recursively 78 // see https://github.com/cujojs/when/issues/410 for details 79 return function () { 80 return process.nextTick(flush); 81 }; 82} 83 84// vertx 85function useVertxTimer() { 86 if (typeof vertxNext !== 'undefined') { 87 return function () { 88 vertxNext(flush); 89 }; 90 } 91 92 return useSetTimeout(); 93} 94 95function useMutationObserver() { 96 var iterations = 0; 97 var observer = new BrowserMutationObserver(flush); 98 var node = document.createTextNode(''); 99 observer.observe(node, { characterData: true }); 100 101 return function () { 102 node.data = iterations = ++iterations % 2; 103 }; 104} 105 106// web worker 107function useMessageChannel() { 108 var channel = new MessageChannel(); 109 channel.port1.onmessage = flush; 110 return function () { 111 return channel.port2.postMessage(0); 112 }; 113} 114 115function useSetTimeout() { 116 // Store setTimeout reference so es6-promise will be unaffected by 117 // other code modifying setTimeout (like sinon.useFakeTimers()) 118 var globalSetTimeout = setTimeout; 119 return function () { 120 return globalSetTimeout(flush, 1); 121 }; 122} 123 124var queue = new Array(1000); 125function flush() { 126 for (var i = 0; i < len; i += 2) { 127 var callback = queue[i]; 128 var arg = queue[i + 1]; 129 130 callback(arg); 131 132 queue[i] = undefined; 133 queue[i + 1] = undefined; 134 } 135 136 len = 0; 137} 138 139function attemptVertx() { 140 try { 141 var vertx = Function('return this')().require('vertx'); 142 vertxNext = vertx.runOnLoop || vertx.runOnContext; 143 return useVertxTimer(); 144 } catch (e) { 145 return useSetTimeout(); 146 } 147} 148 149var scheduleFlush = void 0; 150// Decide what async method to use to triggering processing of queued callbacks: 151if (isNode) { 152 scheduleFlush = useNextTick(); 153} else if (BrowserMutationObserver) { 154 scheduleFlush = useMutationObserver(); 155} else if (isWorker) {
156 scheduleFlush = useMessageChannel(); 157} else if (browserWindow === undefined && typeof _dereq_
vendor: 8,702 bytes, lines 157-538
157 === 'function') { 158 scheduleFlush = attemptVertx(); 159} else { 160 scheduleFlush = useSetTimeout(); 161} 162 163function then(onFulfillment, onRejection) { 164 var parent = this; 165 166 var child = new this.constructor(noop); 167 168 if (child[PROMISE_ID] === undefined) { 169 makePromise(child); 170 } 171 172 var _state = parent._state; 173 174 175 if (_state) { 176 var callback = arguments[_state - 1]; 177 asap(function () { 178 return invokeCallback(_state, child, callback, parent._result); 179 }); 180 } else { 181 subscribe(parent, child, onFulfillment, onRejection); 182 } 183 184 return child; 185} 186 187/** 188 `Promise.resolve` returns a promise that will become resolved with the 189 passed `value`. It is shorthand for the following: 190 191 ```javascript 192 let promise = new Promise(function(resolve, reject){ 193 resolve(1); 194 }); 195 196 promise.then(function(value){ 197 // value === 1 198 }); 199 ``` 200 201 Instead of writing the above, your code now simply becomes the following: 202 203 ```javascript 204 let promise = Promise.resolve(1); 205 206 promise.then(function(value){ 207 // value === 1 208 }); 209 ``` 210 211 @method resolve 212 @static 213 @param {Any} value value that the returned promise will be resolved with 214 Useful for tooling. 215 @return {Promise} a promise that will become fulfilled with the given 216 `value` 217*/ 218function resolve$1(object) { 219 /*jshint validthis:true */ 220 var Constructor = this; 221 222 if (object && typeof object === 'object' && object.constructor === Constructor) { 223 return object; 224 } 225 226 var promise = new Constructor(noop); 227 resolve(promise, object); 228 return promise; 229} 230 231var PROMISE_ID = Math.random().toString(36).substring(2); 232 233function noop() {} 234 235var PENDING = void 0; 236var FULFILLED = 1; 237var REJECTED = 2; 238 239var TRY_CATCH_ERROR = { error: null }; 240 241function selfFulfillment() { 242 return new TypeError("You cannot resolve a promise with itself"); 243} 244 245function cannotReturnOwn() { 246 return new TypeError('A promises callback cannot return that same promise.'); 247} 248 249function getThen(promise) { 250 try { 251 return promise.then; 252 } catch (error) { 253 TRY_CATCH_ERROR.error = error; 254 return TRY_CATCH_ERROR; 255 } 256} 257 258function tryThen(then$$1, value, fulfillmentHandler, rejectionHandler) { 259 try { 260 then$$1.call(value, fulfillmentHandler, rejectionHandler); 261 } catch (e) { 262 return e; 263 } 264} 265 266function handleForeignThenable(promise, thenable, then$$1) { 267 asap(function (promise) { 268 var sealed = false; 269 var error = tryThen(then$$1, thenable, function (value) { 270 if (sealed) { 271 return; 272 } 273 sealed = true; 274 if (thenable !== value) { 275 resolve(promise, value); 276 } else { 277 fulfill(promise, value); 278 } 279 }, function (reason) { 280 if (sealed) { 281 return; 282 } 283 sealed = true; 284 285 reject(promise, reason); 286 }, 'Settle: ' + (promise._label || ' unknown promise')); 287 288 if (!sealed && error) { 289 sealed = true; 290 reject(promise, error); 291 } 292 }, promise); 293} 294 295function handleOwnThenable(promise, thenable) { 296 if (thenable._state === FULFILLED) { 297 fulfill(promise, thenable._result); 298 } else if (thenable._state === REJECTED) { 299 reject(promise, thenable._result); 300 } else { 301 subscribe(thenable, undefined, function (value) { 302 return resolve(promise, value); 303 }, function (reason) { 304 return reject(promise, reason); 305 }); 306 } 307} 308 309function handleMaybeThenable(promise, maybeThenable, then$$1) { 310 if (maybeThenable.constructor === promise.constructor && then$$1 === then && maybeThenable.constructor.resolve === resolve$1) { 311 handleOwnThenable(promise, maybeThenable); 312 } else { 313 if (then$$1 === TRY_CATCH_ERROR) { 314 reject(promise, TRY_CATCH_ERROR.error); 315 TRY_CATCH_ERROR.error = null; 316 } else if (then$$1 === undefined) { 317 fulfill(promise, maybeThenable); 318 } else if (isFunction(then$$1)) { 319 handleForeignThenable(promise, maybeThenable, then$$1); 320 } else { 321 fulfill(promise, maybeThenable); 322 } 323 } 324} 325 326function resolve(promise, value) { 327 if (promise === value) { 328 reject(promise, selfFulfillment()); 329 } else if (objectOrFunction(value)) { 330 handleMaybeThenable(promise, value, getThen(value)); 331 } else { 332 fulfill(promise, value); 333 } 334} 335 336function publishRejection(promise) { 337 if (promise._onerror) { 338 promise._onerror(promise._result); 339 } 340 341 publish(promise); 342} 343 344function fulfill(promise, value) { 345 if (promise._state !== PENDING) { 346 return; 347 } 348 349 promise._result = value; 350 promise._state = FULFILLED; 351 352 if (promise._subscribers.length !== 0) { 353 asap(publish, promise); 354 } 355} 356 357function reject(promise, reason) { 358 if (promise._state !== PENDING) { 359 return; 360 } 361 promise._state = REJECTED; 362 promise._result = reason; 363 364 asap(publishRejection, promise); 365} 366 367function subscribe(parent, child, onFulfillment, onRejection) { 368 var _subscribers = parent._subscribers; 369 var length = _subscribers.length; 370 371 372 parent._onerror = null; 373 374 _subscribers[length] = child; 375 _subscribers[length + FULFILLED] = onFulfillment; 376 _subscribers[length + REJECTED] = onRejection; 377 378 if (length === 0 && parent._state) { 379 asap(publish, parent); 380 } 381} 382 383function publish(promise) { 384 var subscribers = promise._subscribers; 385 var settled = promise._state; 386 387 if (subscribers.length === 0) { 388 return; 389 } 390 391 var child = void 0, 392 callback = void 0, 393 detail = promise._result; 394 395 for (var i = 0; i < subscribers.length; i += 3) { 396 child = subscribers[i]; 397 callback = subscribers[i + settled]; 398 399 if (child) { 400 invokeCallback(settled, child, callback, detail); 401 } else { 402 callback(detail); 403 } 404 } 405 406 promise._subscribers.length = 0; 407} 408 409function tryCatch(callback, detail) { 410 try { 411 return callback(detail); 412 } catch (e) { 413 TRY_CATCH_ERROR.error = e; 414 return TRY_CATCH_ERROR; 415 } 416} 417 418function invokeCallback(settled, promise, callback, detail) { 419 var hasCallback = isFunction(callback), 420 value = void 0, 421 error = void 0, 422 succeeded = void 0, 423 failed = void 0; 424 425 if (hasCallback) { 426 value = tryCatch(callback, detail); 427 428 if (value === TRY_CATCH_ERROR) { 429 failed = true; 430 error = value.error; 431 value.error = null; 432 } else { 433 succeeded = true; 434 } 435 436 if (promise === value) { 437 reject(promise, cannotReturnOwn()); 438 return; 439 } 440 } else { 441 value = detail; 442 succeeded = true; 443 } 444 445 if (promise._state !== PENDING) { 446 // noop 447 } else if (hasCallback && succeeded) { 448 resolve(promise, value); 449 } else if (failed) { 450 reject(promise, error); 451 } else if (settled === FULFILLED) { 452 fulfill(promise, value); 453 } else if (settled === REJECTED) { 454 reject(promise, value); 455 } 456} 457 458function initializePromise(promise, resolver) { 459 try { 460 resolver(function resolvePromise(value) { 461 resolve(promise, value); 462 }, function rejectPromise(reason) { 463 reject(promise, reason); 464 }); 465 } catch (e) { 466 reject(promise, e); 467 } 468} 469 470var id = 0; 471function nextId() { 472 return id++; 473} 474 475function makePromise(promise) { 476 promise[PROMISE_ID] = id++; 477 promise._state = undefined; 478 promise._result = undefined; 479 promise._subscribers = []; 480} 481 482function validationError() { 483 return new Error('Array Methods must be provided an Array'); 484} 485 486var Enumerator = function () { 487 function Enumerator(Constructor, input) { 488 this._instanceConstructor = Constructor; 489 this.promise = new Constructor(noop); 490 491 if (!this.promise[PROMISE_ID]) { 492 makePromise(this.promise); 493 } 494 495 if (isArray(input)) { 496 this.length = input.length; 497 this._remaining = input.length; 498 499 this._result = new Array(this.length); 500 501 if (this.length === 0) { 502 fulfill(this.promise, this._result); 503 } else { 504 this.length = this.length || 0; 505 this._enumerate(input); 506 if (this._remaining === 0) { 507 fulfill(this.promise, this._result); 508 } 509 } 510 } else { 511 reject(this.promise, validationError()); 512 } 513 } 514 515 Enumerator.prototype._enumerate = function _enumerate(input) { 516 for (var i = 0; this._state === PENDING && i < input.length; i++) { 517 this._eachEntry(input[i], i); 518 } 519 }; 520 521 Enumerator.prototype._eachEntry = function _eachEntry(entry, i) { 522 var c = this._instanceConstructor; 523 var resolve$$1 = c.resolve; 524 525 526 if (resolve$$1 === resolve$1) { 527 var _then = getThen(entry); 528 529 if (_then === then && entry._state !== PENDING) { 530 this._settledAt(entry._state, i, entry._result); 531 } else if (typeof _then !== 'function') { 532 this._remaining--; 533 this._result[i] = entry; 534 } else if (c === Promise$1) { 535 var promise = new c(noop); 536 handleMaybeThenable(promise, entry, _then); 537 this._willSettleAt(promise, i); 538 } else {
vendor: 16,494 bytes, lines 539-1184
539 this._willSettleAt(new c(function (resolve$$1) { 540 return resolve$$1(entry); 541 }), i); 542 } 543 } else { 544 this._willSettleAt(resolve$$1(entry), i); 545 } 546 }; 547 548 Enumerator.prototype._settledAt = function _settledAt(state, i, value) { 549 var promise = this.promise; 550 551 552 if (promise._state === PENDING) { 553 this._remaining--; 554 555 if (state === REJECTED) { 556 reject(promise, value); 557 } else { 558 this._result[i] = value; 559 } 560 } 561 562 if (this._remaining === 0) { 563 fulfill(promise, this._result); 564 } 565 }; 566 567 Enumerator.prototype._willSettleAt = function _willSettleAt(promise, i) { 568 var enumerator = this; 569 570 subscribe(promise, undefined, function (value) { 571 return enumerator._settledAt(FULFILLED, i, value); 572 }, function (reason) { 573 return enumerator._settledAt(REJECTED, i, reason); 574 }); 575 }; 576 577 return Enumerator; 578}(); 579 580/** 581 `Promise.all` accepts an array of promises, and returns a new promise which 582 is fulfilled with an array of fulfillment values for the passed promises, or 583 rejected with the reason of the first passed promise to be rejected. It casts all 584 elements of the passed iterable to promises as it runs this algorithm. 585 586 Example: 587 588 ```javascript 589 let promise1 = resolve(1); 590 let promise2 = resolve(2); 591 let promise3 = resolve(3); 592 let promises = [ promise1, promise2, promise3 ]; 593 594 Promise.all(promises).then(function(array){ 595 // The array here would be [ 1, 2, 3 ]; 596 }); 597 ``` 598 599 If any of the `promises` given to `all` are rejected, the first promise 600 that is rejected will be given as an argument to the returned promises's 601 rejection handler. For example: 602 603 Example: 604 605 ```javascript 606 let promise1 = resolve(1); 607 let promise2 = reject(new Error("2")); 608 let promise3 = reject(new Error("3")); 609 let promises = [ promise1, promise2, promise3 ]; 610 611 Promise.all(promises).then(function(array){ 612 // Code here never runs because there are rejected promises! 613 }, function(error) { 614 // error.message === "2" 615 }); 616 ``` 617 618 @method all 619 @static 620 @param {Array} entries array of promises 621 @param {String} label optional string for labeling the promise. 622 Useful for tooling. 623 @return {Promise} promise that is fulfilled when all `promises` have been 624 fulfilled, or rejected if any of them become rejected. 625 @static 626*/ 627function all(entries) { 628 return new Enumerator(this, entries).promise; 629} 630 631/** 632 `Promise.race` returns a new promise which is settled in the same way as the 633 first passed promise to settle. 634 635 Example: 636 637 ```javascript 638 let promise1 = new Promise(function(resolve, reject){ 639 setTimeout(function(){ 640 resolve('promise 1'); 641 }, 200); 642 }); 643 644 let promise2 = new Promise(function(resolve, reject){ 645 setTimeout(function(){ 646 resolve('promise 2'); 647 }, 100); 648 }); 649 650 Promise.race([promise1, promise2]).then(function(result){ 651 // result === 'promise 2' because it was resolved before promise1 652 // was resolved. 653 }); 654 ``` 655 656 `Promise.race` is deterministic in that only the state of the first 657 settled promise matters. For example, even if other promises given to the 658 `promises` array argument are resolved, but the first settled promise has 659 become rejected before the other promises became fulfilled, the returned 660 promise will become rejected: 661 662 ```javascript 663 let promise1 = new Promise(function(resolve, reject){ 664 setTimeout(function(){ 665 resolve('promise 1'); 666 }, 200); 667 }); 668 669 let promise2 = new Promise(function(resolve, reject){ 670 setTimeout(function(){ 671 reject(new Error('promise 2')); 672 }, 100); 673 }); 674 675 Promise.race([promise1, promise2]).then(function(result){ 676 // Code here never runs 677 }, function(reason){ 678 // reason.message === 'promise 2' because promise 2 became rejected before 679 // promise 1 became fulfilled 680 }); 681 ``` 682 683 An example real-world use case is implementing timeouts: 684 685 ```javascript 686 Promise.race([ajax('foo.json'), timeout(5000)]) 687 ``` 688 689 @method race 690 @static 691 @param {Array} promises array of promises to observe 692 Useful for tooling. 693 @return {Promise} a promise which settles in the same way as the first passed 694 promise to settle. 695*/ 696function race(entries) { 697 /*jshint validthis:true */ 698 var Constructor = this; 699 700 if (!isArray(entries)) { 701 return new Constructor(function (_, reject) { 702 return reject(new TypeError('You must pass an array to race.')); 703 }); 704 } else { 705 return new Constructor(function (resolve, reject) { 706 var length = entries.length; 707 for (var i = 0; i < length; i++) { 708 Constructor.resolve(entries[i]).then(resolve, reject); 709 } 710 }); 711 } 712} 713 714/** 715 `Promise.reject` returns a promise rejected with the passed `reason`. 716 It is shorthand for the following: 717 718 ```javascript 719 let promise = new Promise(function(resolve, reject){ 720 reject(new Error('WHOOPS')); 721 }); 722 723 promise.then(function(value){ 724 // Code here doesn't run because the promise is rejected! 725 }, function(reason){ 726 // reason.message === 'WHOOPS' 727 }); 728 ``` 729 730 Instead of writing the above, your code now simply becomes the following: 731 732 ```javascript 733 let promise = Promise.reject(new Error('WHOOPS')); 734 735 promise.then(function(value){ 736 // Code here doesn't run because the promise is rejected! 737 }, function(reason){ 738 // reason.message === 'WHOOPS' 739 }); 740 ``` 741 742 @method reject 743 @static 744 @param {Any} reason value that the returned promise will be rejected with. 745 Useful for tooling. 746 @return {Promise} a promise rejected with the given `reason`. 747*/ 748function reject$1(reason) { 749 /*jshint validthis:true */ 750 var Constructor = this; 751 var promise = new Constructor(noop); 752 reject(promise, reason); 753 return promise; 754} 755 756function needsResolver() { 757 throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); 758} 759 760function needsNew() { 761 throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); 762} 763 764/** 765 Promise objects represent the eventual result of an asynchronous operation. The 766 primary way of interacting with a promise is through its `then` method, which 767 registers callbacks to receive either a promise's eventual value or the reason 768 why the promise cannot be fulfilled. 769 770 Terminology 771 ----------- 772 773 - `promise` is an object or function with a `then` method whose behavior conforms to this specification. 774 - `thenable` is an object or function that defines a `then` method. 775 - `value` is any legal JavaScript value (including undefined, a thenable, or a promise). 776 - `exception` is a value that is thrown using the throw statement. 777 - `reason` is a value that indicates why a promise was rejected. 778 - `settled` the final resting state of a promise, fulfilled or rejected. 779 780 A promise can be in one of three states: pending, fulfilled, or rejected. 781 782 Promises that are fulfilled have a fulfillment value and are in the fulfilled 783 state. Promises that are rejected have a rejection reason and are in the 784 rejected state. A fulfillment value is never a thenable. 785 786 Promises can also be said to *resolve* a value. If this value is also a 787 promise, then the original promise's settled state will match the value's 788 settled state. So a promise that *resolves* a promise that rejects will 789 itself reject, and a promise that *resolves* a promise that fulfills will 790 itself fulfill. 791 792 793 Basic Usage: 794 ------------ 795 796 ```js 797 let promise = new Promise(function(resolve, reject) { 798 // on success 799 resolve(value); 800 801 // on failure 802 reject(reason); 803 }); 804 805 promise.then(function(value) { 806 // on fulfillment 807 }, function(reason) { 808 // on rejection 809 }); 810 ``` 811 812 Advanced Usage: 813 --------------- 814 815 Promises shine when abstracting away asynchronous interactions such as 816 `XMLHttpRequest`s. 817 818 ```js 819 function getJSON(url) { 820 return new Promise(function(resolve, reject){ 821 let xhr = new XMLHttpRequest(); 822 823 xhr.open('GET', url); 824 xhr.onreadystatechange = handler; 825 xhr.responseType = 'json'; 826 xhr.setRequestHeader('Accept', 'application/json'); 827 xhr.send(); 828 829 function handler() { 830 if (this.readyState === this.DONE) { 831 if (this.status === 200) { 832 resolve(this.response); 833 } else { 834 reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']')); 835 } 836 } 837 }; 838 }); 839 } 840 841 getJSON('/posts.json').then(function(json) { 842 // on fulfillment 843 }, function(reason) { 844 // on rejection 845 }); 846 ``` 847 848 Unlike callbacks, promises are great composable primitives. 849 850 ```js 851 Promise.all([ 852 getJSON('/posts'), 853 getJSON('/comments') 854 ]).then(function(values){ 855 values[0] // => postsJSON 856 values[1] // => commentsJSON 857 858 return values; 859 }); 860 ``` 861 862 @class Promise 863 @param {Function} resolver 864 Useful for tooling. 865 @constructor 866*/ 867 868var Promise$1 = function () { 869 function Promise(resolver) { 870 this[PROMISE_ID] = nextId(); 871 this._result = this._state = undefined; 872 this._subscribers = []; 873 874 if (noop !== resolver) { 875 typeof resolver !== 'function' && needsResolver(); 876 this instanceof Promise ? initializePromise(this, resolver) : needsNew(); 877 } 878 } 879 880 /** 881 The primary way of interacting with a promise is through its `then` method, 882 which registers callbacks to receive either a promise's eventual value or the 883 reason why the promise cannot be fulfilled. 884 ```js 885 findUser().then(function(user){ 886 // user is available 887 }, function(reason){ 888 // user is unavailable, and you are given the reason why 889 }); 890 ``` 891 Chaining 892 -------- 893 The return value of `then` is itself a promise. This second, 'downstream' 894 promise is resolved with the return value of the first promise's fulfillment 895 or rejection handler, or rejected if the handler throws an exception. 896 ```js 897 findUser().then(function (user) { 898 return user.name; 899 }, function (reason) { 900 return 'default name'; 901 }).then(function (userName) { 902 // If `findUser` fulfilled, `userName` will be the user's name, otherwise it 903 // will be `'default name'` 904 }); 905 findUser().then(function (user) { 906 throw new Error('Found user, but still unhappy'); 907 }, function (reason) { 908 throw new Error('`findUser` rejected and we're unhappy'); 909 }).then(function (value) { 910 // never reached 911 }, function (reason) { 912 // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'. 913 // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'. 914 }); 915 ``` 916 If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream. 917 ```js 918 findUser().then(function (user) { 919 throw new PedagogicalException('Upstream error'); 920 }).then(function (value) { 921 // never reached 922 }).then(function (value) { 923 // never reached 924 }, function (reason) { 925 // The `PedgagocialException` is propagated all the way down to here 926 }); 927 ``` 928 Assimilation 929 ------------ 930 Sometimes the value you want to propagate to a downstream promise can only be 931 retrieved asynchronously. This can be achieved by returning a promise in the 932 fulfillment or rejection handler. The downstream promise will then be pending 933 until the returned promise is settled. This is called *assimilation*. 934 ```js 935 findUser().then(function (user) { 936 return findCommentsByAuthor(user); 937 }).then(function (comments) { 938 // The user's comments are now available 939 }); 940 ``` 941 If the assimliated promise rejects, then the downstream promise will also reject. 942 ```js 943 findUser().then(function (user) { 944 return findCommentsByAuthor(user); 945 }).then(function (comments) { 946 // If `findCommentsByAuthor` fulfills, we'll have the value here 947 }, function (reason) { 948 // If `findCommentsByAuthor` rejects, we'll have the reason here 949 }); 950 ``` 951 Simple Example 952 -------------- 953 Synchronous Example 954 ```javascript 955 let result; 956 try { 957 result = findResult(); 958 // success 959 } catch(reason) { 960 // failure 961 } 962 ``` 963 Errback Example 964 ```js 965 findResult(function(result, err){ 966 if (err) { 967 // failure 968 } else { 969 // success 970 } 971 }); 972 ``` 973 Promise Example; 974 ```javascript 975 findResult().then(function(result){ 976 // success 977 }, function(reason){ 978 // failure 979 }); 980 ``` 981 Advanced Example 982 -------------- 983 Synchronous Example 984 ```javascript 985 let author, books; 986 try { 987 author = findAuthor(); 988 books = findBooksByAuthor(author); 989 // success 990 } catch(reason) { 991 // failure 992 } 993 ``` 994 Errback Example 995 ```js 996 function foundBooks(books) { 997 } 998 function failure(reason) { 999 } 1000 findAuthor(function(author, err){ 1001 if (err) { 1002 failure(err); 1003 // failure 1004 } else { 1005 try { 1006 findBoooksByAuthor(author, function(books, err) { 1007 if (err) { 1008 failure(err); 1009 } else { 1010 try { 1011 foundBooks(books); 1012 } catch(reason) { 1013 failure(reason); 1014 } 1015 } 1016 }); 1017 } catch(error) { 1018 failure(err); 1019 } 1020 // success 1021 } 1022 }); 1023 ``` 1024 Promise Example; 1025 ```javascript 1026 findAuthor(). 1027 then(findBooksByAuthor). 1028 then(function(books){ 1029 // found books 1030 }).catch(function(reason){ 1031 // something went wrong 1032 }); 1033 ``` 1034 @method then 1035 @param {Function} onFulfilled 1036 @param {Function} onRejected 1037 Useful for tooling. 1038 @return {Promise} 1039 */ 1040 1041 /** 1042 `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same 1043 as the catch block of a try/catch statement. 1044 ```js 1045 function findAuthor(){ 1046 throw new Error('couldn't find that author'); 1047 } 1048 // synchronous 1049 try { 1050 findAuthor(); 1051 } catch(reason) { 1052 // something went wrong 1053 } 1054 // async with promises 1055 findAuthor().catch(function(reason){ 1056 // something went wrong 1057 }); 1058 ``` 1059 @method catch 1060 @param {Function} onRejection 1061 Useful for tooling. 1062 @return {Promise} 1063 */ 1064 1065 1066 Promise.prototype.catch = function _catch(onRejection) { 1067 return this.then(null, onRejection); 1068 }; 1069 1070 /** 1071 `finally` will be invoked regardless of the promise's fate just as native 1072 try/catch/finally behaves 1073 1074 Synchronous example: 1075 1076 ```js 1077 findAuthor() { 1078 if (Math.random() > 0.5) { 1079 throw new Error(); 1080 } 1081 return new Author(); 1082 } 1083 1084 try { 1085 return findAuthor(); // succeed or fail 1086 } catch(error) { 1087 return findOtherAuther(); 1088 } finally { 1089 // always runs 1090 // doesn't affect the return value 1091 } 1092 ``` 1093 1094 Asynchronous example: 1095 1096 ```js 1097 findAuthor().catch(function(reason){ 1098 return findOtherAuther(); 1099 }).finally(function(){ 1100 // author was either found, or not 1101 }); 1102 ``` 1103 1104 @method finally 1105 @param {Function} callback 1106 @return {Promise} 1107 */ 1108 1109 1110 Promise.prototype.finally = function _finally(callback) { 1111 var promise = this; 1112 var constructor = promise.constructor; 1113 1114 if (isFunction(callback)) { 1115 return promise.then(function (value) { 1116 return constructor.resolve(callback()).then(function () { 1117 return value; 1118 }); 1119 }, function (reason) { 1120 return constructor.resolve(callback()).then(function () { 1121 throw reason; 1122 }); 1123 }); 1124 } 1125 1126 return promise.then(callback, callback); 1127 }; 1128 1129 return Promise; 1130}(); 1131 1132Promise$1.prototype.then = then; 1133Promise$1.all = all; 1134Promise$1.race = race; 1135Promise$1.resolve = resolve$1; 1136Promise$1.reject = reject$1; 1137Promise$1._setScheduler = setScheduler; 1138Promise$1._setAsap = setAsap; 1139Promise$1._asap = asap; 1140 1141/*global self*/ 1142function polyfill() { 1143 var local = void 0; 1144 1145 if (typeof global !== 'undefined') { 1146 local = global; 1147 } else if (typeof self !== 'undefined') { 1148 local = self; 1149 } else { 1150 try { 1151 local = Function('return this')(); 1152 } catch (e) { 1153 throw new Error('polyfill failed because global object is unavailable in this environment'); 1154 } 1155 } 1156 1157 var P = local.Promise; 1158 1159 if (P) { 1160 var promiseToString = null; 1161 try { 1162 promiseToString = Object.prototype.toString.call(P.resolve()); 1163 } catch (e) { 1164 // silently ignored 1165 } 1166 1167 if (promiseToString === '[object Promise]' && !P.cast) { 1168 return; 1169 } 1170 } 1171 1172 local.Promise = Promise$1; 1173} 1174 1175// Strange compat.. 1176Promise$1.polyfill = polyfill; 1177Promise$1.Promise = Promise$1; 1178 1179return Promise$1; 1180 1181}))); 1182 1183 1184
1185 1186 1187}).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 1188 1189},{"_process":3}],2:[function(_dereq_,module,exports){ 1190// Copyright Joyent, Inc. and other Node contributors. 1191// 1192// Permission is hereby granted, free of charge, to any person obtaining a 1193// copy of this software and associated documentation files (the 1194// "Software"), to deal in the Software without restriction, including 1195// without limitation the rights to use, copy, modify, merge, publish, 1196// distribute, sublicense, and/or sell copies of the Software, and to permit 1197// persons to whom the Software is furnished to do so, subject to the 1198// following conditions: 1199// 1200// The above copyright notice and this permission notice shall be included 1201// in all copies or substantial portions of the Software. 1202// 1203// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 1204// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1205// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 1206// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 1207// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 1208// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 1209// USE OR OTHER DEALINGS IN THE SOFTWARE. 1210 1211function EventEmitter() { 1212 this._events = this._events || {}; 1213 this._maxListeners = this._maxListeners || undefined; 1214} 1215module.exports = EventEmitter; 1216 1217// Backwards-compat with node 0.10.x 1218EventEmitter.EventEmitter = EventEmitter; 1219 1220EventEmitter.prototype._events = undefined; 1221EventEmitter.prototype._maxListeners = undefined; 1222 1223// By default EventEmitters will print a warning if more than 10 listeners are 1224// added to it. This is a useful default which helps finding memory leaks. 1225EventEmitter.defaultMaxListeners = 10; 1226 1227// Obviously not all Emitters should be limited to 10. This function allows 1228// that to be increased. Set to zero for unlimited. 1229EventEmitter.prototype.setMaxListeners = function(n) { 1230 if (!isNumber(n) || n < 0 || isNaN(n)) 1231 throw TypeError('n must be a positive number'); 1232 this._maxListeners = n; 1233 return this; 1234}; 1235 1236EventEmitter.prototype.emit = function(type) { 1237 var er, handler, len, args, i, listeners; 1238 1239 if (!this._events) 1240 this._events = {}; 1241 1242 // If there is no 'error' event listener then throw. 1243 if (type === 'error') { 1244 if (!this._events.error || 1245 (isObject(this._events.error) && !this._events.error.length)) { 1246 er = arguments[1]; 1247 if (er instanceof Error) { 1248 //throw er; // Unhandled 'error' event //Edited By BuddyBoss 1249 } else { 1250 // At least give some kind of context to the user 1251 var err = new Error('Uncaught, unspecified "error" event. (' + er + ')'); 1252 err.context = er; 1253 //throw err; //Edited By BuddyBoss 1254 } 1255 } 1256 } 1257 1258 handler = this._events[type]; 1259 1260 if (isUndefined(handler)) 1261 return false;
vendor: 5,655 bytes, lines 1262-1493
1262 1263 if (isFunction(handler)) { 1264 switch (arguments.length) { 1265 // fast cases 1266 case 1: 1267 handler.call(this); 1268 break; 1269 case 2: 1270 handler.call(this, arguments[1]); 1271 break; 1272 case 3: 1273 handler.call(this, arguments[1], arguments[2]); 1274 break; 1275 // slower 1276 default: 1277 args = Array.prototype.slice.call(arguments, 1); 1278 handler.apply(this, args); 1279 } 1280 } else if (isObject(handler)) { 1281 args = Array.prototype.slice.call(arguments, 1); 1282 listeners = handler.slice(); 1283 len = listeners.length; 1284 for (i = 0; i < len; i++) 1285 listeners[i].apply(this, args); 1286 } 1287 1288 return true; 1289}; 1290 1291EventEmitter.prototype.addListener = function(type, listener) { 1292 var m; 1293 1294 if (!isFunction(listener)) 1295 throw TypeError('listener must be a function'); 1296 1297 if (!this._events) 1298 this._events = {}; 1299 1300 // To avoid recursion in the case that type === "newListener"! Before 1301 // adding it to the listeners, first emit "newListener". 1302 if (this._events.newListener) 1303 this.emit('newListener', type, 1304 isFunction(listener.listener) ? 1305 listener.listener : listener); 1306 1307 if (!this._events[type]) 1308 // Optimize the case of one listener. Don't need the extra array object. 1309 this._events[type] = listener; 1310 else if (isObject(this._events[type])) 1311 // If we've already got an array, just append. 1312 this._events[type].push(listener); 1313 else 1314 // Adding the second element, need to change to array. 1315 this._events[type] = [this._events[type], listener]; 1316 1317 // Check for listener leak 1318 if (isObject(this._events[type]) && !this._events[type].warned) { 1319 if (!isUndefined(this._maxListeners)) { 1320 m = this._maxListeners; 1321 } else { 1322 m = EventEmitter.defaultMaxListeners; 1323 } 1324 1325 if (m && m > 0 && this._events[type].length > m) { 1326 this._events[type].warned = true; 1327 console.error('(node) warning: possible EventEmitter memory ' + 1328 'leak detected. %d listeners added. ' + 1329 'Use emitter.setMaxListeners() to increase limit.', 1330 this._events[type].length); 1331 if (typeof console.trace === 'function') { 1332 // not supported in IE 10 1333 console.trace(); 1334 } 1335 } 1336 } 1337 1338 return this; 1339}; 1340 1341EventEmitter.prototype.on = EventEmitter.prototype.addListener; 1342 1343EventEmitter.prototype.once = function(type, listener) { 1344 if (!isFunction(listener)) 1345 throw TypeError('listener must be a function'); 1346 1347 var fired = false; 1348 1349 function g() { 1350 this.removeListener(type, g); 1351 1352 if (!fired) { 1353 fired = true; 1354 listener.apply(this, arguments); 1355 } 1356 } 1357 1358 g.listener = listener; 1359 this.on(type, g); 1360 1361 return this; 1362}; 1363 1364// emits a 'removeListener' event iff the listener was removed 1365EventEmitter.prototype.removeListener = function(type, listener) { 1366 var list, position, length, i; 1367 1368 if (!isFunction(listener)) 1369 throw TypeError('listener must be a function'); 1370 1371 if (!this._events || !this._events[type]) 1372 return this; 1373 1374 list = this._events[type]; 1375 length = list.length; 1376 position = -1; 1377 1378 if (list === listener || 1379 (isFunction(list.listener) && list.listener === listener)) { 1380 delete this._events[type]; 1381 if (this._events.removeListener) 1382 this.emit('removeListener', type, listener); 1383 1384 } else if (isObject(list)) { 1385 for (i = length; i-- > 0;) { 1386 if (list[i] === listener || 1387 (list[i].listener && list[i].listener === listener)) { 1388 position = i; 1389 break; 1390 } 1391 } 1392 1393 if (position < 0) 1394 return this; 1395 1396 if (list.length === 1) { 1397 list.length = 0; 1398 delete this._events[type]; 1399 } else { 1400 list.splice(position, 1); 1401 } 1402 1403 if (this._events.removeListener) 1404 this.emit('removeListener', type, listener); 1405 } 1406 1407 return this; 1408}; 1409 1410EventEmitter.prototype.removeAllListeners = function(type) { 1411 var key, listeners; 1412 1413 if (!this._events) 1414 return this; 1415 1416 // not listening for removeListener, no need to emit 1417 if (!this._events.removeListener) { 1418 if (arguments.length === 0) 1419 this._events = {}; 1420 else if (this._events[type]) 1421 delete this._events[type]; 1422 return this; 1423 } 1424 1425 // emit removeListener for all listeners on all events 1426 if (arguments.length === 0) { 1427 for (key in this._events) { 1428 if (key === 'removeListener') continue; 1429 this.removeAllListeners(key); 1430 } 1431 this.removeAllListeners('removeListener'); 1432 this._events = {}; 1433 return this; 1434 } 1435 1436 listeners = this._events[type]; 1437 1438 if (isFunction(listeners)) { 1439 this.removeListener(type, listeners); 1440 } else if (listeners) { 1441 // LIFO order 1442 while (listeners.length) 1443 this.removeListener(type, listeners[listeners.length - 1]); 1444 } 1445 delete this._events[type]; 1446 1447 return this; 1448}; 1449 1450EventEmitter.prototype.listeners = function(type) { 1451 var ret; 1452 if (!this._events || !this._events[type]) 1453 ret = []; 1454 else if (isFunction(this._events[type])) 1455 ret = [this._events[type]]; 1456 else 1457 ret = this._events[type].slice(); 1458 return ret; 1459}; 1460 1461EventEmitter.prototype.listenerCount = function(type) { 1462 if (this._events) { 1463 var evlistener = this._events[type]; 1464 1465 if (isFunction(evlistener)) 1466 return 1; 1467 else if (evlistener) 1468 return evlistener.length; 1469 } 1470 return 0; 1471}; 1472 1473EventEmitter.listenerCount = function(emitter, type) { 1474 return emitter.listenerCount(type); 1475}; 1476 1477function isFunction(arg) { 1478 return typeof arg === 'function'; 1479} 1480 1481function isNumber(arg) { 1482 return typeof arg === 'number'; 1483} 1484 1485function isObject(arg) { 1486 return typeof arg === 'object' && arg !== null; 1487} 1488 1489function isUndefined(arg) { 1490 return arg === void 0; 1491} 1492 1493},{}],3:[function(_dereq_
vendor: 5,443 bytes, lines 1493-1679
1493,module,exports){ 1494// shim for using process in browser 1495var process = module.exports = {}; 1496 1497// cached from whatever global is present so that test runners that stub it 1498// don't break things. But we need to wrap it in a try catch in case it is 1499// wrapped in strict mode code which doesn't define any globals. It's inside a 1500// function because try/catches deoptimize in certain engines. 1501 1502var cachedSetTimeout; 1503var cachedClearTimeout; 1504 1505function defaultSetTimout() { 1506 throw new Error('setTimeout has not been defined'); 1507} 1508function defaultClearTimeout () { 1509 throw new Error('clearTimeout has not been defined'); 1510} 1511(function () { 1512 try { 1513 if (typeof setTimeout === 'function') { 1514 cachedSetTimeout = setTimeout; 1515 } else { 1516 cachedSetTimeout = defaultSetTimout; 1517 } 1518 } catch (e) { 1519 cachedSetTimeout = defaultSetTimout; 1520 } 1521 try { 1522 if (typeof clearTimeout === 'function') { 1523 cachedClearTimeout = clearTimeout; 1524 } else { 1525 cachedClearTimeout = defaultClearTimeout; 1526 } 1527 } catch (e) { 1528 cachedClearTimeout = defaultClearTimeout; 1529 } 1530} ()) 1531function runTimeout(fun) { 1532 if (cachedSetTimeout === setTimeout) { 1533 //normal enviroments in sane situations 1534 return setTimeout(fun, 0); 1535 } 1536 // if setTimeout wasn't available but was latter defined 1537 if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { 1538 cachedSetTimeout = setTimeout; 1539 return setTimeout(fun, 0); 1540 } 1541 try { 1542 // when when somebody has screwed with setTimeout but no I.E. maddness 1543 return cachedSetTimeout(fun, 0); 1544 } catch(e){ 1545 try { 1546 // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally 1547 return cachedSetTimeout.call(null, fun, 0); 1548 } catch(e){ 1549 // 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 1550 return cachedSetTimeout.call(this, fun, 0); 1551 } 1552 } 1553 1554 1555} 1556function runClearTimeout(marker) { 1557 if (cachedClearTimeout === clearTimeout) { 1558 //normal enviroments in sane situations 1559 return clearTimeout(marker); 1560 } 1561 // if clearTimeout wasn't available but was latter defined 1562 if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { 1563 cachedClearTimeout = clearTimeout; 1564 return clearTimeout(marker); 1565 } 1566 try { 1567 // when when somebody has screwed with setTimeout but no I.E. maddness 1568 return cachedClearTimeout(marker); 1569 } catch (e){ 1570 try { 1571 // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally 1572 return cachedClearTimeout.call(null, marker); 1573 } catch (e){ 1574 // 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. 1575 // Some versions of I.E. have different rules for clearTimeout vs setTimeout 1576 return cachedClearTimeout.call(this, marker); 1577 } 1578 } 1579 1580 1581 1582} 1583var queue = []; 1584var draining = false; 1585var currentQueue; 1586var queueIndex = -1; 1587 1588function cleanUpNextTick() { 1589 if (!draining || !currentQueue) { 1590 return; 1591 } 1592 draining = false; 1593 if (currentQueue.length) { 1594 queue = currentQueue.concat(queue); 1595 } else { 1596 queueIndex = -1; 1597 } 1598 if (queue.length) { 1599 drainQueue(); 1600 } 1601} 1602 1603function drainQueue() { 1604 if (draining) { 1605 return; 1606 } 1607 var timeout = runTimeout(cleanUpNextTick); 1608 draining = true; 1609 1610 var len = queue.length; 1611 while(len) { 1612 currentQueue = queue; 1613 queue = []; 1614 while (++queueIndex < len) { 1615 if (currentQueue) { 1616 currentQueue[queueIndex].run(); 1617 } 1618 } 1619 queueIndex = -1; 1620 len = queue.length; 1621 } 1622 currentQueue = null; 1623 draining = false; 1624 runClearTimeout(timeout); 1625} 1626 1627process.nextTick = function (fun) { 1628 var args = new Array(arguments.length - 1); 1629 if (arguments.length > 1) { 1630 for (var i = 1; i < arguments.length; i++) { 1631 args[i - 1] = arguments[i]; 1632 } 1633 } 1634 queue.push(new Item(fun, args)); 1635 if (queue.length === 1 && !draining) { 1636 runTimeout(drainQueue); 1637 } 1638}; 1639 1640// v8 likes predictible objects 1641function Item(fun, array) { 1642 this.fun = fun; 1643 this.array = array; 1644} 1645Item.prototype.run = function () { 1646 this.fun.apply(null, this.array); 1647}; 1648process.title = 'browser'; 1649process.browser = true; 1650process.env = {}; 1651process.argv = []; 1652process.version = ''; // empty string to avoid regexp issues 1653process.versions = {}; 1654 1655function noop() {} 1656 1657process.on = noop; 1658process.addListener = noop; 1659process.once = noop; 1660process.off = noop; 1661process.removeListener = noop; 1662process.removeAllListeners = noop; 1663process.emit = noop; 1664process.prependListener = noop; 1665process.prependOnceListener = noop; 1666 1667process.listeners = function (name) { return [] } 1668 1669process.binding = function (name) { 1670 throw new Error('process.binding is not supported'); 1671}; 1672 1673process.cwd = function () { return '/' }; 1674process.chdir = function (dir) { 1675 throw new Error('process.chdir is not supported'); 1676}; 1677process.umask = function() { return 0; }; 1678 1679},{}],
16794:[function(_dereq_,module,exports){ 1680var bundleFn = arguments[3]; 1681var sources = arguments[4]; 1682var cache = arguments[5]; 1683 1684var stringify = JSON.stringify; 1685 1686module.exports = function (fn, options) { 1687 var wkey; 1688 var cacheKeys = Object.keys(cache); 1689 1690 for (var i = 0, l = cacheKeys.length; i < l; i++) { 1691 var key = cacheKeys[i]; 1692 var exp = cache[key].exports; 1693 // Using babel as a transpiler to use esmodule, the export will always 1694 // be an object with the default export as a property of it. To ensure 1695 // the existing api and babel esmodule exports are both supported we 1696 // check for both 1697 if (exp === fn || exp && exp.default === fn) { 1698 wkey = key; 1699 break; 1700 } 1701 } 1702 1703 if (!wkey) { 1704 wkey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16); 1705 var wcache = {}; 1706 for (var i = 0, l = cacheKeys.length; i < l; i++) { 1707 var key = cacheKeys[i]; 1708 wcache[key] = key; 1709 } 1710 sources[wkey] = [ 1711 'function(require,module,exports){' + fn + '(self); }', 1712 wcache 1713 ]; 1714 } 1715 var skey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16); 1716 1717 var scache = {}; scache[wkey] = wkey; 1718 sources[skey] = [ 1719 'function(require,module,exports){' + 1720 // try to call default if defined to also support babel esmodule exports 1721 'var f = require(' + stringify(wkey) + ');' + 1722 '(f.default ? f.default : f)(self);' + 1723 '}', 1724 scache 1725 ]; 1726 1727 var workerSources = {}; 1728 resolveSources(skey); 1729 1730 function resolveSources(key) { 1731 workerSources[key] = true; 1732 1733 for (var depPath in sources[key][1]) { 1734 var depKey = sources[key][1][depPath]; 1735 if (!workerSources[depKey]) { 1736 resolveSources(depKey); 1737 } 1738 } 1739 } 1740 1741 var src = '(' + bundleFn + ')({' 1742 + Object.keys(workerSources).map(function (key) { 1743 return stringify(key) + ':[' 1744 + sources[key][0] 1745 + ',' + stringify(sources[key][1]) + ']' 1746 ; 1747 }).join(',') 1748 + '},{},[' + stringify(skey) + '])' 1749 ; 1750 1751 var URL = window.URL || window.webkitURL || window.mozURL || window.msURL; 1752 1753 var blob = new Blob([src], { type: 'text/javascript' }); 1754 if (options && options.bare) { return blob; } 1755 var workerUrl = URL.createObjectURL(blob); 1756 var worker = new Worker(workerUrl); 1757 worker.objectURL = workerUrl; 1758 return worker; 1759}; 1760 1761},{}],5:[function(_dereq_,module,exports){ 1762'use strict'; 1763 1764Object.defineProperty(exports, "__esModule", { 1765 value: true 1766}); 1767exports.createDefaultConfig = createDefaultConfig; 1768/* 1769 * Copyright (C) 2016 Bilibili. All Rights Reserved. 1770 * 1771 * @author zheng qian <[email protected]> 1772 * 1773 * Licensed under the Apache License, Version 2.0 (the "License"); 1774 * you may not use this file except in compliance with the License. 1775 * You may obtain a copy of the License at 1776 * 1777 * http://www.apache.org/licenses/LICENSE-2.0 1778 * 1779 * Unless required by applicable law or agreed to in writing, software 1780 * distributed under the License is distributed on an "AS IS" BASIS, 1781 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1782 * See the License for the specific language governing permissions and 1783 * limitations under the License. 1784 */ 1785 1786var defaultConfig = exports.defaultConfig = { 1787 enableWorker: false, 1788 enableStashBuffer: true, 1789 stashInitialSize: undefined, 1790 1791 isLive: false, 1792 1793 lazyLoad: true, 1794 lazyLoadMaxDuration: 3 * 60, 1795 lazyLoadRecoverDuration: 30, 1796 deferLoadAfterSourceOpen: true, 1797 1798 // autoCleanupSourceBuffer: default as false, leave unspecified 1799 autoCleanupMaxBackwardDuration: 3 * 60, 1800 autoCleanupMinBackwardDuration: 2 * 60, 1801 1802 statisticsInfoReportInterval: 600, 1803 1804 fixAudioTimestampGap: true, 1805 1806 accurateSeek: false, 1807 seekType: 'range', // [range, param, custom] 1808 seekParamStart: 'bstart', 1809 seekParamEnd: 'bend', 1810 rangeLoadZeroStart: false, 1811 customSeekHandler: undefined, 1812 reuseRedirectedURL: false, 1813 // referrerPolicy: leave as unspecified 1814 1815 headers: undefined, 1816 customLoader: undefined 1817}; 1818 1819function createDefaultConfig() { 1820 return Object.assign({}, defaultConfig); 1821} 1822 1823},{}],6:[function(_dereq_,module,exports){ 1824'use strict'; 1825 1826Object.defineProperty(exports, "__esModule", { 1827 value: true 1828}); 1829 1830var _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; }; }(); /* 1831 * Copyright (C) 2016 Bilibili. All Rights Reserved. 1832 * 1833 * @author zheng qian <[email protected]> 1834 * 1835 * Licensed under the Apache License, Version 2.0 (the "License"); 1836 * you may
1836not use this file except in compliance with the License. 1837 * You may obtain a copy of the License at 1838 * 1839 * http://www.apache.org/licenses/LICENSE-2.0 1840 * 1841 * Unless required by applicable law or agreed to in writing, software 1842 * distributed under the License is distributed on an "AS IS" BASIS, 1843 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1844 * See the License for the specific language governing permissions and 1845 * limitations under the License. 1846 */ 1847 1848var _ioController = _dereq_('../io/io-controller.js'); 1849 1850var _ioController2 = _interopRequireDefault(_ioController); 1851 1852var _config = _dereq_('../config.js'); 1853 1854function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1855 1856function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 1857 1858var Features = function () { 1859 function Features() { 1860 _classCallCheck(this, Features); 1861 } 1862 1863 _createClass(Features, null, [{ 1864 key: 'supportMSEH264Playback', 1865 value: function supportMSEH264Playback() { 1866 return window.MediaSource && window.MediaSource.isTypeSupp
1866orted('video/mp4; codecs="avc1.42E01E,mp4a.40.2"'); 1867 } 1868 }, { 1869 key: 'supportNetworkStreamIO', 1870 value: function supportNetworkStreamIO() { 1871 var ioctl = new _ioController2.default({}, (0, _config.createDefaultConfig)()); 1872 var loaderType = ioctl.loaderType; 1873 ioctl.destroy(); 1874 return loaderType == 'fetch-stream-loader' || loaderType == 'xhr-moz-chunked-loader'; 1875 } 1876 }, { 1877 key: 'getNetworkLoaderTypeName', 1878 value: function getNetworkLoaderTypeName() { 1879 var ioctl = new _ioController2.default({}, (0, _config.createDefaultConfig)()); 1880 var loaderType = ioctl.loaderType; 1881 ioctl.destroy(); 1882 return loaderType; 1883 } 1884 }, { 1885 key: 'supportNativeMediaPlayback', 1886 value: function supportNativeMediaPlayback(mimeType) { 1887 if (Features.videoElement == undefined) { 1888 Features.videoElement = window.document.createElement('video'); 1889 } 1890 var canPlay = Features.videoElement.canPlayType(mimeType); 1891 return canPlay === 'probably' || canPlay == 'maybe'; 1892 } 1893 }, { 1894 key: 'getFeatureList', 1895 value: function getFeatureList() { 1896 var features = { 1897 mseFlvPlayback: false, 1898 mseLiveFlvPlayback: false, 1899 networkStreamIO: false, 1900 networkLoaderName: '', 1901 nativeMP4H264Playback: false, 1902 nativeWebmVP8Playback: false, 1903 nativeWebmVP9Playback: false 1904 }; 1905 1906 features.mseFlvPlayback = Features.supportMSEH264Playback(); 1907 features.networkStreamIO = Features.supportNetworkStreamIO(); 1908 features.networkLoaderName = Features.getNetworkLoaderTypeName(); 1909 features.mseLiveFlvPlayback = features.mseFlvPlayback && features.networkStreamIO; 1910 features.nativeMP4H264Playback = Features.supportNativeMediaPlayback('video/mp4; codecs="avc1.42001E, mp4a.40.2"'); 1911 features.nativeWebmVP8Playback = Features.supportNativeMediaPlayback('video/webm; codecs="vp8.0, vorbis"'); 1912 features.nativeWebmVP9Playback = Features.supportNativeMediaPlayback('video/webm; codecs="vp9"'); 1913 1914 return features; 1915 } 1916 }]); 1917 1918 return Features; 1919}(); 1920 1921exports.default = Features; 1922 1923},{"../config.js":5,"../io/io-controller.js":23}],7:[function(_dereq_,module,exports){ 1924"use strict"; 1925 1926Object.defineProperty(exports, "__esModule", { 1927 value: true 1928}); 1929 1930var _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; }; }(); 1931 1932function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 1933 1934/* 1935 * Copyright (C) 2016 Bilibili. All Rights Reserved. 1936 * 1937 * @author zheng qian <[email protected]> 1938 * 1939 * Licensed under the Apache License, Version 2.0 (the "License"); 1940 * you may not use this file except in compliance with the License. 1941 * You may obtain a copy of the License at 1942 * 1943 * http://www.apache.org/licenses/LICENSE-2.0 1944 * 1945 * Unless required by applicable law or agreed to in writing, software 1946 * distributed under the License is distributed on an "AS IS" BASIS, 1947 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1948 * See the License for the specific language governing permissions and 1949 * limitations under the License. 1950 */ 1951 1952var MediaInfo = function () { 1953 function MediaInfo() { 1954 _classCallCheck(this, MediaInfo); 1955 1956 this.mimeType = null; 1957 this.duration = null; 1958 1959 this.hasAudio = null; 1960 this.hasVideo = null; 1961 this.audioCodec = null; 1962 this.videoCodec = null; 1963 this.audioDataRate = null; 1964 this.videoDataRate = null; 1965 1966 this.audioSampleRate = null; 1967 this.audioChannelCount = null; 1968 1969 this.width = null; 1970 this.height = null; 1971 this.fps = null; 1972 this.profile = null; 1973 this.level = null; 1974 this.refFrames = null; 1975 this.chromaFormat = null; 1976 this.sarNum = null; 1977 this.sarDen = null; 1978 1979 this.metadata = null; 1980 this.segments = null; // MediaInfo[] 1981 this.segmentCount = null; 1982 this.hasKeyframesIndex = null; 1983 this.keyframesIndex = null; 1984 } 1985 1986 _createClass(MediaInfo, [{ 1987 key: "isComplete", 1988 value: function isComplete() { 1989 var audioInfoComplete = this.hasAudio === false || this.hasAudio === true && this.audioCodec != null && this.audioSampleRate != null && this.audioChannelCount != null; 1990 1991 var videoInfoComplete = this.hasVideo === false || this.hasVideo === true && this.videoCodec != null && this.width != null && this.height != null && this.fps != null && this.profile != null && this.level != null && this.refFrames != null && this.chromaFormat != null && this.sarNum != null && this.sarDen != null; 1992 1993 // keyframesIndex may not be present 1994 return this.mimeType != null && this.duration != null && this.metadata != null && this.hasKeyframesIndex != null && audioInfoComplete && videoInfoComplete; 1995 } 1996 }, {
1997 key: "isSeekable", 1998 value: function isSeekable() { 1999 return this.hasKeyframesIndex === true; 2000 } 2001 }, { 2002 key: "getNearestKeyframe", 2003 value: function getNearestKeyframe(milliseconds) { 2004 if (this.keyframesIndex == null) { 2005 return null; 2006 } 2007 2008 var table = this.keyframesIndex; 2009 var keyframeIdx = this._search(table.times, milliseconds); 2010 2011 return { 2012 index: keyframeIdx, 2013 milliseconds: table.times[keyframeIdx], 2014 fileposition: table.filepositions[keyframeIdx] 2015 }; 2016 } 2017 }, { 2018 key: "_search", 2019 value: function _search(list, value) { 2020 var idx = 0; 2021 2022 var last = list.length - 1; 2023 var mid = 0; 2024 var lbound = 0; 2025 var ubound = last; 2026 2027 if (value < list[0]) { 2028 idx = 0; 2029 lbound = ubound + 1; // skip search 2030 } 2031 2032 while (lbound <= ubound) { 2033 mid = lbound + Math.floor((ubound - lbound) / 2); 2034 if (mid === last || value >= list[mid] && value < list[mid + 1]) { 2035 idx = mid; 2036 break; 2037 } else if (list[mid] < value) { 2038 lbound = mid + 1; 2039 } else { 2040 ubound = mid - 1; 2041 } 2042 } 2043 2044 return idx; 2045 } 2046 }]); 2047 2048 return MediaInfo; 2049}(); 2050 2051exports.default = MediaInfo; 2052 2053},{}],8:[function(_dereq_,module,exports){ 2054"use strict"; 2055 2056Object.defineProperty(exports, "__esModule", { 2057 value: true 2058}); 2059 2060var _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; }; }(); 2061 2062function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 2063 2064/* 2065 * Copyright (C) 2016 Bilibili. All Rights Reserved. 2066 * 2067 * @author zheng qian <[email protected]> 2068 * 2069 * Licensed under the Apache License, Version 2.0 (the "License"); 2070 * you may not use this file except in compliance with the License. 2071 * You may obtain a copy of the License at 2072 * 2073 * http://www.apache.org/licenses/LICENSE-2.0 2074 * 2075 * Unless required by applicable law or agreed to in writing, software 2076 * distributed under the License is distributed on an "AS IS" BASIS, 2077 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2078 * See the License for the specific language governing permissions and 2079 * limitations under the License. 2080 */ 2081 2082// Represents an media sample (audio / video) 2083var SampleInfo = exports.SampleInfo = function SampleInfo(dts, pts, duration, originalDts, isSync) { 2084 _classCallCheck(this, SampleInfo); 2085 2086 this.dts = dts; 2087 this.pts = pts; 2088 this.duration = duration; 2089 this.originalDts = originalDts; 2090 this.isSyncPoint = isSync; 2091 this.fileposition = null; 2092}; 2093 2094// Media Segment concept is defined in Media Source Extensions spec. 2095// Particularly in ISO BMFF format, an Media Segment contains a moof box followed by a mdat box. 2096 2097 2098var MediaSegmentInfo = exports.MediaSegmentInfo = function () { 2099 function MediaSegmentInfo() { 2100 _classCallCheck(this, MediaSegmentInfo); 2101 2102 this.beginDts = 0; 2103 this.endDts = 0; 2104 this.beginPts = 0; 2105 this.endPts = 0; 2106 this.originalBeginDts = 0; 2107 this.originalEndDts = 0; 2108 this.syncPoints = []; // SampleInfo[n], for video IDR frames only 2109 this.firstSample = null; // SampleInfo 2110 this.lastSample = null; // SampleInfo 2111 } 2112 2113 _createClass(MediaSegmentInfo, [{ 2114 key: "appendSyncPoint", 2115 value: function appendSyncPoint(sampleInfo) { 2116 // also called Random Access Point 2117 sampleInfo.isSyncPoint = true; 2118 this.syncPoints.push(sampleInfo); 2119 } 2120 }]); 2121 2122 return MediaSegmentInfo; 2123}(); 2124 2125// Ordered list for recording video IDR frames, sorted by originalDts 2126 2127 2128var IDRSampleList = exports.IDRSampleList = function () { 2129 function IDRSampleList() { 2130 _classCallCheck(this, IDRSampleList); 2131 2132 this._list = []; 2133 } 2134 2135 _createClass(IDRSampleList, [{ 2136 key: "clear", 2137 value: function clear() { 2138 this._list = []; 2139 } 2140 }, {
2141 key: "appendArray", 2142 value: function appendArray(syncPoints) { 2143 var list = this._list; 2144 2145 if (syncPoints.length === 0) { 2146 return; 2147 } 2148 2149 if (list.length > 0 && syncPoints[0].originalDts < list[list.length - 1].originalDts) { 2150 this.clear(); 2151 } 2152 2153 Array.prototype.push.apply(list, syncPoints); 2154 } 2155 }, { 2156 key: "getLastSyncPointBeforeDts", 2157 value: function getLastSyncPointBeforeDts(dts) { 2158 if (this._list.length == 0) { 2159 return null; 2160 } 2161 2162 var list = this._list; 2163 var idx = 0; 2164 var last = list.length - 1; 2165 var mid = 0; 2166 var lbound = 0; 2167 var ubound = last; 2168 2169 if (dts < list[0].dts) { 2170 idx = 0; 2171 lbound = ubound + 1; 2172 } 2173 2174 while (lbound <= ubound) { 2175 mid = lbound + Math.floor((ubound - lbound) / 2); 2176 if (mid === last || dts >= list[mid].dts && dts < list[mid + 1].dts) { 2177 idx = mid; 2178 break; 2179 } else if (list[mid].dts < dts) { 2180 lbound = mid + 1; 2181 } else { 2182 ubound = mid - 1; 2183 } 2184 } 2185 return this._list[idx]; 2186 } 2187 }]); 2188 2189 return IDRSampleList; 2190}(); 2191 2192// Data structure for recording information of media segments in single track. 2193 2194 2195var MediaSegmentInfoList = exports.MediaSegmentInfoList = function () { 2196 function MediaSegmentInfoList(type) { 2197 _classCallCheck(this, MediaSegmentInfoList); 2198 2199 this._type = type; 2200 this._list = []; 2201 this._lastAppendLocation = -1; // cached last insert location 2202 } 2203 2204 _createClass(MediaSegmentInfoList, [{ 2205 key: "isEmpty", 2206 value: function isEmpty() { 2207 return this._list.length === 0; 2208 } 2209 }, { 2210 key: "clear", 2211 value: function clear() { 2212 this._list = []; 2213 this._lastAppendLocation = -1; 2214 } 2215 }, { 2216 key: "_searchNearestSegmentBefore", 2217 value: function _searchNearestSegmentBefore(originalBeginDts) { 2218 var list = this._list; 2219 if (list.length === 0) { 2220 return -2; 2221 } 2222 var last = list.length - 1; 2223 var mid = 0; 2224 var lbound = 0; 2225 var ubound = last; 2226 2227 var idx = 0; 2228 2229 if (originalBeginDts < list[0].originalBeginDts) { 2230 idx = -1; 2231 return idx; 2232 } 2233 2234 while (lbound <= ubound) { 2235 mid = lbound + Math.floor((ubound - lbound) / 2); 2236 if (mid === last || originalBeginDts > list[mid].lastSample.originalDts && originalBeginDts < list[mid + 1].originalBeginDts) { 2237 idx = mid; 2238 break; 2239 } else if (list[mid].originalBeginDts < originalBeginDts) { 2240 lbound = mid + 1; 2241 } else { 2242 ubound = mid - 1; 2243 } 2244 } 2245 return idx; 2246 } 2247 }, { 2248 key: "_searchNearestSegmentAfter", 2249 value: function _searchNearestSegmentAfter(originalBeginDts) { 2250 return this._searchNearestSegmentBefore(originalBeginDts) + 1; 2251 } 2252 }, { 2253 key: "append", 2254 value: function append(mediaSegmentInfo) { 2255 var list = this._list; 2256 var msi = mediaSegmentInfo; 2257 var lastAppendIdx = this._lastAppendLocation; 2258 var insertIdx = 0; 2259 2260 if (lastAppendIdx !== -1 && lastAppendIdx < list.length && msi.originalBeginDts >= list[lastAppendIdx].lastSample.originalDts && (lastAppendIdx === list.length - 1 || lastAppendIdx < list.length - 1 && msi.originalBeginDts < list[lastAppendIdx + 1].originalBeginDts)) { 2261 insertIdx = lastAppendIdx + 1; // use cached location idx 2262 } else { 2263 if (list.length > 0) { 2264 insertIdx = this._searchNearestSegmentBefore(msi.originalBeginDts) + 1; 2265 } 2266 } 2267 2268 this._lastAppendLocation = insertIdx; 2269 this._list.splice(insertIdx, 0, msi); 2270 } 2271 }, {
2272 key: "getLastSegmentBefore", 2273 value: function getLastSegmentBefore(originalBeginDts) { 2274 var idx = this._searchNearestSegmentBefore(originalBeginDts); 2275 if (idx >= 0) { 2276 return this._list[idx]; 2277 } else { 2278 // -1 2279 return null; 2280 } 2281 } 2282 }, { 2283 key: "getLastSampleBefore", 2284 value: function getLastSampleBefore(originalBeginDts) { 2285 var segment = this.getLastSegmentBefore(originalBeginDts); 2286 if (segment != null) { 2287 return segment.lastSample; 2288 } else { 2289 return null; 2290 } 2291 } 2292 }, { 2293 key: "getLastSyncPointBefore", 2294 value: function getLastSyncPointBefore(originalBeginDts) { 2295 var segmentIdx = this._searchNearestSegmentBefore(originalBeginDts); 2296 var syncPoints = this._list[segmentIdx].syncPoints; 2297 while (syncPoints.length === 0 && segmentIdx > 0) { 2298 segmentIdx--; 2299 syncPoints = this._list[segmentIdx].syncPoints; 2300 } 2301 if (syncPoints.length > 0) { 2302 return syncPoints[syncPoints.length - 1]; 2303 } else { 2304 return null; 2305 } 2306 } 2307 }, { 2308 key: "type", 2309 get: function get() { 2310 return this._type; 2311 } 2312 }, { 2313 key: "length", 2314 get: function get() { 2315 return this._list.length; 2316 } 2317 }]); 2318 2319 return MediaSegmentInfoList; 2320}(); 2321 2322},{}],9:[function(_dereq_,module,exports){ 2323'use strict'; 2324 2325Object.defineProperty(exports, "__esModule", { 2326 value: true 2327}); 2328 2329var _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; }; }(); /* 2330 * Copyright (C) 2016 Bilibili. All Rights Reserved. 2331 * 2332 * @author zheng qian <[email protected]> 2333 * 2334 * Licensed under the Apache License, Version 2.0 (the "License"); 2335 * you may
2335not use this file except in compliance with the License. 2336 * You may obtain a copy of the License at 2337 * 2338 * http://www.apache.org/licenses/LICENSE-2.0 2339 * 2340 * Unless required by applicable law or agreed to in writing, software 2341 * distributed under the License is distributed on an "AS IS" BASIS, 2342 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2343 * See the License for the specific language governing permissions and 2344 * limitations under the License. 2345 */ 2346 2347var _events = _dereq_('events'); 2348 2349var _events2 = _interopRequireDefault(_events); 2350 2351var _logger = _dereq_('../utils/logger.js'); 2352 2353var _logger2 = _interopRequireDefault(_logger); 2354 2355var _browser = _dereq_('../utils/browser.js'); 2356 2357var _browser2 = _interopRequireDefault(_browser); 2358 2359var _mseEvents = _dereq_('./mse-events.js'); 2360 2361var _mseEvents2 = _interopRequireDefault(_mseEvents); 2362 2363var _mediaSegmentInfo = _dereq_('./media-segment-info.js'); 2364 2365var _exception = _dereq_('../utils/exception.js'); 2366 2367function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 2368 2369function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 2370 2371// Media Source Extensions controller 2372var MSEController = function () { 2373 function MSEController(config) { 2374 _classCallCheck(this, MSEController); 2375 2376 this.TAG = 'MSEController'; 2377 2378 this._config = config; 2379 this._emitter = new _events2.default(); 2380 2381 if (this._config.isLive && this._config.autoCleanupSourceBuffer == undefined) { 2382 // For live stream, do auto cleanup by default 2383 this._config.autoCleanupSourceBuffer = true; 2384 } 2385 2386 this.e = { 2387 onSourceOpen: this._onSourceOpen.bind(this), 2388 onSourceEnded: this._onSourceEnded.bind(this), 2389 onSourceClose: this._onSourceClose.bind(this), 2390 onSourceBufferError: this._onSourceBufferError.bind(this), 2391 onSourceBufferUpdateEnd: this._onSourceBufferUpdateEnd.bind(this) 2392 }; 2393 2394 this._mediaSource = null; 2395 this._mediaSourceObjectURL = null; 2396 this._mediaElement = null; 2397 2398 this._isBufferFull = false;
vendor: 12,391 bytes, lines 2399-2692
2399 this._hasPendingEos = false; 2400 2401 this._requireSetMediaDuration = false; 2402 this._pendingMediaDuration = 0; 2403 2404 this._pendingSourceBufferInit = []; 2405 this._mimeTypes = { 2406 video: null, 2407 audio: null 2408 }; 2409 this._sourceBuffers = { 2410 video: null, 2411 audio: null 2412 }; 2413 this._lastInitSegments = { 2414 video: null, 2415 audio: null 2416 }; 2417 this._pendingSegments = { 2418 video: [], 2419 audio: [] 2420 }; 2421 this._pendingRemoveRanges = { 2422 video: [], 2423 audio: [] 2424 }; 2425 this._idrList = new _mediaSegmentInfo.IDRSampleList(); 2426 } 2427 2428 _createClass(MSEController, [{ 2429 key: 'destroy', 2430 value: function destroy() { 2431 if (this._mediaElement || this._mediaSource) { 2432 this.detachMediaElement(); 2433 } 2434 this.e = null; 2435 this._emitter.removeAllListeners(); 2436 this._emitter = null; 2437 } 2438 }, { 2439 key: 'on', 2440 value: function on(event, listener) { 2441 this._emitter.addListener(event, listener); 2442 } 2443 }, { 2444 key: 'off', 2445 value: function off(event, listener) { 2446 this._emitter.removeListener(event, listener); 2447 } 2448 }, { 2449 key: 'attachMediaElement', 2450 value: function attachMediaElement(mediaElement) { 2451 if (this._mediaSource) { 2452 throw new _exception.IllegalStateException('MediaSource has been attached to an HTMLMediaElement!'); 2453 } 2454 var ms = this._mediaSource = new window.MediaSource(); 2455 ms.addEventListener('sourceopen', this.e.onSourceOpen); 2456 ms.addEventListener('sourceended', this.e.onSourceEnded); 2457 ms.addEventListener('sourceclose', this.e.onSourceClose); 2458 2459 this._mediaElement = mediaElement; 2460 this._mediaSourceObjectURL = window.URL.createObjectURL(this._mediaSource); 2461 mediaElement.src = this._mediaSourceObjectURL; 2462 } 2463 }, { 2464 key: 'detachMediaElement', 2465 value: function detachMediaElement() { 2466 if (this._mediaSource) { 2467 var ms = this._mediaSource; 2468 for (var type in this._sourceBuffers) { 2469 // pending segments should be discard 2470 var ps = this._pendingSegments[type]; 2471 ps.splice(0, ps.length); 2472 this._pendingSegments[type] = null; 2473 this._pendingRemoveRanges[type] = null; 2474 this._lastInitSegments[type] = null; 2475 2476 // remove all sourcebuffers 2477 var sb = this._sourceBuffers[type]; 2478 if (sb) { 2479 if (ms.readyState !== 'closed') { 2480 // ms edge can throw an error: Unexpected call to method or property access 2481 try { 2482 ms.removeSourceBuffer(sb); 2483 } catch (error) { 2484 _logger2.default.e(this.TAG, error.message); 2485 } 2486 sb.removeEventListener('error', this.e.onSourceBufferError); 2487 sb.removeEventListener('updateend', this.e.onSourceBufferUpdateEnd); 2488 } 2489 this._mimeTypes[type] = null; 2490 this._sourceBuffers[type] = null; 2491 } 2492 } 2493 if (ms.readyState === 'open') { 2494 try { 2495 ms.endOfStream(); 2496 } catch (error) { 2497 _logger2.default.e(this.TAG, error.message); 2498 } 2499 } 2500 ms.removeEventListener('sourceopen', this.e.onSourceOpen); 2501 ms.removeEventListener('sourceended', this.e.onSourceEnded); 2502 ms.removeEventListener('sourceclose', this.e.onSourceClose); 2503 this._pendingSourceBufferInit = []; 2504 this._isBufferFull = false; 2505 this._idrList.clear(); 2506 this._mediaSource = null; 2507 } 2508 2509 if (this._mediaElement) { 2510 this._mediaElement.src = ''; 2511 this._mediaElement.removeAttribute('src'); 2512 this._mediaElement = null; 2513 } 2514 if (this._mediaSourceObjectURL) { 2515 window.URL.revokeObjectURL(this._mediaSourceObjectURL); 2516 this._mediaSourceObjectURL = null; 2517 } 2518 } 2519 }, { 2520 key: 'appendInitSegment', 2521 value: function appendInitSegment(initSegment, deferred) { 2522 if (!this._mediaSource || this._mediaSource.readyState !== 'open') { 2523 // sourcebuffer creation requires mediaSource.readyState === 'open' 2524 // so we defer the sourcebuffer creation, until sourceopen event triggered 2525 this._pendingSourceBufferInit.push(initSegment); 2526 // make sure that this InitSegment is in the front of pending segments queue 2527 this._pendingSegments[initSegment.type].push(initSegment); 2528 return; 2529 } 2530 2531 var is = initSegment; 2532 var mimeType = '' + is.container; 2533 if (is.codec && is.codec.length > 0) { 2534 mimeType += ';codecs=' + is.codec; 2535 } 2536 2537 var firstInitSegment = false; 2538 2539 _logger2.default.v(this.TAG, 'Received Initialization Segment, mimeType: ' + mimeType); 2540 this._lastInitSegments[is.type] = is; 2541 2542 if (mimeType !== this._mimeTypes[is.type]) { 2543 if (!this._mimeTypes[is.type]) { 2544 // empty, first chance create sourcebuffer 2545 firstInitSegment = true; 2546 try { 2547 var sb = this._sourceBuffers[is.type] = this._mediaSource.addSourceBuffer(mimeType); 2548 sb.addEventListener('error', this.e.onSourceBufferError); 2549 sb.addEventListener('updateend', this.e.onSourceBufferUpdateEnd); 2550 } catch (error) { 2551 _logger2.default.e(this.TAG, error.message); 2552 this._emitter.emit(_mseEvents2.default.ERROR, { code: error.code, msg: error.message }); 2553 return; 2554 } 2555 } else { 2556 _logger2.default.v(this.TAG, 'Notice: ' + is.type + ' mimeType changed, origin: ' + this._mimeTypes[is.type] + ', target: ' + mimeType); 2557 } 2558 this._mimeTypes[is.type] = mimeType; 2559 } 2560 2561 if (!deferred) { 2562 // deferred means this InitSegment has been pushed to pendingSegments queue 2563 this._pendingSegments[is.type].push(is); 2564 } 2565 if (!firstInitSegment) { 2566 // append immediately only if init segment in subsequence 2567 if (this._sourceBuffers[is.type] && !this._sourceBuffers[is.type].updating) { 2568 this._doAppendSegments(); 2569 } 2570 } 2571 if (_browser2.default.safari && is.container === 'audio/mpeg' && is.mediaDuration > 0) { 2572 // 'audio/mpeg' track under Safari may cause MediaElement's duration to be NaN 2573 // Manually correct MediaSource.duration to make progress bar seekable, and report right duration 2574 this._requireSetMediaDuration = true; 2575 this._pendingMediaDuration = is.mediaDuration / 1000; // in seconds 2576 this._updateMediaSourceDuration(); 2577 } 2578 } 2579 }, { 2580 key: 'appendMediaSegment', 2581 value: function appendMediaSegment(mediaSegment) { 2582 var ms = mediaSegment; 2583 this._pendingSegments[ms.type].push(ms); 2584 2585 if (this._config.autoCleanupSourceBuffer && this._needCleanupSourceBuffer()) { 2586 this._doCleanupSourceBuffer(); 2587 } 2588 2589 var sb = this._sourceBuffers[ms.type]; 2590 if (sb && !sb.updating && !this._hasPendingRemoveRanges()) { 2591 this._doAppendSegments(); 2592 } 2593 } 2594 }, { 2595 key: 'seek', 2596 value: function seek(seconds) { 2597 // remove all appended buffers 2598 for (var type in this._sourceBuffers) { 2599 if (!this._sourceBuffers[type]) { 2600 continue; 2601 } 2602 2603 // abort current buffer append algorithm 2604 var sb = this._sourceBuffers[type]; 2605 if (this._mediaSource.readyState === 'open') { 2606 try { 2607 // If range removal algorithm is running, InvalidStateError will be throwed 2608 // Ignore it. 2609 sb.abort(); 2610 } catch (error) { 2611 _logger2.default.e(this.TAG, error.message); 2612 } 2613 } 2614 2615 // IDRList should be clear 2616 this._idrList.clear(); 2617 2618 // pending segments should be discard 2619 var ps = this._pendingSegments[type]; 2620 ps.splice(0, ps.length); 2621 2622 if (this._mediaSource.readyState === 'closed') { 2623 // Parent MediaSource object has been detached from HTMLMediaElement 2624 continue; 2625 } 2626 2627 // record ranges to be remove from SourceBuffer 2628 for (var i = 0; i < sb.buffered.length; i++) { 2629 var start = sb.buffered.start(i); 2630 var end = sb.buffered.end(i); 2631 this._pendingRemoveRanges[type].push({ start: start, end: end }); 2632 } 2633 2634 // if sb is not updating, let's remove ranges now! 2635 if (!sb.updating) { 2636 this._doRemoveRanges(); 2637 } 2638 2639 // Safari 10 may get InvalidStateError in the later appendBuffer() after SourceBuffer.remove() call 2640 // Internal parser's state may be invalid at this time. Re-append last InitSegment to workaround. 2641 // Related issue: https://bugs.webkit.org/show_bug.cgi?id=159230 2642 if (_browser2.default.safari) { 2643 var lastInitSegment = this._lastInitSegments[type]; 2644 if (lastInitSegment) { 2645 this._pendingSegments[type].push(lastInitSegment); 2646 if (!sb.updating) { 2647 this._doAppendSegments(); 2648 } 2649 } 2650 } 2651 } 2652 } 2653 }, { 2654 key: 'endOfStream', 2655 value: function endOfStream() { 2656 var ms = this._mediaSource; 2657 var sb = this._sourceBuffers; 2658 if (!ms || ms.readyState !== 'open') { 2659 if (ms && ms.readyState === 'closed' && this._hasPendingSegments()) { 2660 // If MediaSource hasn't turned into open state, and there're pending segments 2661 // Mark pending endOfStream, defer call until all pending segments appended complete 2662 this._hasPendingEos = true; 2663 } 2664 return; 2665 } 2666 if (sb.video && sb.video.updating || sb.audio && sb.audio.updating) { 2667 // If any sourcebuffer is updating, defer endOfStream operation 2668 // See _onSourceBufferUpdateEnd() 2669 this._hasPendingEos = true; 2670 } else { 2671 this._hasPendingEos = false; 2672 // Notify media data loading complete 2673 // This is helpful for correcting total duration to match last media segment 2674 // Otherwise MediaElement's ended event may not be triggered 2675 ms.endOfStream(); 2676 } 2677 } 2678 }, { 2679 key: 'getNearestKeyframe', 2680 value: function getNearestKeyframe(dts) { 2681 return this._idrList.getLastSyncPointBeforeDts(dts); 2682 } 2683 }, { 2684 key: '_needCleanupSourceBuffer', 2685 value: function _needCleanupSourceBuffer() { 2686 if (!this._config.autoCleanupSourceBuffer) { 2687 return false; 2688 } 2689 2690 var currentTime = this._mediaElement.currentTime; 2691 2692 for (var type in this._sourceBuffers) {
2693 var sb = this._sourceBuffers[type]; 2694 if (sb) { 2695 var buffered = sb.buffered; 2696 if (buffered.length >= 1) { 2697 if (currentTime - buffered.start(0) >= this._config.autoCleanupMaxBackwardDuration) { 2698 return true; 2699 } 2700 } 2701 } 2702 } 2703 2704 return false; 2705 } 2706 }, { 2707 key: '_doCleanupSourceBuffer', 2708 value: function _doCleanupSourceBuffer() { 2709 var currentTime = this._mediaElement.currentTime; 2710 2711 for (var type in this._sourceBuffers) { 2712 var sb = this._sourceBuffers[type]; 2713 if (sb) { 2714 var buffered = sb.buffered; 2715 var doRemove = false; 2716 2717 for (var i = 0; i < buffered.length; i++) { 2718 var start = buffered.start(i); 2719 var end = buffered.end(i); 2720 2721 if (start <= currentTime && currentTime < end + 3) { 2722 // padding 3 seconds 2723 if (currentTime - start >= this._config.autoCleanupMaxBackwardDuration) { 2724 doRemove = true; 2725 var removeEnd = currentTime - this._config.autoCleanupMinBackwardDuration; 2726 this._pendingRemoveRanges[type].push({ start: start, end: removeEnd }); 2727 } 2728 } else if (end < currentTime) { 2729 doRemove = true; 2730 this._pendingRemoveRanges[type].push({ start: start, end: end }); 2731 } 2732 } 2733 2734 if (doRemove && !sb.updating) { 2735 this._doRemoveRanges(); 2736 } 2737 } 2738 } 2739 } 2740 }, { 2741 key: '_updateMediaSourceDuration', 2742 value: function _updateMediaSourceDuration() { 2743 var sb = this._sourceBuffers; 2744 if (this._mediaElement.readyState === 0 || this._mediaSource.readyState !== 'open') { 2745 return; 2746 } 2747 if (sb.video && sb.video.updating || sb.audio && sb.audio.updating) { 2748 return; 2749 } 2750 2751 var current = this._mediaSource.duration; 2752 var target = this._pendingMediaDuration; 2753 2754 if (target > 0 && (isNaN(current) || target > current)) { 2755 _logger2.default.v(this.TAG, 'Update MediaSource duration from ' + current + ' to ' + target); 2756 this._mediaSource.duration = target; 2757 } 2758 2759 this._requireSetMediaDuration = false; 2760 this._pendingMediaDuration = 0; 2761 } 2762 }, { 2763 key: '_doRemoveRanges', 2764 value: function _doRemoveRanges() { 2765 for (var type in this._pendingRemoveRanges) { 2766 if (!this._sourceBuffers[type] || this._sourceBuffers[type].updating) { 2767 continue; 2768 } 2769 var sb = this._sourceBuffers[type]; 2770 var ranges = this._pendingRemoveRanges[type]; 2771 while (ranges.length && !sb.updating) { 2772 var range = ranges.shift(); 2773 sb.remove(range.start, range.end); 2774 } 2775 } 2776 } 2777 }, { 2778 key: '_doAppendSegments', 2779 value: function _doAppendSegments() { 2780 var pendingSegments = this._pendingSegments; 2781 2782 for (var type in pendingSegments) { 2783 if (!this._sourceBuffers[type] || this._sourceBuffers[type].updating) { 2784 continue; 2785 } 2786 2787 if (pendingSegments[type].length > 0) { 2788 var segment = pendingSegments[type].shift(); 2789 2790 if (segment.timestampOffset) { 2791 // For MPEG audio stream in MSE, if unbuffered-seeking occurred 2792 // We need explicitly set timestampOffset to the desired point in timeline for mpeg SourceBuffer. 2793 var currentOffset = this._sourceBuffers[t
vendor: 4,171 bytes, lines 2793-2878
2793ype].timestampOffset; 2794 var targetOffset = segment.timestampOffset / 1000; // in seconds 2795 2796 var delta = Math.abs(currentOffset - targetOffset); 2797 if (delta > 0.1) { 2798 // If time delta > 100ms 2799 _logger2.default.v(this.TAG, 'Update MPEG audio timestampOffset from ' + currentOffset + ' to ' + targetOffset); 2800 this._sourceBuffers[type].timestampOffset = targetOffset; 2801 } 2802 delete segment.timestampOffset; 2803 } 2804 2805 if (!segment.data || segment.data.byteLength === 0) { 2806 // Ignore empty buffer 2807 continue; 2808 } 2809 2810 try { 2811 this._sourceBuffers[type].appendBuffer(segment.data); 2812 this._isBufferFull = false; 2813 if (type === 'video' && segment.hasOwnProperty('info')) { 2814 this._idrList.appendArray(segment.info.syncPoints); 2815 } 2816 } catch (error) { 2817 this._pendingSegments[type].unshift(segment); 2818 if (error.code === 22) { 2819 // QuotaExceededError 2820 /* Notice that FireFox may not throw QuotaExceededError if SourceBuffer is full 2821 * Currently we can only do lazy-load to avoid SourceBuffer become scattered. 2822 * SourceBuffer eviction policy may be changed in future version of FireFox. 2823 * 2824 * Related issues: 2825 * https://bugzilla.mozilla.org/show_bug.cgi?id=1279885 2826 * https://bugzilla.mozilla.org/show_bug.cgi?id=1280023 2827 */ 2828 2829 // report buffer full, abort network IO 2830 if (!this._isBufferFull) { 2831 this._emitter.emit(_mseEvents2.default.BUFFER_FULL); 2832 } 2833 this._isBufferFull = true; 2834 } else { 2835 _logger2.default.e(this.TAG, error.message); 2836 this._emitter.emit(_mseEvents2.default.ERROR, { code: error.code, msg: error.message }); 2837 } 2838 } 2839 } 2840 } 2841 } 2842 }, { 2843 key: '_onSourceOpen', 2844 value: function _onSourceOpen() { 2845 _logger2.default.v(this.TAG, 'MediaSource onSourceOpen'); 2846 this._mediaSource.removeEventListener('sourceopen', this.e.onSourceOpen); 2847 // deferred sourcebuffer creation / initialization 2848 if (this._pendingSourceBufferInit.length > 0) { 2849 var pendings = this._pendingSourceBufferInit; 2850 while (pendings.length) { 2851 var segment = pendings.shift(); 2852 this.appendInitSegment(segment, true); 2853 } 2854 } 2855 // there may be some pending media segments, append them 2856 if (this._hasPendingSegments()) { 2857 this._doAppendSegments(); 2858 } 2859 this._emitter.emit(_mseEvents2.default.SOURCE_OPEN); 2860 } 2861 }, { 2862 key: '_onSourceEnded', 2863 value: function _onSourceEnded() { 2864 // fired on endOfStream 2865 _logger2.default.v(this.TAG, 'MediaSource onSourceEnded'); 2866 } 2867 }, { 2868 key: '_onSourceClose', 2869 value: function _onSourceClose() { 2870 // fired on detaching from media element 2871 _logger2.default.v(this.TAG, 'MediaSource onSourceClose'); 2872 if (this._mediaSource && this.e != null) { 2873 this._mediaSource.removeEventListener('sourceopen', this.e.onSourceOpen); 2874 this._mediaSource.removeEventListener('sourceended', this.e.onSourceEnded); 2875 this._mediaSource.removeEventListener('sourceclose', this.e.onSourceClose); 2876 } 2877 } 2878 }, {
2879 key: '_hasPendingSegments', 2880 value: function _hasPendingSegments() { 2881 var ps = this._pendingSegments; 2882 return ps.video.length > 0 || ps.audio.length > 0; 2883 } 2884 }, { 2885 key: '_hasPendingRemoveRanges', 2886 value: function _hasPendingRemoveRanges() { 2887 var prr = this._pendingRemoveRanges; 2888 return prr.video.length > 0 || prr.audio.length > 0; 2889 } 2890 }, { 2891 key: '_onSourceBufferUpdateEnd', 2892 value: function _onSourceBufferUpdateEnd() { 2893 if (this._requireSetMediaDuration) { 2894 this._updateMediaSourceDuration(); 2895 } else if (this._hasPendingRemoveRanges()) { 2896 this._doRemoveRanges(); 2897 } else if (this._hasPendingSegments()) { 2898 this._doAppendSegments(); 2899 } else if (this._hasPendingEos) { 2900 this.endOfStream(); 2901 } 2902 this._emitter.emit(_mseEvents2.default.UPDATE_END); 2903 } 2904 }, { 2905 key: '_onSourceBufferError', 2906 value: function _onSourceBufferError(e) { 2907 _logger2.default.e(this.TAG, 'SourceBuffer Error: ' + e); 2908 // this error might not always be fatal, just ignore it 2909 } 2910 }]); 2911 2912 return MSEController; 2913}(); 2914 2915exports.default = MSEController; 2916 2917},{"../utils/browser.js":39,"../utils/exception.js":40,"../utils/logger.js":41,"./media-segment-info.js":8,"./mse-events.js":10,"events":2}],10:[function(_dereq_,module,exports){ 2918'use strict'; 2919 2920Object.defineProperty(exports, "__esModule", { 2921 value: true 2922}); 2923/* 2924 * Copyright (C) 2016 Bilibili. All Rights Reserved. 2925 * 2926 * @author zheng qian <[email protected]> 2927 * 2928 * Licensed under the Apache License, Version 2.0 (the "License"); 2929 * you may not use this file except in compliance with the License. 2930 * You may obtain a copy of the License at 2931 * 2932 * http://www.apache.org/licenses/LICENSE-2.0 2933 * 2934 * Unless required by applicable law or agreed to in writing, software 2935 * distributed under the License is distributed on an "AS IS" BASIS, 2936 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2937 * See the License for the specific language governing permissions and 2938 * limitations under the License. 2939 */ 2940 2941var MSEEvents = { 2942 ERROR: 'error', 2943 SOURCE_OPEN: 'source_open', 2944 UPDATE_END: 'update_end', 2945 BUFFER_FULL: 'buffer_full' 2946}; 2947 2948exports.default = MSEEvents; 2949 2950},{}],11:[function(_dereq_,module,exports){ 2951'use strict'; 2952 2953Object.defineProperty(exports, "__esModule", { 2954 value: true 2955}); 2956 2957var _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; }; }(); /* 2958 * Copyright (C) 2016 Bilibili. All Rights Reserved. 2959 * 2960 * @author zheng qian <[email protected]> 2961 * 2962 * Licensed under the Apache License, Version 2.0 (the "License"); 2963 * you may
2963not use this file except in compliance with the License. 2964 * You may obtain a copy of the License at 2965 * 2966 * http://www.apache.org/licenses/LICENSE-2.0 2967 * 2968 * Unless required by applicable law or agreed to in writing, software 2969 * distributed under the License is distributed on an "AS IS" BASIS, 2970 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2971 * See the License for the specific language governing permissions and 2972 * limitations under the License. 2973 */ 2974 2975var _events = _dereq_('events'); 2976 2977var _events2 = _interopRequireDefault(_events); 2978 2979var _logger = _dereq_('../utils/logger.js'); 2980 2981var _logger2 = _interopRequireDefault(_logger); 2982 2983var _loggingControl = _dereq_('../utils/logging-control.js'); 2984 2985var _loggingControl2 = _interopRequireDefault(_loggingControl); 2986 2987var _transmuxingController = _dereq_('./transmuxing-controller.js'); 2988 2989var _transmuxingController2 = _interopRequireDefault(_transmuxingController); 2990 2991var _transmuxingEvents = _dereq_('./transmuxing-events.js'); 2992 2993var _transmuxingEvents2 = _interopRequireDefault(_transmuxingEvents); 2994 2995var _transmuxingWorker = _dereq_('./transmuxing-worker.js'); 2996 2997var _transmuxingWorker2 = _interopRequireDefault(_transmuxingWorker); 2998 2999var _mediaInfo = _dereq_('./media-info.js'); 3000 3001var _mediaInfo2 = _interopRequireDefault(_mediaInfo); 3002 3003function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 3004 3005function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 3006 3007var Transmuxer = function () { 3008 function Transmuxer(mediaDataSource, config) { 3009 _classCallCheck(this, Transmuxer); 3010 3011 this.TAG = 'Transmuxer'; 3012 this._emitter = new _events2.default(); 3013 3014 if (config.enableWorker && typeof Worker !== 'undefined') { 3015 try { 3016 var work = _dereq_('webworkify'); 3017 this._worker = work(_transmuxingWorker2.default); 3018 this._workerDestroying = false;
3019 this._worker.addEventListener('message', this._onWorkerMessage.bind(this)); 3020 this._worker.postMessage({ cmd: 'init', param: [mediaDataSource, config] }); 3021 this.e = { 3022 onLoggingConfigChanged: this._onLoggingConfigChanged.bind(this) 3023 }; 3024 _loggingControl2.default.registerListener(this.e.onLoggingConfigChanged); 3025 this._worker.postMessage({ cmd: 'logging_config', param: _loggingControl2.default.getConfig() }); 3026 } catch (error) { 3027 _logger2.default.e(this.TAG, 'Error while initialize transmuxing worker, fallback to inline transmuxing'); 3028 this._worker = null; 3029 this._controller = new _transmuxingController2.default(mediaDataSource, config); 3030 } 3031 } else { 3032 this._controller = new _transmuxingController2.default(mediaDataSource, config); 3033 } 3034 3035 if (this._controller) { 3036 var ctl = this._controller; 3037 ctl.on(_transmuxingEvents2.default.IO_ERROR, this._onIOError.bind(this)); 3038 ctl.on(_transmuxingEvents2.default.DEMUX_ERROR, this._onDemuxError.bind(this)); 3039 ctl.on(_transmuxingEvents2.default.INIT_SEGMENT, this._onInitSegment.bind(this)); 3040 ctl.on(_transmuxingEvents2.default.MEDIA_SEGMENT, this._onMediaSegment.bind(this)); 3041 ctl.on(_transmuxingEvents2.default.LOADING_COMPLETE, this._onLoadingComplete.bind(this)); 3042 ctl.on(_transmuxingEvents2.default.RECOVERED_EARLY_EOF, this._onRecoveredEarlyEof.bind(this)); 3043 ctl.on(_transmuxingEvents2.default.MEDIA_INFO, this._onMediaInfo.bind(this)); 3044 ctl.on(_transmuxingEvents2.default.METADATA_ARRIVED, this._onMetaDataArrived.bind(this)); 3045 ctl.on(_transmuxingEvents2.default.SCRIPTDATA_ARRIVED, this._onScriptDataArrived.bind(this)); 3046 ctl.on(_transmuxingEvents2.default.STATISTICS_INFO, this._onStatisticsInfo.bind(this)); 3047 ctl.on(_transmuxingEvents2.default.RECOMMEND_SEEKPOINT, this._onRecommendSeekpoint.bind(this)); 3048 } 3049 } 3050 3051 _createClass(Transmuxer, [{ 3052 key: 'destroy', 3053 value: function destroy() { 3054 if (this._worker) { 3055 if (!this._workerDestroying) { 3056 this._workerDestroying = true; 3057 this._worker.postMessage({ cmd: 'destroy' }); 3058 _loggingControl2.default.removeListener(this.e.onLoggingConfigChanged); 3059 this.e = null; 3060 } 3061 } else { 3062 this._controller.destroy(); 3063 this._controller = null; 3064 } 3065 this._emitter.removeAllListeners(); 3066 this._emitter = null; 3067 } 3068 }, { 3069 key: 'on', 3070 value: function on(event, listener) { 3071 this._emitter.addListener(event, listener); 3072 } 3073 }, { 3074 key: 'off', 3075 value: function off(event, listener) { 3076 this._emitter.removeListener(event, listener); 3077 } 3078 }, { 3079 key: 'hasWorker', 3080 value: function hasWorker() { 3081 return this._worker != null; 3082 } 3083 }, { 3084 key: 'open', 3085 value: function open() { 3086 if (this._worker) { 3087 this._worker.postMessage({ cmd: 'start' }); 3088 } else { 3089 this._controller.start(); 3090 } 3091 } 3092 }, { 3093 key: 'close', 3094 value: function close() { 3095 if (this._worker) { 3096 this._worker.postMessage({ cmd: 'stop' }); 3097 } else { 3098 this._controller.stop(); 3099 } 3100 } 3101 }, { 3102 key: 'seek', 3103 value: function seek(milliseconds) { 3104 if (this._worker) { 3105 this._worker.postMessage({ cmd: 'seek', param: milliseconds }); 3106 } else { 3107 this._controller.seek(milliseconds); 3108 } 3109 } 3110 }, { 3111 key: 'pause', 3112 value: function pause() { 3113 if (this._worker) { 3114 this._worker.postMessage({ cmd: 'pause' }); 3115 } else { 3116 this._controller.pause(); 3117 } 3118 } 3119 }, {
3120 key: 'resume', 3121 value: function resume() { 3122 if (this._worker) { 3123 this._worker.postMessage({ cmd: 'resume' }); 3124 } else { 3125 this._controller.resume(); 3126 } 3127 } 3128 }, { 3129 key: '_onInitSegment', 3130 value: function _onInitSegment(type, initSegment) { 3131 var _this = this; 3132 3133 // do async invoke 3134 Promise.resolve().then(function () { 3135 _this._emitter.emit(_transmuxingEvents2.default.INIT_SEGMENT, type, initSegment); 3136 }); 3137 } 3138 }, { 3139 key: '_onMediaSegment', 3140 value: function _onMediaSegment(type, mediaSegment) { 3141 var _this2 = this; 3142 3143 Promise.resolve().then(function () { 3144 _this2._emitter.emit(_transmuxingEvents2.default.MEDIA_SEGMENT, type, mediaSegment); 3145 }); 3146 } 3147 }, { 3148 key: '_onLoadingComplete', 3149 value: function _onLoadingComplete() { 3150 var _this3 = this; 3151 3152 Promise.resolve().then(function () { 3153 _this3._emitter.emit(_transmuxingEvents2.default.LOADING_COMPLETE); 3154 }); 3155 } 3156 }, { 3157 key: '_onRecoveredEarlyEof', 3158 value: function _onRecoveredEarlyEof() { 3159 var _this4 = this; 3160 3161 Promise.resolve().then(function () { 3162 _this4._emitter.emit(_transmuxingEvents2.default.RECOVERED_EARLY_EOF); 3163 }); 3164 } 3165 }, { 3166 key: '_onMediaInfo', 3167 value: function _onMediaInfo(mediaInfo) { 3168 var _this5 = this; 3169 3170 Promise.resolve().then(function () { 3171 _this5._emitter.emit(_transmuxingEvents2.default.MEDIA_INFO, mediaInfo); 3172 }); 3173 } 3174 }, { 3175 key: '_onMetaDataArrived', 3176 value: function _onMetaDataArrived(metadata) { 3177 var _this6 = this; 3178 3179 Promise.resolve().then(function () { 3180 _this6._emitter.emit(_transmuxingEvents2.default.METADATA_ARRIVED, metadata); 3181 }); 3182 } 3183 }, { 3184 key: '_onScriptDataArrived', 3185 value: function _onScriptDataArrived(data) { 3186 var _this7 = this; 3187 3188 Promise.resolve().then(function () { 3189 _this7._emitter.emit(_transmuxingEvents2.default.SCRIPTDATA_ARRIVED, data); 3190 }); 3191 } 3192 }, { 3193 key: '_onStatisticsInfo', 3194 value: function _onStatisticsInfo(statisticsInfo) { 3195 var _this8 = this; 3196 3197 Promise.resolve().then(function () { 3198 _this8._emitter.emit(_transmuxingEvents2.default.STATISTICS_INFO, statisticsInfo); 3199 }); 3200 } 3201 }, { 3202 key: '_onIOError', 3203 value: function _onIOError(type, info) { 3204 var _this9 = this; 3205 3206 Promise.resolve().then(function () { 3207 _this9._emitter.emit(_transmuxingEvents2.default.IO_ERROR, type, info); 3208 }); 3209 } 3210 }, { 3211 key: '_onDemuxError', 3212 value: function _onDemuxError(type, info) { 3213 var _this10 = this; 3214 3215 Promise.resolve().then(function () { 3216 _this10._emitter.emit(_transmuxingEvents2.default.DEMUX_ERROR, type, info); 3217 }); 3218 } 3219 }, { 3220 key: '_onRecommendSeekpoint', 3221 value: function _onRecommendSeekpoint(milliseconds) { 3222 var _this11 = this; 3223 3224 Promise.resolve().then(function () { 3225 _this11._emitter.emit(_transmuxingEvents2.default.RECOMMEND_SEEKPOINT, milliseconds); 3226 }); 3227 } 3228 }, { 3229 key: '_onLoggingConfigChanged', 3230 value: function _onLoggingConfigChanged(config) { 3231 if (this._worker) { 3232 this._worker.postMessage({ cmd: 'logging_config', param: config }); 3233 } 3234 } 3235 }, { 3236 key: '_onWorkerMessage', 3237 value: function _onWorkerMessage(e) { 3238 var message = e.data; 3239 var data = message.data; 3240 3241 if (message.msg === 'destroyed' || this._workerDestroying) { 3242 this._workerDestroying = false; 3243 this._worker.terminate(); 3244 this._worker = null; 3245 return; 3246 } 3247 3248 switch (message.msg) { 3249 case _transmuxingEvents2.default.INIT_SEGMENT: 3250 case _transmuxingEvents2.default.MEDIA_SEGMENT: 3251 this._emitter.emit(message.msg, data.type, data.data); 3252 break; 3253 case _transmuxingEvents2.default.LOADING_COMPLETE: 3254 case _transmuxingEvents2.default.RECOVERED_EARLY_EOF: 3255 this._emitter.emit(message.msg); 3256 break; 3257 case _transmuxingEvents2.default.MEDIA_INFO: 3258 Object.setPrototypeOf(data, _mediaInfo2.default.prototype); 3259 this._emitter.emit(message.msg, data); 3260 break; 3261 case _transmuxingEvents2.default.METADATA_ARRIVED: 3262 case _transmuxingEvents2.default.SCRIPTDATA_ARRIVED: 3263 case _transmuxingEvents2.default.STATISTICS_INFO: 3264 this._emitter.emit(message.msg, data); 3265 break; 3266 case _transmuxingEvents2.default.IO_ERROR: 3267 case _transmuxingEvents2.default.DEMUX_ERROR: 3268 this._emitter.emit(message.msg, data.type, data.info); 3269 break; 3270 case _transmuxingEvents2.default.RECOMMEND_SEEKPOINT: 3271 this._emitter.emit(message.msg, data); 3272 break; 3273 case 'logcat_callback': 3274 _logger2.default.emitter.emit('log', data.type, data.logcat); 3275 break; 3276 default: 3277 break; 3278 } 3279 } 3280 }]); 3281 3282 return Transmuxer; 3283}(); 3284 3285exports.default = Transmuxer; 3286 3287},{"../utils/logger.js":41,"../utils/logging-control.js":42,"./media-info.js":7,"./transmuxing-controller.js":12,"./transmuxing-events.js":13,"./transmuxing-worker.js":14,"events":2,"webworkify":4}],12:[function(_dereq_,module,exports){ 3288'use strict'; 3289 3290Object.defineProperty(exports, "__esModule", { 3291 value: true 3292}); 3293 3294var _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; }; }(); /* 3295 * Copyright (C) 2016 Bilibili. All Rights Reserved. 3296 * 3297 * @author zheng qian <[email protected]> 3298 * 3299 * Licensed under the Apache License, Version 2.0 (the "License"); 3300 * you may
3300not use this file except in compliance with the License. 3301 * You may obtain a copy of the License at 3302 * 3303 * http://www.apache.org/licenses/LICENSE-2.0 3304 * 3305 * Unless required by applicable law or agreed to in writing, software 3306 * distributed under the License is distributed on an "AS IS" BASIS, 3307 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3308 * See the License for the specific language governing permissions and 3309 * limitations under the License. 3310 */ 3311 3312var _events = _dereq_('events'); 3313 3314var _events2 = _interopRequireDefault(_events); 3315 3316var _logger = _dereq_('../utils/logger.js'); 3317 3318var _logger2 = _interopRequireDefault(_logger); 3319 3320var _browser = _dereq_('../utils/browser.js'); 3321 3322var _browser2 = _interopRequireDefault(_browser); 3323 3324var _mediaInfo = _dereq_('./media-info.js'); 3325 3326var _mediaInfo2 = _interopRequireDefault(_mediaInfo); 3327 3328var _flvDemuxer = _dereq_('../demux/flv-demuxer.js'); 3329 3330var _flvDemuxer2 = _interopRequireDefault(_flvDemuxer); 3331 3332var _mp4Remuxer = _dereq_('../remux/mp4-remuxer.js'); 3333 3334var _mp4Remuxer2 = _interopRequireDefault(_mp4Remuxer); 3335 3336var _demuxErrors = _dereq_('../demux/demux-errors.js'); 3337 3338var _demuxErrors2 = _interopRequireDefault(_demuxErrors); 3339 3340var _ioController = _dereq_('../io/io-controller.js'); 3341 3342var _ioController2 = _interopRequireDefault(_ioController); 3343 3344var _transmuxingEvents = _dereq_('./transmuxing-events.js'); 3345 3346var _transmuxingEvents2 = _interopRequireDefault(_transmuxingEvents); 3347 3348var _loader = _dereq_('../io/loader.js'); 3349 3350function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 3351 3352function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 3353 3354// Transmuxing (IO, Demuxing, Remuxing) controller, with multipart support 3355var TransmuxingController = function () { 3356 function TransmuxingController(mediaDataSource, config) { 3357 _classCallCheck(this, TransmuxingController); 3358 3359 this.TAG = 'TransmuxingController'; 3360 this._emitter = new _events2.default(); 3361 3362 this._config = config; 3363 3364 // treat single part media as multipart media, which has only one segment 3365 if (!mediaDataSource.segments) { 3366 mediaDataSource.segments = [{ 3367 duration: mediaDataSource.duration, 3368 filesize: mediaDataSource.filesize, 3369 url: mediaDataSource.url 3370 }]; 3371 } 3372 3373 // fill in default IO params if not exists 3374 if (typeof mediaDataSource.cors !== 'boolean') { 3375 mediaDataSource.cors = true; 3376 } 3377 if (typeof mediaDataSource.withCredentials !== 'boolean') { 3378 mediaDataSource.withCredentials = false;
3379 } 3380 3381 this._mediaDataSource = mediaDataSource; 3382 this._currentSegmentIndex = 0; 3383 var totalDuration = 0; 3384 3385 this._mediaDataSource.segments.forEach(function (segment) { 3386 // timestampBase for each segment, and calculate total duration 3387 segment.timestampBase = totalDuration; 3388 totalDuration += segment.duration; 3389 // params needed by IOController 3390 segment.cors = mediaDataSource.cors; 3391 segment.withCredentials = mediaDataSource.withCredentials; 3392 // referrer policy control, if exist 3393 if (config.referrerPolicy) { 3394 segment.referrerPolicy = config.referrerPolicy; 3395 } 3396 }); 3397 3398 if (!isNaN(totalDuration) && this._mediaDataSource.duration !== totalDuration) { 3399 this._mediaDataSource.duration = totalDuration; 3400 } 3401 3402 this._mediaInfo = null; 3403 this._demuxer = null; 3404 this._remuxer = null; 3405 this._ioctl = null; 3406 3407 this._pendingSeekTime = null; 3408 this._pendingResolveSeekPoint = null; 3409 3410 this._statisticsReporter = null; 3411 } 3412 3413 _createClass(TransmuxingController, [{ 3414 key: 'destroy', 3415 value: function destroy() { 3416 this._mediaInfo = null; 3417 this._mediaDataSource = null; 3418 3419 if (this._statisticsReporter) { 3420 this._disableStatisticsReporter(); 3421 } 3422 if (this._ioctl) { 3423 this._ioctl.destroy(); 3424 this._ioctl = null; 3425 } 3426 if (this._demuxer) { 3427 this._demuxer.destroy(); 3428 this._demuxer = null; 3429 } 3430 if (this._remuxer) { 3431 this._remuxer.destroy(); 3432 this._remuxer = null; 3433 } 3434 3435 this._emitter.removeAllListeners(); 3436 this._emitter = null; 3437 } 3438 }, { 3439 key: 'on', 3440 value: function on(event, listener) { 3441 this._emitter.addListener(event, listener); 3442 } 3443 }, { 3444 key: 'off', 3445 value: function off(event, listener) { 3446 this._emitter.removeListener(event, listener); 3447 } 3448 }, { 3449 key: 'start', 3450 value: function start() { 3451 this._loadSegment(0); 3452 this._enableStatisticsReporter(); 3453 } 3454 }, { 3455 key: '_loadSegment', 3456 value: function _loadSegment(segmentIndex, optionalFrom) { 3457 this._currentSegmentIndex = segmentIndex; 3458 var dataSource = this._mediaDataSource.segments[segmentIndex]; 3459 3460 var ioctl = this._ioctl = new _ioController2.default(dataSource, this._config, segmentIndex); 3461 ioctl.onError = this._onIOException.bind(this); 3462 ioctl.onSeeked = this._onIOSeeked.bind(this); 3463 ioctl.onComplete = this._onIOComplete.bind(this); 3464 ioctl.onRedirect = this._onIORedirect.bind(this); 3465 ioctl.onRecoveredEarlyEof = this._onIORecoveredEarlyEof.bind(this); 3466 3467 if (optionalFrom) { 3468 this._demuxer.bindDataSource(this._ioctl); 3469 } else { 3470 ioctl.onDataArrival = this._onInitChunkArrival.bind(this); 3471 } 3472 3473 ioctl.open(optionalFrom); 3474 } 3475 }, { 3476 key: 'stop', 3477 value: function stop() { 3478 this._internalAbort(); 3479 this._disableStatisticsReporter(); 3480 } 3481 }, { 3482 key: '_internalAbort', 3483 value: function _internalAbort() { 3484 if (this._ioctl) { 3485 this._ioctl.destroy(); 3486 this._ioctl = null; 3487 } 3488 } 3489 }, { 3490 key: 'pause', 3491 value: function pause() { 3492 // take a rest 3493 if (this._ioctl && this._ioctl.isWorking()) { 3494 this._ioctl.pause(); 3495 this._disableStatisticsReporter(); 3496 } 3497 } 3498 }, { 3499 key: 'resume', 3500 value: function resume() { 3501 if (this._ioctl && this._ioctl.isPaused()) { 3502 this._ioctl.resume(); 3503 this._enableStatisticsReporter(); 3504 } 3505 } 3506 }, {
vendor: 5,808 bytes, lines 3507-3631
3507 key: 'seek', 3508 value: function seek(milliseconds) { 3509 if (this._mediaInfo == null || !this._mediaInfo.isSeekable()) { 3510 return; 3511 } 3512 3513 var targetSegmentIndex = this._searchSegmentIndexContains(milliseconds); 3514 3515 if (targetSegmentIndex === this._currentSegmentIndex) { 3516 // intra-segment seeking 3517 var segmentInfo = this._mediaInfo.segments[targetSegmentIndex]; 3518 3519 if (segmentInfo == undefined) { 3520 // current segment loading started, but mediainfo hasn't received yet 3521 // wait for the metadata loaded, then seek to expected position 3522 this._pendingSeekTime = milliseconds; 3523 } else { 3524 var keyframe = segmentInfo.getNearestKeyframe(milliseconds); 3525 this._remuxer.seek(keyframe.milliseconds); 3526 this._ioctl.seek(keyframe.fileposition); 3527 // Will be resolved in _onRemuxerMediaSegmentArrival() 3528 this._pendingResolveSeekPoint = keyframe.milliseconds; 3529 } 3530 } else { 3531 // cross-segment seeking 3532 var targetSegmentInfo = this._mediaInfo.segments[targetSegmentIndex]; 3533 3534 if (targetSegmentInfo == undefined) { 3535 // target segment hasn't been loaded. We need metadata then seek to expected time 3536 this._pendingSeekTime = milliseconds; 3537 this._internalAbort(); 3538 this._remuxer.seek(); 3539 this._remuxer.insertDiscontinuity(); 3540 this._loadSegment(targetSegmentIndex); 3541 // Here we wait for the metadata loaded, then seek to expected position 3542 } else { 3543 // We have target segment's metadata, direct seek to target position 3544 var _keyframe = targetSegmentInfo.getNearestKeyframe(milliseconds); 3545 this._internalAbort(); 3546 this._remuxer.seek(milliseconds); 3547 this._remuxer.insertDiscontinuity(); 3548 this._demuxer.resetMediaInfo(); 3549 this._demuxer.timestampBase = this._mediaDataSource.segments[targetSegmentIndex].timestampBase; 3550 this._loadSegment(targetSegmentIndex, _keyframe.fileposition); 3551 this._pendingResolveSeekPoint = _keyframe.milliseconds; 3552 this._reportSegmentMediaInfo(targetSegmentIndex); 3553 } 3554 } 3555 3556 this._enableStatisticsReporter(); 3557 } 3558 }, { 3559 key: '_searchSegmentIndexContains', 3560 value: function _searchSegmentIndexContains(milliseconds) { 3561 var segments = this._mediaDataSource.segments; 3562 var idx = segments.length - 1; 3563 3564 for (var i = 0; i < segments.length; i++) { 3565 if (milliseconds < segments[i].timestampBase) { 3566 idx = i - 1; 3567 break; 3568 } 3569 } 3570 return idx; 3571 } 3572 }, { 3573 key: '_onInitChunkArrival', 3574 value: function _onInitChunkArrival(data, byteStart) { 3575 var _this = this; 3576 3577 var probeData = null; 3578 var consumed = 0; 3579 3580 if (byteStart > 0) { 3581 // IOController seeked immediately after opened, byteStart > 0 callback may received 3582 this._demuxer.bindDataSource(this._ioctl); 3583 this._demuxer.timestampBase = this._mediaDataSource.segments[this._currentSegmentIndex].timestampBase; 3584 3585 consumed = this._demuxer.parseChunks(data, byteStart); 3586 } else if ((probeData = _flvDemuxer2.default.probe(data)).match) { 3587 // Always create new FLVDemuxer 3588 this._demuxer = new _flvDemuxer2.default(probeData, this._config); 3589 3590 if (!this._remuxer) { 3591 this._remuxer = new _mp4Remuxer2.default(this._config); 3592 } 3593 3594 var mds = this._mediaDataSource; 3595 if (mds.duration != undefined && !isNaN(mds.duration)) { 3596 this._demuxer.overridedDuration = mds.duration; 3597 } 3598 if (typeof mds.hasAudio === 'boolean') { 3599 this._demuxer.overridedHasAudio = mds.hasAudio; 3600 } 3601 if (typeof mds.hasVideo === 'boolean') { 3602 this._demuxer.overridedHasVideo = mds.hasVideo; 3603 } 3604 3605 this._demuxer.timestampBase = mds.segments[this._currentSegmentIndex].timestampBase; 3606 3607 this._demuxer.onError = this._onDemuxException.bind(this); 3608 this._demuxer.onMediaInfo = this._onMediaInfo.bind(this); 3609 this._demuxer.onMetaDataArrived = this._onMetaDataArrived.bind(this); 3610 this._demuxer.onScriptDataArrived = this._onScriptDataArrived.bind(this); 3611 3612 this._remuxer.bindDataSource(this._demuxer.bindDataSource(this._ioctl)); 3613 3614 this._remuxer.onInitSegment = this._onRemuxerInitSegmentArrival.bind(this); 3615 this._remuxer.onMediaSegment = this._onRemuxerMediaSegmentArrival.bind(this); 3616 3617 consumed = this._demuxer.parseChunks(data, byteStart); 3618 } else { 3619 probeData = null; 3620 _logger2.default.e(this.TAG, 'Non-FLV, Unsupported media type!'); 3621 Promise.resolve().then(function () { 3622 _this._internalAbort(); 3623 }); 3624 this._emitter.emit(_transmuxingEvents2.default.DEMUX_ERROR, _demuxErrors2.default.FORMAT_UNSUPPORTED, 'Non-FLV, Unsupported media type'); 3625 3626 consumed = 0; 3627 } 3628 3629 return consumed; 3630 } 3631 }, {
3632 key: '_onMediaInfo', 3633 value: function _onMediaInfo(mediaInfo) { 3634 var _this2 = this; 3635 3636 if (this._mediaInfo == null) { 3637 // Store first segment's mediainfo as global mediaInfo 3638 this._mediaInfo = Object.assign({}, mediaInfo); 3639 this._mediaInfo.keyframesIndex = null; 3640 this._mediaInfo.segments = []; 3641 this._mediaInfo.segmentCount = this._mediaDataSource.segments.length; 3642 Object.setPrototypeOf(this._mediaInfo, _mediaInfo2.default.prototype); 3643 } 3644 3645 var segmentInfo = Object.assign({}, mediaInfo); 3646 Object.setPrototypeOf(segmentInfo, _mediaInfo2.default.prototype); 3647 this._mediaInfo.segments[this._currentSegmentIndex] = segmentInfo; 3648 3649 // notify mediaInfo update 3650 this._reportSegmentMediaInfo(this._currentSegmentIndex); 3651 3652 if (this._pendingSeekTime != null) { 3653 Promise.resolve().then(function () { 3654 var target = _this2._pendingSeekTime; 3655 _this2._pendingSeekTime = null; 3656 _this2.seek(target); 3657 }); 3658 } 3659 } 3660 }, { 3661 key: '_onMetaDataArrived', 3662 value: function _onMetaDataArrived(metadata) { 3663 this._emitter.emit(_transmuxingEvents2.default.METADATA_ARRIVED, metadata); 3664 } 3665 }, { 3666 key: '_onScriptDataArrived', 3667 value: function _onScriptDataArrived(data) { 3668 this._emitter.emit(_transmuxingEvents2.default.SCRIPTDATA_ARRIVED, data); 3669 } 3670 }, { 3671 key: '_onIOSeeked', 3672 value: function _onIOSeeked() { 3673 this._remuxer.insertDiscontinuity(); 3674 } 3675 }, { 3676 key: '_onIOComplete', 3677 value: function _onIOComplete(extraData) { 3678 var segmentIndex = extraData; 3679 var nextSegmentIndex = segmentIndex + 1; 3680 3681 if (nextSegmentIndex < this._mediaDataSource.segments.length) { 3682 this._internalAbort(); 3683 this._remuxer.flushStashedSamples(); 3684 this._loadSegment(nextSegmentIndex); 3685 } else { 3686 this._remuxer.flushStashedSamples(); 3687 this._emitter.emit(_transmuxingEvents2.default.LOADING_COMPLETE); 3688 this._disableStatisticsReporter(); 3689 } 3690 } 3691 }, { 3692 key: '_onIORedirect', 3693 value: function _onIORedirect(redirectedURL) { 3694 var segmentIndex = this._ioctl.extraData; 3695 this._mediaDataSource.segments[segmentIndex].redirectedURL = redirectedURL; 3696 } 3697 }, { 3698 key: '_onIORecoveredEarlyEof', 3699 value: function _onIORecoveredEarlyEof() { 3700 this._emitter.emit(_transmuxingEvents2.default.RECOVERED_EARLY_EOF); 3701 } 3702 }, { 3703 key: '_onIOException', 3704 value: function _onIOException(type, info) { 3705 _logger2.default.e(this.TAG, 'IOException: type = ' + type + ', code = ' + info.code + ', msg = ' + info.msg); 3706 this._emitter.emit(_transmuxingEvents2.default.IO_ERROR, type, info); 3707 this._disableStatisticsReporter(); 3708 } 3709 }, { 3710 key: '_onDemuxException', 3711 value: function _onDemuxException(type, info) { 3712 _logger2.default.e(this.TAG, 'DemuxException: type = ' + type + ', info = ' + info); 3713 this._emitter.emit(_transmuxingEvents2.default.DEMUX_ERROR, type, info); 3714 } 3715 }, { 3716 key: '_onRemuxerInitSegmentArrival', 3717 value: function _onRemuxerInitSegmentArrival(type, initSegment) { 3718 this._emitter.emit(_transmuxingEvents2.default.INIT_SEGMENT, type, initSegment); 3719 } 3720 }, { 3721 key: '_onRemuxerMediaSegmentArrival', 3722 value: function _onRemuxerMediaSegmentArrival(type, mediaSegment) { 3723 if (this._pendingSeekTime != null) { 3724 // Media segments after new-segment cross-seeking should be dropped. 3725 return; 3726 } 3727 this._emitter.emit(_transmuxingEvents2.default.MEDIA_SEGMENT, type, mediaSegment); 3728 3729 // Resolve pending seekPoint
vendor: 10,704 bytes, lines 3730-4049
3730 if (this._pendingResolveSeekPoint != null && type === 'video') { 3731 var syncPoints = mediaSegment.info.syncPoints; 3732 var seekpoint = this._pendingResolveSeekPoint; 3733 this._pendingResolveSeekPoint = null; 3734 3735 // Safari: Pass PTS for recommend_seekpoint 3736 if (_browser2.default.safari && syncPoints.length > 0 && syncPoints[0].originalDts === seekpoint) { 3737 seekpoint = syncPoints[0].pts; 3738 } 3739 // else: use original DTS (keyframe.milliseconds) 3740 3741 this._emitter.emit(_transmuxingEvents2.default.RECOMMEND_SEEKPOINT, seekpoint); 3742 } 3743 } 3744 }, { 3745 key: '_enableStatisticsReporter', 3746 value: function _enableStatisticsReporter() { 3747 if (this._statisticsReporter == null) { 3748 this._statisticsReporter = self.setInterval(this._reportStatisticsInfo.bind(this), this._config.statisticsInfoReportInterval); 3749 } 3750 } 3751 }, { 3752 key: '_disableStatisticsReporter', 3753 value: function _disableStatisticsReporter() { 3754 if (this._statisticsReporter) { 3755 self.clearInterval(this._statisticsReporter); 3756 this._statisticsReporter = null; 3757 } 3758 } 3759 }, { 3760 key: '_reportSegmentMediaInfo', 3761 value: function _reportSegmentMediaInfo(segmentIndex) { 3762 var segmentInfo = this._mediaInfo.segments[segmentIndex]; 3763 var exportInfo = Object.assign({}, segmentInfo); 3764 3765 exportInfo.duration = this._mediaInfo.duration; 3766 exportInfo.segmentCount = this._mediaInfo.segmentCount; 3767 delete exportInfo.segments; 3768 delete exportInfo.keyframesIndex; 3769 3770 this._emitter.emit(_transmuxingEvents2.default.MEDIA_INFO, exportInfo); 3771 } 3772 }, { 3773 key: '_reportStatisticsInfo', 3774 value: function _reportStatisticsInfo() { 3775 var info = {}; 3776 3777 info.url = this._ioctl.currentURL; 3778 info.hasRedirect = this._ioctl.hasRedirect; 3779 if (info.hasRedirect) { 3780 info.redirectedURL = this._ioctl.currentRedirectedURL; 3781 } 3782 3783 info.speed = this._ioctl.currentSpeed; 3784 info.loaderType = this._ioctl.loaderType; 3785 info.currentSegmentIndex = this._currentSegmentIndex; 3786 info.totalSegmentCount = this._mediaDataSource.segments.length; 3787 3788 this._emitter.emit(_transmuxingEvents2.default.STATISTICS_INFO, info); 3789 } 3790 }]); 3791 3792 return TransmuxingController; 3793}(); 3794 3795exports.default = TransmuxingController; 3796 3797},{"../demux/demux-errors.js":16,"../demux/flv-demuxer.js":18,"../io/io-controller.js":23,"../io/loader.js":24,"../remux/mp4-remuxer.js":38,"../utils/browser.js":39,"../utils/logger.js":41,"./media-info.js":7,"./transmuxing-events.js":13,"events":2}],13:[function(_dereq_,module,exports){ 3798'use strict'; 3799 3800Object.defineProperty(exports, "__esModule", { 3801 value: true 3802}); 3803/* 3804 * Copyright (C) 2016 Bilibili. All Rights Reserved. 3805 * 3806 * @author zheng qian <[email protected]> 3807 * 3808 * Licensed under the Apache License, Version 2.0 (the "License"); 3809 * you may not use this file except in compliance with the License. 3810 * You may obtain a copy of the License at 3811 * 3812 * http://www.apache.org/licenses/LICENSE-2.0 3813 * 3814 * Unless required by applicable law or agreed to in writing, software 3815 * distributed under the License is distributed on an "AS IS" BASIS, 3816 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3817 * See the License for the specific language governing permissions and 3818 * limitations under the License. 3819 */ 3820 3821var TransmuxingEvents = { 3822 IO_ERROR: 'io_error', 3823 DEMUX_ERROR: 'demux_error', 3824 INIT_SEGMENT: 'init_segment', 3825 MEDIA_SEGMENT: 'media_segment', 3826 LOADING_COMPLETE: 'loading_complete', 3827 RECOVERED_EARLY_EOF: 'recovered_early_eof', 3828 MEDIA_INFO: 'media_info', 3829 METADATA_ARRIVED: 'metadata_arrived', 3830 SCRIPTDATA_ARRIVED: 'scriptdata_arrived', 3831 STATISTICS_INFO: 'statistics_info', 3832 RECOMMEND_SEEKPOINT: 'recommend_seekpoint' 3833}; 3834 3835exports.default = TransmuxingEvents; 3836 3837},{}],14:[function(_dereq_,module,exports){ 3838'use strict'; 3839 3840Object.defineProperty(exports, "__esModule", { 3841 value: true 3842}); 3843 3844var _logger = _dereq_('../utils/logger.js'); 3845 3846var _logger2 = _interopRequireDefault(_logger); 3847 3848var _loggingControl = _dereq_('../utils/logging-control.js'); 3849 3850var _loggingControl2 = _interopRequireDefault(_loggingControl); 3851 3852var _polyfill = _dereq_('../utils/polyfill.js'); 3853 3854var _polyfill2 = _interopRequireDefault(_polyfill); 3855 3856var _transmuxingController = _dereq_('./transmuxing-controller.js'); 3857 3858var _transmuxingController2 = _interopRequireDefault(_transmuxingController); 3859 3860var _transmuxingEvents = _dereq_('./transmuxing-events.js'); 3861 3862var _transmuxingEvents2 = _interopRequireDefault(_transmuxingEvents); 3863 3864function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 3865 3866/* post message to worker: 3867 data: { 3868 cmd: string 3869 param: any 3870 } 3871 3872 receive message from worker: 3873 data: { 3874 msg: string, 3875 data: any 3876 } 3877 */ 3878 3879var TransmuxingWorker = function TransmuxingWorker(self) { 3880 3881 var TAG = 'TransmuxingWorker'; 3882 var controller = null; 3883 var logcatListener = onLogcatCallback.bind(this); 3884 3885 _polyfill2.default.install(); 3886 3887 self.addEventListener('message', function (e) { 3888 switch (e.data.cmd) { 3889 case 'init': 3890 controller = new _transmuxingController2.default(e.data.param[0], e.data.param[1]); 3891 controller.on(_transmuxingEvents2.default.IO_ERROR, onIOError.bind(this)); 3892 controller.on(_transmuxingEvents2.default.DEMUX_ERROR, onDemuxError.bind(this)); 3893 controller.on(_transmuxingEvents2.default.INIT_SEGMENT, onInitSegment.bind(this)); 3894 controller.on(_transmuxingEvents2.default.MEDIA_SEGMENT, onMediaSegment.bind(this)); 3895 controller.on(_transmuxingEvents2.default.LOADING_COMPLETE, onLoadingComplete.bind(this)); 3896 controller.on(_transmuxingEvents2.default.RECOVERED_EARLY_EOF, onRecoveredEarlyEof.bind(this)); 3897 controller.on(_transmuxingEvents2.default.MEDIA_INFO, onMediaInfo.bind(this)); 3898 controller.on(_transmuxingEvents2.default.METADATA_ARRIVED, onMetaDataArrived.bind(this)); 3899 controller.on(_transmuxingEvents2.default.SCRIPTDATA_ARRIVED, onScriptDataArrived.bind(this)); 3900 controller.on(_transmuxingEvents2.default.STATISTICS_INFO, onStatisticsInfo.bind(this)); 3901 controller.on(_transmuxingEvents2.default.RECOMMEND_SEEKPOINT, onRecommendSeekpoint.bind(this)); 3902 break; 3903 case 'destroy': 3904 if (controller) { 3905 controller.destroy(); 3906 controller = null; 3907 } 3908 self.postMessage({ msg: 'destroyed' }); 3909 break; 3910 case 'start': 3911 controller.start(); 3912 break; 3913 case 'stop': 3914 controller.stop(); 3915 break; 3916 case 'seek': 3917 controller.seek(e.data.param); 3918 break; 3919 case 'pause': 3920 controller.pause(); 3921 break; 3922 case 'resume': 3923 controller.resume(); 3924 break; 3925 case 'logging_config': 3926 { 3927 var config = e.data.param; 3928 _loggingControl2.default.applyConfig(config); 3929 3930 if (config.enableCallback === true) { 3931 _loggingControl2.default.addLogListener(logcatListener); 3932 } else { 3933 _loggingControl2.default.removeLogListener(logcatListener); 3934 } 3935 break; 3936 } 3937 } 3938 }); 3939 3940 function onInitSegment(type, initSegment) { 3941 var obj = { 3942 msg: _transmuxingEvents2.default.INIT_SEGMENT, 3943 data: { 3944 type: type, 3945 data: initSegment 3946 } 3947 }; 3948 self.postMessage(obj, [initSegment.data]); // data: ArrayBuffer 3949 } 3950 3951 function onMediaSegment(type, mediaSegment) { 3952 var obj = { 3953 msg: _transmuxingEvents2.default.MEDIA_SEGMENT, 3954 data: { 3955 type: type, 3956 data: mediaSegment 3957 } 3958 }; 3959 self.postMessage(obj, [mediaSegment.data]); // data: ArrayBuffer 3960 } 3961 3962 function onLoadingComplete() { 3963 var obj = { 3964 msg: _transmuxingEvents2.default.LOADING_COMPLETE 3965 }; 3966 self.postMessage(obj); 3967 } 3968 3969 function onRecoveredEarlyEof() { 3970 var obj = { 3971 msg: _transmuxingEvents2.default.RECOVERED_EARLY_EOF 3972 }; 3973 self.postMessage(obj); 3974 } 3975 3976 function onMediaInfo(mediaInfo) { 3977 var obj = { 3978 msg: _transmuxingEvents2.default.MEDIA_INFO, 3979 data: mediaInfo 3980 }; 3981 self.postMessage(obj); 3982 } 3983 3984 function onMetaDataArrived(metadata) { 3985 var obj = { 3986 msg: _transmuxingEvents2.default.METADATA_ARRIVED, 3987 data: metadata 3988 }; 3989 self.postMessage(obj); 3990 } 3991 3992 function onScriptDataArrived(data) { 3993 var obj = { 3994 msg: _transmuxingEvents2.default.SCRIPTDATA_ARRIVED, 3995 data: data 3996 }; 3997 self.postMessage(obj); 3998 } 3999 4000 function onStatisticsInfo(statInfo) { 4001 var obj = { 4002 msg: _transmuxingEvents2.default.STATISTICS_INFO, 4003 data: statInfo 4004 }; 4005 self.postMessage(obj); 4006 } 4007 4008 function onIOError(type, info) { 4009 self.postMessage({ 4010 msg: _transmuxingEvents2.default.IO_ERROR, 4011 data: { 4012 type: type, 4013 info: info 4014 } 4015 }); 4016 } 4017 4018 function onDemuxError(type, info) { 4019 self.postMessage({ 4020 msg: _transmuxingEvents2.default.DEMUX_ERROR, 4021 data: { 4022 type: type, 4023 info: info 4024 } 4025 }); 4026 } 4027 4028 function onRecommendSeekpoint(milliseconds) { 4029 self.postMessage({ 4030 msg: _transmuxingEvents2.default.RECOMMEND_SEEKPOINT, 4031 data: milliseconds 4032 }); 4033 } 4034 4035 function onLogcatCallback(type, str) { 4036 self.postMessage({ 4037 msg: 'logcat_callback', 4038 data: { 4039 type: type, 4040 logcat: str 4041 } 4042 }); 4043 } 4044}; /* 4045 * Copyright (C) 2016 Bilibili. All Rights Reserved. 4046 * 4047 * @author zheng qian <[email protected]> 4048 * 4049 * Licensed under the Apache License, Version 2.0 (the "License");
4050 * you may not use this file except in compliance with the License. 4051 * You may obtain a copy of the License at 4052 * 4053 * http://www.apache.org/licenses/LICENSE-2.0 4054 * 4055 * Unless required by applicable law or agreed to in writing, software 4056 * distributed under the License is distributed on an "AS IS" BASIS, 4057 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 4058 * See the License for the specific language governing permissions and 4059 * limitations under the License. 4060 */ 4061 4062exports.default = TransmuxingWorker; 4063 4064},{"../utils/logger.js":41,"../utils/logging-control.js":42,"../utils/polyfill.js":43,"./transmuxing-controller.js":12,"./transmuxing-events.js":13}],15:[function(_dereq_,module,exports){ 4065'use strict'; 4066 4067Object.defineProperty(exports, "__esModule", { 4068 value: true 4069}); 4070 4071var _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; }; }(); /* 4072 * Copyright (C) 2016 Bilibili. All Rights Reserved. 4073 * 4074 * @author zheng qian <[email protected]> 4075 * 4076 * Licensed under the Apache License, Version 2.0 (the "License"); 4077 * you may
4077not use this file except in compliance with the License. 4078 * You may obtain a copy of the License at 4079 * 4080 * http://www.apache.org/licenses/LICENSE-2.0 4081 * 4082 * Unless required by applicable law or agreed to in writing, software 4083 * distributed under the License is distributed on an "AS IS" BASIS, 4084 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 4085 * See the License for the specific language governing permissions and 4086 * limitations under the License. 4087 */ 4088 4089var _logger = _dereq_('../utils/logger.js'); 4090 4091var _logger2 = _interopRequireDefault(_logger); 4092 4093var _utf8Conv = _dereq_('../utils/utf8-conv.js'); 4094 4095var _utf8Conv2 = _interopRequireDefault(_utf8Conv); 4096 4097var _exception = _dereq_('../utils/exception.js'); 4098 4099function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 4100 4101function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 4102 4103var le = function () { 4104 var buf = new ArrayBuffer(2); 4105 new DataView(buf).setInt16(0, 256, true); // little-endian write 4106 return new Int16Array(buf)[0] === 256; // platform-spec read, if equal then LE 4107}(); 4108 4109var AMF = function () { 4110 function AMF() { 4111 _classCallCheck(this, AMF); 4112 } 4113 4114 _createClass(AMF, null, [{ 4115 key: 'parseScriptData', 4116 value: function parseScriptData(arrayBuffer, dataOffset, dataSize) { 4117 var data = {}; 4118 4119 try { 4120 var name = AMF.parseValue(arrayBuffer, dataOffset, dataSize); 4121 var value = AMF.parseValue(arrayBuffer, dataOffset + name.size, dataSize - name.size); 4122 4123 data[name.data] = value.data; 4124 } catch (e) { 4125 _logger2.default.e('AMF', e.toString()); 4126 } 4127 4128 return data; 4129 } 4130 }, {
4131 key: 'parseObject', 4132 value: function parseObject(arrayBuffer, dataOffset, dataSize) { 4133 if (dataSize < 3) { 4134 throw new _exception.IllegalStateException('Data not enough when parse ScriptDataObject'); 4135 } 4136 var name = AMF.parseString(arrayBuffer, dataOffset, dataSize); 4137 var value = AMF.parseValue(arrayBuffer, dataOffset + name.size, dataSize - name.size); 4138 var isObjectEnd = value.objectEnd; 4139 4140 return { 4141 data: { 4142 name: name.data, 4143 value: value.data 4144 }, 4145 size: name.size + value.size, 4146 objectEnd: isObjectEnd 4147 }; 4148 } 4149 }, { 4150 key: 'parseVariable', 4151 value: function parseVariable(arrayBuffer, dataOffset, dataSize) { 4152 return AMF.parseObject(arrayBuffer, dataOffset, dataSize); 4153 } 4154 }, { 4155 key: 'parseString', 4156 value: function parseString(arrayBuffer, dataOffset, dataSize) { 4157 if (dataSize < 2) { 4158 throw new _exception.IllegalStateException('Data not enough when parse String'); 4159 } 4160 var v = new DataView(arrayBuffer, dataOffset, dataSize); 4161 var length = v.getUint16(0, !le); 4162 4163 var str = void 0; 4164 if (length > 0) { 4165 str = (0, _utf8Conv2.default)(new Uint8Array(arrayBuffer, dataOffset + 2, length)); 4166 } else { 4167 str = ''; 4168 } 4169 4170 return { 4171 data: str, 4172 size: 2 + length 4173 }; 4174 } 4175 }, { 4176 key: 'parseLongString', 4177 value: function parseLongString(arrayBuffer, dataOffset, dataSize) { 4178 if (dataSize < 4) { 4179 throw new _exception.IllegalStateException('Data not enough when parse LongString'); 4180 } 4181 var v = new DataView(arrayBuffer, dataOffset, dataSize); 4182 var length = v.getUint32(0, !le); 4183 4184 var str = void 0; 4185 if (length > 0) { 4186 str = (0, _utf8Conv2.default)(new Uint8Array(arrayBuffer, dataOffset + 4, length)); 4187 } else { 4188 str = ''; 4189 } 4190 4191 return { 4192 data: str, 4193 size: 4 + length 4194 }; 4195 } 4196 }, { 4197 key: 'parseDate', 4198 value: function parseDate(arrayBuffer, dataOffset, dataSize) { 4199 if (dataSize < 10) { 4200 throw new _exception.IllegalStateException('Data size invalid when parse Date'); 4201 } 4202 var v = new DataView(arrayBuffer, dataOffset, dataSize); 4203 var timestamp = v.getFloat64(0, !le); 4204 var localTimeOffset = v.getInt16(8, !le); 4205 timestamp += localTimeOffset * 60 * 1000; // get UTC time 4206 4207 return { 4208 data: new Date(timestamp), 4209 size: 8 + 2 4210 }; 4211 } 4212 }, { 4213 key: 'parseValue', 4214 value: function parseValue(arrayBuffer, dataOffset, dataSize) { 4215 if (dataSize < 1) { 4216 throw new _exception.IllegalStateException('Data not enough when parse Value'); 4217 } 4218 4219 var v = new DataView(arrayBuffer, dataOffset, dataSize); 4220 4221 var offset = 1; 4222 var type = v.getUint8(0); 4223 var value = void 0; 4224 var objectEnd = false; 4225 4226 try { 4227 switch (type) { 4228 case 0: 4229 // Number(Double) type 4230 value = v.getFloat64(1, !le); 4231 offset += 8; 4232 break; 4233 case 1: 4234 { 4235 // Boolean type 4236 var b = v.getUint8(1); 4237 value = b ? true : false; 4238 offset += 1; 4239 break; 4240 } 4241 case 2: 4242 { 4243 // String type 4244 var amfstr = AMF.parseString(arrayBuffer, dataOffset + 1, dataSize - 1); 4245 value = amfstr.data; 4246 offset += amfstr.size; 4247 break; 4248 } 4249 case 3: 4250 { 4251 // Object(s) type 4252 value = {}; 4253 var terminal = 0; // workaround for malformed Objects which has missing ScriptDataObjectEnd
vendor: 2,898 bytes, lines 4254-4306
4254 if ((v.getUint32(dataSize - 4, !le) & 0x00FFFFFF) === 9) { 4255 terminal = 3; 4256 } 4257 while (offset < dataSize - 4) { 4258 // 4 === type(UI8) + ScriptDataObjectEnd(UI24) 4259 var amfobj = AMF.parseObject(arrayBuffer, dataOffset + offset, dataSize - offset - terminal); 4260 if (amfobj.objectEnd) break; 4261 value[amfobj.data.name] = amfobj.data.value; 4262 offset += amfobj.size; 4263 } 4264 if (offset <= dataSize - 3) { 4265 var marker = v.getUint32(offset - 1, !le) & 0x00FFFFFF; 4266 if (marker === 9) { 4267 offset += 3; 4268 } 4269 } 4270 break; 4271 } 4272 case 8: 4273 { 4274 // ECMA array type (Mixed array) 4275 value = {}; 4276 offset += 4; // ECMAArrayLength(UI32) 4277 var _terminal = 0; // workaround for malformed MixedArrays which has missing ScriptDataObjectEnd 4278 if ((v.getUint32(dataSize - 4, !le) & 0x00FFFFFF) === 9) { 4279 _terminal = 3; 4280 } 4281 while (offset < dataSize - 8) { 4282 // 8 === type(UI8) + ECMAArrayLength(UI32) + ScriptDataVariableEnd(UI24) 4283 var amfvar = AMF.parseVariable(arrayBuffer, dataOffset + offset, dataSize - offset - _terminal); 4284 if (amfvar.objectEnd) break; 4285 value[amfvar.data.name] = amfvar.data.value; 4286 offset += amfvar.size; 4287 } 4288 if (offset <= dataSize - 3) { 4289 var _marker = v.getUint32(offset - 1, !le) & 0x00FFFFFF; 4290 if (_marker === 9) { 4291 offset += 3; 4292 } 4293 } 4294 break; 4295 } 4296 case 9: 4297 // ScriptDataObjectEnd 4298 value = undefined; 4299 offset = 1; 4300 objectEnd = true; 4301 break; 4302 case 10: 4303 { 4304 // Strict array type 4305 // ScriptDataValue[n]. NOTE: according to video_file_format_spec_v10_1.pdf 4306 value = [];
4307 var strictArrayLength = v.getUint32(1, !le); 4308 offset += 4; 4309 for (var i = 0; i < strictArrayLength; i++) { 4310 var val = AMF.parseValue(arrayBuffer, dataOffset + offset, dataSize - offset); 4311 value.push(val.data); 4312 offset += val.size; 4313 } 4314 break; 4315 } 4316 case 11: 4317 { 4318 // Date type 4319 var date = AMF.parseDate(arrayBuffer, dataOffset + 1, dataSize - 1); 4320 value = date.data; 4321 offset += date.size; 4322 break; 4323 } 4324 case 12: 4325 { 4326 // Long string type 4327 var amfLongStr = AMF.parseString(arrayBuffer, dataOffset + 1, dataSize - 1); 4328 value = amfLongStr.data; 4329 offset += amfLongStr.size; 4330 break; 4331 } 4332 default: 4333 // ignore and skip 4334 offset = dataSize; 4335 _logger2.default.w('AMF', 'Unsupported AMF value type ' + type); 4336 } 4337 } catch (e) { 4338 _logger2.default.e('AMF', e.toString()); 4339 } 4340 4341 return { 4342 data: value, 4343 size: offset, 4344 objectEnd: objectEnd 4345 }; 4346 } 4347 }]); 4348 4349 return AMF; 4350}(); 4351 4352exports.default = AMF; 4353 4354},{"../utils/exception.js":40,"../utils/logger.js":41,"../utils/utf8-conv.js":44}],16:[function(_dereq_,module,exports){ 4355'use strict'; 4356 4357Object.defineProperty(exports, "__esModule", { 4358 value: true 4359}); 4360/* 4361 * Copyright (C) 2016 Bilibili. All Rights Reserved. 4362 * 4363 * @author zheng qian <[email protected]> 4364 * 4365 * Licensed under the Apache License, Version 2.0 (the "License"); 4366 * you may not use this file except in compliance with the License. 4367 * You may obtain a copy of the License at 4368 * 4369 * http://www.apache.org/licenses/LICENSE-2.0 4370 * 4371 * Unless required by applicable law or agreed to in writing, software 4372 * distributed under the License is distributed on an "AS IS" BASIS, 4373 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 4374 * See the License for the specific language governing permissions and 4375 * limitations under the License. 4376 */ 4377 4378var DemuxErrors = { 4379 OK: 'OK', 4380 FORMAT_ERROR: 'FormatError', 4381 FORMAT_UNSUPPORTED: 'FormatUnsupported', 4382 CODEC_UNSUPPORTED: 'CodecUnsupported' 4383}; 4384 4385exports.default = DemuxErrors; 4386 4387},{}],17:[function(_dereq_,module,exports){ 4388'use strict'; 4389 4390Object.defineProperty(exports, "__esModule", { 4391 value: true 4392}); 4393 4394var _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; }; }(); /* 4395 * Copyright (C) 2016 Bilibili. All Rights Reserved. 4396 * 4397 * @author zheng qian <[email protected]> 4398 * 4399 * Licensed under the Apache License, Version 2.0 (the "License"); 4400 * you may
4400not use this file except in compliance with the License. 4401 * You may obtain a copy of the License at 4402 * 4403 * http://www.apache.org/licenses/LICENSE-2.0 4404 * 4405 * Unless required by applicable law or agreed to in writing, software 4406 * distributed under the License is distributed on an "AS IS" BASIS, 4407 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 4408 * See the License for the specific language governing permissions and 4409 * limitations under the License. 4410 */ 4411 4412var _exception = _dereq_('../utils/exception.js'); 4413 4414function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 4415 4416// Exponential-Golomb buffer decoder 4417var ExpGolomb = function () { 4418 function ExpGolomb(uint8array) { 4419 _classCallCheck(this, ExpGolomb); 4420 4421 this.TAG = 'ExpGolomb'; 4422 4423 this._buffer = uint8array; 4424 this._buffer_index = 0; 4425 this._total_bytes = uint8array.byteLength; 4426 this._total_bits = uint8array.byteLength * 8; 4427 this._current_word = 0; 4428 this._current_word_bits_left = 0; 4429 } 4430 4431 _createClass(ExpGolomb, [{ 4432 key: 'destroy', 4433 value: function destroy() { 4434 this._buffer = null; 4435 } 4436 }, {
4437 key: '_fillCurrentWord', 4438 value: function _fillCurrentWord() { 4439 var buffer_bytes_left = this._total_bytes - this._buffer_index; 4440 if (buffer_bytes_left <= 0) throw new _exception.IllegalStateException('ExpGolomb: _fillCurrentWord() but no bytes available'); 4441 4442 var bytes_read = Math.min(4, buffer_bytes_left); 4443 var word = new Uint8Array(4); 4444 word.set(this._buffer.subarray(this._buffer_index, this._buffer_index + bytes_read)); 4445 this._current_word = new DataView(word.buffer).getUint32(0, false); 4446 4447 this._buffer_index += bytes_read; 4448 this._current_word_bits_left = bytes_read * 8; 4449 } 4450 }, { 4451 key: 'readBits', 4452 value: function readBits(bits) { 4453 if (bits > 32) throw new _exception.InvalidArgumentException('ExpGolomb: readBits() bits exceeded max 32bits!'); 4454 4455 if (bits <= this._current_word_bits_left) { 4456 var _result = this._current_word >>> 32 - bits; 4457 this._current_word <<= bits; 4458 this._current_word_bits_left -= bits; 4459 return _result; 4460 } 4461 4462 var result = this._current_word_bits_left ? this._current_word : 0; 4463 result = result >>> 32 - this._current_word_bits_left; 4464 var bits_need_left = bits - this._current_word_bits_left; 4465 4466 this._fillCurrentWord(); 4467 var bits_read_next = Math.min(bits_need_left, this._current_word_bits_left); 4468 4469 var result2 = this._current_word >>> 32 - bits_read_next; 4470 this._current_word <<= bits_read_next; 4471 this._current_word_bits_left -= bits_read_next; 4472 4473 result = result << bits_read_next | result2; 4474 return result; 4475 } 4476 }, { 4477 key: 'readBool', 4478 value: function readBool() { 4479 return this.readBits(1) === 1; 4480 } 4481 }, { 4482 key: 'readByte', 4483 value: function readByte() { 4484 return this.readBits(8); 4485 } 4486 }, { 4487 key: '_skipLeadingZero', 4488 value: function _skipLeadingZero() { 4489 var zero_count = void 0; 4490 for (zero_count = 0; zero_count < this._current_word_bits_left; zero_count++) { 4491 if (0 !== (this._current_word & 0x80000000 >>> zero_count)) { 4492 this._current_word <<= zero_count; 4493 this._current_word_bits_left -= zero_count; 4494 return zero_count; 4495 } 4496 } 4497 this._fillCurrentWord(); 4498 return zero_count + this._skipLeadingZero(); 4499 } 4500 }, { 4501 key: 'readUEG', 4502 value: function readUEG() { 4503 // unsigned exponential golomb 4504 var leading_zeros = this._skipLeadingZero(); 4505 return this.readBits(leading_zeros + 1) - 1; 4506 } 4507 }, { 4508 key: 'readSEG', 4509 value: function readSEG() { 4510 // signed exponential golomb 4511 var value = this.readUEG(); 4512 if (value & 0x01) { 4513 return value + 1 >>> 1; 4514 } else { 4515 return -1 * (value >>> 1); 4516 } 4517 } 4518 }]); 4519 4520 return ExpGolomb; 4521}(); 4522 4523exports.default = ExpGolomb; 4524 4525},{"../utils/exception.js":40}],18:[function(_dereq_,module,exports){ 4526'use strict'; 4527 4528Object.defineProperty(exports, "__esModule", { 4529 value: true 4530}); 4531 4532var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 4533 4534var _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; }; }(); /* 4535 * Copyright (C) 2016 Bilibili. All Rights Reserved. 4536 * 4537 * @author zheng qian <[email protected]> 4538 * 4539 * Licensed under the Apache License, Version 2.0 (the "License"); 4540 * you may
4540not use this file except in compliance with the License. 4541 * You may obtain a copy of the License at 4542 * 4543 * http://www.apache.org/licenses/LICENSE-2.0 4544 * 4545 * Unless required by applicable law or agreed to in writing, software 4546 * distributed under the License is distributed on an "AS IS" BASIS, 4547 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 4548 * See the License for the specific language governing permissions and 4549 * limitations under the License. 4550 */ 4551 4552var _logger = _dereq_('../utils/logger.js'); 4553 4554var _logger2 = _interopRequireDefault(_logger); 4555 4556var _amfParser = _dereq_('./amf-parser.js'); 4557 4558var _amfParser2 = _interopRequireDefault(_amfParser); 4559
4560var _spsParser = _dereq_('./sps-parser.js'); 4561 4562var _spsParser2 = _interopRequireDefault(_spsParser); 4563 4564var _demuxErrors = _dereq_('./demux-errors.js'); 4565 4566var _demuxErrors2 = _interopRequireDefault(_demuxErrors); 4567 4568var _mediaInfo = _dereq_('../core/media-info.js'); 4569 4570var _mediaInfo2 = _interopRequireDefault(_mediaInfo); 4571 4572var _exception = _dereq_('../utils/exception.js'); 4573 4574function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 4575 4576function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 4577 4578function Swap16(src) { 4579 return src >>> 8 & 0xFF | (src & 0xFF) << 8; 4580} 4581 4582function Swap32(src) { 4583 return (src & 0xFF000000) >>> 24 | (src & 0x00FF0000) >>> 8 | (src & 0x0000FF00) << 8 | (src & 0x000000FF) << 24; 4584} 4585 4586function ReadBig32(array, index) { 4587 return array[index] << 24 | array[index + 1] << 16 | array[index + 2] << 8 | array[index + 3]; 4588} 4589 4590var FLVDemuxer = function () { 4591 function FLVDemuxer(probeData, config) { 4592 _classCallCheck(this, FLVDemuxer); 4593 4594 this.TAG = 'FLVDemuxer'; 4595 4596 this._config = config; 4597 4598 this._onError = null; 4599 this._onMediaInfo = null; 4600 this._onMetaDataArrived = null; 4601 this._onScriptDataArrived = null; 4602 this._onTrackMetadata = null; 4603 this._onDataAvailable = null; 4604 4605 this._dataOffset = probeData.dataOffset; 4606 this._firstParse = true; 4607 this._dispatch = false; 4608 4609 this._hasAudio = probeData.hasAudioTrack; 4610 this._hasVideo = probeData.hasVideoTrack; 4611 4612 this._hasAudioFlagOverrided = false; 4613 this._hasVideoFlagOverrided = false; 4614 4615 this._audioInitialMetadataDispatched = false; 4616 this._videoInitialMetadataDispatched = false; 4617 4618 this._mediaInfo = new _mediaInfo2.default(); 4619 this._mediaInfo.hasAudio = this._hasAudio; 4620 this._mediaInfo.hasVideo = this._hasVideo; 4621 this._metadata = null; 4622 this._audioMetadata = null; 4623 this._videoMetadata = null; 4624 4625 this._naluLengthSize = 4; 4626 this._timestampBase = 0; // int32, in milliseconds 4627 this._timescale = 1000; 4628 this._duration = 0; // int32, in milliseconds 4629 this._durationOverrided = false; 4630 this._referenceFrameRate = { 4631 fixed: true, 4632 fps: 23.976, 4633 fps_num: 23976, 4634 fps_den: 1000 4635 }; 4636 4637 this._flvSoundRateTable = [5500, 11025, 22050, 44100, 48000]; 4638 4639 this._mpegSamplingRates = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350]; 4640 4641 this._mpegAudioV10SampleRateTable = [44100, 48000, 32000, 0]; 4642 this._mpegAudioV20SampleRateTable = [22050, 24000, 16000, 0]; 4643 this._mpegAudioV25SampleRateTable = [11025, 12000, 8000, 0]; 4644 4645 this._mpegAudioL1BitRateTable = [0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, -1]; 4646 this._mpegAudioL2BitRateTable = [0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, -1]; 4647 this._mpegAudioL3BitRateTable = [0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1]; 4648 4649 this._videoTrack = { type: 'video', id: 1, sequenceNumber: 0, samples: [], length: 0 }; 4650 this._audioTrack = { type: 'audio', id: 2, sequenceNumber: 0, samples: [], length: 0 }; 4651 4652 this._littleEndian = function () { 4653 var buf = new ArrayBuffer(2); 4654 new DataView(buf).setInt16(0, 256, true); // little-endian write 4655 return new Int16Array(buf)[0] === 256; // platform-spec read, if equal then LE 4656 }(); 4657 } 4658 4659 _createClass(FLVDemuxer, [{ 4660 key: 'destroy', 4661 value: function destroy() { 4662 this._mediaInfo = null; 4663 this._metadata = null; 4664 this._audioMetadata = null; 4665 this._videoMetadata = null; 4666 this._videoTrack = null; 4667 this._audioTrack = null; 4668 4669 this._onError = null; 4670 this._onMediaInfo = null; 4671 this._onMetaDataArrived = null; 4672 this._onScriptDataArrived = null; 4673 this._onTrackMetadata = null; 4674 this._onDataAvailable = null; 4675 } 4676 }, {
4677 key: 'bindDataSource', 4678 value: function bindDataSource(loader) { 4679 loader.onDataArrival = this.parseChunks.bind(this); 4680 return this; 4681 } 4682 4683 // prototype: function(type: string, metadata: any): void 4684 4685 }, { 4686 key: 'resetMediaInfo', 4687 value: function resetMediaInfo() { 4688 this._mediaInfo = new _mediaInfo2.default(); 4689 } 4690 }, { 4691 key: '_isInitialMetadataDispatched', 4692 value: function _isInitialMetadataDispatched() { 4693 if (this._hasAudio && this._hasVideo) { 4694 // both audio & video 4695 return this._audioInitialMetadataDispatched && this._videoInitialMetadataDispatched; 4696 } 4697 if (this._hasAudio && !this._hasVideo) { 4698 // audio only 4699 return this._audioInitialMetadataDispatched; 4700 } 4701 if (!this._hasAudio && this._hasVideo) { 4702 // video only 4703 return this._videoInitialMetadataDispatched; 4704 } 4705 return false; 4706 } 4707 4708 // function parseChunks(chunk: ArrayBuffer, byteStart: number): number; 4709 4710 }, { 4711 key: 'parseChunks', 4712 value: function parseChunks(chunk, byteStart) { 4713 if (!this._onError || !this._onMediaInfo || !this._onTrackMetadata || !this._onDataAvailable) { 4714 throw new _exception.IllegalStateException('Flv: onError & onMediaInfo & onTrackMetadata & onDataAvailable callback must be specified'); 4715 } 4716 4717 var offset = 0; 4718 var le = this._littleEndian; 4719 4720 if (byteStart === 0) { 4721 // buffer with FLV header 4722 if (chunk.byteLength > 13) { 4723 var probeData = FLVDemuxer.probe(chunk); 4724 offset = probeData.dataOffset; 4725 } else { 4726 return 0; 4727 } 4728 } 4729 4730 if (this._firstParse) { 4731 // handle PreviousTagSize0 before Tag1 4732 this._firstParse = false;
vendor: 20,009 bytes, lines 4733-5196
4733 if (byteStart + offset !== this._dataOffset) { 4734 _logger2.default.w(this.TAG, 'First time parsing but chunk byteStart invalid!'); 4735 } 4736 4737 var v = new DataView(chunk, offset); 4738 var prevTagSize0 = v.getUint32(0, !le); 4739 if (prevTagSize0 !== 0) { 4740 _logger2.default.w(this.TAG, 'PrevTagSize0 !== 0 !!!'); 4741 } 4742 offset += 4; 4743 } 4744 4745 while (offset < chunk.byteLength) { 4746 this._dispatch = true; 4747 4748 var _v = new DataView(chunk, offset); 4749 4750 if (offset + 11 + 4 > chunk.byteLength) { 4751 // data not enough for parsing an flv tag 4752 break; 4753 } 4754 4755 var tagType = _v.getUint8(0); 4756 var dataSize = _v.getUint32(0, !le) & 0x00FFFFFF; 4757 4758 if (offset + 11 + dataSize + 4 > chunk.byteLength) { 4759 // data not enough for parsing actual data body 4760 break; 4761 } 4762 4763 if (tagType !== 8 && tagType !== 9 && tagType !== 18) { 4764 _logger2.default.w(this.TAG, 'Unsupported tag type ' + tagType + ', skipped'); 4765 // consume the whole tag (skip it) 4766 offset += 11 + dataSize + 4; 4767 continue; 4768 } 4769 4770 var ts2 = _v.getUint8(4); 4771 var ts1 = _v.getUint8(5); 4772 var ts0 = _v.getUint8(6); 4773 var ts3 = _v.getUint8(7); 4774 4775 var timestamp = ts0 | ts1 << 8 | ts2 << 16 | ts3 << 24; 4776 4777 var streamId = _v.getUint32(7, !le) & 0x00FFFFFF; 4778 if (streamId !== 0) { 4779 _logger2.default.w(this.TAG, 'Meet tag which has StreamID != 0!'); 4780 } 4781 4782 var dataOffset = offset + 11; 4783 4784 switch (tagType) { 4785 case 8: 4786 // Audio 4787 this._parseAudioData(chunk, dataOffset, dataSize, timestamp); 4788 break; 4789 case 9: 4790 // Video 4791 this._parseVideoData(chunk, dataOffset, dataSize, timestamp, byteStart + offset); 4792 break; 4793 case 18: 4794 // ScriptDataObject 4795 this._parseScriptData(chunk, dataOffset, dataSize); 4796 break; 4797 } 4798 4799 var prevTagSize = _v.getUint32(11 + dataSize, !le); 4800 if (prevTagSize !== 11 + dataSize) { 4801 _logger2.default.w(this.TAG, 'Invalid PrevTagSize ' + prevTagSize); 4802 } 4803 4804 offset += 11 + dataSize + 4; // tagBody + dataSize + prevTagSize 4805 } 4806 4807 // dispatch parsed frames to consumer (typically, the remuxer) 4808 if (this._isInitialMetadataDispatched()) { 4809 if (this._dispatch && (this._audioTrack.length || this._videoTrack.length)) { 4810 this._onDataAvailable(this._audioTrack, this._videoTrack); 4811 } 4812 } 4813 4814 return offset; // consumed bytes, just equals latest offset index 4815 } 4816 }, { 4817 key: '_parseScriptData', 4818 value: function _parseScriptData(arrayBuffer, dataOffset, dataSize) { 4819 var scriptData = _amfParser2.default.parseScriptData(arrayBuffer, dataOffset, dataSize); 4820 4821 if (scriptData.hasOwnProperty('onMetaData')) { 4822 if (scriptData.onMetaData == null || _typeof(scriptData.onMetaData) !== 'object') { 4823 _logger2.default.w(this.TAG, 'Invalid onMetaData structure!'); 4824 return; 4825 } 4826 if (this._metadata) { 4827 _logger2.default.w(this.TAG, 'Found another onMetaData tag!'); 4828 } 4829 this._metadata = scriptData; 4830 var onMetaData = this._metadata.onMetaData; 4831 4832 if (this._onMetaDataArrived) { 4833 this._onMetaDataArrived(Object.assign({}, onMetaData)); 4834 } 4835 4836 if (typeof onMetaData.hasAudio === 'boolean') { 4837 // hasAudio 4838 if (this._hasAudioFlagOverrided === false) { 4839 this._hasAudio = onMetaData.hasAudio; 4840 this._mediaInfo.hasAudio = this._hasAudio; 4841 } 4842 } 4843 if (typeof onMetaData.hasVideo === 'boolean') { 4844 // hasVideo 4845 if (this._hasVideoFlagOverrided === false) { 4846 this._hasVideo = onMetaData.hasVideo; 4847 this._mediaInfo.hasVideo = this._hasVideo; 4848 } 4849 } 4850 if (typeof onMetaData.audiodatarate === 'number') { 4851 // audiodatarate 4852 this._mediaInfo.audioDataRate = onMetaData.audiodatarate; 4853 } 4854 if (typeof onMetaData.videodatarate === 'number') { 4855 // videodatarate 4856 this._mediaInfo.videoDataRate = onMetaData.videodatarate; 4857 } 4858 if (typeof onMetaData.width === 'number') { 4859 // width 4860 this._mediaInfo.width = onMetaData.width; 4861 } 4862 if (typeof onMetaData.height === 'number') { 4863 // height 4864 this._mediaInfo.height = onMetaData.height; 4865 } 4866 if (typeof onMetaData.duration === 'number') { 4867 // duration 4868 if (!this._durationOverrided) { 4869 var duration = Math.floor(onMetaData.duration * this._timescale); 4870 this._duration = duration; 4871 this._mediaInfo.duration = duration; 4872 } 4873 } else { 4874 this._mediaInfo.duration = 0; 4875 } 4876 if (typeof onMetaData.framerate === 'number') { 4877 // framerate 4878 var fps_num = Math.floor(onMetaData.framerate * 1000); 4879 if (fps_num > 0) { 4880 var fps = fps_num / 1000; 4881 this._referenceFrameRate.fixed = true; 4882 this._referenceFrameRate.fps = fps; 4883 this._referenceFrameRate.fps_num = fps_num; 4884 this._referenceFrameRate.fps_den = 1000; 4885 this._mediaInfo.fps = fps; 4886 } 4887 } 4888 if (_typeof(onMetaData.keyframes) === 'object') { 4889 // keyframes 4890 this._mediaInfo.hasKeyframesIndex = true; 4891 var keyframes = onMetaData.keyframes; 4892 this._mediaInfo.keyframesIndex = this._parseKeyframesIndex(keyframes); 4893 onMetaData.keyframes = null; // keyframes has been extracted, remove it 4894 } else { 4895 this._mediaInfo.hasKeyframesIndex = false; 4896 } 4897 this._dispatch = false; 4898 this._mediaInfo.metadata = onMetaData; 4899 _logger2.default.v(this.TAG, 'Parsed onMetaData'); 4900 if (this._mediaInfo.isComplete()) { 4901 this._onMediaInfo(this._mediaInfo); 4902 } 4903 } 4904 4905 if (Object.keys(scriptData).length > 0) { 4906 if (this._onScriptDataArrived) { 4907 this._onScriptDataArrived(Object.assign({}, scriptData)); 4908 } 4909 } 4910 } 4911 }, { 4912 key: '_parseKeyframesIndex', 4913 value: function _parseKeyframesIndex(keyframes) { 4914 var times = []; 4915 var filepositions = []; 4916 4917 // ignore first keyframe which is actually AVC Sequence Header (AVCDecoderConfigurationRecord) 4918 for (var i = 1; i < keyframes.times.length; i++) { 4919 var time = this._timestampBase + Math.floor(keyframes.times[i] * 1000); 4920 times.push(time); 4921 filepositions.push(keyframes.filepositions[i]); 4922 } 4923 4924 return { 4925 times: times, 4926 filepositions: filepositions 4927 }; 4928 } 4929 }, { 4930 key: '_parseAudioData', 4931 value: function _parseAudioData(arrayBuffer, dataOffset, dataSize, tagTimestamp) { 4932 if (dataSize <= 1) { 4933 _logger2.default.w(this.TAG, 'Flv: Invalid audio packet, missing SoundData payload!'); 4934 return; 4935 } 4936 4937 if (this._hasAudioFlagOverrided === true && this._hasAudio === false) { 4938 // If hasAudio: false indicated explicitly in MediaDataSource, 4939 // Ignore all the audio packets 4940 return; 4941 } 4942 4943 var le = this._littleEndian; 4944 var v = new DataView(arrayBuffer, dataOffset, dataSize); 4945 4946 var soundSpec = v.getUint8(0); 4947 4948 var soundFormat = soundSpec >>> 4; 4949 if (soundFormat !== 2 && soundFormat !== 10) { 4950 // MP3 or AAC 4951 this._onError(_demuxErrors2.default.CODEC_UNSUPPORTED, 'Flv: Unsupported audio codec idx: ' + soundFormat); 4952 return; 4953 } 4954 4955 var soundRate = 0; 4956 var soundRateIndex = (soundSpec & 12) >>> 2; 4957 if (soundRateIndex >= 0 && soundRateIndex <= 4) { 4958 soundRate = this._flvSoundRateTable[soundRateIndex]; 4959 } else { 4960 this._onError(_demuxErrors2.default.FORMAT_ERROR, 'Flv: Invalid audio sample rate idx: ' + soundRateIndex); 4961 return; 4962 } 4963 4964 var soundSize = (soundSpec & 2) >>> 1; // unused 4965 var soundType = soundSpec & 1; 4966 4967 var meta = this._audioMetadata; 4968 var track = this._audioTrack; 4969 4970 if (!meta) { 4971 if (this._hasAudio === false && this._hasAudioFlagOverrided === false) { 4972 this._hasAudio = true; 4973 this._mediaInfo.hasAudio = true; 4974 } 4975 4976 // initial metadata 4977 meta = this._audioMetadata = {}; 4978 meta.type = 'audio'; 4979 meta.id = track.id; 4980 meta.timescale = this._timescale; 4981 meta.duration = this._duration; 4982 meta.audioSampleRate = soundRate; 4983 meta.channelCount = soundType === 0 ? 1 : 2; 4984 } 4985 4986 if (soundFormat === 10) { 4987 // AAC 4988 var aacData = this._parseAACAudioData(arrayBuffer, dataOffset + 1, dataSize - 1); 4989 if (aacData == undefined) { 4990 return; 4991 } 4992 4993 if (aacData.packetType === 0) { 4994 // AAC sequence header (AudioSpecificConfig) 4995 if (meta.config) { 4996 _logger2.default.w(this.TAG, 'Found another AudioSpecificConfig!'); 4997 } 4998 var misc = aacData.data; 4999 meta.audioSampleRate = misc.samplingRate; 5000 meta.channelCount = misc.channelCount; 5001 meta.codec = misc.codec; 5002 meta.originalCodec = misc.originalCodec; 5003 meta.config = misc.config; 5004 // The decode result of an aac sample is 1024 PCM samples 5005 meta.refSampleDuration = 1024 / meta.audioSampleRate * meta.timescale; 5006 _logger2.default.v(this.TAG, 'Parsed AudioSpecificConfig'); 5007 5008 if (this._isInitialMetadataDispatched()) { 5009 // Non-initial metadata, force dispatch (or flush) parsed frames to remuxer 5010 if (this._dispatch && (this._audioTrack.length || this._videoTrack.length)) { 5011 this._onDataAvailable(this._audioTrack, this._videoTrack); 5012 } 5013 } else { 5014 this._audioInitialMetadataDispatched = true; 5015 } 5016 // then notify new metadata 5017 this._dispatch = false; 5018 this._onTrackMetadata('audio', meta); 5019 5020 var mi = this._mediaInfo; 5021 mi.audioCodec = meta.originalCodec; 5022 mi.audioSampleRate = meta.audioSampleRate; 5023 mi.audioChannelCount = meta.channelCount; 5024 if (mi.hasVideo) { 5025 if (mi.videoCodec != null) { 5026 mi.mimeType = 'video/x-flv; codecs="' + mi.videoCodec + ',' + mi.audioCodec + '"'; 5027 } 5028 } else { 5029 mi.mimeType = 'video/x-flv; codecs="' + mi.audioCodec + '"'; 5030 } 5031 if (mi.isComplete()) { 5032 this._onMediaInfo(mi); 5033 } 5034 } else if (aacData.packetType === 1) { 5035 // AAC raw frame data 5036 var dts = this._timestampBase + tagTimestamp; 5037 var aacSample = { unit: aacData.data, length: aacData.data.byteLength, dts: dts, pts: dts }; 5038 track.samples.push(aacSample); 5039 track.length += aacData.data.length; 5040 } else { 5041 _logger2.default.e(this.TAG, 'Flv: Unsupported AAC data type ' + aacData.packetType); 5042 } 5043 } else if (soundFormat === 2) { 5044 // MP3 5045 if (!meta.codec) { 5046 // We need metadata for mp3 audio track, extract info from frame header 5047 var _misc = this._parseMP3AudioData(arrayBuffer, dataOffset + 1, dataSize - 1, true); 5048 if (_misc == undefined) { 5049 return; 5050 } 5051 meta.audioSampleRate = _misc.samplingRate; 5052 meta.channelCount = _misc.channelCount; 5053 meta.codec = _misc.codec; 5054 meta.originalCodec = _misc.originalCodec; 5055 // The decode result of an mp3 sample is 1152 PCM samples 5056 meta.refSampleDuration = 1152 / meta.audioSampleRate * meta.timescale; 5057 _logger2.default.v(this.TAG, 'Parsed MPEG Audio Frame Header'); 5058 5059 this._audioInitialMetadataDispatched = true; 5060 this._onTrackMetadata('audio', meta); 5061 5062 var _mi = this._mediaInfo; 5063 _mi.audioCodec = meta.codec; 5064 _mi.audioSampleRate = meta.audioSampleRate; 5065 _mi.audioChannelCount = meta.channelCount; 5066 _mi.audioDataRate = _misc.bitRate; 5067 if (_mi.hasVideo) { 5068 if (_mi.videoCodec != null) { 5069 _mi.mimeType = 'video/x-flv; codecs="' + _mi.videoCodec + ',' + _mi.audioCodec + '"'; 5070 } 5071 } else { 5072 _mi.mimeType = 'video/x-flv; codecs="' + _mi.audioCodec + '"'; 5073 } 5074 if (_mi.isComplete()) { 5075 this._onMediaInfo(_mi); 5076 } 5077 } 5078 5079 // This packet is always a valid audio packet, extract it 5080 var data = this._parseMP3AudioData(arrayBuffer, dataOffset + 1, dataSize - 1, false); 5081 if (data == undefined) { 5082 return; 5083 } 5084 var _dts = this._timestampBase + tagTimestamp; 5085 var mp3Sample = { unit: data, length: data.byteLength, dts: _dts, pts: _dts }; 5086 track.samples.push(mp3Sample); 5087 track.length += data.length; 5088 } 5089 } 5090 }, { 5091 key: '_parseAACAudioData', 5092 value: function _parseAACAudioData(arrayBuffer, dataOffset, dataSize) { 5093 if (dataSize <= 1) { 5094 _logger2.default.w(this.TAG, 'Flv: Invalid AAC packet, missing AACPacketType or/and Data!'); 5095 return; 5096 } 5097 5098 var result = {}; 5099 var array = new Uint8Array(arrayBuffer, dataOffset, dataSize); 5100 5101 result.packetType = array[0]; 5102 5103 if (array[0] === 0) { 5104 result.data = this._parseAACAudioSpecificConfig(arrayBuffer, dataOffset + 1, dataSize - 1); 5105 } else { 5106 result.data = array.subarray(1); 5107 } 5108 5109 return result; 5110 } 5111 }, { 5112 key: '_parseAACAudioSpecificConfig', 5113 value: function _parseAACAudioSpecificConfig(arrayBuffer, dataOffset, dataSize) { 5114 var array = new Uint8Array(arrayBuffer, dataOffset, dataSize); 5115 var config = null; 5116 5117 /* Audio Object Type: 5118 0: Null 5119 1: AAC Main 5120 2: AAC LC 5121 3: AAC SSR (Scalable Sample Rate) 5122 4: AAC LTP (Long Term Prediction) 5123 5: HE-AAC / SBR (Spectral Band Replication) 5124 6: AAC Scalable 5125 */ 5126 5127 var audioObjectType = 0; 5128 var originalAudioObjectType = 0; 5129 var audioExtensionObjectType = null; 5130 var samplingIndex = 0; 5131 var extensionSamplingIndex = null; 5132 5133 // 5 bits 5134 audioObjectType = originalAudioObjectType = array[0] >>> 3; 5135 // 4 bits 5136 samplingIndex = (array[0] & 0x07) << 1 | array[1] >>> 7; 5137 if (samplingIndex < 0 || samplingIndex >= this._mpegSamplingRates.length) { 5138 this._onError(_demuxErrors2.default.FORMAT_ERROR, 'Flv: AAC invalid sampling frequency index!'); 5139 return; 5140 } 5141 5142 var samplingFrequence = this._mpegSamplingRates[samplingIndex]; 5143 5144 // 4 bits 5145 var channelConfig = (array[1] & 0x78) >>> 3; 5146 if (channelConfig < 0 || channelConfig >= 8) { 5147 this._onError(_demuxErrors2.default.FORMAT_ERROR, 'Flv: AAC invalid channel configuration'); 5148 return; 5149 } 5150 5151 if (audioObjectType === 5) { 5152 // HE-AAC? 5153 // 4 bits 5154 extensionSamplingIndex = (array[1] & 0x07) << 1 | array[2] >>> 7; 5155 // 5 bits 5156 audioExtensionObjectType = (array[2] & 0x7C) >>> 2; 5157 } 5158 5159 // workarounds for various browsers 5160 var userAgent = self.navigator.userAgent.toLowerCase(); 5161 5162 if (userAgent.indexOf('firefox') !== -1) { 5163 // firefox: use SBR (HE-AAC) if freq less than 24kHz 5164 if (samplingIndex >= 6) { 5165 audioObjectType = 5; 5166 config = new Array(4); 5167 extensionSamplingIndex = samplingIndex - 3; 5168 } else { 5169 // use LC-AAC 5170 audioObjectType = 2; 5171 config = new Array(2); 5172 extensionSamplingIndex = samplingIndex; 5173 } 5174 } else if (userAgent.indexOf('android') !== -1) { 5175 // android: always use LC-AAC 5176 audioObjectType = 2; 5177 config = new Array(2); 5178 extensionSamplingIndex = samplingIndex; 5179 } else { 5180 // for other browsers, e.g. chrome... 5181 // Always use HE-AAC to make it easier to switch aac codec profile 5182 audioObjectType = 5; 5183 extensionSamplingIndex = samplingIndex; 5184 config = new Array(4); 5185 5186 if (samplingIndex >= 6) { 5187 extensionSamplingIndex = samplingIndex - 3; 5188 } else if (channelConfig === 1) { 5189 // Mono channel 5190 audioObjectType = 2; 5191 config = new Array(2); 5192 extensionSamplingIndex = samplingIndex; 5193 } 5194 } 5195 5196 config[0] = audioObjectType << 3;
5197 config[0] |= (samplingIndex & 0x0F) >>> 1; 5198 config[1] = (samplingIndex & 0x0F) << 7; 5199 config[1] |= (channelConfig & 0x0F) << 3; 5200 if (audioObjectType === 5) { 5201 config[1] |= (extensionSamplingIndex & 0x0F) >>> 1; 5202 config[2] = (extensionSamplingIndex & 0x01) << 7; 5203 // extended audio object type: force to 2 (LC-AAC) 5204 config[2] |= 2 << 2; 5205 config[3] = 0; 5206 } 5207 5208 return { 5209 config: config, 5210 samplingRate: samplingFrequence, 5211 channelCount: channelConfig, 5212 codec: 'mp4a.40.' + audioObjectType, 5213 originalCodec: 'mp4a.40.' + originalAudioObjectType 5214 }; 5215 } 5216 }, { 5217 key: '_parseMP3AudioData', 5218 value: function _parseMP3AudioData(arrayBuffer, dataOffset, dataSize, requestHeader) { 5219 if (dataSize < 4) { 5220 _logger2.default.w(this.TAG, 'Flv: Invalid MP3 packet, header missing!'); 5221 return; 5222 } 5223 5224 var le = this._littleEndian; 5225 var array = new Uint8Array(arrayBuffer, dataOffset, dataSize); 5226 var result = null; 5227 5228 if (requestHeader) { 5229 if (array[0] !== 0xFF) { 5230 return; 5231 } 5232 var ver = array[1] >>> 3 & 0x03; 5233 var layer = (array[1] & 0x06) >> 1; 5234 5235 var bitrate_index = (array[2] & 0xF0) >>> 4; 5236 var sampling_freq_index = (array[2] & 0x0C) >>> 2; 5237 5238 var channel_mode = array[3] >>> 6 & 0x03; 5239 var channel_count = channel_mode !== 3 ? 2 : 1; 5240 5241 var sample_rate = 0; 5242 var bit_rate = 0; 5243 var object_type = 34; // Layer-3, listed in MPEG-4 Audio Object Types 5244 5245 var codec = 'mp3'; 5246 5247 switch (ver) { 5248 case 0: 5249 // MPEG 2.5 5250 sample_rate = this._mpegAudioV25SampleRateTable[sampling_freq_index]; 5251 break; 5252 case 2: 5253 // MPEG 2 5254 sample_rate = this._mpegAudioV20SampleRateTable[sampling_freq_index]; 5255 break; 5256 case 3: 5257 // MPEG 1 5258 sample_rate = this._mpegAudioV10SampleRateTable[sampling_freq_index]; 5259 break; 5260 } 5261 5262 switch (layer) { 5263 case 1: 5264 // Layer 3 5265 object_type = 34; 5266 if (bitrate_index < this._mpegAudioL3BitRateTable.length) { 5267 bit_rate = this._mpegAudioL3BitRateTable[bitrate_index]; 5268 } 5269 break; 5270 case 2: 5271 // Layer 2 5272 object_type = 33; 5273 if (bitrate_index < this._mpegAudioL2BitRateTable.length) { 5274 bit_rate = this._mpegAudioL2BitRateTable[bitrate_index]; 5275 } 5276 break; 5277 case 3: 5278 // Layer 1 5279 object_type = 32; 5280 if (bitrate_index < this._mpegAudioL1BitRateTable.length) { 5281 bit_rate = this._mpegAudioL1BitRateTable[bitrate_index]; 5282 } 5283 break; 5284 } 5285 5286 result = { 5287 bitRate: bit_rate, 5288 samplingRate: sample_rate, 5289 channelCount: channel_count, 5290 codec: codec, 5291 originalCodec: codec 5292 }; 5293 } else { 5294 result = array; 5295 } 5296 5297 return result; 5298 } 5299 }, { 5300 key: '_parseVideoData', 5301 value: function _parseVideoData(arrayBuffer, dataOffset, dataSize, tagTimestamp, tagPosition) { 5302 if (dataSize <= 1) { 5303 _logger2.default.w(this.TAG, 'Flv: Invalid video packet, missing VideoData payload!'); 5304 return; 5305 } 5306 5307 if (this._hasVideoFlagOverrided === true && this._hasVideo === false) { 5308 // If hasVideo: false indicated explicitly in MediaDataSource, 5309 // Ignore all the video packets 5310 return; 5311 } 5312 5313 var spec = new Uint8Array(arrayBuffer, dataOffset, dataSize)[0]; 5314 5315 var frameType = (spec & 240) >>> 4; 5316 var codecId = spec & 15; 5317 5318 if (codecId !== 7) { 5319 this._onError(_demuxErrors2.default.CODEC_UNSUPPORTED, 'Flv: Unsupported codec in video frame: ' + codecId); 5320 return; 5321 } 5322 5323 this._parseAVCVideoPacket(arrayBuffer, dataOffset + 1, dataSize - 1, tagTimestamp, tagPosition, frameType); 5324 } 5325 }, {
vendor: 8,228 bytes, lines 5326-5518
5326 key: '_parseAVCVideoPacket', 5327 value: function _parseAVCVideoPacket(arrayBuffer, dataOffset, dataSize, tagTimestamp, tagPosition, frameType) { 5328 if (dataSize < 4) { 5329 _logger2.default.w(this.TAG, 'Flv: Invalid AVC packet, missing AVCPacketType or/and CompositionTime'); 5330 return; 5331 } 5332 5333 var le = this._littleEndian; 5334 var v = new DataView(arrayBuffer, dataOffset, dataSize); 5335 5336 var packetType = v.getUint8(0); 5337 var cts_unsigned = v.getUint32(0, !le) & 0x00FFFFFF; 5338 var cts = cts_unsigned << 8 >> 8; // convert to 24-bit signed int 5339 5340 if (packetType === 0) { 5341 // AVCDecoderConfigurationRecord 5342 this._parseAVCDecoderConfigurationRecord(arrayBuffer, dataOffset + 4, dataSize - 4); 5343 } else if (packetType === 1) { 5344 // One or more Nalus 5345 this._parseAVCVideoData(arrayBuffer, dataOffset + 4, dataSize - 4, tagTimestamp, tagPosition, frameType, cts); 5346 } else if (packetType === 2) { 5347 // empty, AVC end of sequence 5348 } else { 5349 this._onError(_demuxErrors2.default.FORMAT_ERROR, 'Flv: Invalid video packet type ' + packetType); 5350 return; 5351 } 5352 } 5353 }, { 5354 key: '_parseAVCDecoderConfigurationRecord', 5355 value: function _parseAVCDecoderConfigurationRecord(arrayBuffer, dataOffset, dataSize) { 5356 if (dataSize < 7) { 5357 _logger2.default.w(this.TAG, 'Flv: Invalid AVCDecoderConfigurationRecord, lack of data!'); 5358 return; 5359 } 5360 5361 var meta = this._videoMetadata; 5362 var track = this._videoTrack; 5363 var le = this._littleEndian; 5364 var v = new DataView(arrayBuffer, dataOffset, dataSize); 5365 5366 if (!meta) { 5367 if (this._hasVideo === false && this._hasVideoFlagOverrided === false) { 5368 this._hasVideo = true; 5369 this._mediaInfo.hasVideo = true; 5370 } 5371 5372 meta = this._videoMetadata = {}; 5373 meta.type = 'video'; 5374 meta.id = track.id; 5375 meta.timescale = this._timescale; 5376 meta.duration = this._duration; 5377 } else { 5378 if (typeof meta.avcc !== 'undefined') { 5379 _logger2.default.w(this.TAG, 'Found another AVCDecoderConfigurationRecord!'); 5380 } 5381 } 5382 5383 var version = v.getUint8(0); // configurationVersion 5384 var avcProfile = v.getUint8(1); // avcProfileIndication 5385 var profileCompatibility = v.getUint8(2); // profile_compatibility 5386 var avcLevel = v.getUint8(3); // AVCLevelIndication 5387 5388 if (version !== 1 || avcProfile === 0) { 5389 this._onError(_demuxErrors2.default.FORMAT_ERROR, 'Flv: Invalid AVCDecoderConfigurationRecord'); 5390 return; 5391 } 5392 5393 this._naluLengthSize = (v.getUint8(4) & 3) + 1; // lengthSizeMinusOne 5394 if (this._naluLengthSize !== 3 && this._naluLengthSize !== 4) { 5395 // holy shit!!! 5396 this._onError(_demuxErrors2.default.FORMAT_ERROR, 'Flv: Strange NaluLengthSizeMinusOne: ' + (this._naluLengthSize - 1)); 5397 return; 5398 } 5399 5400 var spsCount = v.getUint8(5) & 31; // numOfSequenceParameterSets 5401 if (spsCount === 0) { 5402 this._onError(_demuxErrors2.default.FORMAT_ERROR, 'Flv: Invalid AVCDecoderConfigurationRecord: No SPS'); 5403 return; 5404 } else if (spsCount > 1) { 5405 _logger2.default.w(this.TAG, 'Flv: Strange AVCDecoderConfigurationRecord: SPS Count = ' + spsCount); 5406 } 5407 5408 var offset = 6; 5409 5410 for (var i = 0; i < spsCount; i++) { 5411 var len = v.getUint16(offset, !le); // sequenceParameterSetLength 5412 offset += 2; 5413 5414 if (len === 0) { 5415 continue; 5416 } 5417 5418 // Notice: Nalu without startcode header (00 00 00 01) 5419 var sps = new Uint8Array(arrayBuffer, dataOffset + offset, len); 5420 offset += len; 5421 5422 var config = _spsParser2.default.parseSPS(sps); 5423 if (i !== 0) { 5424 // ignore other sps's config 5425 continue; 5426 } 5427 5428 meta.codecWidth = config.codec_size.width; 5429 meta.codecHeight = config.codec_size.height; 5430 meta.presentWidth = config.present_size.width; 5431 meta.presentHeight = config.present_size.height; 5432 5433 meta.profile = config.profile_string; 5434 meta.level = config.level_string; 5435 meta.bitDepth = config.bit_depth; 5436 meta.chromaFormat = config.chroma_format; 5437 meta.sarRatio = config.sar_ratio; 5438 meta.frameRate = config.frame_rate; 5439 5440 if (config.frame_rate.fixed === false || config.frame_rate.fps_num === 0 || config.frame_rate.fps_den === 0) { 5441 meta.frameRate = this._referenceFrameRate; 5442 } 5443 5444 var fps_den = meta.frameRate.fps_den; 5445 var fps_num = meta.frameRate.fps_num; 5446 meta.refSampleDuration = meta.timescale * (fps_den / fps_num); 5447 5448 var codecArray = sps.subarray(1, 4); 5449 var codecString = 'avc1.'; 5450 for (var j = 0; j < 3; j++) { 5451 var h = codecArray[j].toString(16); 5452 if (h.length < 2) { 5453 h = '0' + h; 5454 } 5455 codecString += h; 5456 } 5457 meta.codec = codecString; 5458 5459 var mi = this._mediaInfo; 5460 mi.width = meta.codecWidth; 5461 mi.height = meta.codecHeight; 5462 mi.fps = meta.frameRate.fps; 5463 mi.profile = meta.profile; 5464 mi.level = meta.level; 5465 mi.refFrames = config.ref_frames; 5466 mi.chromaFormat = config.chroma_format_string; 5467 mi.sarNum = meta.sarRatio.width; 5468 mi.sarDen = meta.sarRatio.height; 5469 mi.videoCodec = codecString; 5470 5471 if (mi.hasAudio) { 5472 if (mi.audioCodec != null) { 5473 mi.mimeType = 'video/x-flv; codecs="' + mi.videoCodec + ',' + mi.audioCodec + '"'; 5474 } 5475 } else { 5476 mi.mimeType = 'video/x-flv; codecs="' + mi.videoCodec + '"'; 5477 } 5478 if (mi.isComplete()) { 5479 this._onMediaInfo(mi); 5480 } 5481 } 5482 5483 var ppsCount = v.getUint8(offset); // numOfPictureParameterSets 5484 if (ppsCount === 0) { 5485 this._onError(_demuxErrors2.default.FORMAT_ERROR, 'Flv: Invalid AVCDecoderConfigurationRecord: No PPS'); 5486 return; 5487 } else if (ppsCount > 1) { 5488 _logger2.default.w(this.TAG, 'Flv: Strange AVCDecoderConfigurationRecord: PPS Count = ' + ppsCount); 5489 } 5490 5491 offset++; 5492 5493 for (var _i = 0; _i < ppsCount; _i++) { 5494 var _len = v.getUint16(offset, !le); // pictureParameterSetLength 5495 offset += 2; 5496 5497 if (_len === 0) { 5498 continue; 5499 } 5500 5501 // pps is useless for extracting video information 5502 offset += _len; 5503 } 5504 5505 meta.avcc = new Uint8Array(dataSize); 5506 meta.avcc.set(new Uint8Array(arrayBuffer, dataOffset, dataSize), 0); 5507 _logger2.default.v(this.TAG, 'Parsed AVCDecoderConfigurationRecord'); 5508 5509 if (this._isInitialMetadataDispatched()) { 5510 // flush parsed frames 5511 if (this._dispatch && (this._audioTrack.length || this._videoTrack.length)) { 5512 this._onDataAvailable(this._audioTrack, this._videoTrack); 5513 } 5514 } else { 5515 this._videoInitialMetadataDispatched = true; 5516 } 5517 // notify new metadata 5518 this._dispatch = false;
5519 this._onTrackMetadata('video', meta); 5520 } 5521 }, { 5522 key: '_parseAVCVideoData', 5523 value: function _parseAVCVideoData(arrayBuffer, dataOffset, dataSize, tagTimestamp, tagPosition, frameType, cts) { 5524 var le = this._littleEndian; 5525 var v = new DataView(arrayBuffer, dataOffset, dataSize); 5526 5527 var units = [], 5528 length = 0; 5529 5530 var offset = 0; 5531 var lengthSize = this._naluLengthSize; 5532 var dts = this._timestampBase + tagTimestamp; 5533 var keyframe = frameType === 1; // from FLV Frame Type constants 5534 5535 while (offset < dataSize) { 5536 if (offset + 4 >= dataSize) { 5537 _logger2.default.w(this.TAG, 'Malformed Nalu near timestamp ' + dts + ', offset = ' + offset + ', dataSize = ' + dataSize); 5538 break; // data not enough for next Nalu 5539 } 5540 // Nalu with length-header (AVC1) 5541 var naluSize = v.getUint32(offset, !le); // Big-Endian read 5542 if (lengthSize === 3) { 5543 naluSize >>>= 8; 5544 } 5545 if (naluSize > dataSize - lengthSize) { 5546 _logger2.default.w(this.TAG, 'Malformed Nalus near timestamp ' + dts + ', NaluSize > DataSize!'); 5547 return; 5548 } 5549 5550 var unitType = v.getUint8(offset + lengthSize) & 0x1F; 5551 5552 if (unitType === 5) { 5553 // IDR 5554 keyframe = true; 5555 } 5556 5557 var data = new Uint8Array(arrayBuffer, dataOffset + offset, lengthSize + naluSize); 5558 var unit = { type: unitType, data: data }; 5559 units.push(unit); 5560 length += data.byteLength; 5561 5562 offset += lengthSize + naluSize; 5563 } 5564 5565 if (units.length) { 5566 var track = this._videoTrack; 5567 var avcSample = { 5568 units: units, 5569 length: length, 5570 isKeyframe: keyframe, 5571 dts: dts, 5572 cts: cts, 5573 pts: dts + cts 5574 }; 5575 if (keyframe) { 5576 avcSample.fileposition = tagPosition; 5577 } 5578 track.samples.push(avcSample); 5579 track.length += length; 5580 } 5581 } 5582 }, { 5583 key: 'onTrackMetadata', 5584 get: function get() { 5585 return this._onTrackMetadata; 5586 }, 5587 set: function set(callback) { 5588 this._onTrackMetadata = callback; 5589 } 5590 5591 // prototype: function(mediaInfo: MediaInfo): void 5592 5593 }, { 5594 key: 'onMediaInfo', 5595 get: function get() { 5596 return this._onMediaInfo; 5597 }, 5598 set: function set(callback) { 5599 this._onMediaInfo = callback; 5600 } 5601 }, { 5602 key: 'onMetaDataArrived', 5603 get: function get() { 5604 return this._onMetaDataArrived; 5605 }, 5606 set: function set(callback) { 5607 this._onMetaDataArrived = callback; 5608 } 5609 }, { 5610 key: 'onScriptDataArrived', 5611 get: function get() { 5612 return this._onScriptDataArrived; 5613 }, 5614 set: function set(callback) { 5615 this._onScriptDataArrived = callback; 5616 } 5617 5618 // prototype: function(type: number, info: string): void 5619 5620 }, { 5621 key: 'onError', 5622 get: function get() { 5623 return this._onError; 5624 }, 5625 set: function set(callback) { 5626 this._onError = callback; 5627 } 5628 5629 // prototype: function(videoTrack: any, audioTrack: any): void 5630 5631 }, { 5632 key: 'onDataAvailable', 5633 get: function get() { 5634 return this._onDataAvailable; 5635 }, 5636 set: function set(callback) { 5637 this._onDataAvailable = callback; 5638 } 5639 5640 // timestamp base for output samples, must be in milliseconds 5641 5642 }, { 5643 key: 'timestampBase', 5644 get: function get() { 5645 return this._timestampBase; 5646 }, 5647 set: function set(base) { 5648 this._timestampBase = base; 5649 } 5650 }, {
5651 key: 'overridedDuration', 5652 get: function get() { 5653 return this._duration; 5654 } 5655 5656 // Force-override media duration. Must be in milliseconds, int32 5657 , 5658 set: function set(duration) { 5659 this._durationOverrided = true; 5660 this._duration = duration; 5661 this._mediaInfo.duration = duration; 5662 } 5663 5664 // Force-override audio track present flag, boolean 5665 5666 }, { 5667 key: 'overridedHasAudio', 5668 set: function set(hasAudio) { 5669 this._hasAudioFlagOverrided = true; 5670 this._hasAudio = hasAudio; 5671 this._mediaInfo.hasAudio = hasAudio; 5672 } 5673 5674 // Force-override video track present flag, boolean 5675 5676 }, { 5677 key: 'overridedHasVideo', 5678 set: function set(hasVideo) { 5679 this._hasVideoFlagOverrided = true; 5680 this._hasVideo = hasVideo; 5681 this._mediaInfo.hasVideo = hasVideo; 5682 } 5683 }], [{ 5684 key: 'probe', 5685 value: function probe(buffer) { 5686 var data = new Uint8Array(buffer); 5687 var mismatch = { match: false }; 5688 5689 if (data[0] !== 0x46 || data[1] !== 0x4C || data[2] !== 0x56 || data[3] !== 0x01) { 5690 return mismatch; 5691 } 5692 5693 var hasAudio = (data[4] & 4) >>> 2 !== 0; 5694 var hasVideo = (data[4] & 1) !== 0; 5695 5696 var offset = ReadBig32(data, 5); 5697 5698 if (offset < 9) { 5699 return mismatch; 5700 } 5701 5702 return { 5703 match: true, 5704 consumed: offset, 5705 dataOffset: offset, 5706 hasAudioTrack: hasAudio, 5707 hasVideoTrack: hasVideo 5708 }; 5709 } 5710 }]); 5711 5712 return FLVDemuxer; 5713}(); 5714 5715exports.default = FLVDemuxer; 5716 5717},{"../core/media-info.js":7,"../utils/exception.js":40,"../utils/logger.js":41,"./amf-parser.js":15,"./demux-errors.js":16,"./sps-parser.js":19}],19:[function(_dereq_,module,exports){ 5718'use strict'; 5719 5720Object.defineProperty(exports, "__esModule", { 5721 value: true 5722}); 5723 5724var _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; }; }(); /* 5725 * Copyright (C) 2016 Bilibili. All Rights Reserved. 5726 * 5727 * @author zheng qian <[email protected]> 5728 * 5729 * Licensed under the Apache License, Version 2.0 (the "License"); 5730 * you may
5730not use this file except in compliance with the License. 5731 * You may obtain a copy of the License at 5732 * 5733 * http://www.apache.org/licenses/LICENSE-2.0 5734 * 5735 * Unless required by applicable law or agreed to in writing, software 5736 * distributed under the License is distributed on an "AS IS" BASIS, 5737 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 5738 * See the License for the specific language governing permissions and 5739 * limitations under the License. 5740 */ 5741 5742var _expGolomb = _dereq_('./exp-golomb.js'); 5743 5744var _expGolomb2 = _interopRequireDefault(_expGolomb); 5745 5746function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 5747 5748function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 5749 5750var SPSParser = function () { 5751 function SPSParser() { 5752 _classCallCheck(this, SPSParser); 5753 } 5754 5755 _createClass(SPSParser, null, [{ 5756 key: '_ebsp2rbsp', 5757 value: function _ebsp2rbsp(uint8array) { 5758 var src = uint8array; 5759 var src_length = src.byteLength; 5760 var dst = new Uint8Array(src_length); 5761 var dst_idx = 0; 5762 5763 for (var i = 0; i < src_length; i++) { 5764 if (i >= 2) { 5765 // Unescape: Skip 0x03 after 00 00 5766 if (src[i] === 0x03 && src[i - 1] === 0x00 && src[i - 2] === 0x00) { 5767 continue; 5768 } 5769 } 5770 dst[dst_idx] = src[i]; 5771 dst_idx++; 5772 } 5773 5774 return new Uint8Array(dst.buffer, 0, dst_idx); 5775 } 5776 }, {
vendor: 6,100 bytes, lines 5777-5906
5777 key: 'parseSPS', 5778 value: function parseSPS(uint8array) { 5779 var rbsp = SPSParser._ebsp2rbsp(uint8array); 5780 var gb = new _expGolomb2.default(rbsp); 5781 5782 gb.readByte(); 5783 var profile_idc = gb.readByte(); // profile_idc 5784 gb.readByte(); // constraint_set_flags[5] + reserved_zero[3] 5785 var level_idc = gb.readByte(); // level_idc 5786 gb.readUEG(); // seq_parameter_set_id 5787 5788 var profile_string = SPSParser.getProfileString(profile_idc); 5789 var level_string = SPSParser.getLevelString(level_idc); 5790 var chroma_format_idc = 1; 5791 var chroma_format = 420; 5792 var chroma_format_table = [0, 420, 422, 444]; 5793 var bit_depth = 8; 5794 5795 if (profile_idc === 100 || profile_idc === 110 || profile_idc === 122 || profile_idc === 244 || profile_idc === 44 || profile_idc === 83 || profile_idc === 86 || profile_idc === 118 || profile_idc === 128 || profile_idc === 138 || profile_idc === 144) { 5796 5797 chroma_format_idc = gb.readUEG(); 5798 if (chroma_format_idc === 3) { 5799 gb.readBits(1); // separate_colour_plane_flag 5800 } 5801 if (chroma_format_idc <= 3) { 5802 chroma_format = chroma_format_table[chroma_format_idc]; 5803 } 5804 5805 bit_depth = gb.readUEG() + 8; // bit_depth_luma_minus8 5806 gb.readUEG(); // bit_depth_chroma_minus8 5807 gb.readBits(1); // qpprime_y_zero_transform_bypass_flag 5808 if (gb.readBool()) { 5809 // seq_scaling_matrix_present_flag 5810 var scaling_list_count = chroma_format_idc !== 3 ? 8 : 12; 5811 for (var i = 0; i < scaling_list_count; i++) { 5812 if (gb.readBool()) { 5813 // seq_scaling_list_present_flag 5814 if (i < 6) { 5815 SPSParser._skipScalingList(gb, 16); 5816 } else { 5817 SPSParser._skipScalingList(gb, 64); 5818 } 5819 } 5820 } 5821 } 5822 } 5823 gb.readUEG(); // log2_max_frame_num_minus4 5824 var pic_order_cnt_type = gb.readUEG(); 5825 if (pic_order_cnt_type === 0) { 5826 gb.readUEG(); // log2_max_pic_order_cnt_lsb_minus_4 5827 } else if (pic_order_cnt_type === 1) { 5828 gb.readBits(1); // delta_pic_order_always_zero_flag 5829 gb.readSEG(); // offset_for_non_ref_pic 5830 gb.readSEG(); // offset_for_top_to_bottom_field 5831 var num_ref_frames_in_pic_order_cnt_cycle = gb.readUEG(); 5832 for (var _i = 0; _i < num_ref_frames_in_pic_order_cnt_cycle; _i++) { 5833 gb.readSEG(); // offset_for_ref_frame 5834 } 5835 } 5836 var ref_frames = gb.readUEG(); // max_num_ref_frames 5837 gb.readBits(1); // gaps_in_frame_num_value_allowed_flag 5838 5839 var pic_width_in_mbs_minus1 = gb.readUEG(); 5840 var pic_height_in_map_units_minus1 = gb.readUEG(); 5841 5842 var frame_mbs_only_flag = gb.readBits(1); 5843 if (frame_mbs_only_flag === 0) { 5844 gb.readBits(1); // mb_adaptive_frame_field_flag 5845 } 5846 gb.readBits(1); // direct_8x8_inference_flag 5847 5848 var frame_crop_left_offset = 0; 5849 var frame_crop_right_offset = 0; 5850 var frame_crop_top_offset = 0; 5851 var frame_crop_bottom_offset = 0; 5852 5853 var frame_cropping_flag = gb.readBool(); 5854 if (frame_cropping_flag) { 5855 frame_crop_left_offset = gb.readUEG(); 5856 frame_crop_right_offset = gb.readUEG(); 5857 frame_crop_top_offset = gb.readUEG(); 5858 frame_crop_bottom_offset = gb.readUEG(); 5859 } 5860 5861 var sar_width = 1, 5862 sar_height = 1; 5863 var fps = 0, 5864 fps_fixed = true, 5865 fps_num = 0, 5866 fps_den = 0; 5867 5868 var vui_parameters_present_flag = gb.readBool(); 5869 if (vui_parameters_present_flag) { 5870 if (gb.readBool()) { 5871 // aspect_ratio_info_present_flag 5872 var aspect_ratio_idc = gb.readByte(); 5873 var sar_w_table = [1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160, 4, 3, 2]; 5874 var sar_h_table = [1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99, 3, 2, 1]; 5875 5876 if (aspect_ratio_idc > 0 && aspect_ratio_idc < 16) { 5877 sar_width = sar_w_table[aspect_ratio_idc - 1]; 5878 sar_height = sar_h_table[aspect_ratio_idc - 1]; 5879 } else if (aspect_ratio_idc === 255) { 5880 sar_width = gb.readByte() << 8 | gb.readByte(); 5881 sar_height = gb.readByte() << 8 | gb.readByte(); 5882 } 5883 } 5884 5885 if (gb.readBool()) { 5886 // overscan_info_present_flag 5887 gb.readBool(); // overscan_appropriate_flag 5888 } 5889 if (gb.readBool()) { 5890 // video_signal_type_present_flag 5891 gb.readBits(4); // video_format & video_full_range_flag 5892 if (gb.readBool()) { 5893 // colour_description_present_flag 5894 gb.readBits(24); // colour_primaries & transfer_characteristics & matrix_coefficients 5895 } 5896 } 5897 if (gb.readBool()) { 5898 // chroma_loc_info_present_flag 5899 gb.readUEG(); // chroma_sample_loc_type_top_field 5900 gb.readUEG(); // chroma_sample_loc_type_bottom_field 5901 } 5902 if (gb.readBool()) { 5903 // timing_info_present_flag 5904 var num_units_in_tick = gb.readBits(32); 5905 var time_scale = gb.readBits(32); 5906 fps_fixed = gb.readBool();
5906 // fixed_frame_rate_flag 5907 5908 fps_num = time_scale; 5909 fps_den = num_units_in_tick * 2; 5910 fps = fps_num / fps_den; 5911 } 5912 } 5913 5914 var sarScale = 1; 5915 if (sar_width !== 1 || sar_height !== 1) { 5916 sarScale = sar_width / sar_height; 5917 } 5918 5919 var crop_unit_x = 0, 5920 crop_unit_y = 0; 5921 if (chroma_format_idc === 0) { 5922 crop_unit_x = 1; 5923 crop_unit_y = 2 - frame_mbs_only_flag; 5924 } else { 5925 var sub_wc = chroma_format_idc === 3 ? 1 : 2; 5926 var sub_hc = chroma_format_idc === 1 ? 2 : 1; 5927 crop_unit_x = sub_wc; 5928 crop_unit_y = sub_hc * (2 - frame_mbs_only_flag); 5929 } 5930 5931 var codec_width = (pic_width_in_mbs_minus1 + 1) * 16; 5932 var codec_height = (2 - frame_mbs_only_flag) * ((pic_height_in_map_units_minus1 + 1) * 16); 5933 5934 codec_width -= (frame_crop_left_offset + frame_crop_right_offset) * crop_unit_x; 5935 codec_height -= (frame_crop_top_offset + frame_crop_bottom_offset) * crop_unit_y; 5936 5937 var present_width = Math.ceil(codec_width * sarScale); 5938 5939 gb.destroy(); 5940 gb = null; 5941 5942 return { 5943 profile_string: profile_string, // baseline, high, high10, ... 5944 level_string: level_string, // 3, 3.1, 4, 4.1, 5, 5.1, ... 5945 bit_depth: bit_depth, // 8bit, 10bit, ... 5946 ref_frames: ref_frames, 5947 chroma_format: chroma_format, // 4:2:0, 4:2:2, ... 5948 chroma_format_string: SPSParser.getChromaFormatString(chroma_format), 5949 5950 frame_rate: { 5951 fixed: fps_fixed, 5952 fps: fps, 5953 fps_den: fps_den, 5954 fps_num: fps_num 5955 }, 5956 5957 sar_ratio: { 5958 width: sar_width, 5959 height: sar_height 5960 }, 5961 5962 codec_size: { 5963 width: codec_width, 5964 height: codec_height 5965 }, 5966 5967 present_size: { 5968 width: present_width, 5969 height: codec_height 5970 } 5971 }; 5972 } 5973 }, { 5974 key: '_skipScalingList', 5975 value: function _skipScalingList(gb, count) { 5976 var last_scale = 8, 5977 next_scale = 8; 5978 var delta_scale = 0; 5979 for (var i = 0; i < count; i++) { 5980 if (next_scale !== 0) { 5981 delta_scale = gb.readSEG(); 5982 next_scale = (last_scale + delta_scale + 256) % 256; 5983 } 5984 last_scale = next_scale === 0 ? last_scale : next_scale; 5985 } 5986 } 5987 }, { 5988 key: 'getProfileString', 5989 value: function getProfileString(profile_idc) { 5990 switch (profile_idc) { 5991 case 66: 5992 return 'Baseline'; 5993 case 77: 5994 return 'Main'; 5995 case 88: 5996 return 'Extended'; 5997 case 100: 5998 return 'High'; 5999 case 110: 6000 return 'High10'; 6001 case 122: 6002 return 'High422'; 6003 case 244: 6004 return 'High444'; 6005 default: 6006 return 'Unknown'; 6007 } 6008 } 6009 }, { 6010 key: 'getLevelString', 6011 value: function getLevelString(level_idc) { 6012 return (level_idc / 10).toFixed(1); 6013 } 6014 }, { 6015 key: 'getChromaFormatString', 6016 value: function getChromaFormatString(chroma) { 6017 switch (chroma) { 6018 case 420: 6019 return '4:2:0'; 6020 case 422: 6021 return '4:2:2'; 6022 case 444: 6023 return '4:4:4'; 6024 default: 6025 return 'Unknown'; 6026 } 6027 } 6028 }]); 6029 6030 return SPSParser; 6031}(); 6032 6033exports.default = SPSParser; 6034 6035},{"./exp-golomb.js":17}],20:[function(_dereq_,module,exports){ 6036'use strict'; 6037 6038Object.defineProperty(exports, "__esModule", { 6039 value: true 6040}); 6041 6042var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; /* 6043 * Copyright (C) 2016 Bilibili. All Rights Reserved. 6044 * 6045 * @author zheng qian <[email protected]> 6046 * 6047 * Licensed under the Apache License, Version 2.0 (the "License"); 6048 * you may
6048not use this file except in compliance with the License. 6049 * You may obtain a copy of the License at 6050 * 6051 * http://www.apache.org/licenses/LICENSE-2.0 6052 * 6053 * Unless required by applicable law or agreed to in writing, software 6054 * distributed under the License is distributed on an "AS IS" BASIS, 6055 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 6056 * See the License for the specific language governing permissions and 6057 * limitations under the License. 6058 */ 6059 6060var _polyfill = _dereq_('./utils/polyfill.js'); 6061 6062var _polyfill2 = _interopRequireDefault(_polyfill); 6063 6064var _features = _dereq_('./core/features.js'); 6065 6066var _features2 = _interopRequireDefault(_features); 6067 6068var _loader = _dereq_('./io/loader.js'); 6069 6070var _flvPlayer = _dereq_('./player/flv-player.js'); 6071 6072var _flvPlayer2 = _interopRequireDefault(_flvPlayer); 6073 6074var _nativePlayer = _dereq_('./player/native-player.js'); 6075 6076var _nativePlayer2 = _interopRequireDefault(_nativePlayer); 6077 6078var _playerEvents = _dereq_('./player/player-events.js'); 6079 6080var _playerEvents2 = _interopRequireDefault(_playerEvents); 6081 6082var _playerErrors = _dereq_('./player/player-errors.js'); 6083 6084var _loggingControl = _dereq_('./utils/logging-control.js'); 6085 6086var _loggingControl2 = _interopRequireDefault(_loggingControl); 6087 6088var _exception = _dereq_('./utils/exception.js'); 6089 6090function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 6091 6092// here are all the interfaces 6093 6094// install polyfills 6095_polyfill2.default.install(); 6096 6097// factory method 6098function createPlayer(mediaDataSource, optionalConfig) { 6099 var mds = mediaDataSource; 6100 if (mds == null || (typeof mds === 'undefined' ? 'undefined' : _typeof(mds)) !== 'object') { 6101 throw new _exception.InvalidArgumentException('MediaDataSource must be an javascript object!'); 6102 } 6103 6104 if (!mds.hasOwnProperty('type')) { 6105 throw new _exception.InvalidArgumentException('MediaDataSource must has type field to indicate video file type!'); 6106 } 6107 6108 switch (mds.type) { 6109 case 'flv': 6110 return new _flvPlayer2.default(mds, optionalConfig); 6111 default: 6112 return new _nativePlayer2.default(mds, optionalConfig); 6113 } 6114} 6115 6116// feature detection 6117function isSupported() { 6118 return _features2.default.supportMSEH264Playback(); 6119} 6120 6121function getFeatureList() { 6122 return _features2.default.getFeatureList(); 6123} 6124 6125// interfaces 6126var flvjs = {}; 6127 6128flvjs.createPlayer = createPlayer; 6129flvjs.isSupported = isSupported; 6130flvjs.getFeatureList = getFeatureList; 6131 6132flvjs.BaseLoader = _loader.BaseLoader; 6133flvjs.LoaderStatus = _loader.LoaderStatus; 6134flvjs.LoaderErrors = _loader.LoaderErrors; 6135 6136flvjs.Events = _playerEvents2.default; 6137flvjs.ErrorTypes = _playerErrors.ErrorTypes; 6138flvjs.ErrorDetails = _playerErrors.ErrorDetails; 6139 6140flvjs.FlvPlayer = _flvPlayer2.default; 6141flvjs.NativePlayer = _nativePlayer2.default; 6142flvjs.LoggingControl = _loggingControl2.default; 6143 6144Object.defineProperty(flvjs, 'version', { 6145 enumerable: true, 6146 get: function get() { 6147 // replaced by browserify-versionify transform 6148 return '1.5.0'; 6149 } 6150}); 6151 6152exports.default = flvjs; 6153 6154},{"./core/features.js":6,"./io/loader.js":24,"./player/flv-player.js":32,"./player/native-player.js":33,"./player/player-errors.js":34,"./player/player-events.js":35,"./utils/exception.js":40,"./utils/logging-control.js":42,"./utils/polyfill.js":43}],21:[function(_dereq_,module,exports){ 6155'use strict'; 6156 6157// entry/index file 6158 6159// make it compatible with browserify's umd wrapper 6160module.exports = _dereq_('./flv.js').default; 6161 6162},{"./flv.js":20}],22:[function(_dereq_,module,exports){ 6163'use strict'; 6164 6165Object.defineProperty(exports, "__esModule", { 6166 value: true 6167}); 6168 6169var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 6170 6171var _get = function get(object, property, receiver) { 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 { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; 6172 6173var _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; }; }(); 6174 6175var _logger = _dereq_('../utils/logger.js'); 6176 6177var _logger2 = _interopRequireDefault(_logger); 6178 6179var _browser = _dereq_('../utils/browser.js'); 6180 6181var _browser2 = _interopRequireDefault(_browser); 6182 6183var _loader = _dereq_('./loader.js'); 6184 6185var _exception = _dereq_('../utils/exception.js'); 6186 6187function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 6188 6189function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 6190 6191function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 6192 6193function _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
6193onstructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /* 6194 * Copyright (C) 2016 Bilibili. All Rights Reserved. 6195 * 6196 * @author zheng qian <[email protected]> 6197 * 6198 * Licensed under the Apache License, Version 2.0 (the "License"); 6199 * you may not use this file except in compliance with the License. 6200 * You may obtain a copy of the License at 6201 * 6202 * http://www.apache.org/licenses/LICENSE-2.0 6203 * 6204 * Unless required by applicable law or agreed to in writing, softw
6204are 6205 * distributed under the License is distributed on an "AS IS" BASIS, 6206 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 6207 * See the License for the specific language governing permissions and 6208 * limitations under the License. 6209 */ 6210 6211/* fetch + stream IO loader. Currently working on chrome 43+. 6212 * fetch provides a better alternative http API to XMLHttpRequest 6213 * 6214 * fetch spec https://fetch.spec.whatwg.org/ 6215 * stream spec https://streams.spec.whatwg.org/ 6216 */ 6217var FetchStreamLoader = function (_BaseLoader) { 6218 _inherits(FetchStreamLoader, _BaseLoader); 6219 6220 _createClass(FetchStreamLoader, null, [{ 6221 key: 'isSupported', 6222 value: function isSupported() { 6223 try { 6224 // fetch + stream is broken on Microsoft Edge. Disable before build 15048. 6225 // see https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/8196907/ 6226 // Fixed in Jan 10, 2017. Build 15048+ removed from blacklist. 6227 var isWorkWellEdge = _browser2.default.msedge && _browser2.default.version.minor >= 15048; 6228 var browserNotBlacklisted = _browser2.default.msedge ? isWorkWellEdge : true; 6229 return self.fetch && self.ReadableStream && browserNotBlacklisted; 6230 } catch (e) { 6231 return false; 6232 } 6233 } 6234 }]); 6235 6236 function FetchStreamLoader(seekHandler, config) { 6237 _classCallCheck(this, FetchStreamLoader); 6238 6239 var _this = _possibleConstructorReturn(this, (FetchStreamLoader.__proto__ || Object.getPrototypeOf(FetchStreamLoader)).call(this, 'fetch-stream-loader')); 6240
6241 _this.TAG = 'FetchStreamLoader'; 6242 6243 _this._seekHandler = seekHandler; 6244 _this._config = config; 6245 _this._needStash = true; 6246 6247 _this._requestAbort = false; 6248 _this._contentLength = null; 6249 _this._receivedLength = 0; 6250 return _this; 6251 } 6252 6253 _createClass(FetchStreamLoader, [{ 6254 key: 'destroy', 6255 value: function destroy() { 6256 if (this.isWorking()) { 6257 this.abort(); 6258 } 6259 _get(FetchStreamLoader.prototype.__proto__ || Object.getPrototypeOf(FetchStreamLoader.prototype), 'destroy', this).call(this); 6260 } 6261 }, { 6262 key: 'open', 6263 value: function open(dataSource, range) { 6264 var _this2 = this; 6265 6266 this._dataSource = dataSource; 6267 this._range = range; 6268 6269 var sourceURL = dataSource.url; 6270 if (this._config.reuseRedirectedURL && dataSource.redirectedURL != undefined) { 6271 sourceURL = dataSource.redirectedURL; 6272 } 6273 6274 var seekConfig = this._seekHandler.getConfig(sourceURL, range); 6275 6276 var headers = new self.Headers(); 6277 6278 if (_typeof(seekConfig.headers) === 'object') { 6279 var configHeaders = seekConfig.headers; 6280 for (var key in configHeaders) { 6281 if (configHeaders.hasOwnProperty(key)) { 6282 headers.append(key, configHeaders[key]); 6283 } 6284 } 6285 } 6286 6287 var params = { 6288 method: 'GET', 6289 headers: headers, 6290 mode: 'cors', 6291 cache: 'default', 6292 // The default policy of Fetch API in the whatwg standard 6293 // Safari incorrectly indicates 'no-referrer' as default policy, fuck it 6294 referrerPolicy: 'no-referrer-when-downgrade' 6295 }; 6296 6297 // add additional headers 6298 if (_typeof(this._config.headers) === 'object') { 6299 for (var _key in this._config.headers) { 6300 headers.append(_key, this._config.headers[_key]); 6301 } 6302 } 6303 6304 // cors is enabled by default 6305 if (dataSource.cors === false) { 6306 // no-cors means 'disregard cors policy', which can only be used in ServiceWorker 6307 params.mode = 'same-origin'; 6308 } 6309 6310 // withCredentials is disabled by default 6311 if (dataSource.withCredentials) { 6312 params.credentials = 'include'; 6313 } 6314 6315 // referrerPolicy from config 6316 if (dataSource.referrerPolicy) { 6317 params.referrerPolicy = dataSource.referrerPolicy; 6318 } 6319 6320 this._status = _loader.LoaderStatus.kConnecting; 6321 self.fetch(seekConfig.url, params).then(function (res) { 6322 if (_this2._requestAbort) { 6323 _this2._requestAbort = false;
6324 _this2._status = _loader.LoaderStatus.kIdle; 6325 return; 6326 } 6327 if (res.ok && res.status >= 200 && res.status <= 299) { 6328 if (res.url !== seekConfig.url) { 6329 if (_this2._onURLRedirect) { 6330 var redirectedURL = _this2._seekHandler.removeURLParameters(res.url); 6331 _this2._onURLRedirect(redirectedURL); 6332 } 6333 } 6334 6335 var lengthHeader = res.headers.get('Content-Length'); 6336 if (lengthHeader != null) { 6337 _this2._contentLength = parseInt(lengthHeader); 6338 if (_this2._contentLength !== 0) { 6339 if (_this2._onContentLengthKnown) { 6340 _this2._onContentLengthKnown(_this2._contentLength); 6341 } 6342 } 6343 } 6344 6345 return _this2._pump.call(_this2, res.body.getReader()); 6346 } else { 6347 _this2._status = _loader.LoaderStatus.kError; 6348 if (_this2._onError) { 6349 _this2._onError(_loader.LoaderErrors.HTTP_STATUS_CODE_INVALID, { code: res.status, msg: res.statusText }); 6350 } else { 6351 throw new _exception.RuntimeException('FetchStreamLoader: Http code invalid, ' + res.status + ' ' + res.statusText); 6352 } 6353 } 6354 }).catch(function (e) { 6355 _this2._status = _loader.LoaderStatus.kError; 6356 if (_this2._onError) { 6357 _this2._onError(_loader.LoaderErrors.EXCEPTION, { code: -1, msg: e.message }); 6358 } else { 6359 throw e; 6360 } 6361 }); 6362 } 6363 }, { 6364 key: 'abort', 6365 value: function abort() { 6366 this._requestAbort = true; 6367 } 6368 }, { 6369 key: '_pump', 6370 value: function _pump(reader) { 6371 var _this3 = this; 6372 6373 // ReadableStreamReader 6374 return reader.read().then(function (result) { 6375 if (result.done) { 6376 // First check received length 6377 if (_this3._contentLength !== null && _this3._receivedLength < _this3._contentLength) { 6378 // Report Early-EOF 6379 _this3._status = _loader.LoaderStatus.kError; 6380 var type = _loader.LoaderErrors.EARLY_EOF; 6381 var info = { code: -1, msg: 'Fetch stream meet Early-EOF' }; 6382 if (_this3._onError) { 6383 _this3._onError(type, info); 6384 } else { 6385 throw new _exception.RuntimeException(info.msg); 6386 } 6387 } else { 6388 // OK. Download complete 6389 _this3._status = _loader.LoaderStatus.kComplete; 6390 if (_this3._onComplete) { 6391 _this3._onComplete(_this3._range.from, _this3._range.from + _this3._receivedLength - 1); 6392 } 6393 } 6394 } else { 6395 if (_this3._requestAbort === true) { 6396 _this3._requestAbort = false;
6397 _this3._status = _loader.LoaderStatus.kComplete; 6398 return reader.cancel(); 6399 } 6400 6401 _this3._status = _loader.LoaderStatus.kBuffering; 6402 6403 var chunk = result.value.buffer; 6404 var byteStart = _this3._range.from + _this3._receivedLength; 6405 _this3._receivedLength += chunk.byteLength; 6406 6407 if (_this3._onDataArrival) { 6408 _this3._onDataArrival(chunk, byteStart, _this3._receivedLength); 6409 } 6410 6411 _this3._pump(reader); 6412 } 6413 }).catch(function (e) { 6414 if (e.code === 11 && _browser2.default.msedge) { 6415 // InvalidStateError on Microsoft Edge 6416 // Workaround: Edge may throw InvalidStateError after ReadableStreamReader.cancel() call 6417 // Ignore the unknown exception. 6418 // Related issue: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/11265202/ 6419 return; 6420 } 6421 6422 _this3._status = _loader.LoaderStatus.kError; 6423 var type = 0; 6424 var info = null; 6425 6426 if ((e.code === 19 || e.message === 'network error') && ( // NETWORK_ERR 6427 _this3._contentLength === null || _this3._contentLength !== null && _this3._receivedLength < _this3._contentLength)) { 6428 type = _loader.LoaderErrors.EARLY_EOF; 6429 info = { code: e.code, msg: 'Fetch stream meet Early-EOF' }; 6430 } else { 6431 type = _loader.LoaderErrors.EXCEPTION; 6432 info = { code: e.code, msg: e.message }; 6433 } 6434 6435 if (_this3._onError) { 6436 _this3._onError(type, info); 6437 } else { 6438 throw new _exception.RuntimeException(info.msg); 6439 } 6440 }); 6441 } 6442 }]); 6443 6444 return FetchStreamLoader; 6445}(_loader.BaseLoader); 6446 6447exports.default = FetchStreamLoader; 6448 6449},{"../utils/browser.js":39,"../utils/exception.js":40,"../utils/logger.js":41,"./loader.js":24}],23:[function(_dereq_,module,exports){ 6450'use strict'; 6451 6452Object.defineProperty(exports, "__esModule", { 6453 value: true 6454}); 6455 6456var _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; }; }(); /* 6457 * Copyright (C) 2016 Bilibili. All Rights Reserved. 6458 * 6459 * @author zheng qian <[email protected]> 6460 * 6461 * Licensed under the Apache License, Version 2.0 (the "License"); 6462 * you may
6462not use this file except in compliance with the License. 6463 * You may obtain a copy of the License at 6464 * 6465 * http://www.apache.org/licenses/LICENSE-2.0 6466 * 6467 * Unless required by applicable law or agreed to in writing, software 6468 * distributed under the License is distributed on an "AS IS" BASIS, 6469 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 6470 * See the License for the specific language governing permissions and 6471 * limitations under the License. 6472 */ 6473 6474var _logger = _dereq_('../utils/logger.js'); 6475 6476var _logger2 = _interopRequireDefault(_logger); 6477
vendor: 4,348 bytes, lines 6478-6613
6478var _speedSampler = _dereq_('./speed-sampler.js'); 6479 6480var _speedSampler2 = _interopRequireDefault(_speedSampler); 6481 6482var _loader = _dereq_('./loader.js'); 6483 6484var _fetchStreamLoader = _dereq_('./fetch-stream-loader.js'); 6485 6486var _fetchStreamLoader2 = _interopRequireDefault(_fetchStreamLoader); 6487 6488var _xhrMozChunkedLoader = _dereq_('./xhr-moz-chunked-loader.js'); 6489 6490var _xhrMozChunkedLoader2 = _interopRequireDefault(_xhrMozChunkedLoader); 6491 6492var _xhrMsstreamLoader = _dereq_('./xhr-msstream-loader.js'); 6493 6494var _xhrMsstreamLoader2 = _interopRequireDefault(_xhrMsstreamLoader); 6495 6496var _xhrRangeLoader = _dereq_('./xhr-range-loader.js'); 6497 6498var _xhrRangeLoader2 = _interopRequireDefault(_xhrRangeLoader); 6499 6500var _websocketLoader = _dereq_('./websocket-loader.js'); 6501 6502var _websocketLoader2 = _interopRequireDefault(_websocketLoader); 6503 6504var _rangeSeekHandler = _dereq_('./range-seek-handler.js'); 6505 6506var _rangeSeekHandler2 = _interopRequireDefault(_rangeSeekHandler); 6507 6508var _paramSeekHandler = _dereq_('./param-seek-handler.js'); 6509 6510var _paramSeekHandler2 = _interopRequireDefault(_paramSeekHandler); 6511 6512var _exception = _dereq_('../utils/exception.js'); 6513 6514function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 6515 6516function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 6517 6518/** 6519 * DataSource: { 6520 * url: string, 6521 * filesize: number, 6522 * cors: boolean, 6523 * withCredentials: boolean 6524 * } 6525 * 6526 */ 6527 6528// Manage IO Loaders 6529var IOController = function () { 6530 function IOController(dataSource, config, extraData) { 6531 _classCallCheck(this, IOController); 6532 6533 this.TAG = 'IOController'; 6534 6535 this._config = config; 6536 this._extraData = extraData; 6537 6538 this._stashInitialSize = 1024 * 384; // default initial size: 384KB 6539 if (config.stashInitialSize != undefined && config.stashInitialSize > 0) { 6540 // apply from config 6541 this._stashInitialSize = config.stashInitialSize; 6542 } 6543 6544 this._stashUsed = 0; 6545 this._stashSize = this._stashInitialSize; 6546 this._bufferSize = 1024 * 1024 * 3; // initial size: 3MB 6547 this._stashBuffer = new ArrayBuffer(this._bufferSize); 6548 this._stashByteStart = 0; 6549 this._enableStash = true; 6550 if (config.enableStashBuffer === false) { 6551 this._enableStash = false; 6552 } 6553 6554 this._loader = null; 6555 this._loaderClass = null; 6556 this._seekHandler = null; 6557 6558 this._dataSource = dataSource; 6559 this._isWebSocketURL = /wss?:\/\/(.+?)/.test(dataSource.url); 6560 this._refTotalLength = dataSource.filesize ? dataSource.filesize : null; 6561 this._totalLength = this._refTotalLength; 6562 this._fullRequestFlag = false; 6563 this._currentRange = null; 6564 this._redirectedURL = null; 6565 6566 this._speedNormalized = 0; 6567 this._speedSampler = new _speedSampler2.default(); 6568 this._speedNormalizeList = [64, 128, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096]; 6569 6570 this._isEarlyEofReconnecting = false; 6571 6572 this._paused = false; 6573 this._resumeFrom = 0; 6574 6575 this._onDataArrival = null; 6576 this._onSeeked = null; 6577 this._onError = null; 6578 this._onComplete = null; 6579 this._onRedirect = null; 6580 this._onRecoveredEarlyEof = null; 6581 6582 this._selectSeekHandler(); 6583 this._selectLoader(); 6584 this._createLoader(); 6585 } 6586 6587 _createClass(IOController, [{ 6588 key: 'destroy', 6589 value: function destroy() { 6590 if (this._loader.isWorking()) { 6591 this._loader.abort(); 6592 } 6593 this._loader.destroy(); 6594 this._loader = null; 6595 this._loaderClass = null; 6596 this._dataSource = null; 6597 this._stashBuffer = null; 6598 this._stashUsed = this._stashSize = this._bufferSize = this._stashByteStart = 0; 6599 this._currentRange = null; 6600 this._speedSampler = null; 6601 6602 this._isEarlyEofReconnecting = false; 6603 6604 this._onDataArrival = null; 6605 this._onSeeked = null; 6606 this._onError = null; 6607 this._onComplete = null; 6608 this._onRedirect = null; 6609 this._onRecoveredEarlyEof = null; 6610 6611 this._extraData = null; 6612 } 6613 }, {
6614 key: 'isWorking', 6615 value: function isWorking() { 6616 return this._loader && this._loader.isWorking() && !this._paused; 6617 } 6618 }, { 6619 key: 'isPaused', 6620 value: function isPaused() { 6621 return this._paused; 6622 } 6623 }, { 6624 key: '_selectSeekHandler', 6625 value: function _selectSeekHandler() { 6626 var config = this._config; 6627 6628 if (config.seekType === 'range') { 6629 this._seekHandler = new _rangeSeekHandler2.default(this._config.rangeLoadZeroStart); 6630 } else if (config.seekType === 'param') { 6631 var paramStart = config.seekParamStart || 'bstart'; 6632 var paramEnd = config.seekParamEnd || 'bend'; 6633 6634 this._seekHandler = new _paramSeekHandler2.default(paramStart, paramEnd); 6635 } else if (config.seekType === 'custom') { 6636 if (typeof config.customSeekHandler !== 'function') { 6637 throw new _exception.InvalidArgumentException('Custom seekType specified in config but invalid customSeekHandler!'); 6638 } 6639 this._seekHandler = new config.customSeekHandler(); 6640 } else { 6641 throw new _exception.InvalidArgumentException('Invalid seekType in config: ' + config.seekType); 6642 } 6643 } 6644 }, { 6645 key: '_selectLoader', 6646 value: function _selectLoader() { 6647 if (this._config.customLoader != null) { 6648 this._loaderClass = this._config.customLoader; 6649 } else if (this._isWebSocketURL) { 6650 this._loaderClass = _websocketLoader2.default; 6651 } else if (_fetchStreamLoader2.default.isSupported()) { 6652 this._loaderClass = _fetchStreamLoader2.default; 6653 } else if (_xhrMozChunkedLoader2.default.isSupported()) { 6654 this._loaderClass = _xhrMozChunkedLoader2.default; 6655 } else if (_xhrRangeLoader2.default.isSupported()) { 6656 this._loaderClass = _xhrRangeLoader2.default; 6657 } else { 6658 throw new _exception.RuntimeException('Your browser doesn\'t support xhr with arraybuffer responseType!'); 6659 } 6660 } 6661 }, { 6662 key: '_createLoader', 6663 value: function _createLoader() { 6664 this._loader = new this._loaderClass(this._seekHandler, this._config); 6665 if (this._loader.needStashBuffer === false) { 6666 this._enableStash = false; 6667 } 6668 this._loader.onContentLengthKnown = this._onContentLengthKnown.bind(this); 6669 this._loader.onURLRedirect = this._onURLRedirect.bind(this); 6670 this._loader.onDataArrival = this._onLoaderChunkArrival.bind(this); 6671 this._loader.onComplete = this._onLoaderComplete.bind(this); 6672 this._loader.onError = this._onLoaderError.bind(this); 6673 } 6674 }, { 6675 key: 'open', 6676 value: function open(optionalFrom) { 6677 this._currentRange = { from: 0, to: -1 }; 6678 if (optionalFrom) { 6679 this._currentRange.from = optionalFrom; 6680 } 6681 6682 this._speedSampler.reset(); 6683 if (!optionalFrom) { 6684 this._fullRequestFlag = true; 6685 } 6686 6687 this._loader.open(this._dataSource, Object.assign({}, this._currentRange)); 6688 } 6689 }, { 6690 key: 'abort', 6691 value: function abort() { 6692 this._loader.abort(); 6693 6694 if (this._paused) { 6695 this._paused = false; 6696 this._resumeFrom = 0; 6697 } 6698 } 6699 }, { 6700 key: 'pause', 6701 value: function pause() { 6702 if (this.isWorking()) { 6703 this._loader.abort(); 6704 6705 if (this._stashUsed !== 0) { 6706 this._resumeFrom = this._stashByteStart; 6707 this._currentRange.to = this._stashByteStart - 1; 6708 } else { 6709 this._resumeFrom = this._currentRange.to + 1; 6710 } 6711 this._stashUsed = 0; 6712 this._stashByteStart = 0; 6713 this._paused = true; 6714 } 6715 } 6716 }, {
6717 key: 'resume', 6718 value: function resume() { 6719 if (this._paused) { 6720 this._paused = false; 6721 var bytes = this._resumeFrom; 6722 this._resumeFrom = 0; 6723 this._internalSeek(bytes, true); 6724 } 6725 } 6726 }, { 6727 key: 'seek', 6728 value: function seek(bytes) { 6729 this._paused = false; 6730 this._stashUsed = 0; 6731 this._stashByteStart = 0; 6732 this._internalSeek(bytes, true); 6733 } 6734 6735 /** 6736 * When seeking request is from media seeking, unconsumed stash data should be dropped 6737 * However, stash data shouldn't be dropped if seeking requested from http reconnection 6738 * 6739 * @dropUnconsumed: Ignore and discard all unconsumed data in stash buffer 6740 */ 6741 6742 }, { 6743 key: '_internalSeek', 6744 value: function _internalSeek(bytes, dropUnconsumed) { 6745 if (this._loader.isWorking()) { 6746 this._loader.abort(); 6747 } 6748 6749 // dispatch & flush stash buffer before seek 6750 this._flushStashBuffer(dropUnconsumed); 6751 6752 this._loader.destroy(); 6753 this._loader = null; 6754 6755 var requestRange = { from: bytes, to: -1 }; 6756 this._currentRange = { from: requestRange.from, to: -1 }; 6757 6758 this._speedSampler.reset(); 6759 this._stashSize = this._stashInitialSize; 6760 this._createLoader(); 6761 this._loader.open(this._dataSource, requestRange); 6762 6763 if (this._onSeeked) { 6764 this._onSeeked(); 6765 } 6766 } 6767 }, { 6768 key: 'updateUrl', 6769 value: function updateUrl(url) { 6770 if (!url || typeof url !== 'string' || url.length === 0) { 6771 throw new _exception.InvalidArgumentException('Url must be a non-empty string!'); 6772 } 6773 6774 this._dataSource.url = url; 6775 6776 // TODO: replace with new url 6777 } 6778 }, { 6779 key: '_expandBuffer', 6780 value: function _expandBuffer(expectedBytes) { 6781 var bufferNewSize = this._stashSize; 6782 while (bufferNewSize + 1024 * 1024 * 1 < expectedBytes) { 6783 bufferNewSize *= 2; 6784 } 6785 6786 bufferNewSize += 1024 * 1024 * 1; // bufferSize = stashSize + 1MB 6787 if (bufferNewSize === this._bufferSize) { 6788 return; 6789 } 6790 6791 var newBuffer = new ArrayBuffer(bufferNewSize); 6792 6793 if (this._stashUsed > 0) { 6794 // copy existing data into new buffer 6795 var stashOldArray = new Uint8Array(this._stashBuffer, 0, this._stashUsed); 6796 var stashNewArray = new Uint8Array(newBuffer, 0, bufferNewSize); 6797 stashNewArray.set(stashOldArray, 0); 6798 } 6799 6800 this._stashBuffer = newBuffer; 6801 this._bufferSize = bufferNewSize; 6802 } 6803 }, { 6804 key: '_normalizeSpeed', 6805 value: function _normalizeSpeed(input) { 6806 var list = this._speedNormalizeList; 6807 var last = list.length - 1; 6808 var mid = 0; 6809 var lbound = 0; 6810 var ubound = last; 6811 6812 if (input < list[0]) { 6813 return list[0]; 6814 } 6815 6816 // binary search 6817 while (lbound <= ubound) { 6818 mid = lbound + Math.floor((ubound - lbound) / 2); 6819 if (mid === last || input >= list[mid] && input < list[mid + 1]) { 6820 return list[mid]; 6821 } else if (list[mid] < input) { 6822 lbound = mid + 1; 6823 } else { 6824 ubound = mid - 1; 6825 } 6826 } 6827 } 6828 }, { 6829 key: '_adjustStashSize', 6830 value: function _adjustStashSize(normalized) { 6831 var stashSizeKB = 0; 6832 6833 if (this._config.isLive) { 6834 // live stream: always use single normalized speed for size of stashSizeKB 6835 stashSizeKB = normalized; 6836 } else { 6837 if (normalized < 512) { 6838 stashSizeKB = normalized; 6839 } else if (normalized >= 512 && normalized <= 1024) { 6840 stashSizeKB = Math.floor(normalized * 1.5); 6841 } else { 6842 stashSizeKB = normalized * 2; 6843 } 6844 } 6845 6846 if (stashSizeKB > 8192) { 6847 stashSizeKB = 8192; 6848 } 6849 6850 var bufferSize = stashSizeKB * 1024 + 1024 * 1024 * 1; // stashSize + 1MB 6851 if (this._bufferSize < bufferSize) { 6852 this._expandBuffer(bufferSize); 6853 } 6854 this._stashSize = stashSizeKB * 1024; 6855 } 6856 }, {
vendor: 11,052 bytes, lines 6857-7081
6857 key: '_dispatchChunks', 6858 value: function _dispatchChunks(chunks, byteStart) { 6859 this._currentRange.to = byteStart + chunks.byteLength - 1; 6860 return this._onDataArrival(chunks, byteStart); 6861 } 6862 }, { 6863 key: '_onURLRedirect', 6864 value: function _onURLRedirect(redirectedURL) { 6865 this._redirectedURL = redirectedURL; 6866 if (this._onRedirect) { 6867 this._onRedirect(redirectedURL); 6868 } 6869 } 6870 }, { 6871 key: '_onContentLengthKnown', 6872 value: function _onContentLengthKnown(contentLength) { 6873 if (contentLength && this._fullRequestFlag) { 6874 this._totalLength = contentLength; 6875 this._fullRequestFlag = false; 6876 } 6877 } 6878 }, { 6879 key: '_onLoaderChunkArrival', 6880 value: function _onLoaderChunkArrival(chunk, byteStart, receivedLength) { 6881 if (!this._onDataArrival) { 6882 throw new _exception.IllegalStateException('IOController: No existing consumer (onDataArrival) callback!'); 6883 } 6884 if (this._paused) { 6885 return; 6886 } 6887 if (this._isEarlyEofReconnecting) { 6888 // Auto-reconnect for EarlyEof succeed, notify to upper-layer by callback 6889 this._isEarlyEofReconnecting = false; 6890 if (this._onRecoveredEarlyEof) { 6891 this._onRecoveredEarlyEof(); 6892 } 6893 } 6894 6895 this._speedSampler.addBytes(chunk.byteLength); 6896 6897 // adjust stash buffer size according to network speed dynamically 6898 var KBps = this._speedSampler.lastSecondKBps; 6899 if (KBps !== 0) { 6900 var normalized = this._normalizeSpeed(KBps); 6901 if (this._speedNormalized !== normalized) { 6902 this._speedNormalized = normalized; 6903 this._adjustStashSize(normalized); 6904 } 6905 } 6906 6907 if (!this._enableStash) { 6908 // disable stash 6909 if (this._stashUsed === 0) { 6910 // dispatch chunk directly to consumer; 6911 // check ret value (consumed bytes) and stash unconsumed to stashBuffer 6912 var consumed = this._dispatchChunks(chunk, byteStart); 6913 if (consumed < chunk.byteLength) { 6914 // unconsumed data remain. 6915 var remain = chunk.byteLength - consumed; 6916 if (remain > this._bufferSize) { 6917 this._expandBuffer(remain); 6918 } 6919 var stashArray = new Uint8Array(this._stashBuffer, 0, this._bufferSize); 6920 stashArray.set(new Uint8Array(chunk, consumed), 0); 6921 this._stashUsed += remain; 6922 this._stashByteStart = byteStart + consumed; 6923 } 6924 } else { 6925 // else: Merge chunk into stashBuffer, and dispatch stashBuffer to consumer. 6926 if (this._stashUsed + chunk.byteLength > this._bufferSize) { 6927 this._expandBuffer(this._stashUsed + chunk.byteLength); 6928 } 6929 var _stashArray = new Uint8Array(this._stashBuffer, 0, this._bufferSize); 6930 _stashArray.set(new Uint8Array(chunk), this._stashUsed); 6931 this._stashUsed += chunk.byteLength; 6932 var _consumed = this._dispatchChunks(this._stashBuffer.slice(0, this._stashUsed), this._stashByteStart); 6933 if (_consumed < this._stashUsed && _consumed > 0) { 6934 // unconsumed data remain 6935 var remainArray = new Uint8Array(this._stashBuffer, _consumed); 6936 _stashArray.set(remainArray, 0); 6937 } 6938 this._stashUsed -= _consumed; 6939 this._stashByteStart += _consumed; 6940 } 6941 } else { 6942 // enable stash 6943 if (this._stashUsed === 0 && this._stashByteStart === 0) { 6944 // seeked? or init chunk? 6945 // This is the first chunk after seek action 6946 this._stashByteStart = byteStart; 6947 } 6948 if (this._stashUsed + chunk.byteLength <= this._stashSize) { 6949 // just stash 6950 var _stashArray2 = new Uint8Array(this._stashBuffer, 0, this._stashSize); 6951 _stashArray2.set(new Uint8Array(chunk), this._stashUsed); 6952 this._stashUsed += chunk.byteLength; 6953 } else { 6954 // stashUsed + chunkSize > stashSize, size limit exceeded 6955 var _stashArray3 = new Uint8Array(this._stashBuffer, 0, this._bufferSize); 6956 if (this._stashUsed > 0) { 6957 // There're stash datas in buffer 6958 // dispatch the whole stashBuffer, and stash remain data 6959 // then append chunk to stashBuffer (stash) 6960 var buffer = this._stashBuffer.slice(0, this._stashUsed); 6961 var _consumed2 = this._dispatchChunks(buffer, this._stashByteStart); 6962 if (_consumed2 < buffer.byteLength) { 6963 if (_consumed2 > 0) { 6964 var _remainArray = new Uint8Array(buffer, _consumed2); 6965 _stashArray3.set(_remainArray, 0); 6966 this._stashUsed = _remainArray.byteLength; 6967 this._stashByteStart += _consumed2; 6968 } 6969 } else { 6970 this._stashUsed = 0; 6971 this._stashByteStart += _consumed2; 6972 } 6973 if (this._stashUsed + chunk.byteLength > this._bufferSize) { 6974 this._expandBuffer(this._stashUsed + chunk.byteLength); 6975 _stashArray3 = new Uint8Array(this._stashBuffer, 0, this._bufferSize); 6976 } 6977 _stashArray3.set(new Uint8Array(chunk), this._stashUsed); 6978 this._stashUsed += chunk.byteLength; 6979 } else { 6980 // stash buffer empty, but chunkSize > stashSize (oh, holy shit) 6981 // dispatch chunk directly and stash remain data 6982 var _consumed3 = this._dispatchChunks(chunk, byteStart); 6983 if (_consumed3 < chunk.byteLength) { 6984 var _remain = chunk.byteLength - _consumed3; 6985 if (_remain > this._bufferSize) { 6986 this._expandBuffer(_remain); 6987 _stashArray3 = new Uint8Array(this._stashBuffer, 0, this._bufferSize); 6988 } 6989 _stashArray3.set(new Uint8Array(chunk, _consumed3), 0); 6990 this._stashUsed += _remain; 6991 this._stashByteStart = byteStart + _consumed3; 6992 } 6993 } 6994 } 6995 } 6996 } 6997 }, { 6998 key: '_flushStashBuffer', 6999 value: function _flushStashBuffer(dropUnconsumed) { 7000 if (this._stashUsed > 0) { 7001 var buffer = this._stashBuffer.slice(0, this._stashUsed); 7002 var consumed = this._dispatchChunks(buffer, this._stashByteStart); 7003 var remain = buffer.byteLength - consumed; 7004 7005 if (consumed < buffer.byteLength) { 7006 if (dropUnconsumed) { 7007 _logger2.default.w(this.TAG, remain + ' bytes unconsumed data remain when flush buffer, dropped'); 7008 } else { 7009 if (consumed > 0) { 7010 var stashArray = new Uint8Array(this._stashBuffer, 0, this._bufferSize); 7011 var remainArray = new Uint8Array(buffer, consumed); 7012 stashArray.set(remainArray, 0); 7013 this._stashUsed = remainArray.byteLength; 7014 this._stashByteStart += consumed; 7015 } 7016 return 0; 7017 } 7018 } 7019 this._stashUsed = 0; 7020 this._stashByteStart = 0; 7021 return remain; 7022 } 7023 return 0; 7024 } 7025 }, { 7026 key: '_onLoaderComplete', 7027 value: function _onLoaderComplete(from, to) { 7028 // Force-flush stash buffer, and drop unconsumed data 7029 this._flushStashBuffer(true); 7030 7031 if (this._onComplete) { 7032 this._onComplete(this._extraData); 7033 } 7034 } 7035 }, { 7036 key: '_onLoaderError', 7037 value: function _onLoaderError(type, data) { 7038 _logger2.default.e(this.TAG, 'Loader error, code = ' + data.code + ', msg = ' + data.msg); 7039 7040 this._flushStashBuffer(false); 7041 7042 if (this._isEarlyEofReconnecting) { 7043 // Auto-reconnect for EarlyEof failed, throw UnrecoverableEarlyEof error to upper-layer 7044 this._isEarlyEofReconnecting = false; 7045 type = _loader.LoaderErrors.UNRECOVERABLE_EARLY_EOF; 7046 } 7047 7048 switch (type) { 7049 case _loader.LoaderErrors.EARLY_EOF: 7050 { 7051 if (!this._config.isLive) { 7052 // Do internal http reconnect if not live stream 7053 if (this._totalLength) { 7054 var nextFrom = this._currentRange.to + 1; 7055 if (nextFrom < this._totalLength) { 7056 _logger2.default.w(this.TAG, 'Connection lost, trying reconnect...'); 7057 this._isEarlyEofReconnecting = true; 7058 this._internalSeek(nextFrom, false); 7059 } 7060 return; 7061 } 7062 // else: We don't know totalLength, throw UnrecoverableEarlyEof 7063 } 7064 // live stream: throw UnrecoverableEarlyEof error to upper-layer 7065 type = _loader.LoaderErrors.UNRECOVERABLE_EARLY_EOF; 7066 break; 7067 } 7068 case _loader.LoaderErrors.UNRECOVERABLE_EARLY_EOF: 7069 case _loader.LoaderErrors.CONNECTING_TIMEOUT: 7070 case _loader.LoaderErrors.HTTP_STATUS_CODE_INVALID: 7071 case _loader.LoaderErrors.EXCEPTION: 7072 break; 7073 } 7074 7075 if (this._onError) { 7076 this._onError(type, data); 7077 } else { 7078 throw new _exception.RuntimeException('IOException: ' + data.msg); 7079 } 7080 } 7081 }, {
7082 key: 'status', 7083 get: function get() { 7084 return this._loader.status; 7085 } 7086 }, { 7087 key: 'extraData', 7088 get: function get() { 7089 return this._extraData; 7090 }, 7091 set: function set(data) { 7092 this._extraData = data; 7093 } 7094 7095 // prototype: function onDataArrival(chunks: ArrayBuffer, byteStart: number): number 7096 7097 }, { 7098 key: 'onDataArrival', 7099 get: function get() { 7100 return this._onDataArrival; 7101 }, 7102 set: function set(callback) { 7103 this._onDataArrival = callback; 7104 } 7105 }, { 7106 key: 'onSeeked', 7107 get: function get() { 7108 return this._onSeeked; 7109 }, 7110 set: function set(callback) { 7111 this._onSeeked = callback; 7112 } 7113 7114 // prototype: function onError(type: number, info: {code: number, msg: string}): void 7115 7116 }, { 7117 key: 'onError', 7118 get: function get() { 7119 return this._onError; 7120 }, 7121 set: function set(callback) { 7122 this._onError = callback; 7123 } 7124 }, { 7125 key: 'onComplete', 7126 get: function get() { 7127 return this._onComplete; 7128 }, 7129 set: function set(callback) { 7130 this._onComplete = callback; 7131 } 7132 }, { 7133 key: 'onRedirect', 7134 get: function get() { 7135 return this._onRedirect; 7136 }, 7137 set: function set(callback) { 7138 this._onRedirect = callback; 7139 } 7140 }, { 7141 key: 'onRecoveredEarlyEof', 7142 get: function get() { 7143 return this._onRecoveredEarlyEof; 7144 }, 7145 set: function set(callback) { 7146 this._onRecoveredEarlyEof = callback; 7147 } 7148 }, { 7149 key: 'currentURL', 7150 get: function get() { 7151 return this._dataSource.url; 7152 } 7153 }, { 7154 key: 'hasRedirect', 7155 get: function get() { 7156 return this._redirectedURL != null || this._dataSource.redirectedURL != undefined; 7157 } 7158 }, { 7159 key: 'currentRedirectedURL', 7160 get: function get() { 7161 return this._redirectedURL || this._dataSource.redirectedURL; 7162 } 7163 7164 // in KB/s 7165 7166 }, { 7167 key: 'currentSpeed', 7168 get: function get() { 7169 if (this._loaderClass === _xhrRangeLoader2.default) { 7170 // SpeedSampler is inaccuracy if loader is RangeLoader 7171 return this._loader.currentSpeed; 7172 } 7173 return this._speedSampler.lastSecondKBps; 7174 } 7175 }, { 7176 key: 'loaderType', 7177 get: function get() { 7178 return this._loader.type; 7179 } 7180 }]); 7181 7182 return IOController; 7183}(); 7184 7185exports.default = IOController; 7186 7187},{"../utils/exception.js":40,"../utils/logger.js":41,"./fetch-stream-loader.js":22,"./loader.js":24,"./param-seek-handler.js":25,"./range-seek-handler.js":26,"./speed-sampler.js":27,"./websocket-loader.js":28,"./xhr-moz-chunked-loader.js":29,"./xhr-msstream-loader.js":30,"./xhr-range-loader.js":31}],24:[function(_dereq_,module,exports){ 7188'use strict'; 7189 7190Object.defineProperty(exports, "__esModule", { 7191 value: true 7192}); 7193exports.BaseLoader = exports.LoaderErrors = exports.LoaderStatus = undefined; 7194 7195var _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; }; }(); /* 7196 * Copyright (C) 2016 Bilibili. All Rights Reserved. 7197 * 7198 * @author zheng qian <[email protected]> 7199 * 7200 * Licensed under the Apache License, Version 2.0 (the "License"); 7201 * you may
7201not use this file except in compliance with the License. 7202 * You may obtain a copy of the License at 7203 * 7204 * http://www.apache.org/licenses/LICENSE-2.0 7205 * 7206 * Unless required by applicable law or agreed to in writing, software 7207 * distributed under the License is distributed on an "AS IS" BASIS, 7208 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 7209 * See the License for the specific language governing permissions and 7210 * limitations under the License. 7211 */ 7212 7213var _exception = _dereq_('../utils/exception.js'); 7214 7215function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 7216
7217var LoaderStatus = exports.LoaderStatus = { 7218 kIdle: 0, 7219 kConnecting: 1, 7220 kBuffering: 2, 7221 kError: 3, 7222 kComplete: 4 7223}; 7224 7225var LoaderErrors = exports.LoaderErrors = { 7226 OK: 'OK', 7227 EXCEPTION: 'Exception', 7228 HTTP_STATUS_CODE_INVALID: 'HttpStatusCodeInvalid', 7229 CONNECTING_TIMEOUT: 'ConnectingTimeout', 7230 EARLY_EOF: 'EarlyEof', 7231 UNRECOVERABLE_EARLY_EOF: 'UnrecoverableEarlyEof' 7232}; 7233 7234/* Loader has callbacks which have following prototypes: 7235 * function onContentLengthKnown(contentLength: number): void 7236 * function onURLRedirect(url: string): void 7237 * function onDataArrival(chunk: ArrayBuffer, byteStart: number, receivedLength: number): void 7238 * function onError(errorType: number, errorInfo: {code: number, msg: string}): void 7239 * function onComplete(rangeFrom: number, rangeTo: number): void 7240 */ 7241 7242var BaseLoader = exports.BaseLoader = function () { 7243 function BaseLoader(typeName) { 7244 _classCallCheck(this, BaseLoader); 7245 7246 this._type = typeName || 'undefined'; 7247 this._status = LoaderStatus.kIdle; 7248 this._needStash = false; 7249 // callbacks 7250 this._onContentLengthKnown = null; 7251 this._onURLRedirect = null; 7252 this._onDataArrival = null; 7253 this._onError = null; 7254 this._onComplete = null; 7255 } 7256 7257 _createClass(BaseLoader, [{ 7258 key: 'destroy', 7259 value: function destroy() { 7260 this._status = LoaderStatus.kIdle; 7261 this._onContentLengthKnown = null; 7262 this._onURLRedirect = null; 7263 this._onDataArrival = null; 7264 this._onError = null; 7265 this._onComplete = null; 7266 } 7267 }, { 7268 key: 'isWorking', 7269 value: function isWorking() { 7270 return this._status === LoaderStatus.kConnecting || this._status === LoaderStatus.kBuffering; 7271 } 7272 }, { 7273 key: 'open', 7274 7275 7276 // pure virtual 7277 value: function open(dataSource, range) { 7278 throw new _exception.NotImplementedException('Unimplemented abstract function!'); 7279 } 7280 }, { 7281 key: 'abort', 7282 value: function abort() { 7283 throw new _exception.NotImplementedException('Unimplemented abstract function!'); 7284 } 7285 }, { 7286 key: 'type', 7287 get: function get() { 7288 return this._type; 7289 } 7290 }, { 7291 key: 'status', 7292 get: function get() { 7293 return this._status; 7294 } 7295 }, { 7296 key: 'needStashBuffer', 7297 get: function get() { 7298 return this._needStash; 7299 } 7300 }, { 7301 key: 'onContentLengthKnown', 7302 get: function get() { 7303 return this._onContentLengthKnown; 7304 }, 7305 set: function set(callback) { 7306 this._onContentLengthKnown = callback; 7307 } 7308 }, { 7309 key: 'onURLRedirect', 7310 get: function get() { 7311 return this._onURLRedirect; 7312 }, 7313 set: function set(callback) { 7314 this._onURLRedirect = callback; 7315 } 7316 }, { 7317 key: 'onDataArrival', 7318 get: function get() { 7319 return this._onDataArrival; 7320 }, 7321 set: function set(callback) { 7322 this._onDataArrival = callback; 7323 } 7324 }, { 7325 key: 'onError', 7326 get: function get() { 7327 return this._onError; 7328 }, 7329 set: function set(callback) { 7330 this._onError = callback; 7331 } 7332 }, { 7333 key: 'onComplete', 7334 get: function get() { 7335 return this._onComplete; 7336 }, 7337 set: function set(callback) { 7338 this._onComplete = callback; 7339 } 7340 }]); 7341 7342 return BaseLoader; 7343}(); 7344 7345},{"../utils/exception.js":40}],25:[function(_dereq_,module,exports){ 7346'use strict'; 7347 7348Object.defineProperty(exports, "__esModule", { 7349 value: true 7350}); 7351 7352var _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; }; }(); 7353 7354function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 7355 7356/* 7357 * Copyright (C) 2016 Bilibili. All Rights Reserved. 7358 * 7359 * @author zheng qian <[email protected]> 7360 * 7361 * Licensed under the Apache License, Version 2.0 (the "License");
7362 * you may not use this file except in compliance with the License. 7363 * You may obtain a copy of the License at 7364 * 7365 * http://www.apache.org/licenses/LICENSE-2.0 7366 * 7367 * Unless required by applicable law or agreed to in writing, software 7368 * distributed under the License is distributed on an "AS IS" BASIS, 7369 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 7370 * See the License for the specific language governing permissions and 7371 * limitations under the License. 7372 */ 7373 7374var ParamSeekHandler = function () { 7375 function ParamSeekHandler(paramStart, paramEnd) { 7376 _classCallCheck(this, ParamSeekHandler); 7377 7378 this._startName = paramStart; 7379 this._endName = paramEnd; 7380 } 7381 7382 _createClass(ParamSeekHandler, [{ 7383 key: 'getConfig', 7384 value: function getConfig(baseUrl, range) { 7385 var url = baseUrl; 7386 7387 if (range.from !== 0 || range.to !== -1) { 7388 var needAnd = true; 7389 if (url.indexOf('?') === -1) { 7390 url += '?'; 7391 needAnd = false; 7392 } 7393 7394 if (needAnd) { 7395 url += '&'; 7396 } 7397 7398 url += this._startName + '=' + range.from.toString(); 7399 7400 if (range.to !== -1) { 7401 url += '&' + this._endName + '=' + range.to.toString(); 7402 } 7403 } 7404 7405 return { 7406 url: url, 7407 headers: {} 7408 }; 7409 } 7410 }, { 7411 key: 'removeURLParameters', 7412 value: function removeURLParameters(seekedURL) { 7413 var baseURL = seekedURL.split('?')[0]; 7414 var params = undefined; 7415 7416 var queryIndex = seekedURL.indexOf('?'); 7417 if (queryIndex !== -1) { 7418 params = seekedURL.substring(queryIndex + 1); 7419 } 7420 7421 var resultParams = ''; 7422 7423 if (params != undefined && params.length > 0) { 7424 var pairs = params.split('&'); 7425 7426 for (var i = 0; i < pairs.length; i++) { 7427 var pair = pairs[i].split('='); 7428 var requireAnd = i > 0; 7429 7430 if (pair[0] !== this._startName && pair[0] !== this._endName) { 7431 if (requireAnd) { 7432 resultParams += '&'; 7433 } 7434 resultParams += pairs[i]; 7435 } 7436 } 7437 } 7438 7439 return resultParams.length === 0 ? baseURL : baseURL + '?' + resultParams; 7440 } 7441 }]); 7442 7443 return ParamSeekHandler; 7444}(); 7445 7446exports.default = ParamSeekHandler; 7447 7448},{}],26:[function(_dereq_,module,exports){ 7449'use strict'; 7450 7451Object.defineProperty(exports, "__esModule", { 7452 value: true 7453}); 7454 7455var _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; }; }(); 7456 7457function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 7458 7459/* 7460 * Copyright (C) 2016 Bilibili. All Rights Reserved. 7461 * 7462 * @author zheng qian <[email protected]> 7463 * 7464 * Licensed under the Apache License, Version 2.0 (the "License"); 7465 * you may not use this file except in compliance with the License. 7466 * You may obtain a copy of the License at 7467 * 7468 * http://www.apache.org/licenses/LICENSE-2.0 7469 * 7470 * Unless required by applicable law or agreed to in writing, software 7471 * distributed under the License is distributed on an "AS IS" BASIS, 7472 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 7473 * See the License for the specific language governing permissions and 7474 * limitations under the License. 7475 */ 7476 7477var RangeSeekHandler = function () { 7478 function RangeSeekHandler(zeroStart) { 7479 _classCallCheck(this, RangeSeekHandler); 7480 7481 this._zeroStart = zeroStart || false; 7482 } 7483 7484 _createClass(RangeSeekHandler, [{ 7485 key: 'getConfig', 7486 value: function getConfig(url, range) { 7487 var headers = {}; 7488 7489 if (range.from !== 0 || range.to !== -1) { 7490 var param = void 0; 7491 if (range.to !== -1) { 7492 param = 'bytes=' + range.from.toString() + '-' + range.to.toString(); 7493 } else { 7494 param = 'bytes=' + range.from.toString() + '-'; 7495 } 7496 headers['Range'] = param; 7497 } else if (this._zeroStart) { 7498 headers['Range'] = 'bytes=0-'; 7499 } 7500 7501 return { 7502 url: url, 7503 headers: headers 7504 }; 7505 } 7506 }, {
7507 key: 'removeURLParameters', 7508 value: function removeURLParameters(seekedURL) { 7509 return seekedURL; 7510 } 7511 }]); 7512 7513 return RangeSeekHandler; 7514}(); 7515 7516exports.default = RangeSeekHandler; 7517 7518},{}],27:[function(_dereq_,module,exports){ 7519"use strict"; 7520 7521Object.defineProperty(exports, "__esModule", { 7522 value: true 7523}); 7524 7525var _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; }; }(); 7526 7527function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 7528 7529/* 7530 * Copyright (C) 2016 Bilibili. All Rights Reserved. 7531 * 7532 * @author zheng qian <[email protected]> 7533 * 7534 * Licensed under the Apache License, Version 2.0 (the "License"); 7535 * you may not use this file except in compliance with the License. 7536 * You may obtain a copy of the License at 7537 * 7538 * http://www.apache.org/licenses/LICENSE-2.0 7539 * 7540 * Unless required by applicable law or agreed to in writing, software 7541 * distributed under the License is distributed on an "AS IS" BASIS, 7542 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 7543 * See the License for the specific language governing permissions and 7544 * limitations under the License. 7545 */ 7546 7547// Utility class to calculate realtime network I/O speed 7548var SpeedSampler = function () { 7549 function SpeedSampler() { 7550 _classCallCheck(this, SpeedSampler); 7551 7552 // milliseconds 7553 this._firstCheckpoint = 0; 7554 this._lastCheckpoint = 0; 7555 this._intervalBytes = 0; 7556 this._totalBytes = 0; 7557 this._lastSecondBytes = 0; 7558 7559 // compatibility detection 7560 if (self.performance && self.performance.now) { 7561 this._now = self.performance.now.bind(self.performance); 7562 } else { 7563 this._now = Date.now; 7564 } 7565 } 7566 7567 _createClass(SpeedSampler, [{ 7568 key: "reset", 7569 value: function reset() { 7570 this._firstCheckpoint = this._lastCheckpoint = 0; 7571 this._totalBytes = this._intervalBytes = 0; 7572 this._lastSecondBytes = 0; 7573 } 7574 }, { 7575 key: "addBytes", 7576 value: function addBytes(bytes) { 7577 if (this._firstCheckpoint === 0) { 7578 this._firstCheckpoint = this._now(); 7579 this._lastCheckpoint = this._firstCheckpoint; 7580 this._intervalBytes += bytes; 7581 this._totalBytes += bytes; 7582 } else if (this._now() - this._lastCheckpoint < 1000) { 7583 this._intervalBytes += bytes; 7584 this._totalBytes += bytes; 7585 } else { 7586 // duration >= 1000 7587 this._lastSecondBytes = this._intervalBytes; 7588 this._intervalBytes = bytes; 7589 this._totalBytes += bytes; 7590 this._lastCheckpoint = this._now(); 7591 } 7592 } 7593 }, { 7594 key: "currentKBps", 7595 get: function get() { 7596 this.addBytes(0); 7597 7598 var durationSeconds = (this._now() - this._lastCheckpoint) / 1000; 7599 if (durationSeconds == 0) durationSeconds = 1; 7600 return this._intervalBytes / durationSeconds / 1024; 7601 } 7602 }, { 7603 key: "lastSecondKBps", 7604 get: function get() { 7605 this.addBytes(0); 7606 7607 if (this._lastSecondBytes !== 0) { 7608 return this._lastSecondBytes / 1024; 7609 } else { 7610 // lastSecondBytes === 0 7611 if (this._now() - this._lastCheckpoint >= 500) { 7612 // if time interval since last checkpoint has exceeded 500ms 7613 // the speed is nearly accurate 7614 return this.currentKBps; 7615 } else { 7616 // We don't know 7617 return 0; 7618 } 7619 } 7620 } 7621 }, {
vendor: 5,790 bytes, lines 7622-7665
7622 key: "averageKBps", 7623 get: function get() { 7624 var durationSeconds = (this._now() - this._firstCheckpoint) / 1000; 7625 return this._totalBytes / durationSeconds / 1024; 7626 } 7627 }]); 7628 7629 return SpeedSampler; 7630}(); 7631 7632exports.default = SpeedSampler; 7633 7634},{}],28:[function(_dereq_,module,exports){ 7635'use strict'; 7636 7637Object.defineProperty(exports, "__esModule", { 7638 value: true 7639}); 7640 7641var _get = function get(object, property, receiver) { 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 { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; 7642 7643var _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; }; }(); 7644 7645var _logger = _dereq_('../utils/logger.js'); 7646 7647var _logger2 = _interopRequireDefault(_logger); 7648 7649var _loader = _dereq_('./loader.js'); 7650 7651var _exception = _dereq_('../utils/exception.js'); 7652 7653function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 7654 7655function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 7656 7657function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 7658 7659function _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; } /* 7660 * Copyright (C) 2016 Bilibili. All Rights Reserved. 7661 * 7662 * @author zheng qian <[email protected]> 7663 * 7664 * Licensed under the Apache License, Version 2.0 (the "License"); 7665 * you may
7665not use this file except in compliance with the License. 7666 * You may obtain a copy of the License at 7667 * 7668 * http://www.apache.org/licenses/LICENSE-2.0 7669 * 7670 * Unless required by applicable law or agreed to in writing, software 7671 * distributed under the License is distributed on an "AS IS" BASIS, 7672 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 7673 * See the License for the specific language governing permissions and 7674 * limitations under the License. 7675 */ 7676 7677// For FLV over WebSocket live stream 7678var WebSocketLoader = function (_BaseLoader) { 7679 _inherits(WebSocketLoader, _BaseLoader); 7680 7681 _createClass(WebSocketLoader, null, [{ 7682 key: 'isSupported', 7683 value: function isSupported() { 7684 try { 7685 return typeof self.WebSocket !== 'undefined'; 7686 } catch (e) { 7687 return false;
7688 } 7689 } 7690 }]); 7691 7692 function WebSocketLoader() { 7693 _classCallCheck(this, WebSocketLoader); 7694 7695 var _this = _possibleConstructorReturn(this, (WebSocketLoader.__proto__ || Object.getPrototypeOf(WebSocketLoader)).call(this, 'websocket-loader')); 7696 7697 _this.TAG = 'WebSocketLoader'; 7698 7699 _this._needStash = true; 7700 7701 _this._ws = null; 7702 _this._requestAbort = false; 7703 _this._receivedLength = 0; 7704 return _this; 7705 } 7706 7707 _createClass(WebSocketLoader, [{ 7708 key: 'destroy', 7709 value: function destroy() { 7710 if (this._ws) { 7711 this.abort(); 7712 } 7713 _get(WebSocketLoader.prototype.__proto__ || Object.getPrototypeOf(WebSocketLoader.prototype), 'destroy', this).call(this); 7714 } 7715 }, { 7716 key: 'open', 7717 value: function open(dataSource) { 7718 try { 7719 var ws = this._ws = new self.WebSocket(dataSource.url); 7720 ws.binaryType = 'arraybuffer'; 7721 ws.onopen = this._onWebSocketOpen.bind(this); 7722 ws.onclose = this._onWebSocketClose.bind(this); 7723 ws.onmessage = this._onWebSocketMessage.bind(this); 7724 ws.onerror = this._onWebSocketError.bind(this); 7725 7726 this._status = _loader.LoaderStatus.kConnecting; 7727 } catch (e) { 7728 this._status = _loader.LoaderStatus.kError; 7729 7730 var info = { code: e.code, msg: e.message }; 7731 7732 if (this._onError) { 7733 this._onError(_loader.LoaderErrors.EXCEPTION, info); 7734 } else { 7735 throw new _exception.RuntimeException(info.msg); 7736 } 7737 } 7738 } 7739 }, { 7740 key: 'abort', 7741 value: function abort() { 7742 var ws = this._ws; 7743 if (ws && (ws.readyState === 0 || ws.readyState === 1)) { 7744 // CONNECTING || OPEN 7745 this._requestAbort = true; 7746 ws.close(); 7747 } 7748 7749 this._ws = null; 7750 this._status = _loader.LoaderStatus.kComplete; 7751 } 7752 }, { 7753 key: '_onWebSocketOpen', 7754 value: function _onWebSocketOpen(e) { 7755 this._status = _loader.LoaderStatus.kBuffering; 7756 } 7757 }, { 7758 key: '_onWebSocketClose', 7759 value: function _onWebSocketClose(e) { 7760 if (this._requestAbort === true) { 7761 this._requestAbort = false;
7762 return; 7763 } 7764 7765 this._status = _loader.LoaderStatus.kComplete; 7766 7767 if (this._onComplete) { 7768 this._onComplete(0, this._receivedLength - 1); 7769 } 7770 } 7771 }, { 7772 key: '_onWebSocketMessage', 7773 value: function _onWebSocketMessage(e) { 7774 var _this2 = this; 7775 7776 if (e.data instanceof ArrayBuffer) { 7777 this._dispatchArrayBuffer(e.data); 7778 } else if (e.data instanceof Blob) { 7779 var reader = new FileReader(); 7780 reader.onload = function () { 7781 _this2._dispatchArrayBuffer(reader.result); 7782 }; 7783 reader.readAsArrayBuffer(e.data); 7784 } else { 7785 this._status = _loader.LoaderStatus.kError; 7786 var info = { code: -1, msg: 'Unsupported WebSocket message type: ' + e.data.constructor.name }; 7787 7788 if (this._onError) { 7789 this._onError(_loader.LoaderErrors.EXCEPTION, info); 7790 } else { 7791 throw new _exception.RuntimeException(info.msg); 7792 } 7793 } 7794 } 7795 }, { 7796 key: '_dispatchArrayBuffer', 7797 value: function _dispatchArrayBuffer(arraybuffer) { 7798 var chunk = arraybuffer; 7799 var byteStart = this._receivedLength; 7800 this._receivedLength += chunk.byteLength; 7801 7802 if (this._onDataArrival) { 7803 this._onDataArrival(chunk, byteStart, this._receivedLength); 7804 } 7805 } 7806 }, { 7807 key: '_onWebSocketError', 7808 value: function _onWebSocketError(e) { 7809 this._status = _loader.LoaderStatus.kError; 7810 7811 var info = { 7812 code: e.code, 7813 msg: e.message 7814 }; 7815 7816 if (this._onError) { 7817 this._onError(_loader.LoaderErrors.EXCEPTION, info); 7818 } else { 7819 throw new _exception.RuntimeException(info.msg); 7820 } 7821 } 7822 }]); 7823 7824 return WebSocketLoader; 7825}(_loader.BaseLoader); 7826 7827exports.default = WebSocketLoader; 7828 7829},{"../utils/exception.js":40,"../utils/logger.js":41,"./loader.js":24}],29:[function(_dereq_,module,exports){ 7830'use strict'; 7831 7832Object.defineProperty(exports, "__esModule", { 7833 value: true 7834}); 7835 7836var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 7837 7838var _get = function get(object, property, receiver) { 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 { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; 7839 7840var _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; }; }(); 7841 7842var _logger = _dereq_('../utils/logger.js'); 7843 7844var _logger2 = _interopRequireDefault(_logger); 7845 7846var _loader = _dereq_('./loader.js'); 7847 7848var _exception = _dereq_('../utils/exception.js'); 7849 7850function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 7851 7852function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 7853 7854function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 7855 7856function _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
7856onstructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /* 7857 * Copyright (C) 2016 Bilibili. All Rights Reserved. 7858 * 7859 * @author zheng qian <[email protected]> 7860 * 7861 * Licensed under the Apache License, Version 2.0 (the "License"); 7862 * you may not use this file except in compliance with the License. 7863 * You may obtain a copy of the License at 7864 * 7865 * http://www.apache.org/licenses/LICENSE-2.0 7866 * 7867 * Unless required by applicable law or agreed to in writing, softw
7867are 7868 * distributed under the License is distributed on an "AS IS" BASIS, 7869 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 7870 * See the License for the specific language governing permissions and 7871 * limitations under the License. 7872 */ 7873 7874// For FireFox browser which supports `xhr.responseType = 'moz-chunked-arraybuffer'` 7875var MozChunkedLoader = function (_BaseLoader) { 7876 _inherits(MozChunkedLoader, _BaseLoader); 7877 7878 _createClass(MozChunkedLoader, null, [{ 7879 key: 'isSupported', 7880 value: function isSupported() { 7881 try { 7882 var xhr = new XMLHttpRequest(); 7883 // Firefox 37- requires .open() to be called before setting responseType 7884 xhr.open('GET', 'https://example.com', true); 7885 xhr.responseType = 'moz-chunked-arraybuffer'; 7886 return xhr.responseType === 'moz-chunked-arraybuffer'; 7887 } catch (e) { 7888 _logger2.default.w('MozChunkedLoader', e.message); 7889 return false; 7890 } 7891 } 7892 }]); 7893 7894 function MozChunkedLoader(seekHandler, config) { 7895 _classCallCheck(this, MozChunkedLoader); 7896 7897 var _this = _possibleConstructorReturn(this, (MozChunkedLoader.__proto__ || Object.getPrototypeOf(MozChunkedLoader)).call(this, 'xhr-moz-chunked-loader')); 7898 7899 _this.TAG = 'MozChunkedLoader'; 7900 7901 _this._seekHandler = seekHandler; 7902 _this._config = config; 7903 _this._needStash = true; 7904 7905 _this._xhr = null; 7906 _this._requestAbort = false;
7907 _this._contentLength = null; 7908 _this._receivedLength = 0; 7909 return _this; 7910 } 7911 7912 _createClass(MozChunkedLoader, [{ 7913 key: 'destroy', 7914 value: function destroy() { 7915 if (this.isWorking()) { 7916 this.abort(); 7917 } 7918 if (this._xhr) { 7919 this._xhr.onreadystatechange = null; 7920 this._xhr.onprogress = null; 7921 this._xhr.onloadend = null; 7922 this._xhr.onerror = null; 7923 this._xhr = null; 7924 } 7925 _get(MozChunkedLoader.prototype.__proto__ || Object.getPrototypeOf(MozChunkedLoader.prototype), 'destroy', this).call(this); 7926 } 7927 }, { 7928 key: 'open', 7929 value: function open(dataSource, range) { 7930 this._dataSource = dataSource; 7931 this._range = range; 7932 7933 var sourceURL = dataSource.url; 7934 if (this._config.reuseRedirectedURL && dataSource.redirectedURL != undefined) { 7935 sourceURL = dataSource.redirectedURL; 7936 } 7937 7938 var seekConfig = this._seekHandler.getConfig(sourceURL, range); 7939 this._requestURL = seekConfig.url; 7940 7941 var xhr = this._xhr = new XMLHttpRequest(); 7942 xhr.open('GET', seekConfig.url, true); 7943 xhr.responseType = 'moz-chunked-arraybuffer'; 7944 xhr.onreadystatechange = this._onReadyStateChange.bind(this); 7945 xhr.onprogress = this._onProgress.bind(this); 7946 xhr.onloadend = this._onLoadEnd.bind(this); 7947 xhr.onerror = this._onXhrError.bind(this); 7948 7949 // cors is auto detected and enabled by xhr 7950 7951 // withCredentials is disabled by default 7952 if (dataSource.withCredentials) { 7953 xhr.withCredentials = true; 7954 } 7955 7956 if (_typeof(seekConfig.headers) === 'object') { 7957 var headers = seekConfig.headers; 7958 7959 for (var key in headers) { 7960 if (headers.hasOwnProperty(key)) { 7961 xhr.setRequestHeader(key, headers[key]); 7962 } 7963 } 7964 } 7965 7966 // add additional headers 7967 if (_typeof(this._config.headers) === 'object') { 7968 var _headers = this._config.headers; 7969 7970 for (var _key in _headers) { 7971 if (_headers.hasOwnProperty(_key)) { 7972 xhr.setRequestHeader(_key, _headers[_key]); 7973 } 7974 } 7975 } 7976 7977 this._status = _loader.LoaderStatus.kConnecting; 7978 xhr.send(); 7979 } 7980 }, { 7981 key: 'abort', 7982 value: function abort() { 7983 this._requestAbort = true; 7984 if (this._xhr) { 7985 this._xhr.abort(); 7986 } 7987 this._status = _loader.LoaderStatus.kComplete; 7988 } 7989 }, { 7990 key: '_onReadyStateChange', 7991 value: function _onReadyStateChange(e) { 7992 var xhr = e.target; 7993 7994 if (xhr.readyState === 2) { 7995 // HEADERS_RECEIVED 7996 if (xhr.responseURL != undefined && xhr.responseURL !== this._requestURL) { 7997 if (this._onURLRedirect) { 7998 var redirectedURL = this._seekHandler.removeURLParameters(xhr.responseURL); 7999 this._onURLRedirect(redirectedURL); 8000 } 8001 } 8002 8003 if (xhr.status !== 0 && (xhr.status < 200 || xhr.status > 299)) { 8004 this._status = _loader.LoaderStatus.kError; 8005 if (this._onError) { 8006 this._onError(_loader.LoaderErrors.HTTP_STATUS_CODE_INVALID, { code: xhr.status, msg: xhr.statusText }); 8007 } else { 8008 throw new _exception.RuntimeException('MozChunkedLoader: Http code invalid, ' + xhr.status + ' ' + xhr.statusText); 8009 } 8010 } else { 8011 this._status = _loader.LoaderStatus.kBuffering; 8012 } 8013 } 8014 } 8015 }, { 8016 key: '_onProgress', 8017 value: function _onProgress(e) { 8018 if (this._status === _loader.LoaderStatus.kError) { 8019 // Ignore error response 8020 return; 8021 } 8022 8023 if (this._contentLength === null) { 8024 if (e.total !== null && e.total !== 0) { 8025 this._contentLength = e.total; 8026 if (this._onContentLengthKnown) { 8027 this._onContentLengthKnown(this._contentLength); 8028 } 8029 } 8030 } 8031 8032 var chunk = e.target.response; 8033 var byteStart = this._range.from + this._receivedLength; 8034 this._receivedLength += chunk.byteLength; 8035 8036 if (this._onDataArrival) { 8037 this._onDataArrival(chunk, byteStart, this._receivedLength); 8038 } 8039 } 8040 }, {
8041 key: '_onLoadEnd', 8042 value: function _onLoadEnd(e) { 8043 if (this._requestAbort === true) { 8044 this._requestAbort = false; 8045 return; 8046 } else if (this._status === _loader.LoaderStatus.kError) { 8047 return; 8048 } 8049 8050 this._status = _loader.LoaderStatus.kComplete; 8051 if (this._onComplete) { 8052 this._onComplete(this._range.from, this._range.from + this._receivedLength - 1); 8053 } 8054 } 8055 }, { 8056 key: '_onXhrError', 8057 value: function _onXhrError(e) { 8058 this._status = _loader.LoaderStatus.kError; 8059 var type = 0; 8060 var info = null; 8061 8062 if (this._contentLength && e.loaded < this._contentLength) { 8063 type = _loader.LoaderErrors.EARLY_EOF; 8064 info = { code: -1, msg: 'Moz-Chunked stream meet Early-Eof' }; 8065 } else { 8066 type = _loader.LoaderErrors.EXCEPTION; 8067 info = { code: -1, msg: e.constructor.name + ' ' + e.type }; 8068 } 8069 8070 if (this._onError) { 8071 this._onError(type, info); 8072 } else { 8073 throw new _exception.RuntimeException(info.msg); 8074 } 8075 } 8076 }]); 8077 8078 return MozChunkedLoader; 8079}(_loader.BaseLoader); 8080 8081exports.default = MozChunkedLoader; 8082 8083},{"../utils/exception.js":40,"../utils/logger.js":41,"./loader.js":24}],30:[function(_dereq_,module,exports){ 8084'use strict'; 8085 8086Object.defineProperty(exports, "__esModule", { 8087 value: true 8088}); 8089 8090var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 8091 8092var _get = function get(object, property, receiver) { 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 { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; 8093 8094var _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; }; }(); 8095 8096var _logger = _dereq_('../utils/logger.js'); 8097 8098var _logger2 = _interopRequireDefault(_logger); 8099 8100var _loader = _dereq_('./loader.js'); 8101 8102var _exception = _dereq_('../utils/exception.js'); 8103 8104function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 8105 8106function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 8107 8108function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 8109 8110function _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; } /* 8111 * Copyright (C) 2016 Bilibili. All Rights Reserved. 8112 * 8113 * @author zheng qian <[email protected]> 8114 * 8115 * Licensed under the Apache License, Version 2.0 (the "License"); 8116 * you may
8116not use this file except in compliance with the License. 8117 * You may obtain a copy of the License at 8118 * 8119 * http://www.apache.org/licenses/LICENSE-2.0 8120 * 8121 * Unless required by applicable law or agreed to in writing, software 8122 * distributed under the License is distributed on an "AS IS" BASIS, 8123 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8124 * See the License for the specific language governing permissions and 8125 * limitations under the License. 8126 */ 8127 8128/* Notice: ms-stream may cause IE/Edge browser crash if seek too frequently!!! 8129 * The browser may crash in wininet.dll. Disable for now. 8130 * 8131 * For IE11/Edge browser by microsoft which supports `xhr.responseType = 'ms-stream'` 8132 * Notice that ms-stream API sucks. The buffer is always expanding along with downloading. 8133 * 8134 * We need to abort the xhr if buffer size exceeded limit size (e.g. 16 MiB), then do reconnect. 8135 * in order to release previous ArrayBuffer to avoid memory leak 8136 * 8137 * Otherwise, the ArrayBuffer will increase to a terrible size that equals final file size. 8138 */
8139var MSStreamLoader = function (_BaseLoader) { 8140 _inherits(MSStreamLoader, _BaseLoader); 8141 8142 _createClass(MSStreamLoader, null, [{ 8143 key: 'isSupported', 8144 value: function isSupported() { 8145 try { 8146 if (typeof self.MSStream === 'undefined' || typeof self.MSStreamReader === 'undefined') { 8147 return false; 8148 } 8149 8150 var xhr = new XMLHttpRequest(); 8151 xhr.open('GET', 'https://example.com', true); 8152 xhr.responseType = 'ms-stream'; 8153 return xhr.responseType === 'ms-stream'; 8154 } catch (e) { 8155 _logger2.default.w('MSStreamLoader', e.message); 8156 return false; 8157 } 8158 } 8159 }]); 8160 8161 function MSStreamLoader(seekHandler, config) { 8162 _classCallCheck(this, MSStreamLoader); 8163 8164 var _this = _possibleConstructorReturn(this, (MSStreamLoader.__proto__ || Object.getPrototypeOf(MSStreamLoader)).call(this, 'xhr-msstream-loader')); 8165 8166 _this.TAG = 'MSStreamLoader'; 8167 8168 _this._seekHandler = seekHandler; 8169 _this._config = config; 8170 _this._needStash = true; 8171 8172 _this._xhr = null; 8173 _this._reader = null; // MSStreamReader 8174 8175 _this._totalRange = null; 8176 _this._currentRange = null; 8177 8178 _this._currentRequestURL = null; 8179 _this._currentRedirectedURL = null; 8180 8181 _this._contentLength = null; 8182 _this._receivedLength = 0; 8183 8184 _this._bufferLimit = 16 * 1024 * 1024; // 16MB 8185 _this._lastTimeBufferSize = 0; 8186 _this._isReconnecting = false; 8187 return _this; 8188 } 8189 8190 _createClass(MSStreamLoader, [{ 8191 key: 'destroy', 8192 value: function destroy() { 8193 if (this.isWorking()) { 8194 this.abort(); 8195 } 8196 if (this._reader) { 8197 this._reader.onprogress = null; 8198 this._reader.onload = null; 8199 this._reader.onerror = null; 8200 this._reader = null; 8201 } 8202 if (this._xhr) { 8203 this._xhr.onreadystatechange = null; 8204 this._xhr = null; 8205 } 8206 _get(MSStreamLoader.prototype.__proto__ || Object.getPrototypeOf(MSStreamLoader.prototype), 'destroy', this).call(this); 8207 } 8208 }, { 8209 key: 'open', 8210 value: function open(dataSource, range) { 8211 this._internalOpen(dataSource, range, false); 8212 } 8213 }, { 8214 key: '_internalOpen', 8215 value: function _internalOpen(dataSource, range, isSubrange) { 8216 this._dataSource = dataSource; 8217 8218 if (!isSubrange) { 8219 this._totalRange = range; 8220 } else { 8221 this._currentRange = range; 8222 } 8223 8224 var sourceURL = dataSource.url; 8225 if (this._config.reuseRedirectedURL) { 8226 if (this._currentRedirectedURL != undefined) { 8227 sourceURL = this._currentRedirectedURL; 8228 } else if (dataSource.redirectedURL != undefined) { 8229 sourceURL = dataSource.redirectedURL; 8230 } 8231 } 8232 8233 var seekConfig = this._seekHandler.getConfig(sourceURL, range); 8234 this._currentRequestURL = seekConfig.url; 8235 8236 var reader = this._reader = new self.MSStreamReader(); 8237 reader.onprogress = this._msrOnProgress.bind(this); 8238 reader.onload = this._msrOnLoad.bind(this); 8239 reader.onerror = this._msrOnError.bind(this); 8240 8241 var xhr = this._xhr = new XMLHttpRequest(); 8242 xhr.open('GET', seekConfig.url, true); 8243 xhr.responseType = 'ms-stream'; 8244 xhr.onreadystatechange = this._xhrOnReadyStateChange.bind(this); 8245 xhr.onerror = this._xhrOnError.bind(this); 8246 8247 if (dataSource.withCredentials) { 8248 xhr.withCredentials = true; 8249 } 8250 8251 if (_typeof(seekConfig.headers) === 'object') { 8252 var headers = seekConfig.headers; 8253 8254 for (var key in headers) { 8255 if (headers.hasOwnProperty(key)) { 8256 xhr.setRequestHeader(key, headers[key]); 8257 } 8258 } 8259 } 8260 8261 // add additional headers 8262 if (_typeof(this._config.headers) === 'object') { 8263 var _headers = this._config.headers; 8264 8265 for (var _key in _headers) { 8266 if (_headers.hasOwnProperty(_key)) { 8267 xhr.setRequestHeader(_key, _headers[_key]); 8268 } 8269 } 8270 } 8271 8272 if (this._isReconnecting) { 8273 this._isReconnecting = false;
8274 } else { 8275 this._status = _loader.LoaderStatus.kConnecting; 8276 } 8277 xhr.send(); 8278 } 8279 }, { 8280 key: 'abort', 8281 value: function abort() { 8282 this._internalAbort(); 8283 this._status = _loader.LoaderStatus.kComplete; 8284 } 8285 }, { 8286 key: '_internalAbort', 8287 value: function _internalAbort() { 8288 if (this._reader) { 8289 if (this._reader.readyState === 1) { 8290 // LOADING 8291 this._reader.abort(); 8292 } 8293 this._reader.onprogress = null; 8294 this._reader.onload = null; 8295 this._reader.onerror = null; 8296 this._reader = null; 8297 } 8298 if (this._xhr) { 8299 this._xhr.abort(); 8300 this._xhr.onreadystatechange = null; 8301 this._xhr = null; 8302 } 8303 } 8304 }, { 8305 key: '_xhrOnReadyStateChange', 8306 value: function _xhrOnReadyStateChange(e) { 8307 var xhr = e.target; 8308 8309 if (xhr.readyState === 2) { 8310 // HEADERS_RECEIVED 8311 if (xhr.status >= 200 && xhr.status <= 299) { 8312 this._status = _loader.LoaderStatus.kBuffering; 8313 8314 if (xhr.responseURL != undefined) { 8315 var redirectedURL = this._seekHandler.removeURLParameters(xhr.responseURL); 8316 if (xhr.responseURL !== this._currentRequestURL && redirectedURL !== this._currentRedirectedURL) { 8317 this._currentRedirectedURL = redirectedURL; 8318 if (this._onURLRedirect) { 8319 this._onURLRedirect(redirectedURL); 8320 } 8321 } 8322 } 8323 8324 var lengthHeader = xhr.getResponseHeader('Content-Length'); 8325 if (lengthHeader != null && this._contentLength == null) { 8326 var length = parseInt(lengthHeader); 8327 if (length > 0) { 8328 this._contentLength = length; 8329 if (this._onContentLengthKnown) { 8330 this._onContentLengthKnown(this._contentLength); 8331 } 8332 } 8333 } 8334 } else { 8335 this._status = _loader.LoaderStatus.kError; 8336 if (this._onError) { 8337 this._onError(_loader.LoaderErrors.HTTP_STATUS_CODE_INVALID, { code: xhr.status, msg: xhr.statusText }); 8338 } else { 8339 throw new _exception.RuntimeException('MSStreamLoader: Http code invalid, ' + xhr.status + ' ' + xhr.statusText); 8340 } 8341 } 8342 } else if (xhr.readyState === 3) { 8343 // LOADING 8344 if (xhr.status >= 200 && xhr.status <= 299) { 8345 this._status = _loader.LoaderStatus.kBuffering; 8346 8347 var msstream = xhr.response; 8348 this._reader.readAsArrayBuffer(msstream); 8349 } 8350 } 8351 } 8352 }, { 8353 key: '_xhrOnError', 8354 value: function _xhrOnError(e) { 8355 this._status = _loader.LoaderStatus.kError; 8356 var type = _loader.LoaderErrors.EXCEPTION; 8357 var info = { code: -1, msg: e.constructor.name + ' ' + e.type }; 8358 8359 if (this._onError) { 8360 this._onError(type, info); 8361 } else { 8362 throw new _exception.RuntimeException(info.msg); 8363 } 8364 } 8365 }, { 8366 key: '_msrOnProgress', 8367 value: function _msrOnProgress(e) { 8368 var reader = e.target; 8369 var bigbuffer = reader.result; 8370 if (bigbuffer == null) { 8371 // result may be null, workaround for buggy M$ 8372 this._doReconnectIfNeeded(); 8373 return; 8374 } 8375 8376 var slice = bigbuffer.slice(this._lastTimeBufferSize); 8377 this._lastTimeBufferSize = bigbuffer.byteLength; 8378 var byteStart = this._totalRange.from + this._receivedLength; 8379 this._receivedLength += slice.byteLength; 8380 8381 if (this._onDataArrival) { 8382 this._onDataArrival(slice, byteStart, this._receivedLength); 8383 } 8384 8385 if (bigbuffer.byteLength >= this._bufferLimit) { 8386 _logger2.default.v(this.TAG, 'MSStream buffer exceeded max size near ' + (byteStart + slice.byteLength) + ', reconnecting...'); 8387 this._doReconnectIfNeeded(); 8388 } 8389 } 8390 }, {
8391 key: '_doReconnectIfNeeded', 8392 value: function _doReconnectIfNeeded() { 8393 if (this._contentLength == null || this._receivedLength < this._contentLength) { 8394 this._isReconnecting = true; 8395 this._lastTimeBufferSize = 0; 8396 this._internalAbort(); 8397 8398 var range = { 8399 from: this._totalRange.from + this._receivedLength, 8400 to: -1 8401 }; 8402 this._internalOpen(this._dataSource, range, true); 8403 } 8404 } 8405 }, { 8406 key: '_msrOnLoad', 8407 value: function _msrOnLoad(e) { 8408 // actually it is onComplete event 8409 this._status = _loader.LoaderStatus.kComplete; 8410 if (this._onComplete) { 8411 this._onComplete(this._totalRange.from, this._totalRange.from + this._receivedLength - 1); 8412 } 8413 } 8414 }, { 8415 key: '_msrOnError', 8416 value: function _msrOnError(e) { 8417 this._status = _loader.LoaderStatus.kError; 8418 var type = 0; 8419 var info = null; 8420 8421 if (this._contentLength && this._receivedLength < this._contentLength) { 8422 type = _loader.LoaderErrors.EARLY_EOF; 8423 info = { code: -1, msg: 'MSStream meet Early-Eof' }; 8424 } else { 8425 type = _loader.LoaderErrors.EARLY_EOF; 8426 info = { code: -1, msg: e.constructor.name + ' ' + e.type }; 8427 } 8428 8429 if (this._onError) { 8430 this._onError(type, info); 8431 } else { 8432 throw new _exception.RuntimeException(info.msg); 8433 } 8434 } 8435 }]); 8436 8437 return MSStreamLoader; 8438}(_loader.BaseLoader); 8439 8440exports.default = MSStreamLoader; 8441 8442},{"../utils/exception.js":40,"../utils/logger.js":41,"./loader.js":24}],31:[function(_dereq_,module,exports){ 8443'use strict'; 8444 8445Object.defineProperty(exports, "__esModule", { 8446 value: true 8447}); 8448 8449var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 8450 8451var _get = function get(object, property, receiver) { 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 { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; 8452 8453var _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; }; }(); 8454 8455var _logger = _dereq_('../utils/logger.js'); 8456 8457var _logger2 = _interopRequireDefault(_logger); 8458 8459var _speedSampler = _dereq_('./speed-sampler.js'); 8460 8461var _speedSampler2 = _interopRequireDefault(_speedSampler); 8462 8463var _loader = _dereq_('./loader.js'); 8464 8465var _exception = _dereq_('../utils/exception.js'); 8466 8467function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 8468 8469function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 8470 8471function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 8472 8473function _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
8473onstructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /* 8474 * Copyright (C) 2016 Bilibili. All Rights Reserved. 8475 * 8476 * @author zheng qian <[email protected]> 8477 * 8478 * Licensed under the Apache License, Version 2.0 (the "License"); 8479 * you may not use this file except in compliance with the License. 8480 * You may obtain a copy of the License at 8481 * 8482 * http://www.apache.org/licenses/LICENSE-2.0 8483 * 8484 * Unless required by applicable law or agreed to in writing, softw
8484are 8485 * distributed under the License is distributed on an "AS IS" BASIS, 8486 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8487 * See the License for the specific language governing permissions and 8488 * limitations under the License. 8489 */ 8490 8491// Universal IO Loader, implemented by adding Range header in xhr's request header 8492var RangeLoader = function (_BaseLoader) { 8493 _inherits(RangeLoader, _BaseLoader); 8494 8495 _createClass(RangeLoader, null, [{ 8496 key: 'isSupported', 8497 value: function isSupported() { 8498 try { 8499 var xhr = new XMLHttpRequest(); 8500 xhr.open('GET', 'https://example.com', true); 8501 xhr.responseType = 'arraybuffer'; 8502 return xhr.responseType === 'arraybuffer'; 8503 } catch (e) { 8504 _logger2.default.w('RangeLoader', e.message); 8505 return false; 8506 } 8507 } 8508 }]); 8509 8510 function RangeLoader(seekHandler, config) { 8511 _classCallCheck(this, RangeLoader); 8512 8513 var _this = _possibleConstructorReturn(this, (RangeLoader.__proto__ || Object.getPrototypeOf(RangeLoader)).call(this, 'xhr-range-loader')); 8514 8515 _this.TAG = 'RangeLoader'; 8516 8517 _this._seekHandler = seekHandler; 8518 _this._config = config; 8519 _this._needStash = false; 8520 8521 _this._chunkSizeKBList = [128, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 5120, 6144, 7168, 8192]; 8522 _this._currentChunkSizeKB = 384; 8523 _this._currentSpeedNormalized = 0; 8524 _this._zeroSpeedChunkCount = 0; 8525 8526 _this._xhr = null; 8527 _this._speedSampler = new _speedSampler2.default(); 8528 8529 _this._requestAbort = false;
8530 _this._waitForTotalLength = false; 8531 _this._totalLengthReceived = false; 8532 8533 _this._currentRequestURL = null; 8534 _this._currentRedirectedURL = null; 8535 _this._currentRequestRange = null; 8536 _this._totalLength = null; // size of the entire file 8537 _this._contentLength = null; // Content-Length of entire request range 8538 _this._receivedLength = 0; // total received bytes 8539 _this._lastTimeLoaded = 0; // received bytes of current request sub-range 8540 return _this; 8541 } 8542 8543 _createClass(RangeLoader, [{ 8544 key: 'destroy', 8545 value: function destroy() { 8546 if (this.isWorking()) { 8547 this.abort(); 8548 } 8549 if (this._xhr) { 8550 this._xhr.onreadystatechange = null; 8551 this._xhr.onprogress = null; 8552 this._xhr.onload = null; 8553 this._xhr.onerror = null; 8554 this._xhr = null; 8555 } 8556 _get(RangeLoader.prototype.__proto__ || Object.getPrototypeOf(RangeLoader.prototype), 'destroy', this).call(this); 8557 } 8558 }, { 8559 key: 'open', 8560 value: function open(dataSource, range) { 8561 this._dataSource = dataSource; 8562 this._range = range; 8563 this._status = _loader.LoaderStatus.kConnecting; 8564 8565 var useRefTotalLength = false; 8566 if (this._dataSource.filesize != undefined && this._dataSource.filesize !== 0) { 8567 useRefTotalLength = true; 8568 this._totalLength = this._dataSource.filesize; 8569 } 8570 8571 if (!this._totalLengthReceived && !useRefTotalLength) { 8572 // We need total filesize 8573 this._waitForTotalLength = true; 8574 this._internalOpen(this._dataSource, { from: 0, to: -1 }); 8575 } else { 8576 // We have filesize, start loading 8577 this._openSubRange(); 8578 } 8579 } 8580 }, { 8581 key: '_openSubRange', 8582 value: function _openSubRange() { 8583 var chunkSize = this._currentChunkSizeKB * 1024; 8584 8585 var from = this._range.from + this._receivedLength; 8586 var to = from + chunkSize; 8587 8588 if (this._contentLength != null) { 8589 if (to - this._range.from >= this._contentLength) { 8590 to = this._range.from + this._contentLength - 1; 8591 } 8592 } 8593 8594 this._currentRequestRange = { from: from, to: to }; 8595 this._internalOpen(this._dataSource, this._currentRequestRange); 8596 } 8597 }, { 8598 key: '_internalOpen', 8599 value: function _internalOpen(dataSource, range) { 8600 this._lastTimeLoaded = 0; 8601 8602 var sourceURL = dataSource.url; 8603 if (this._config.reuseRedirectedURL) { 8604 if (this._currentRedirectedURL != undefined) { 8605 sourceURL = this._currentRedirectedURL; 8606 } else if (dataSource.redirectedURL != undefined) { 8607 sourceURL = dataSource.redirectedURL; 8608 } 8609 } 8610 8611 var seekConfig = this._seekHandler.getConfig(sourceURL, range); 8612 this._currentRequestURL = seekConfig.url; 8613 8614 var xhr = this._xhr = new XMLHttpRequest(); 8615 xhr.open('GET', seekConfig.url, true); 8616 xhr.responseType = 'arraybuffer'; 8617 xhr.onreadystatechange = this._onReadyStateChange.bind(this); 8618 xhr.onprogress = this._onProgress.bind(this); 8619 xhr.onload = this._onLoad.bind(this); 8620 xhr.onerror = this._onXhrError.bind(this); 8621 8622 if (dataSource.withCredentials) { 8623 xhr.withCredentials = true; 8624 } 8625 8626 if (_typeof(seekConfig.headers) === 'object') { 8627 var headers = seekConfig.headers; 8628 8629 for (var key in headers) { 8630 if (headers.hasOwnProperty(key)) { 8631 xhr.setRequestHeader(key, headers[key]); 8632 } 8633 } 8634 } 8635 8636 // add additional headers 8637 if (_typeof(this._config.headers) === 'object') { 8638 var _headers = this._config.headers; 8639 8640 for (var _key in _headers) { 8641 if (_headers.hasOwnProperty(_key)) { 8642 xhr.setRequestHeader(_key, _headers[_key]); 8643 } 8644 } 8645 } 8646 8647 xhr.send(); 8648 } 8649 }, {
8650 key: 'abort', 8651 value: function abort() { 8652 this._requestAbort = true; 8653 this._internalAbort(); 8654 this._status = _loader.LoaderStatus.kComplete; 8655 } 8656 }, { 8657 key: '_internalAbort', 8658 value: function _internalAbort() { 8659 if (this._xhr) { 8660 this._xhr.onreadystatechange = null; 8661 this._xhr.onprogress = null; 8662 this._xhr.onload = null; 8663 this._xhr.onerror = null; 8664 this._xhr.abort(); 8665 this._xhr = null; 8666 } 8667 } 8668 }, { 8669 key: '_onReadyStateChange', 8670 value: function _onReadyStateChange(e) { 8671 var xhr = e.target; 8672 8673 if (xhr.readyState === 2) { 8674 // HEADERS_RECEIVED 8675 if (xhr.responseURL != undefined) { 8676 // if the browser support this property 8677 var redirectedURL = this._seekHandler.removeURLParameters(xhr.responseURL); 8678 if (xhr.responseURL !== this._currentRequestURL && redirectedURL !== this._currentRedirectedURL) { 8679 this._currentRedirectedURL = redirectedURL; 8680 if (this._onURLRedirect) { 8681 this._onURLRedirect(redirectedURL); 8682 } 8683 } 8684 } 8685 8686 if (xhr.status >= 200 && xhr.status <= 299) { 8687 if (this._waitForTotalLength) { 8688 return; 8689 } 8690 this._status = _loader.LoaderStatus.kBuffering; 8691 } else { 8692 this._status = _loader.LoaderStatus.kError; 8693 if (this._onError) { 8694 this._onError(_loader.LoaderErrors.HTTP_STATUS_CODE_INVALID, { code: xhr.status, msg: xhr.statusText }); 8695 } else { 8696 throw new _exception.RuntimeException('RangeLoader: Http code invalid, ' + xhr.status + ' ' + xhr.statusText); 8697 } 8698 } 8699 } 8700 } 8701 }, { 8702 key: '_onProgress', 8703 value: function _onProgress(e) { 8704 if (this._status === _loader.LoaderStatus.kError) { 8705 // Ignore error response 8706 return; 8707 } 8708 8709 if (this._contentLength === null) { 8710 var openNextRange = false; 8711 8712 if (this._waitForTotalLength) { 8713 this._waitForTotalLength = false; 8714 this._totalLengthReceived = true; 8715 openNextRange = true; 8716 8717 var total = e.total; 8718 this._internalAbort(); 8719 if (total != null & total !== 0) { 8720 this._totalLength = total; 8721 } 8722 } 8723 8724 // calculate currrent request range's contentLength 8725 if (this._range.to === -1) { 8726 this._contentLength = this._totalLength - this._range.from; 8727 } else { 8728 // to !== -1 8729 this._contentLength = this._range.to - this._range.from + 1; 8730 } 8731 8732 if (openNextRange) { 8733 this._openSubRange(); 8734 return; 8735 } 8736 if (this._onContentLengthKnown) { 8737 this._onContentLengthKnown(this._contentLength); 8738 } 8739 } 8740 8741 var delta = e.loaded - this._lastTimeLoaded; 8742 this._lastTimeLoaded = e.loaded; 8743 this._speedSampler.addBytes(delta); 8744 } 8745 }, { 8746 key: '_normalizeSpeed', 8747 value: function _normalizeSpeed(input) { 8748 var list = this._chunkSizeKBList; 8749 var last = list.length - 1; 8750 var mid = 0; 8751 var lbound = 0; 8752 var ubound = last; 8753 8754 if (input < list[0]) { 8755 return list[0]; 8756 } 8757 8758 while (lbound <= ubound) { 8759 mid = lbound + Math.floor((ubound - lbound) / 2); 8760 if (mid === last || input >= list[mid] && input < list[mid + 1]) { 8761 return list[mid]; 8762 } else if (list[mid] < input) { 8763 lbound = mid + 1; 8764 } else { 8765 ubound = mid - 1; 8766 } 8767 } 8768 } 8769 }, {
8770 key: '_onLoad', 8771 value: function _onLoad(e) { 8772 if (this._status === _loader.LoaderStatus.kError) { 8773 // Ignore error response 8774 return; 8775 } 8776 8777 if (this._waitForTotalLength) { 8778 this._waitForTotalLength = false; 8779 return; 8780 } 8781 8782 this._lastTimeLoaded = 0; 8783 var KBps = this._speedSampler.lastSecondKBps; 8784 if (KBps === 0) { 8785 this._zeroSpeedChunkCount++; 8786 if (this._zeroSpeedChunkCount >= 3) { 8787 // Try get currentKBps after 3 chunks 8788 KBps = this._speedSampler.currentKBps; 8789 } 8790 } 8791 8792 if (KBps !== 0) { 8793 var normalized = this._normalizeSpeed(KBps); 8794 if (this._currentSpeedNormalized !== normalized) { 8795 this._currentSpeedNormalized = normalized; 8796 this._currentChunkSizeKB = normalized; 8797 } 8798 } 8799 8800 var chunk = e.target.response; 8801 var byteStart = this._range.from + this._receivedLength; 8802 this._receivedLength += chunk.byteLength; 8803 8804 var reportComplete = false; 8805 8806 if (this._contentLength != null && this._receivedLength < this._contentLength) { 8807 // continue load next chunk 8808 this._openSubRange(); 8809 } else { 8810 reportComplete = true; 8811 } 8812 8813 // dispatch received chunk 8814 if (this._onDataArrival) { 8815 this._onDataArrival(chunk, byteStart, this._receivedLength); 8816 } 8817 8818 if (reportComplete) { 8819 this._status = _loader.LoaderStatus.kComplete; 8820 if (this._onComplete) { 8821 this._onComplete(this._range.from, this._range.from + this._receivedLength - 1); 8822 } 8823 } 8824 } 8825 }, { 8826 key: '_onXhrError', 8827 value: function _onXhrError(e) { 8828 this._status = _loader.LoaderStatus.kError; 8829 var type = 0; 8830 var info = null; 8831 8832 if (this._contentLength && this._receivedLength > 0 && this._receivedLength < this._contentLength) { 8833 type = _loader.LoaderErrors.EARLY_EOF; 8834 info = { code: -1, msg: 'RangeLoader meet Early-Eof' }; 8835 } else { 8836 type = _loader.LoaderErrors.EXCEPTION; 8837 info = { code: -1, msg: e.constructor.name + ' ' + e.type }; 8838 } 8839 8840 if (this._onError) { 8841 this._onError(type, info); 8842 } else { 8843 throw new _exception.RuntimeException(info.msg); 8844 } 8845 } 8846 }, { 8847 key: 'currentSpeed', 8848 get: function get() { 8849 return this._speedSampler.lastSecondKBps; 8850 } 8851 }]); 8852 8853 return RangeLoader; 8854}(_loader.BaseLoader); 8855 8856exports.default = RangeLoader; 8857 8858},{"../utils/exception.js":40,"../utils/logger.js":41,"./loader.js":24,"./speed-sampler.js":27}],32:[function(_dereq_,module,exports){ 8859'use strict'; 8860 8861Object.defineProperty(exports, "__esModule", { 8862 value: true 8863}); 8864 8865var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 8866 8867var _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; }; }(); /* 8868 * Copyright (C) 2016 Bilibili. All Rights Reserved. 8869 * 8870 * @author zheng qian <[email protected]> 8871 * 8872 * Licensed under the Apache License, Version 2.0 (the "License"); 8873 * you may
8873not use this file except in compliance with the License. 8874 * You may obtain a copy of the License at 8875 * 8876 * http://www.apache.org/licenses/LICENSE-2.0 8877 * 8878 * Unless required by applicable law or agreed to in writing, software 8879 * distributed under the License is distributed on an "AS IS" BASIS, 8880 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8881 * See the License for the specific language governing permissions and 8882 * limitations under the License. 8883 */ 8884 8885var _events = _dereq_('events'); 8886 8887var _events2 = _interopRequireDefault(_events); 8888 8889var _logger = _dereq_('../utils/logger.js'); 8890 8891var _logger2 = _interopRequireDefault(_logger); 8892 8893var _browser = _dereq_('../utils/browser.js'); 8894 8895var _browser2 = _interopRequireDefault(_browser); 8896 8897var _playerEvents = _dereq_('./player-events.js'); 8898 8899var _playerEvents2 = _interopRequireDefault(_playerEvents); 8900 8901var _transmuxer = _dereq_('../core/transmuxer.js'); 8902 8903var _transmuxer2 = _interopRequireDefault(_transmuxer); 8904 8905var _transmuxingEvents = _dereq_('../core/transmuxing-events.js'); 8906 8907var _transmuxingEvents2 = _interopRequireDefault(_transmuxingEvents); 8908 8909var _mseController = _dereq_('../core/mse-controller.js'); 8910 8911var _mseController2 = _interopRequireDefault(_mseController); 8912 8913var _mseEvents = _dereq_('../core/mse-events.js'); 8914 8915var _mseEvents2 = _interopRequireDefault(_mseEvents); 8916 8917var _playerErrors = _dereq_('./player-errors.js'); 8918 8919var _config = _dereq_('../config.js'); 8920 8921var _exception = _dereq_('../utils/exception.js'); 8922 8923function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 8924 8925function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 8926 8927var FlvPlayer = function () { 8928 function FlvPlayer(mediaDataSource, config) { 8929 _classCallCheck(this, FlvPlayer); 8930 8931 this.TAG = 'FlvPlayer'; 8932 this._type = 'FlvPlayer'; 8933 this._emitter = new _events2.default(); 8934 8935 this._config = (0, _config.createDefaultConfig)(); 8936 if ((typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object') { 8937 Object.assign(this._config, config); 8938 } 8939 8940 if (mediaDataSource.type.toLowerCase() !== 'flv') { 8941 throw new _exception.InvalidArgumentException('FlvPlayer requires an flv MediaDataSource input!'); 8942 } 8943 8944 if (mediaDataSource.isLive === true) { 8945 this._config.isLive = true; 8946 } 8947 8948 this.e = { 8949 onvLoadedMetadata: this._onvLoadedMetadata.bind(this), 8950 onvSeeking: this._onvSeeking.bind(this), 8951 onvCanPlay: this._onvCanPlay.bind(this), 8952 onvStalled: this._onvStalled.bind(this), 8953 onvProgress: this._onvProgress.bind(this) 8954 }; 8955 8956 if (self.performance && self.performance.now) { 8957 this._now = self.performance.now.bind(self.performance); 8958 } else { 8959 this._now = Date.now; 8960 } 8961 8962 this._pendingSeekTime = null; // in seconds 8963 this._requestSetTime = false;
8964 this._seekpointRecord = null; 8965 this._progressChecker = null; 8966 8967 this._mediaDataSource = mediaDataSource; 8968 this._mediaElement = null; 8969 this._msectl = null; 8970 this._transmuxer = null; 8971 8972 this._mseSourceOpened = false; 8973 this._hasPendingLoad = false; 8974 this._receivedCanPlay = false; 8975 8976 this._mediaInfo = null; 8977 this._statisticsInfo = null; 8978 8979 var chromeNeedIDRFix = _browser2.default.chrome && (_browser2.default.version.major < 50 || _browser2.default.version.major === 50 && _browser2.default.version.build < 2661); 8980 this._alwaysSeekKeyframe = chromeNeedIDRFix || _browser2.default.msedge || _browser2.default.msie ? true : false; 8981 8982 if (this._alwaysSeekKeyframe) { 8983 this._config.accurateSeek = false; 8984 } 8985 } 8986 8987 _createClass(FlvPlayer, [{ 8988 key: 'destroy', 8989 value: function destroy() { 8990 if (this._progressChecker != null) { 8991 window.clearInterval(this._progressChecker); 8992 this._progressChecker = null; 8993 } 8994 if (this._transmuxer) { 8995 this.unload(); 8996 } 8997 if (this._mediaElement) { 8998 this.detachMediaElement(); 8999 } 9000 this.e = null; 9001 this._mediaDataSource = null; 9002 9003 this._emitter.removeAllListeners(); 9004 this._emitter = null; 9005 } 9006 }, { 9007 key: 'on', 9008 value: function on(event, listener) { 9009 var _this = this; 9010 9011 if (event === _playerEvents2.default.MEDIA_INFO) { 9012 if (this._mediaInfo != null) { 9013 Promise.resolve().then(function () { 9014 _this._emitter.emit(_playerEvents2.default.MEDIA_INFO, _this.mediaInfo); 9015 }); 9016 } 9017 } else if (event === _playerEvents2.default.STATISTICS_INFO) { 9018 if (this._statisticsInfo != null) { 9019 Promise.resolve().then(function () { 9020 _this._emitter.emit(_playerEvents2.default.STATISTICS_INFO, _this.statisticsInfo); 9021 }); 9022 } 9023 } 9024 this._emitter.addListener(event, listener); 9025 } 9026 }, { 9027 key: 'off', 9028 value: function off(event, listener) { 9029 this._emitter.removeListener(event, listener); 9030 } 9031 }, { 9032 key: 'attachMediaElement', 9033 value: function attachMediaElement(mediaElement) { 9034 var _this2 = this; 9035 9036 this._mediaElement = mediaElement; 9037 mediaElement.addEventListener('loadedmetadata', this.e.onvLoadedMetadata); 9038 mediaElement.addEventListener('seeking', this.e.onvSeeking); 9039 mediaElement.addEventListener('canplay', this.e.onvCanPlay); 9040 mediaElement.addEventListener('stalled', this.e.onvStalled); 9041 mediaElement.addEventListener('progress', this.e.onvProgress); 9042 9043 this._msectl = new _mseController2.default(this._config); 9044 9045 this._msectl.on(_mseEvents2.default.UPDATE_END, this._onmseUpdateEnd.bind(this)); 9046 this._msectl.on(_mseEvents2.default.BUFFER_FULL, this._onmseBufferFull.bind(this)); 9047 this._msectl.on(_mseEvents2.default.SOURCE_OPEN, function () { 9048 _this2._mseSourceOpened = true; 9049 if (_this2._hasPendingLoad) { 9050 _this2._hasPendingLoad = false; 9051 _this2.load(); 9052 } 9053 }); 9054 this._msectl.on(_mseEvents2.default.ERROR, function (info) { 9055 _this2._emitter.emit(_playerEvents2.default.ERROR, _playerErrors.ErrorTypes.MEDIA_ERROR, _playerErrors.ErrorDetails.MEDIA_MSE_ERROR, info); 9056 }); 9057 9058 this._msectl.attachMediaElement(mediaElement); 9059 9060 if (this._pendingSeekTime != null) { 9061 try { 9062 mediaElement.currentTime = this._pendingSeekTime; 9063 this._pendingSeekTime = null; 9064 } catch (e) { 9065 // IE11 may throw InvalidStateError if readyState === 0 9066 // We can defer set currentTime operation after loadedmetadata 9067 } 9068 } 9069 } 9070 }, {
vendor: 5,054 bytes, lines 9071-9168
9071 key: 'detachMediaElement', 9072 value: function detachMediaElement() { 9073 if (this._mediaElement) { 9074 this._msectl.detachMediaElement(); 9075 this._mediaElement.removeEventListener('loadedmetadata', this.e.onvLoadedMetadata); 9076 this._mediaElement.removeEventListener('seeking', this.e.onvSeeking); 9077 this._mediaElement.removeEventListener('canplay', this.e.onvCanPlay); 9078 this._mediaElement.removeEventListener('stalled', this.e.onvStalled); 9079 this._mediaElement.removeEventListener('progress', this.e.onvProgress); 9080 this._mediaElement = null; 9081 } 9082 if (this._msectl) { 9083 this._msectl.destroy(); 9084 this._msectl = null; 9085 } 9086 } 9087 }, { 9088 key: 'load', 9089 value: function load() { 9090 var _this3 = this; 9091 9092 if (!this._mediaElement) { 9093 throw new _exception.IllegalStateException('HTMLMediaElement must be attached before load()!'); 9094 } 9095 if (this._transmuxer) { 9096 throw new _exception.IllegalStateException('FlvPlayer.load() has been called, please call unload() first!'); 9097 } 9098 if (this._hasPendingLoad) { 9099 return; 9100 } 9101 9102 if (this._config.deferLoadAfterSourceOpen && this._mseSourceOpened === false) { 9103 this._hasPendingLoad = true; 9104 return; 9105 } 9106 9107 if (this._mediaElement.readyState > 0) { 9108 this._requestSetTime = true; 9109 // IE11 may throw InvalidStateError if readyState === 0 9110 this._mediaElement.currentTime = 0; 9111 } 9112 9113 this._transmuxer = new _transmuxer2.default(this._mediaDataSource, this._config); 9114 9115 this._transmuxer.on(_transmuxingEvents2.default.INIT_SEGMENT, function (type, is) { 9116 _this3._msectl.appendInitSegment(is); 9117 }); 9118 this._transmuxer.on(_transmuxingEvents2.default.MEDIA_SEGMENT, function (type, ms) { 9119 _this3._msectl.appendMediaSegment(ms); 9120 9121 // lazyLoad check 9122 if (_this3._config.lazyLoad && !_this3._config.isLive) { 9123 var currentTime = _this3._mediaElement.currentTime; 9124 if (ms.info.endDts >= (currentTime + _this3._config.lazyLoadMaxDuration) * 1000) { 9125 if (_this3._progressChecker == null) { 9126 _logger2.default.v(_this3.TAG, 'Maximum buffering duration exceeded, suspend transmuxing task'); 9127 _this3._suspendTransmuxer(); 9128 } 9129 } 9130 } 9131 }); 9132 this._transmuxer.on(_transmuxingEvents2.default.LOADING_COMPLETE, function () { 9133 _this3._msectl.endOfStream(); 9134 _this3._emitter.emit(_playerEvents2.default.LOADING_COMPLETE); 9135 }); 9136 this._transmuxer.on(_transmuxingEvents2.default.RECOVERED_EARLY_EOF, function () { 9137 _this3._emitter.emit(_playerEvents2.default.RECOVERED_EARLY_EOF); 9138 }); 9139 this._transmuxer.on(_transmuxingEvents2.default.IO_ERROR, function (detail, info) { 9140 _this3._emitter.emit(_playerEvents2.default.ERROR, _playerErrors.ErrorTypes.NETWORK_ERROR, detail, info); 9141 }); 9142 this._transmuxer.on(_transmuxingEvents2.default.DEMUX_ERROR, function (detail, info) { 9143 _this3._emitter.emit(_playerEvents2.default.ERROR, _playerErrors.ErrorTypes.MEDIA_ERROR, detail, { code: -1, msg: info }); 9144 }); 9145 this._transmuxer.on(_transmuxingEvents2.default.MEDIA_INFO, function (mediaInfo) { 9146 _this3._mediaInfo = mediaInfo; 9147 _this3._emitter.emit(_playerEvents2.default.MEDIA_INFO, Object.assign({}, mediaInfo)); 9148 }); 9149 this._transmuxer.on(_transmuxingEvents2.default.METADATA_ARRIVED, function (metadata) { 9150 _this3._emitter.emit(_playerEvents2.default.METADATA_ARRIVED, metadata); 9151 }); 9152 this._transmuxer.on(_transmuxingEvents2.default.SCRIPTDATA_ARRIVED, function (data) { 9153 _this3._emitter.emit(_playerEvents2.default.SCRIPTDATA_ARRIVED, data); 9154 }); 9155 this._transmuxer.on(_transmuxingEvents2.default.STATISTICS_INFO, function (statInfo) { 9156 _this3._statisticsInfo = _this3._fillStatisticsInfo(statInfo); 9157 _this3._emitter.emit(_playerEvents2.default.STATISTICS_INFO, Object.assign({}, _this3._statisticsInfo)); 9158 }); 9159 this._transmuxer.on(_transmuxingEvents2.default.RECOMMEND_SEEKPOINT, function (milliseconds) { 9160 if (_this3._mediaElement && !_this3._config.accurateSeek) { 9161 _this3._requestSetTime = true; 9162 _this3._mediaElement.currentTime = milliseconds / 1000; 9163 } 9164 }); 9165 9166 this._transmuxer.open(); 9167 } 9168 }, {
9169 key: 'unload', 9170 value: function unload() { 9171 if (this._mediaElement) { 9172 this._mediaElement.pause(); 9173 } 9174 if (this._msectl) { 9175 this._msectl.seek(0); 9176 } 9177 if (this._transmuxer) { 9178 this._transmuxer.close(); 9179 this._transmuxer.destroy(); 9180 this._transmuxer = null; 9181 } 9182 } 9183 }, { 9184 key: 'play', 9185 value: function play() { 9186 return this._mediaElement.play(); 9187 } 9188 }, { 9189 key: 'pause', 9190 value: function pause() { 9191 this._mediaElement.pause(); 9192 } 9193 }, { 9194 key: '_fillStatisticsInfo', 9195 value: function _fillStatisticsInfo(statInfo) { 9196 statInfo.playerType = this._type; 9197 9198 if (!(this._mediaElement instanceof HTMLVideoElement)) { 9199 return statInfo; 9200 } 9201 9202 var hasQualityInfo = true; 9203 var decoded = 0; 9204 var dropped = 0; 9205 9206 if (this._mediaElement.getVideoPlaybackQuality) { 9207 var quality = this._mediaElement.getVideoPlaybackQuality(); 9208 decoded = quality.totalVideoFrames; 9209 dropped = quality.droppedVideoFrames; 9210 } else if (this._mediaElement.webkitDecodedFrameCount != undefined) { 9211 decoded = this._mediaElement.webkitDecodedFrameCount; 9212 dropped = this._mediaElement.webkitDroppedFrameCount; 9213 } else { 9214 hasQualityInfo = false; 9215 } 9216 9217 if (hasQualityInfo) { 9218 statInfo.decodedFrames = decoded; 9219 statInfo.droppedFrames = dropped; 9220 } 9221 9222 return statInfo; 9223 } 9224 }, { 9225 key: '_onmseUpdateEnd', 9226 value: function _onmseUpdateEnd() { 9227 if (!this._config.lazyLoad || this._config.isLive) { 9228 return; 9229 } 9230 9231 var buffered = this._mediaElement.buffered; 9232 var currentTime = this._mediaElement.currentTime; 9233 var currentRangeStart = 0; 9234 var currentRangeEnd = 0; 9235 9236 for (var i = 0; i < buffered.length; i++) { 9237 var start = buffered.start(i); 9238 var end = buffered.end(i); 9239 if (start <= currentTime && currentTime < end) { 9240 currentRangeStart = start; 9241 currentRangeEnd = end; 9242 break; 9243 } 9244 } 9245 9246 if (currentRangeEnd >= currentTime + this._config.lazyLoadMaxDuration && this._progressChecker == null) { 9247 _logger2.default.v(this.TAG, 'Maximum buffering duration exceeded, suspend transmuxing task'); 9248 this._suspendTransmuxer(); 9249 } 9250 } 9251 }, { 9252 key: '_onmseBufferFull', 9253 value: function _onmseBufferFull() { 9254 _logger2.default.v(this.TAG, 'MSE SourceBuffer is full, suspend transmuxing task'); 9255 if (this._progressChecker == null) { 9256 this._suspendTransmuxer(); 9257 } 9258 } 9259 }, { 9260 key: '_suspendTransmuxer', 9261 value: function _suspendTransmuxer() { 9262 if (this._transmuxer) { 9263 this._transmuxer.pause(); 9264 9265 if (this._progressChecker == null) { 9266 this._progressChecker = window.setInterval(this._checkProgressAndResume.bind(this), 1000); 9267 } 9268 } 9269 } 9270 }, { 9271 key: '_checkProgressAndResume', 9272 value: function _checkProgressAndResume() { 9273 var currentTime = this._mediaElement.currentTime; 9274 var buffered = this._mediaElement.buffered; 9275 9276 var needResume = false; 9277 9278 for (var i = 0; i < buffered.length; i++) { 9279 var from = buffered.start(i); 9280 var to = buffered.end(i); 9281 if (currentTime >= from && currentTime < to) { 9282 if (currentTime >= to - this._config.lazyLoadRecoverDuration) { 9283 needResume = true; 9284 } 9285 break; 9286 } 9287 } 9288 9289 if (needResume) { 9290 window.clearInterval(this._progressChecker); 9291 this._progressChecker = null; 9292 if (needResume) { 9293 _logger2.default.v(this.TAG, 'Continue loading from paused position'); 9294 this._transmuxer.resume(); 9295 } 9296 } 9297 } 9298 }, {
vendor: 4,310 bytes, lines 9299-9392
9299 key: '_isTimepointBuffered', 9300 value: function _isTimepointBuffered(seconds) { 9301 var buffered = this._mediaElement.buffered; 9302 9303 for (var i = 0; i < buffered.length; i++) { 9304 var from = buffered.start(i); 9305 var to = buffered.end(i); 9306 if (seconds >= from && seconds < to) { 9307 return true; 9308 } 9309 } 9310 return false; 9311 } 9312 }, { 9313 key: '_internalSeek', 9314 value: function _internalSeek(seconds) { 9315 var directSeek = this._isTimepointBuffered(seconds); 9316 9317 var directSeekBegin = false; 9318 var directSeekBeginTime = 0; 9319 9320 if (seconds < 1.0 && this._mediaElement.buffered.length > 0) { 9321 var videoBeginTime = this._mediaElement.buffered.start(0); 9322 if (videoBeginTime < 1.0 && seconds < videoBeginTime || _browser2.default.safari) { 9323 directSeekBegin = true; 9324 // also workaround for Safari: Seek to 0 may cause video stuck, use 0.1 to avoid 9325 directSeekBeginTime = _browser2.default.safari ? 0.1 : videoBeginTime; 9326 } 9327 } 9328 9329 if (directSeekBegin) { 9330 // seek to video begin, set currentTime directly if beginPTS buffered 9331 this._requestSetTime = true; 9332 this._mediaElement.currentTime = directSeekBeginTime; 9333 } else if (directSeek) { 9334 // buffered position 9335 if (!this._alwaysSeekKeyframe) { 9336 this._requestSetTime = true; 9337 this._mediaElement.currentTime = seconds; 9338 } else { 9339 var idr = this._msectl.getNearestKeyframe(Math.floor(seconds * 1000)); 9340 this._requestSetTime = true; 9341 if (idr != null) { 9342 this._mediaElement.currentTime = idr.dts / 1000; 9343 } else { 9344 this._mediaElement.currentTime = seconds; 9345 } 9346 } 9347 if (this._progressChecker != null) { 9348 this._checkProgressAndResume(); 9349 } 9350 } else { 9351 if (this._progressChecker != null) { 9352 window.clearInterval(this._progressChecker); 9353 this._progressChecker = null; 9354 } 9355 this._msectl.seek(seconds); 9356 this._transmuxer.seek(Math.floor(seconds * 1000)); // in milliseconds 9357 // no need to set mediaElement.currentTime if non-accurateSeek, 9358 // just wait for the recommend_seekpoint callback 9359 if (this._config.accurateSeek) { 9360 this._requestSetTime = true; 9361 this._mediaElement.currentTime = seconds; 9362 } 9363 } 9364 } 9365 }, { 9366 key: '_checkAndApplyUnbufferedSeekpoint', 9367 value: function _checkAndApplyUnbufferedSeekpoint() { 9368 if (this._seekpointRecord) { 9369 if (this._seekpointRecord.recordTime <= this._now() - 100) { 9370 var target = this._mediaElement.currentTime; 9371 this._seekpointRecord = null; 9372 if (!this._isTimepointBuffered(target)) { 9373 if (this._progressChecker != null) { 9374 window.clearTimeout(this._progressChecker); 9375 this._progressChecker = null; 9376 } 9377 // .currentTime is consists with .buffered timestamp 9378 // Chrome/Edge use DTS, while FireFox/Safari use PTS 9379 this._msectl.seek(target); 9380 this._transmuxer.seek(Math.floor(target * 1000)); 9381 // set currentTime if accurateSeek, or wait for recommend_seekpoint callback 9382 if (this._config.accurateSeek) { 9383 this._requestSetTime = true; 9384 this._mediaElement.currentTime = target; 9385 } 9386 } 9387 } else { 9388 window.setTimeout(this._checkAndApplyUnbufferedSeekpoint.bind(this), 50); 9389 } 9390 } 9391 } 9392 }, {
9393 key: '_checkAndResumeStuckPlayback', 9394 value: function _checkAndResumeStuckPlayback(stalled) { 9395 var media = this._mediaElement; 9396 if (stalled || !this._receivedCanPlay || media.readyState < 2) { 9397 // HAVE_CURRENT_DATA 9398 var buffered = media.buffered; 9399 if (buffered.length > 0 && media.currentTime < buffered.start(0)) { 9400 _logger2.default.w(this.TAG, 'Playback seems stuck at ' + media.currentTime + ', seek to ' + buffered.start(0)); 9401 this._requestSetTime = true; 9402 this._mediaElement.currentTime = buffered.start(0); 9403 this._mediaElement.removeEventListener('progress', this.e.onvProgress); 9404 } 9405 } else { 9406 // Playback didn't stuck, remove progress event listener 9407 this._mediaElement.removeEventListener('progress', this.e.onvProgress); 9408 } 9409 } 9410 }, { 9411 key: '_onvLoadedMetadata', 9412 value: function _onvLoadedMetadata(e) { 9413 if (this._pendingSeekTime != null) { 9414 this._mediaElement.currentTime = this._pendingSeekTime; 9415 this._pendingSeekTime = null; 9416 } 9417 } 9418 }, { 9419 key: '_onvSeeking', 9420 value: function _onvSeeking(e) { 9421 // handle seeking request from browser's progress bar 9422 var target = this._mediaElement.currentTime; 9423 var buffered = this._mediaElement.buffered; 9424 9425 if (this._requestSetTime) { 9426 this._requestSetTime = false; 9427 return; 9428 } 9429 9430 if (target < 1.0 && buffered.length > 0) { 9431 // seek to video begin, set currentTime directly if beginPTS buffered 9432 var videoBeginTime = buffered.start(0); 9433 if (videoBeginTime < 1.0 && target < videoBeginTime || _browser2.default.safari) { 9434 this._requestSetTime = true; 9435 // also workaround for Safari: Seek to 0 may cause video stuck, use 0.1 to avoid 9436 this._mediaElement.currentTime = _browser2.default.safari ? 0.1 : videoBeginTime; 9437 return; 9438 } 9439 } 9440 9441 if (this._isTimepointBuffered(target)) { 9442 if (this._alwaysSeekKeyframe) { 9443 var idr = this._msectl.getNearestKeyframe(Math.floor(target * 1000)); 9444 if (idr != null) { 9445 this._requestSetTime = true; 9446 this._mediaElement.currentTime = idr.dts / 1000; 9447 } 9448 } 9449 if (this._progressChecker != null) { 9450 this._checkProgressAndResume(); 9451 } 9452 return; 9453 } 9454 9455 this._seekpointRecord = { 9456 seekPoint: target, 9457 recordTime: this._now() 9458 }; 9459 window.setTimeout(this._checkAndApplyUnbufferedSeekpoint.bind(this), 50); 9460 } 9461 }, { 9462 key: '_onvCanPlay', 9463 value: function _onvCanPlay(e) { 9464 this._receivedCanPlay = true; 9465 this._mediaElement.removeEventListener('canplay', this.e.onvCanPlay); 9466 } 9467 }, { 9468 key: '_onvStalled', 9469 value: function _onvStalled(e) { 9470 this._checkAndResumeStuckPlayback(true); 9471 } 9472 }, { 9473 key: '_onvProgress', 9474 value: function _onvProgress(e) { 9475 this._checkAndResumeStuckPlayback(); 9476 } 9477 }, { 9478 key: 'type', 9479 get: function get() { 9480 return this._type; 9481 } 9482 }, { 9483 key: 'buffered', 9484 get: function get() { 9485 return this._mediaElement.buffered; 9486 } 9487 }, { 9488 key: 'duration', 9489 get: function get() { 9490 return this._mediaElement.duration; 9491 } 9492 }, { 9493 key: 'volume', 9494 get: function get() { 9495 return this._mediaElement.volume; 9496 }, 9497 set: function set(value) { 9498 this._mediaElement.volume = value; 9499 } 9500 }, { 9501 key: 'muted', 9502 get: function get() { 9503 return this._mediaElement.muted; 9504 }, 9505 set: function set(muted) { 9506 this._mediaElement.muted = muted; 9507 } 9508 }, {
9509 key: 'currentTime', 9510 get: function get() { 9511 if (this._mediaElement) { 9512 return this._mediaElement.currentTime; 9513 } 9514 return 0; 9515 }, 9516 set: function set(seconds) { 9517 if (this._mediaElement) { 9518 this._internalSeek(seconds); 9519 } else { 9520 this._pendingSeekTime = seconds; 9521 } 9522 } 9523 }, { 9524 key: 'mediaInfo', 9525 get: function get() { 9526 return Object.assign({}, this._mediaInfo); 9527 } 9528 }, { 9529 key: 'statisticsInfo', 9530 get: function get() { 9531 if (this._statisticsInfo == null) { 9532 this._statisticsInfo = {}; 9533 } 9534 this._statisticsInfo = this._fillStatisticsInfo(this._statisticsInfo); 9535 return Object.assign({}, this._statisticsInfo); 9536 } 9537 }]); 9538 9539 return FlvPlayer; 9540}(); 9541 9542exports.default = FlvPlayer; 9543 9544},{"../config.js":5,"../core/mse-controller.js":9,"../core/mse-events.js":10,"../core/transmuxer.js":11,"../core/transmuxing-events.js":13,"../utils/browser.js":39,"../utils/exception.js":40,"../utils/logger.js":41,"./player-errors.js":34,"./player-events.js":35,"events":2}],33:[function(_dereq_,module,exports){ 9545'use strict'; 9546 9547Object.defineProperty(exports, "__esModule", { 9548 value: true 9549}); 9550 9551var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 9552 9553var _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; }; }(); /* 9554 * Copyright (C) 2016 Bilibili. All Rights Reserved. 9555 * 9556 * @author zheng qian <[email protected]> 9557 * 9558 * Licensed under the Apache License, Version 2.0 (the "License"); 9559 * you may
9559not use this file except in compliance with the License. 9560 * You may obtain a copy of the License at 9561 * 9562 * http://www.apache.org/licenses/LICENSE-2.0 9563 * 9564 * Unless required by applicable law or agreed to in writing, software 9565 * distributed under the License is distributed on an "AS IS" BASIS, 9566 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9567 * See the License for the specific language governing permissions and 9568 * limitations under the License. 9569 */ 9570 9571var _events = _dereq_('events'); 9572 9573var _events2 = _interopRequireDefault(_events); 9574 9575var _playerEvents = _dereq_('./player-events.js'); 9576 9577var _playerEvents2 = _interopRequireDefault(_playerEvents); 9578 9579var _config = _dereq_('../config.js'); 9580 9581var _exception = _dereq_('../utils/exception.js'); 9582 9583function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 9584 9585function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 9586 9587// Player wrapper for browser's native player (HTMLVideoElement) without MediaSource src. 9588var NativePlayer = function () { 9589 function NativePlayer(mediaDataSource, config) { 9590 _classCallCheck(this, NativePlayer); 9591 9592 this.TAG = 'NativePlayer'; 9593 this._type = 'NativePlayer'; 9594 this._emitter = new _events2.default(); 9595 9596 this._config = (0, _config.createDefaultConfig)(); 9597 if ((typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object') { 9598 Object.assign(this._config, config); 9599 } 9600 9601 if (mediaDataSource.type.toLowerCase() === 'flv') { 9602 throw new _exception.InvalidArgumentException('NativePlayer does\'t support flv MediaDataSource input!'); 9603 } 9604 if (mediaDataSource.hasOwnProperty('segments')) { 9605 throw new _exception.InvalidArgumentException('NativePlayer(' + mediaDataSource.type + ') doesn\'t support multipart playback!'); 9606 } 9607 9608 this.e = { 9609 onvLoadedMetadata: this._onvLoadedMetadata.bind(this) 9610 }; 9611 9612 this._pendingSeekTime = null; 9613 this._statisticsReporter = null; 9614 9615 this._mediaDataSource = mediaDataSource; 9616 this._mediaElement = null; 9617 } 9618 9619 _createClass(NativePlayer, [{ 9620 key: 'destroy', 9621 value: function destroy() { 9622 if (this._mediaElement) { 9623 this.unload(); 9624 this.detachMediaElement(); 9625 } 9626 this.e = null; 9627 this._mediaDataSource = null; 9628 this._emitter.removeAllListeners(); 9629 this._emitter = null; 9630 } 9631 }, {
9632 key: 'on', 9633 value: function on(event, listener) { 9634 var _this = this; 9635 9636 if (event === _playerEvents2.default.MEDIA_INFO) { 9637 if (this._mediaElement != null && this._mediaElement.readyState !== 0) { 9638 // HAVE_NOTHING 9639 Promise.resolve().then(function () { 9640 _this._emitter.emit(_playerEvents2.default.MEDIA_INFO, _this.mediaInfo); 9641 }); 9642 } 9643 } else if (event === _playerEvents2.default.STATISTICS_INFO) { 9644 if (this._mediaElement != null && this._mediaElement.readyState !== 0) { 9645 Promise.resolve().then(function () { 9646 _this._emitter.emit(_playerEvents2.default.STATISTICS_INFO, _this.statisticsInfo); 9647 }); 9648 } 9649 } 9650 this._emitter.addListener(event, listener); 9651 } 9652 }, { 9653 key: 'off', 9654 value: function off(event, listener) { 9655 this._emitter.removeListener(event, listener); 9656 } 9657 }, { 9658 key: 'attachMediaElement', 9659 value: function attachMediaElement(mediaElement) { 9660 this._mediaElement = mediaElement; 9661 mediaElement.addEventListener('loadedmetadata', this.e.onvLoadedMetadata); 9662 9663 if (this._pendingSeekTime != null) { 9664 try { 9665 mediaElement.currentTime = this._pendingSeekTime; 9666 this._pendingSeekTime = null; 9667 } catch (e) { 9668 // IE11 may throw InvalidStateError if readyState === 0 9669 // Defer set currentTime operation after loadedmetadata 9670 } 9671 } 9672 } 9673 }, { 9674 key: 'detachMediaElement', 9675 value: function detachMediaElement() { 9676 if (this._mediaElement) { 9677 this._mediaElement.src = ''; 9678 this._mediaElement.removeAttribute('src'); 9679 this._mediaElement.removeEventListener('loadedmetadata', this.e.onvLoadedMetadata); 9680 this._mediaElement = null; 9681 } 9682 if (this._statisticsReporter != null) { 9683 window.clearInterval(this._statisticsReporter); 9684 this._statisticsReporter = null; 9685 } 9686 } 9687 }, { 9688 key: 'load', 9689 value: function load() { 9690 if (!this._mediaElement) { 9691 throw new _exception.IllegalStateException('HTMLMediaElement must be attached before load()!'); 9692 } 9693 this._mediaElement.src = this._mediaDataSource.url; 9694 9695 if (this._mediaElement.readyState > 0) { 9696 this._mediaElement.currentTime = 0; 9697 } 9698 9699 this._mediaElement.preload = 'auto'; 9700 this._mediaElement.load(); 9701 this._statisticsReporter = window.setInterval(this._reportStatisticsInfo.bind(this), this._config.statisticsInfoReportInterval); 9702 } 9703 }, { 9704 key: 'unload', 9705 value: function unload() { 9706 if (this._mediaElement) { 9707 this._mediaElement.src = ''; 9708 this._mediaElement.removeAttribute('src'); 9709 } 9710 if (this._statisticsReporter != null) { 9711 window.clearInterval(this._statisticsReporter); 9712 this._statisticsReporter = null; 9713 } 9714 } 9715 }, { 9716 key: 'play', 9717 value: function play() { 9718 return this._mediaElement.play(); 9719 } 9720 }, { 9721 key: 'pause', 9722 value: function pause() { 9723 this._mediaElement.pause(); 9724 } 9725 }, { 9726 key: '_onvLoadedMetadata', 9727 value: function _onvLoadedMetadata(e) { 9728 if (this._pendingSeekTime != null) { 9729 this._mediaElement.currentTime = this._pendingSeekTime; 9730 this._pendingSeekTime = null; 9731 } 9732 this._emitter.emit(_playerEvents2.default.MEDIA_INFO, this.mediaInfo); 9733 } 9734 }, { 9735 key: '_reportStatisticsInfo', 9736 value: function _reportStatisticsInfo() { 9737 this._emitter.emit(_playerEvents2.default.STATISTICS_INFO, this.statisticsInfo); 9738 } 9739 }, {
9740 key: 'type', 9741 get: function get() { 9742 return this._type; 9743 } 9744 }, { 9745 key: 'buffered', 9746 get: function get() { 9747 return this._mediaElement.buffered; 9748 } 9749 }, { 9750 key: 'duration', 9751 get: function get() { 9752 return this._mediaElement.duration; 9753 } 9754 }, { 9755 key: 'volume', 9756 get: function get() { 9757 return this._mediaElement.volume; 9758 }, 9759 set: function set(value) { 9760 this._mediaElement.volume = value; 9761 } 9762 }, { 9763 key: 'muted', 9764 get: function get() { 9765 return this._mediaElement.muted; 9766 }, 9767 set: function set(muted) { 9768 this._mediaElement.muted = muted; 9769 } 9770 }, { 9771 key: 'currentTime', 9772 get: function get() { 9773 if (this._mediaElement) { 9774 return this._mediaElement.currentTime; 9775 } 9776 return 0; 9777 }, 9778 set: function set(seconds) { 9779 if (this._mediaElement) { 9780 this._mediaElement.currentTime = seconds; 9781 } else { 9782 this._pendingSeekTime = seconds; 9783 } 9784 } 9785 }, { 9786 key: 'mediaInfo', 9787 get: function get() { 9788 var mediaPrefix = this._mediaElement instanceof HTMLAudioElement ? 'audio/' : 'video/'; 9789 var info = { 9790 mimeType: mediaPrefix + this._mediaDataSource.type 9791 }; 9792 if (this._mediaElement) { 9793 info.duration = Math.floor(this._mediaElement.duration * 1000); 9794 if (this._mediaElement instanceof HTMLVideoElement) { 9795 info.width = this._mediaElement.videoWidth; 9796 info.height = this._mediaElement.videoHeight; 9797 } 9798 } 9799 return info; 9800 } 9801 }, { 9802 key: 'statisticsInfo', 9803 get: function get() { 9804 var info = { 9805 playerType: this._type, 9806 url: this._mediaDataSource.url 9807 }; 9808 9809 if (!(this._mediaElement instanceof HTMLVideoElement)) { 9810 return info; 9811 } 9812 9813 var hasQualityInfo = true; 9814 var decoded = 0; 9815 var dropped = 0; 9816 9817 if (this._mediaElement.getVideoPlaybackQuality) { 9818 var quality = this._mediaElement.getVideoPlaybackQuality(); 9819 decoded = quality.totalVideoFrames; 9820 dropped = quality.droppedVideoFrames; 9821 } else if (this._mediaElement.webkitDecodedFrameCount != undefined) { 9822 decoded = this._mediaElement.webkitDecodedFrameCount; 9823 dropped = this._mediaElement.webkitDroppedFrameCount; 9824 } else { 9825 hasQualityInfo = false; 9826 } 9827 9828 if (hasQualityInfo) { 9829 info.decodedFrames = decoded; 9830 info.droppedFrames = dropped; 9831 } 9832 9833 return info; 9834 } 9835 }]); 9836 9837 return NativePlayer; 9838}(); 9839 9840exports.default = NativePlayer; 9841 9842},{"../config.js":5,"../utils/exception.js":40,"./player-events.js":35,"events":2}],34:[function(_dereq_,module,exports){ 9843'use strict'; 9844 9845Object.defineProperty(exports, "__esModule", { 9846 value: true 9847}); 9848exports.ErrorDetails = exports.ErrorTypes = undefined; 9849 9850var _loader = _dereq_('../io/loader.js'); 9851 9852var _demuxErrors = _dereq_('../demux/demux-errors.js'); 9853 9854var _demuxErrors2 = _interopRequireDefault(_demuxErrors); 9855 9856function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 9857 9858/* 9859 * Copyright (C) 2016 Bilibili. All Rights Reserved. 9860 * 9861 * @author zheng qian <[email protected]> 9862 * 9863 * Licensed under the Apache License, Version 2.0 (the "License"); 9864 * you may not use this file except in compliance with the License. 9865 * You may obtain a copy of the License at 9866 * 9867 * http://www.apache.org/licenses/LICENSE-2.0 9868 * 9869 * Unless required by applicable law or agreed to in writing, software 9870 * distributed under the License is distributed on an "AS IS" BASIS, 9871 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9872 * See the License for the specific language governing permissions and 9873 * limitations under the License. 9874 */ 9875 9876var ErrorTypes = exports.ErrorTypes = {
9877 NETWORK_ERROR: 'NetworkError', 9878 MEDIA_ERROR: 'MediaError', 9879 OTHER_ERROR: 'OtherError' 9880}; 9881 9882var ErrorDetails = exports.ErrorDetails = { 9883 NETWORK_EXCEPTION: _loader.LoaderErrors.EXCEPTION, 9884 NETWORK_STATUS_CODE_INVALID: _loader.LoaderErrors.HTTP_STATUS_CODE_INVALID, 9885 NETWORK_TIMEOUT: _loader.LoaderErrors.CONNECTING_TIMEOUT, 9886 NETWORK_UNRECOVERABLE_EARLY_EOF: _loader.LoaderErrors.UNRECOVERABLE_EARLY_EOF, 9887 9888 MEDIA_MSE_ERROR: 'MediaMSEError', 9889 9890 MEDIA_FORMAT_ERROR: _demuxErrors2.default.FORMAT_ERROR, 9891 MEDIA_FORMAT_UNSUPPORTED: _demuxErrors2.default.FORMAT_UNSUPPORTED, 9892 MEDIA_CODEC_UNSUPPORTED: _demuxErrors2.default.CODEC_UNSUPPORTED 9893}; 9894 9895},{"../demux/demux-errors.js":16,"../io/loader.js":24}],35:[function(_dereq_,module,exports){ 9896'use strict'; 9897 9898Object.defineProperty(exports, "__esModule", { 9899 value: true 9900}); 9901/* 9902 * Copyright (C) 2016 Bilibili. All Rights Reserved. 9903 * 9904 * @author zheng qian <[email protected]> 9905 * 9906 * Licensed under the Apache License, Version 2.0 (the "License"); 9907 * you may not use this file except in compliance with the License. 9908 * You may obtain a copy of the License at 9909 * 9910 * http://www.apache.org/licenses/LICENSE-2.0 9911 * 9912 * Unless required by applicable law or agreed to in writing, software 9913 * distributed under the License is distributed on an "AS IS" BASIS, 9914 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9915 * See the License for the specific language governing permissions and 9916 * limitations under the License. 9917 */ 9918 9919var PlayerEvents = { 9920 ERROR: 'error', 9921 LOADING_COMPLETE: 'loading_complete', 9922 RECOVERED_EARLY_EOF: 'recovered_early_eof', 9923 MEDIA_INFO: 'media_info', 9924 METADATA_ARRIVED: 'metadata_arrived', 9925 SCRIPTDATA_ARRIVED: 'scriptdata_arrived', 9926 STATISTICS_INFO: 'statistics_info' 9927}; 9928 9929exports.default = PlayerEvents; 9930 9931},{}],36:[function(_dereq_,module,exports){ 9932'use strict'; 9933 9934Object.defineProperty(exports, "__esModule", { 9935 value: true 9936}); 9937 9938var _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; }; }(); 9939 9940function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 9941 9942/* 9943 * Copyright (C) 2016 Bilibili. All Rights Reserved. 9944 * 9945 * This file is modified from dailymotion's hls.js library (hls.js/src/helper/aac.js) 9946 * @author zheng qian <[email protected]> 9947 * 9948 * Licensed under the Apache License, Version 2.0 (the "License"); 9949 * you may not use this file except in compliance with the License. 9950 * You may obtain a copy of the License at 9951 * 9952 * http://www.apache.org/licenses/LICENSE-2.0 9953 * 9954 * Unless required by applicable law or agreed to in writing, software 9955 * distributed under the License is distributed on an "AS IS" BASIS, 9956 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9957 * See the License for the specific language governing permissions and 9958 * limitations under the License. 9959 */ 9960 9961var AAC = function () { 9962 function AAC() { 9963 _classCallCheck(this, AAC); 9964 } 9965 9966 _createClass(AAC, null, [{ 9967 key: 'getSilentFrame', 9968 value: function getSilentFrame(codec, channelCount) { 9969 if (codec === 'mp4a.40.2') { 9970 // handle LC-AAC 9971 if (channelCount === 1) { 9972 return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x23, 0x80]); 9973 } else if (channelCount === 2) { 9974 return new Uint8Array([0x21, 0x00, 0x49, 0x90, 0x02, 0x19, 0x00, 0x23, 0x80]); 9975 } else if (channelCount === 3) { 9976 return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x8e]); 9977 } else if (channelCount === 4) { 9978 return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x80, 0x2c, 0x80, 0x08, 0x02, 0x38]); 9979 } else if (channelCount === 5) { 9980 return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x82, 0x30, 0x04, 0x99, 0x00, 0x21, 0x90, 0x02, 0x38]); 9981 } else if (channelCount === 6) { 9982 return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x82, 0x30, 0x04, 0x99, 0x00, 0x21, 0x90, 0x02, 0x00, 0xb2, 0x00, 0x20, 0x08, 0xe0]); 9983 } 9984 } else { 9985 // handle HE-AAC (mp4a.40.5 / mp4a.40.29) 9986 if (channelCount === 1) { 9987 // ffmpeg -y -f lavfi -i "aevalsrc=0:d=0.05" -c:a libfdk_aac -profile:a aac_he -b:a 4k output.aac && hexdump -v -e '16/1 "0x%x," "\n"' -v output.aac 9988 return new Uint8Array([0x1, 0x40, 0x22, 0x80, 0xa3, 0x4e, 0xe6, 0x80, 0xba, 0x8, 0x0, 0x0, 0x0, 0x1c, 0x6, 0xf1, 0xc1, 0xa, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5e]); 9989 } else if (channelCount === 2) { 9990 // ffmpeg -y -f lavfi -i "aevalsrc=0|0:d=0.05" -c:a libfdk_aac -profile:a aac_he_v2 -b:a 4k output.aac && hexdump -v -e '16/1 "0x%x," "\n"' -v output.aac 9991 return new Uint8Array([0x1, 0x40, 0x22, 0x80, 0xa3, 0x5e, 0xe6, 0x80, 0xba, 0x8, 0x0, 0x0, 0x0, 0x0, 0x95, 0x0, 0x6, 0xf1, 0xa1, 0xa, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5e]); 9992 } else if (channelCount === 3) { 9993 // ffmpeg -y -f lavfi -i "aevalsrc=0|0|0:d=0.05" -c:a libfdk_aac -profile:a aac_he_v2 -b:a 4k output.aac && hexdump -v -e '16/1 "0x%x," "\n"' -v output.aac 9994 return new Uint8Array([0x1, 0x40, 0x22, 0x80, 0xa3, 0x5e, 0xe6, 0x80, 0xba, 0x8, 0x0, 0x0, 0x0, 0x0, 0x95, 0x0, 0x6, 0xf1, 0xa1, 0xa, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5e]); 9995 } 9996 } 9997 return null; 9998 } 9999 }]); 10000 10001 return AAC; 10002}(); 10003 10004exports.default = AAC; 10005 10006},{}],37:[function(_dereq_,module,exports){ 10007'use strict'; 10008 10009Object.defineProperty(exports, "__esModule", { 10010 value: true 10011}); 10012 10013var _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; }; }(); 10014 10015function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 10016 10017/* 10018 * Copyright (C) 2016 Bilibili. All Rights Reserved. 10019 * 10020 * This file is derived from dailymotion's hls.js library (hls.js/src/remux/mp4-generator.js) 10021 * @author zheng qian <[email protected]> 10022 * 10023 * Licensed under the Apache License, Version 2.0 (the "License");
10024 * you may not use this file except in compliance with the License. 10025 * You may obtain a copy of the License at 10026 * 10027 * http://www.apache.org/licenses/LICENSE-2.0 10028 * 10029 * Unless required by applicable law or agreed to in writing, software 10030 * distributed under the License is distributed on an "AS IS" BASIS, 10031 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10032 * See the License for the specific language governing permissions and 10033 * limitations under the License. 10034 */ 10035 10036// MP4 boxes generator for ISO BMFF (ISO Base Media File Format, defined in ISO/IEC 14496-12) 10037var MP4 = function () { 10038 function MP4() { 10039 _classCallCheck(this, MP4); 10040 } 10041 10042 _createClass(MP4, null, [{ 10043 key: 'init', 10044 value: function init() { 10045 MP4.types = { 10046 avc1: [], avcC: [], btrt: [], dinf: [], 10047 dref: [], esds: [], ftyp: [], hdlr: [], 10048 mdat: [], mdhd: [], mdia: [], mfhd: [], 10049 minf: [], moof: [], moov: [], mp4a: [], 10050 mvex: [], mvhd: [], sdtp: [], stbl: [], 10051 stco: [], stsc: [], stsd: [], stsz: [], 10052 stts: [], tfdt: [], tfhd: [], traf: [], 10053 trak: [], trun: [], trex: [], tkhd: [], 10054 vmhd: [], smhd: [], '.mp3': [] 10055 }; 10056 10057 for (var name in MP4.types) { 10058 if (MP4.types.hasOwnProperty(name)) { 10059 MP4.types[name] = [name.charCodeAt(0), name.charCodeAt(1), name.charCodeAt(2), name.charCodeAt(3)]; 10060 } 10061 } 10062 10063 var constants = MP4.constants = {}; 10064 10065 constants.FTYP = new Uint8Array([0x69, 0x73, 0x6F, 0x6D, // major_brand: isom 10066 0x0, 0x0, 0x0, 0x1, // minor_version: 0x01 10067 0x69, 0x73, 0x6F, 0x6D, // isom 10068 0x61, 0x76, 0x63, 0x31 // avc1 10069 ]); 10070 10071 constants.STSD_PREFIX = new Uint8Array([0x00, 0x00, 0x00, 0x00, // version(0) + flags 10072 0x00, 0x00, 0x00, 0x01 // entry_count 10073 ]); 10074 10075 constants.STTS = new Uint8Array([0x00, 0x00, 0x00, 0x00, // version(0) + flags 10076 0x00, 0x00, 0x00, 0x00 // entry_count 10077 ]); 10078 10079 constants.STSC = constants.STCO = constants.STTS; 10080 10081 constants.STSZ = new Uint8Array([0x00, 0x00, 0x00, 0x00, // version(0) + flags 10082 0x00, 0x00, 0x00, 0x00, // sample_size 10083 0x00, 0x00, 0x00, 0x00 // sample_count 10084 ]); 10085 10086 constants.HDLR_VIDEO = new Uint8Array([0x00, 0x00, 0x00, 0x00, // version(0) + flags 10087 0x00, 0x00, 0x00, 0x00, // pre_defined 10088 0x76, 0x69, 0x64, 0x65, // handler_type: 'vide' 10089 0x00, 0x00, 0x00, 0x00, // reserved: 3 * 4 bytes 10090 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00 // name: VideoHandler 10091 ]); 10092 10093 constants.HDLR_AUDIO = new Uint8Array([0x00, 0x00, 0x00, 0x00, // version(0) + flags 10094 0x00, 0x00, 0x00, 0x00, // pre_defined 10095 0x73, 0x6F, 0x75, 0x6E, // handler_type: 'soun' 10096 0x00, 0x00, 0x00, 0x00, // reserved: 3 * 4 bytes 10097 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x6F, 0x75, 0x6E, 0x64, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00 // name: SoundHandler 10098 ]); 10099 10100 constants.DREF = new Uint8Array([0x00, 0x00, 0x00, 0x00, // version(0) + flags 10101 0x00, 0x00, 0x00, 0x01, // entry_count 10102 0x00, 0x00, 0x00, 0x0C, // entry_size 10103 0x75, 0x72, 0x6C, 0x20, // type 'url ' 10104 0x00, 0x00, 0x00, 0x01 // version(0) + flags 10105 ]); 10106 10107 // Sound media header 10108 constants.SMHD = new Uint8Array([0x00, 0x00, 0x00, 0x00, // version(0) + flags 10109 0x00, 0x00, 0x00, 0x00 // balance(2) + reserved(2) 10110 ]); 10111 10112 // video media header 10113 constants.VMHD = new Uint8Array([0x00, 0x00, 0x00, 0x01, // version(0) + flags 10114 0x00, 0x00, // graphicsmode: 2 bytes 10115 0x00, 0x00, 0x00, 0x00, // opcolor: 3 * 2 bytes 10116 0x00, 0x00]); 10117 } 10118 10119 // Generate a box 10120 10121 }, {
10122 key: 'box', 10123 value: function box(type) { 10124 var size = 8; 10125 var result = null; 10126 var datas = Array.prototype.slice.call(arguments, 1); 10127 var arrayCount = datas.length; 10128 10129 for (var i = 0; i < arrayCount; i++) { 10130 size += datas[i].byteLength; 10131 } 10132 10133 result = new Uint8Array(size); 10134 result[0] = size >>> 24 & 0xFF; // size 10135 result[1] = size >>> 16 & 0xFF; 10136 result[2] = size >>> 8 & 0xFF; 10137 result[3] = size & 0xFF; 10138 10139 result.set(type, 4); // type 10140 10141 var offset = 8; 10142 for (var _i = 0; _i < arrayCount; _i++) { 10143 // data body 10144 result.set(datas[_i], offset); 10145 offset += datas[_i].byteLength; 10146 } 10147 10148 return result; 10149 } 10150 10151 // emit ftyp & moov 10152 10153 }, { 10154 key: 'generateInitSegment', 10155 value: function generateInitSegment(meta) { 10156 var ftyp = MP4.box(MP4.types.ftyp, MP4.constants.FTYP); 10157 var moov = MP4.moov(meta); 10158 10159 var result = new Uint8Array(ftyp.byteLength + moov.byteLength); 10160 result.set(ftyp, 0); 10161 result.set(moov, ftyp.byteLength); 10162 return result; 10163 } 10164 10165 // Movie metadata box 10166 10167 }, { 10168 key: 'moov', 10169 value: function moov(meta) { 10170 var mvhd = MP4.mvhd(meta.timescale, meta.duration); 10171 var trak = MP4.trak(meta); 10172 var mvex = MP4.mvex(meta); 10173 return MP4.box(MP4.types.moov, mvhd, trak, mvex); 10174 } 10175 10176 // Movie header box 10177 10178 }, { 10179 key: 'mvhd', 10180 value: function mvhd(timescale, duration) { 10181 return MP4.box(MP4.types.mvhd, new Uint8Array([0x00, 0x00, 0x00, 0x00, // version(0) + flags 10182 0x00, 0x00, 0x00, 0x00, // creation_time 10183 0x00, 0x00, 0x00, 0x00, // modification_time 10184 timescale >>> 24 & 0xFF, // timescale: 4 bytes 10185 timescale >>> 16 & 0xFF, timescale >>> 8 & 0xFF, timescale & 0xFF, duration >>> 24 & 0xFF, // duration: 4 bytes 10186 duration >>> 16 & 0xFF, duration >>> 8 & 0xFF, duration & 0xFF, 0x00, 0x01, 0x00, 0x00, // Preferred rate: 1.0 10187 0x01, 0x00, 0x00, 0x00, // PreferredVolume(1.0, 2bytes) + reserved(2bytes) 10188 0x00, 0x00, 0x00, 0x00, // reserved: 4 + 4 bytes 10189 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, // ----begin composition matrix---- 10190 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, // ----end composition matrix---- 10191 0x00, 0x00, 0x00, 0x00, // ----begin pre_defined 6 * 4 bytes---- 10192 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ----end pre_defined 6 * 4 bytes---- 10193 0xFF, 0xFF, 0xFF, 0xFF // next_track_ID 10194 ])); 10195 } 10196 10197 // Track box 10198 10199 }, { 10200 key: 'trak', 10201 value: function trak(meta) { 10202 return MP4.box(MP4.types.trak, MP4.tkhd(meta), MP4.mdia(meta)); 10203 } 10204 10205 // Track header box 10206 10207 }, { 10208 key: 'tkhd', 10209 value: function tkhd(meta) { 10210 var trackId = meta.id, 10211 duration = meta.duration; 10212 var width = meta.presentWidth, 10213 height = meta.presentHeight; 10214 10215 return MP4.box(MP4.types.tkhd, new Uint8Array([0x00, 0x00, 0x00, 0x07, // version(0) + flags 10216 0x00, 0x00, 0x00, 0x00, // creation_time 10217 0x00, 0x00, 0x00, 0x00, // modification_time 10218 trackId >>> 24 & 0xFF, // track_ID: 4 bytes 10219 trackId >>> 16 & 0xFF, trackId >>> 8 & 0xFF, trackId & 0xFF, 0x00, 0x00, 0x00, 0x00, // reserved: 4 bytes 10220 duration >>> 24 & 0xFF, // duration: 4 bytes 10221 duration >>> 16 & 0xFF, duration >>> 8 & 0xFF, duration & 0xFF, 0x00, 0x00, 0x00, 0x00, // reserved: 2 * 4 bytes 10222 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // layer(2bytes) + alternate_group(2bytes) 10223 0x00, 0x00, 0x00, 0x00, // volume(2bytes) + reserved(2bytes) 10224 0x00, 0x01, 0x00, 0x00, // ----begin composition matrix---- 10225 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, // ----end composition matrix---- 10226 width >>> 8 & 0xFF, // width and height 10227 width & 0xFF, 0x00, 0x00, height >>> 8 & 0xFF, height & 0xFF, 0x00, 0x00])); 10228 } 10229 10230 // Media Box 10231 10232 }, {
10233 key: 'mdia', 10234 value: function mdia(meta) { 10235 return MP4.box(MP4.types.mdia, MP4.mdhd(meta), MP4.hdlr(meta), MP4.minf(meta)); 10236 } 10237 10238 // Media header box 10239 10240 }, { 10241 key: 'mdhd', 10242 value: function mdhd(meta) { 10243 var timescale = meta.timescale; 10244 var duration = meta.duration; 10245 return MP4.box(MP4.types.mdhd, new Uint8Array([0x00, 0x00, 0x00, 0x00, // version(0) + flags 10246 0x00, 0x00, 0x00, 0x00, // creation_time 10247 0x00, 0x00, 0x00, 0x00, // modification_time 10248 timescale >>> 24 & 0xFF, // timescale: 4 bytes 10249 timescale >>> 16 & 0xFF, timescale >>> 8 & 0xFF, timescale & 0xFF, duration >>> 24 & 0xFF, // duration: 4 bytes 10250 duration >>> 16 & 0xFF, duration >>> 8 & 0xFF, duration & 0xFF, 0x55, 0xC4, // language: und (undetermined) 10251 0x00, 0x00 // pre_defined = 0 10252 ])); 10253 } 10254 10255 // Media handler reference box 10256 10257 }, { 10258 key: 'hdlr', 10259 value: function hdlr(meta) { 10260 var data = null; 10261 if (meta.type === 'audio') { 10262 data = MP4.constants.HDLR_AUDIO; 10263 } else { 10264 data = MP4.constants.HDLR_VIDEO; 10265 } 10266 return MP4.box(MP4.types.hdlr, data); 10267 } 10268 10269 // Media infomation box 10270 10271 }, { 10272 key: 'minf', 10273 value: function minf(meta) { 10274 var xmhd = null; 10275 if (meta.type === 'audio') { 10276 xmhd = MP4.box(MP4.types.smhd, MP4.constants.SMHD); 10277 } else { 10278 xmhd = MP4.box(MP4.types.vmhd, MP4.constants.VMHD); 10279 } 10280 return MP4.box(MP4.types.minf, xmhd, MP4.dinf(), MP4.stbl(meta)); 10281 } 10282 10283 // Data infomation box 10284 10285 }, { 10286 key: 'dinf', 10287 value: function dinf() { 10288 var result = MP4.box(MP4.types.dinf, MP4.box(MP4.types.dref, MP4.constants.DREF)); 10289 return result; 10290 } 10291 10292 // Sample table box 10293 10294 }, { 10295 key: 'stbl', 10296 value: function stbl(meta) { 10297 var result = MP4.box(MP4.types.stbl, // type: stbl 10298 MP4.stsd(meta), // Sample Description Table 10299 MP4.box(MP4.types.stts, MP4.constants.STTS), // Time-To-Sample 10300 MP4.box(MP4.types.stsc, MP4.constants.STSC), // Sample-To-Chunk 10301 MP4.box(MP4.types.stsz, MP4.constants.STSZ), // Sample size 10302 MP4.box(MP4.types.stco, MP4.constants.STCO // Chunk offset 10303 )); 10304 return result; 10305 } 10306 10307 // Sample description box 10308 10309 }, { 10310 key: 'stsd', 10311 value: function stsd(meta) { 10312 if (meta.type === 'audio') { 10313 if (meta.codec === 'mp3') { 10314 return MP4.box(MP4.types.stsd, MP4.constants.STSD_PREFIX, MP4.mp3(meta)); 10315 } 10316 // else: aac -> mp4a 10317 return MP4.box(MP4.types.stsd, MP4.constants.STSD_PREFIX, MP4.mp4a(meta)); 10318 } else { 10319 return MP4.box(MP4.types.stsd, MP4.constants.STSD_PREFIX, MP4.avc1(meta)); 10320 } 10321 } 10322 }, { 10323 key: 'mp3', 10324 value: function mp3(meta) { 10325 var channelCount = meta.channelCount; 10326 var sampleRate = meta.audioSampleRate; 10327 10328 var data = new Uint8Array([0x00, 0x00, 0x00, 0x00, // reserved(4) 10329 0x00, 0x00, 0x00, 0x01, // reserved(2) + data_reference_index(2) 10330 0x00, 0x00, 0x00, 0x00, // reserved: 2 * 4 bytes 10331 0x00, 0x00, 0x00, 0x00, 0x00, channelCount, // channelCount(2) 10332 0x00, 0x10, // sampleSize(2) 10333 0x00, 0x00, 0x00, 0x00, // reserved(4) 10334 sampleRate >>> 8 & 0xFF, // Audio sample rate 10335 sampleRate & 0xFF, 0x00, 0x00]); 10336 10337 return MP4.box(MP4.types['.mp3'], data); 10338 } 10339 }, { 10340 key: 'mp4a', 10341 value: function mp4a(meta) { 10342 var channelCount = meta.channelCount; 10343 var sampleRate = meta.audioSampleRate; 10344 10345 var data = new Uint8Array([0x00, 0x00, 0x00, 0x00, // reserved(4) 10346 0x00, 0x00, 0x00, 0x01, // reserved(2) + data_reference_index(2) 10347 0x00, 0x00, 0x00, 0x00, // reserved: 2 * 4 bytes 10348 0x00, 0x00, 0x00, 0x00, 0x00, channelCount, // channelCount(2) 10349 0x00, 0x10, // sampleSize(2) 10350 0x00, 0x00, 0x00, 0x00, // reserved(4) 10351 sampleRate >>> 8 & 0xFF, // Audio sample rate 10352 sampleRate & 0xFF, 0x00, 0x00]); 10353 10354 return MP4.box(MP4.types.mp4a, data, MP4.esds(meta)); 10355 } 10356 }, {
10357 key: 'esds', 10358 value: function esds(meta) { 10359 var config = meta.config || []; 10360 var configSize = config.length; 10361 var data = new Uint8Array([0x00, 0x00, 0x00, 0x00, // version 0 + flags 10362 10363 0x03, // descriptor_type 10364 0x17 + configSize, // length3 10365 0x00, 0x01, // es_id 10366 0x00, // stream_priority 10367 10368 0x04, // descriptor_type 10369 0x0F + configSize, // length 10370 0x40, // codec: mpeg4_audio 10371 0x15, // stream_type: Audio 10372 0x00, 0x00, 0x00, // buffer_size 10373 0x00, 0x00, 0x00, 0x00, // maxBitrate 10374 0x00, 0x00, 0x00, 0x00, // avgBitrate 10375 10376 0x05 // descriptor_type 10377 ].concat([configSize]).concat(config).concat([0x06, 0x01, 0x02 // GASpecificConfig 10378 ])); 10379 return MP4.box(MP4.types.esds, data); 10380 } 10381 }, { 10382 key: 'avc1', 10383 value: function avc1(meta) { 10384 var avcc = meta.avcc; 10385 var width = meta.codecWidth, 10386 height = meta.codecHeight; 10387 10388 var data = new Uint8Array([0x00, 0x00, 0x00, 0x00, // reserved(4) 10389 0x00, 0x00, 0x00, 0x01, // reserved(2) + data_reference_index(2) 10390 0x00, 0x00, 0x00, 0x00, // pre_defined(2) + reserved(2) 10391 0x00, 0x00, 0x00, 0x00, // pre_defined: 3 * 4 bytes 10392 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, width >>> 8 & 0xFF, // width: 2 bytes 10393 width & 0xFF, height >>> 8 & 0xFF, // height: 2 bytes 10394 height & 0xFF, 0x00, 0x48, 0x00, 0x00, // horizresolution: 4 bytes 10395 0x00, 0x48, 0x00, 0x00, // vertresolution: 4 bytes 10396 0x00, 0x00, 0x00, 0x00, // reserved: 4 bytes 10397 0x00, 0x01, // frame_count 10398 0x0A, // strlen 10399 0x78, 0x71, 0x71, 0x2F, // compressorname: 32 bytes 10400 0x66, 0x6C, 0x76, 0x2E, 0x6A, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, // depth 10401 0xFF, 0xFF // pre_defined = -1 10402 ]); 10403 return MP4.box(MP4.types.avc1, data, MP4.box(MP4.types.avcC, avcc)); 10404 } 10405 10406 // Movie Extends box 10407 10408 }, { 10409 key: 'mvex', 10410 value: function mvex(meta) { 10411 return MP4.box(MP4.types.mvex, MP4.trex(meta)); 10412 } 10413 10414 // Track Extends box 10415 10416 }, { 10417 key: 'trex', 10418 value: function trex(meta) { 10419 var trackId = meta.id; 10420 var data = new Uint8Array([0x00, 0x00, 0x00, 0x00, // version(0) + flags 10421 trackId >>> 24 & 0xFF, // track_ID 10422 trackId >>> 16 & 0xFF, trackId >>> 8 & 0xFF, trackId & 0xFF, 0x00, 0x00, 0x00, 0x01, // default_sample_description_index 10423 0x00, 0x00, 0x00, 0x00, // default_sample_duration 10424 0x00, 0x00, 0x00, 0x00, // default_sample_size 10425 0x00, 0x01, 0x00, 0x01 // default_sample_flags 10426 ]); 10427 return MP4.box(MP4.types.trex, data); 10428 } 10429 10430 // Movie fragment box 10431 10432 }, { 10433 key: 'moof', 10434 value: function moof(track, baseMediaDecodeTime) { 10435 return MP4.box(MP4.types.moof, MP4.mfhd(track.sequenceNumber), MP4.traf(track, baseMediaDecodeTime)); 10436 } 10437 }, { 10438 key: 'mfhd', 10439 value: function mfhd(sequenceNumber) { 10440 var data = new Uint8Array([0x00, 0x00, 0x00, 0x00, sequenceNumber >>> 24 & 0xFF, // sequence_number: int32 10441 sequenceNumber >>> 16 & 0xFF, sequenceNumber >>> 8 & 0xFF, sequenceNumber & 0xFF]); 10442 return MP4.box(MP4.types.mfhd, data); 10443 } 10444 10445 // Track fragment box 10446 10447 }, { 10448 key: 'traf', 10449 value: function traf(track, baseMediaDecodeTime) { 10450 var trackId = track.id; 10451 10452 // Track fragment header box 10453 var tfhd = MP4.box(MP4.types.tfhd, new Uint8Array([0x00, 0x00, 0x00, 0x00, // version(0) & flags 10454 trackId >>> 24 & 0xFF, // track_ID 10455 trackId >>> 16 & 0xFF, trackId >>> 8 & 0xFF, trackId & 0xFF])); 10456 // Track Fragment Decode Time 10457 var tfdt = MP4.box(MP4.types.tfdt, new Uint8Array([0x00, 0x00, 0x00, 0x00, // version(0) & flags 10458 baseMediaDecodeTime >>> 24 & 0xFF, // baseMediaDecodeTime: int32 10459 baseMediaDecodeTime >>> 16 & 0xFF, baseMediaDecodeTime >>> 8 & 0xFF, baseMediaDecodeTime & 0xFF])); 10460 var sdtp = MP4.sdtp(track); 10461 var trun = MP4.trun(track, sdtp.byteLength + 16 + 16 + 8 + 16 + 8 + 8); 10462 10463 return MP4.box(MP4.types.traf, tfhd, tfdt, trun, sdtp); 10464 } 10465 10466 // Sample Dependency Type box 10467 10468 }, {
10469 key: 'sdtp', 10470 value: function sdtp(track) { 10471 var samples = track.samples || []; 10472 var sampleCount = samples.length; 10473 var data = new Uint8Array(4 + sampleCount); 10474 // 0~4 bytes: version(0) & flags 10475 for (var i = 0; i < sampleCount; i++) { 10476 var flags = samples[i].flags; 10477 data[i + 4] = flags.isLeading << 6 | // is_leading: 2 (bit) 10478 flags.dependsOn << 4 // sample_depends_on 10479 | flags.isDependedOn << 2 // sample_is_depended_on 10480 | flags.hasRedundancy; // sample_has_redundancy 10481 } 10482 return MP4.box(MP4.types.sdtp, data); 10483 } 10484 10485 // Track fragment run box 10486 10487 }, { 10488 key: 'trun', 10489 value: function trun(track, offset) { 10490 var samples = track.samples || []; 10491 var sampleCount = samples.length; 10492 var dataSize = 12 + 16 * sampleCount; 10493 var data = new Uint8Array(dataSize); 10494 offset += 8 + dataSize; 10495 10496 data.set([0x00, 0x00, 0x0F, 0x01, // version(0) & flags 10497 sampleCount >>> 24 & 0xFF, // sample_count 10498 sampleCount >>> 16 & 0xFF, sampleCount >>> 8 & 0xFF, sampleCount & 0xFF, offset >>> 24 & 0xFF, // data_offset 10499 offset >>> 16 & 0xFF, offset >>> 8 & 0xFF, offset & 0xFF], 0); 10500 10501 for (var i = 0; i < sampleCount; i++) { 10502 var duration = samples[i].duration; 10503 var size = samples[i].size; 10504 var flags = samples[i].flags; 10505 var cts = samples[i].cts; 10506 data.set([duration >>> 24 & 0xFF, // sample_duration 10507 duration >>> 16 & 0xFF, duration >>> 8 & 0xFF, duration & 0xFF, size >>> 24 & 0xFF, // sample_size 10508 size >>> 16 & 0xFF, size >>> 8 & 0xFF, size & 0xFF, flags.isLeading << 2 | flags.dependsOn, // sample_flags 10509 flags.isDependedOn << 6 | flags.hasRedundancy << 4 | flags.isNonSync, 0x00, 0x00, // sample_degradation_priority 10510 cts >>> 24 & 0xFF, // sample_composition_time_offset 10511 cts >>> 16 & 0xFF, cts >>> 8 & 0xFF, cts & 0xFF], 12 + 16 * i); 10512 } 10513 return MP4.box(MP4.types.trun, data); 10514 } 10515 }, { 10516 key: 'mdat', 10517 value: function mdat(data) { 10518 return MP4.box(MP4.types.mdat, data); 10519 } 10520 }]); 10521 10522 return MP4; 10523}(); 10524 10525MP4.init(); 10526 10527exports.default = MP4; 10528 10529},{}],38:[function(_dereq_,module,exports){ 10530'use strict'; 10531 10532Object.defineProperty(exports, "__esModule", { 10533 value: true 10534}); 10535 10536var _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; }; }(); /* 10537 * Copyright (C) 2016 Bilibili. All Rights Reserved. 10538 * 10539 * @author zheng qian <[email protected]> 10540 * 10541 * Licensed under the Apache License, Version 2.0 (the "License"); 10542 * you may
10542not use this file except in compliance with the License. 10543 * You may obtain a copy of the License at 10544 * 10545 * http://www.apache.org/licenses/LICENSE-2.0 10546 * 10547 * Unless required by applicable law or agreed to in writing, software 10548 * distributed under the License is distributed on an "AS IS" BASIS, 10549 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10550 * See the License for the specific language governing permissions and 10551 * limitations under the License. 10552 */ 10553 10554var _logger = _dereq_('../utils/logger.js'); 10555 10556var _logger2 = _interopRequireDefault(_logger); 10557 10558var _mp4Generator = _dereq_('./mp4-generator.js'); 10559 10560var _mp4Generator2 = _interopRequireDefault(_mp4Generator); 10561 10562var _aacSilent = _dereq_('./aac-silent.js'); 10563 10564var _aacSilent2 = _interopRequireDefault(_aacSilent); 10565 10566var _browser = _dereq_('../utils/browser.js'); 10567 10568var _browser2 = _interopRequireDefault(_browser); 10569 10570var _mediaSegmentInfo = _dereq_('../core/media-segment-info.js'); 10571 10572var _exception = _dereq_('../utils/exception.js'); 10573 10574function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 10575 10576function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 10577 10578// Fragmented mp4 remuxer 10579var MP4Remuxer = function () { 10580 function MP4Remuxer(config) { 10581 _classCallCheck(this, MP4Remuxer); 10582 10583 this.TAG = 'MP4Remuxer'; 10584 10585 this._config = config; 10586 this._isLive = config.isLive === true ? true : false;
10587 10588 this._dtsBase = -1; 10589 this._dtsBaseInited = false; 10590 this._audioDtsBase = Infinity; 10591 this._videoDtsBase = Infinity; 10592 this._audioNextDts = undefined; 10593 this._videoNextDts = undefined; 10594 this._audioStashedLastSample = null; 10595 this._videoStashedLastSample = null; 10596 10597 this._audioMeta = null; 10598 this._videoMeta = null; 10599 10600 this._audioSegmentInfoList = new _mediaSegmentInfo.MediaSegmentInfoList('audio'); 10601 this._videoSegmentInfoList = new _mediaSegmentInfo.MediaSegmentInfoList('video'); 10602 10603 this._onInitSegment = null; 10604 this._onMediaSegment = null; 10605 10606 // Workaround for chrome < 50: Always force first sample as a Random Access Point in media segment 10607 // see https://bugs.chromium.org/p/chromium/issues/detail?id=229412 10608 this._forceFirstIDR = _browser2.default.chrome && (_browser2.default.version.major < 50 || _browser2.default.version.major === 50 && _browser2.default.version.build < 2661) ? true : false; 10609 10610 // Workaround for IE11/Edge: Fill silent aac frame after keyframe-seeking 10611 // Make audio beginDts equals with video beginDts, in order to fix seek freeze 10612 this._fillSilentAfterSeek = _browser2.default.msedge || _browser2.default.msie; 10613 10614 // While only FireFox supports 'audio/mp4, codecs="mp3"', use 'audio/mpeg' for chrome, safari, ... 10615 this._mp3UseMpegAudio = !_browser2.default.firefox; 10616 10617 this._fillAudioTimestampGap = this._config.fixAudioTimestampGap; 10618 } 10619 10620 _createClass(MP4Remuxer, [{ 10621 key: 'destroy', 10622 value: function destroy() { 10623 this._dtsBase = -1; 10624 this._dtsBaseInited = false; 10625 this._audioMeta = null; 10626 this._videoMeta = null; 10627 this._audioSegmentInfoList.clear(); 10628 this._audioSegmentInfoList = null; 10629 this._videoSegmentInfoList.clear(); 10630 this._videoSegmentInfoList = null; 10631 this._onInitSegment = null; 10632 this._onMediaSegment = null; 10633 } 10634 }, { 10635 key: 'bindDataSource', 10636 value: function bindDataSource(producer) { 10637 producer.onDataAvailable = this.remux.bind(this); 10638 producer.onTrackMetadata = this._onTrackMetadataReceived.bind(this); 10639 return this; 10640 } 10641 10642 /* prototype: function onInitSegment(type: string, initSegment: ArrayBuffer): void 10643 InitSegment: { 10644 type: string, 10645 data: ArrayBuffer, 10646 codec: string, 10647 container: string 10648 } 10649 */ 10650 10651 }, { 10652 key: 'insertDiscontinuity', 10653 value: function insertDiscontinuity() { 10654 this._audioNextDts = this._videoNextDts = undefined; 10655 } 10656 }, { 10657 key: 'seek', 10658 value: function seek(originalDts) { 10659 this._audioStashedLastSample = null; 10660 this._videoStashedLastSample = null; 10661 this._videoSegmentInfoList.clear(); 10662 this._audioSegmentInfoList.clear(); 10663 } 10664 }, { 10665 key: 'remux', 10666 value: function remux(audioTrack, videoTrack) { 10667 if (!this._onMediaSegment) { 10668 throw new _exception.IllegalStateException('MP4Remuxer: onMediaSegment callback must be specificed!'); 10669 } 10670 if (!this._dtsBaseInited) { 10671 this._calculateDtsBase(audioTrack, videoTrack); 10672 } 10673 this._remuxVideo(videoTrack); 10674 this._remuxAudio(audioTrack); 10675 } 10676 }, { 10677 key: '_onTrackMetadataReceived', 10678 value: function _onTrackMetadataReceived(type, metadata) { 10679 var metabox = null; 10680 10681 var container = 'mp4'; 10682 var codec = metadata.codec; 10683 10684 if (type === 'audio') { 10685 this._audioMeta = metadata; 10686 if (metadata.codec === 'mp3' && this._mp3UseMpegAudio) { 10687 // 'audio/mpeg' for MP3 audio track 10688 container = 'mpeg'; 10689 codec = ''; 10690 metabox = new Uint8Array(); 10691 } else { 10692 // 'audio/mp4, codecs="codec"' 10693 metabox = _mp4Generator2.default.generateInitSegment(metadata); 10694 } 10695 } else if (type === 'video') { 10696 this._videoMeta = metadata; 10697 metabox = _mp4Generator2.default.generateInitSegment(metadata); 10698 } else { 10699 return; 10700 } 10701 10702 // dispatch metabox (Initialization Segment) 10703 if (!this._onInitSegment) { 10704 throw new _exception.IllegalStateException('MP4Remuxer: onInitSegment callback must be specified!'); 10705 } 10706 this._onInitSegment(type, { 10707 type: type, 10708 data: metabox.buffer, 10709 codec: codec, 10710 container: type + '/' + container, 10711 mediaDuration: metadata.duration // in timescale 1000 (milliseconds) 10712 }); 10713 } 10714 }, {
vendor: 4,837 bytes, lines 10715-10850
10715 key: '_calculateDtsBase', 10716 value: function _calculateDtsBase(audioTrack, videoTrack) { 10717 if (this._dtsBaseInited) { 10718 return; 10719 } 10720 10721 if (audioTrack.samples && audioTrack.samples.length) { 10722 this._audioDtsBase = audioTrack.samples[0].dts; 10723 } 10724 if (videoTrack.samples && videoTrack.samples.length) { 10725 this._videoDtsBase = videoTrack.samples[0].dts; 10726 } 10727 10728 this._dtsBase = Math.min(this._audioDtsBase, this._videoDtsBase); 10729 this._dtsBaseInited = true; 10730 } 10731 }, { 10732 key: 'flushStashedSamples', 10733 value: function flushStashedSamples() { 10734 var videoSample = this._videoStashedLastSample; 10735 var audioSample = this._audioStashedLastSample; 10736 10737 var videoTrack = { 10738 type: 'video', 10739 id: 1, 10740 sequenceNumber: 0, 10741 samples: [], 10742 length: 0 10743 }; 10744 10745 if (videoSample != null) { 10746 videoTrack.samples.push(videoSample); 10747 videoTrack.length = videoSample.length; 10748 } 10749 10750 var audioTrack = { 10751 type: 'audio', 10752 id: 2, 10753 sequenceNumber: 0, 10754 samples: [], 10755 length: 0 10756 }; 10757 10758 if (audioSample != null) { 10759 audioTrack.samples.push(audioSample); 10760 audioTrack.length = audioSample.length; 10761 } 10762 10763 this._videoStashedLastSample = null; 10764 this._audioStashedLastSample = null; 10765 10766 this._remuxVideo(videoTrack, true); 10767 this._remuxAudio(audioTrack, true); 10768 } 10769 }, { 10770 key: '_remuxAudio', 10771 value: function _remuxAudio(audioTrack, force) { 10772 if (this._audioMeta == null) { 10773 return; 10774 } 10775 10776 var track = audioTrack; 10777 var samples = track.samples; 10778 var dtsCorrection = undefined; 10779 var firstDts = -1, 10780 lastDts = -1, 10781 lastPts = -1; 10782 var refSampleDuration = this._audioMeta.refSampleDuration; 10783 10784 var mpegRawTrack = this._audioMeta.codec === 'mp3' && this._mp3UseMpegAudio; 10785 var firstSegmentAfterSeek = this._dtsBaseInited && this._audioNextDts === undefined; 10786 10787 var insertPrefixSilentFrame = false; 10788 10789 if (!samples || samples.length === 0) { 10790 return; 10791 } 10792 if (samples.length === 1 && !force) { 10793 // If [sample count in current batch] === 1 && (force != true) 10794 // Ignore and keep in demuxer's queue 10795 return; 10796 } // else if (force === true) do remux 10797 10798 var offset = 0; 10799 var mdatbox = null; 10800 var mdatBytes = 0; 10801 10802 // calculate initial mdat size 10803 if (mpegRawTrack) { 10804 // for raw mpeg buffer 10805 offset = 0; 10806 mdatBytes = track.length; 10807 } else { 10808 // for fmp4 mdat box 10809 offset = 8; // size + type 10810 mdatBytes = 8 + track.length; 10811 } 10812 10813 var lastSample = null; 10814 10815 // Pop the lastSample and waiting for stash 10816 if (samples.length > 1) { 10817 lastSample = samples.pop(); 10818 mdatBytes -= lastSample.length; 10819 } 10820 10821 // Insert [stashed lastSample in the previous batch] to the front 10822 if (this._audioStashedLastSample != null) { 10823 var sample = this._audioStashedLastSample; 10824 this._audioStashedLastSample = null; 10825 samples.unshift(sample); 10826 mdatBytes += sample.length; 10827 } 10828 10829 // Stash the lastSample of current batch, waiting for next batch 10830 if (lastSample != null) { 10831 this._audioStashedLastSample = lastSample; 10832 } 10833 10834 var firstSampleOriginalDts = samples[0].dts - this._dtsBase; 10835 10836 // calculate dtsCorrection 10837 if (this._audioNextDts) { 10838 dtsCorrection = firstSampleOriginalDts - this._audioNextDts; 10839 } else { 10840 // this._audioNextDts == undefined 10841 if (this._audioSegmentInfoList.isEmpty()) { 10842 dtsCorrection = 0; 10843 if (this._fillSilentAfterSeek && !this._videoSegmentInfoList.isEmpty()) { 10844 if (this._audioMeta.originalCodec !== 'mp3') { 10845 insertPrefixSilentFrame = true; 10846 } 10847 } 10848 } else { 10849 var _lastSample = this._audioSegmentInfoList.getLastSampleBefore(firstSampleOriginalDts); 10850 if (_lastSample != null) {
10851 var distance = firstSampleOriginalDts - (_lastSample.originalDts + _lastSample.duration); 10852 if (distance <= 3) { 10853 distance = 0; 10854 } 10855 var expectedDts = _lastSample.dts + _lastSample.duration + distance; 10856 dtsCorrection = firstSampleOriginalDts - expectedDts; 10857 } else { 10858 // lastSample == null, cannot found 10859 dtsCorrection = 0; 10860 } 10861 } 10862 } 10863 10864 if (insertPrefixSilentFrame) { 10865 // align audio segment beginDts to match with current video segment's beginDts 10866 var firstSampleDts = firstSampleOriginalDts - dtsCorrection; 10867 var videoSegment = this._videoSegmentInfoList.getLastSegmentBefore(firstSampleOriginalDts); 10868 if (videoSegment != null && videoSegment.beginDts < firstSampleDts) { 10869 var silentUnit = _aacSilent2.default.getSilentFrame(this._audioMeta.originalCodec, this._audioMeta.channelCount); 10870 if (silentUnit) { 10871 var dts = videoSegment.beginDts; 10872 var silentFrameDuration = firstSampleDts - videoSegment.beginDts; 10873 _logger2.default.v(this.TAG, 'InsertPrefixSilentAudio: dts: ' + dts + ', duration: ' + silentFrameDuration); 10874 samples.unshift({ unit: silentUnit, dts: dts, pts: dts }); 10875 mdatBytes += silentUnit.byteLength; 10876 } // silentUnit == null: Cannot generate, skip 10877 } else { 10878 insertPrefixSilentFrame = false; 10879 } 10880 } 10881 10882 var mp4Samples = []; 10883 10884 // Correct dts for each sample, and calculate sample duration. Then output to mp4Samples 10885 for (var i = 0; i < samples.length; i++) { 10886 var _sample = samples[i]; 10887 var unit = _sample.unit; 10888 var originalDts = _sample.dts - this._dtsBase; 10889 var _dts = originalDts - dtsCorrection; 10890 10891 if (firstDts === -1) { 10892 firstDts = _dts; 10893 } 10894 10895 var sampleDuration = 0; 10896 10897 if (i !== samples.length - 1) { 10898 var nextDts = samples[i + 1].dts - this._dtsBase - dtsCorrection; 10899 sampleDuration = nextDts - _dts; 10900 } else { 10901 // the last sample 10902 if (lastSample != null) { 10903 // use stashed sample's dts to calculate sample duration 10904 var _nextDts = lastSample.dts - this._dtsBase - dtsCorrection; 10905 sampleDuration = _nextDts - _dts; 10906 } else if (mp4Samples.length >= 1) { 10907 // use second last sample duration 10908 sampleDuration = mp4Samples[mp4Samples.length - 1].duration; 10909 } else { 10910 // the only one sample, use reference sample duration 10911 sampleDuration = Math.floor(refSampleDuration); 10912 } 10913 } 10914 10915 var needFillSilentFrames = false; 10916 var silentFrames = null; 10917 10918 // Silent frame generation, if large timestamp gap detected && config.fixAudioTimestampGap 10919 if (sampleDuration > refSampleDuration * 1.5 && this._audioMeta.codec !== 'mp3' && this._fillAudioTimestampGap && !_browser2.default.safari) { 10920 // We need to insert silent frames to fill timestamp gap 10921 needFillSilentFrames = true; 10922 var delta = Math.abs(sampleDuration - refSampleDuration); 10923 var frameCount = Math.ceil(delta / refSampleDuration); 10924 var currentDts = _dts + refSampleDuration; // Notice: in float 10925 10926 _logger2.default.w(this.TAG, 'Large audio timestamp gap detected, may cause AV sync to drift. ' + 'Silent frames will be generated to avoid unsync.\n' + ('dts: ' + (_dts + sampleDuration) + ' ms, expected: ' + (_dts + Math.round(refSampleDuration)) + ' ms, ') + ('delta: ' + Math.round(delta) + ' ms, generate: ' + frameCount + ' frames')); 10927 10928 var _silentUnit = _aacSilent2.default.getSilentFrame(this._audioMeta.originalCodec, this._audioMeta.channelCount); 10929 if (_silentUnit == null) { 10930 _logger2.default.w(this.TAG, 'Unable to generate silent frame for ' + (this._audioMeta.originalCodec + ' with ' + this._audioMeta.channelCount + ' channels, repeat last frame')); 10931 // Repeat last frame 10932 _silentUnit = unit; 10933 } 10934 silentFrames = []; 10935 10936 for (var j = 0; j < frameCount; j++) { 10937 var intDts = Math.round(currentDts); // round to integer 10938 if (silentFrames.length > 0) { 10939 // Set previous frame sample duration 10940 var previousFrame = silentFrames[silentFrames.length - 1]; 10941 previousFrame.duration = intDts - previousFrame.dts; 10942 } 10943 var frame = { 10944 dts: intDts, 10945 pts: intDts, 10946 cts: 0, 10947 unit: _silentUnit, 10948 size: _silentUnit.byteLength, 10949 duration: 0, // wait for next sample 10950 originalDts: originalDts, 10951 flags: { 10952 isLeading: 0, 10953 dependsOn: 1, 10954 isDependedOn: 0, 10955 hasRedundancy: 0 10956 } 10957 }; 10958 silentFrames.push(frame); 10959 mdatBytes += frame.size; 10960 currentDts += refSampleDuration; 10961 } 10962 10963 // last frame: align end time to next frame dts 10964 var lastFrame = silentFrames[silentFrames.length - 1]; 10965 lastFrame.duration = _dts + sampleDuration - lastFrame.dts; 10966
10967 // silentFrames.forEach((frame) => { 10968 // Log.w(this.TAG, `SilentAudio: dts: ${frame.dts}, duration: ${frame.duration}`); 10969 // }); 10970 10971 // Set correct sample duration for current frame 10972 sampleDuration = Math.round(refSampleDuration); 10973 } 10974 10975 mp4Samples.push({ 10976 dts: _dts, 10977 pts: _dts, 10978 cts: 0, 10979 unit: _sample.unit, 10980 size: _sample.unit.byteLength, 10981 duration: sampleDuration, 10982 originalDts: originalDts, 10983 flags: { 10984 isLeading: 0, 10985 dependsOn: 1, 10986 isDependedOn: 0, 10987 hasRedundancy: 0 10988 } 10989 }); 10990 10991 if (needFillSilentFrames) { 10992 // Silent frames should be inserted after wrong-duration frame 10993 mp4Samples.push.apply(mp4Samples, silentFrames); 10994 } 10995 } 10996 10997 // allocate mdatbox 10998 if (mpegRawTrack) { 10999 // allocate for raw mpeg buffer 11000 mdatbox = new Uint8Array(mdatBytes); 11001 } else { 11002 // allocate for fmp4 mdat box 11003 mdatbox = new Uint8Array(mdatBytes); 11004 // size field 11005 mdatbox[0] = mdatBytes >>> 24 & 0xFF; 11006 mdatbox[1] = mdatBytes >>> 16 & 0xFF; 11007 mdatbox[2] = mdatBytes >>> 8 & 0xFF; 11008 mdatbox[3] = mdatBytes & 0xFF; 11009 // type field (fourCC) 11010 mdatbox.set(_mp4Generator2.default.types.mdat, 4); 11011 } 11012 11013 // Write samples into mdatbox 11014 for (var _i = 0; _i < mp4Samples.length; _i++) { 11015 var _unit = mp4Samples[_i].unit; 11016 mdatbox.set(_unit, offset); 11017 offset += _unit.byteLength; 11018 } 11019 11020 var latest = mp4Samples[mp4Samples.length - 1]; 11021 lastDts = latest.dts + latest.duration; 11022 this._audioNextDts = lastDts; 11023 11024 // fill media segment info & add to info list 11025 var info = new _mediaSegmentInfo.MediaSegmentInfo(); 11026 info.beginDts = firstDts; 11027 info.endDts = lastDts; 11028 info.beginPts = firstDts; 11029 info.endPts = lastDts; 11030 info.originalBeginDts = mp4Samples[0].originalDts; 11031 info.originalEndDts = latest.originalDts + latest.duration; 11032 info.firstSample = new _mediaSegmentInfo.SampleInfo(mp4Samples[0].dts, mp4Samples[0].pts, mp4Samples[0].duration, mp4Samples[0].originalDts, false); 11033 info.lastSample = new _mediaSegmentInfo.SampleInfo(latest.dts, latest.pts, latest.duration, latest.originalDts, false); 11034 if (!this._isLive) { 11035 this._audioSegmentInfoList.append(info); 11036 } 11037 11038 track.samples = mp4Samples; 11039 track.sequenceNumber++; 11040 11041 var moofbox = null; 11042 11043 if (mpegRawTrack) { 11044 // Generate empty buffer, because useless for raw mpeg 11045 moofbox = new Uint8Array(); 11046 } else { 11047 // Generate moof for fmp4 segment 11048 moofbox = _mp4Generator2.default.moof(track, firstDts); 11049 } 11050 11051 track.samples = []; 11052 track.length = 0; 11053 11054 var segment = { 11055 type: 'audio', 11056 data: this._mergeBoxes(moofbox, mdatbox).buffer, 11057 sampleCount: mp4Samples.length, 11058 info: info 11059 }; 11060 11061 if (mpegRawTrack && firstSegmentAfterSeek) { 11062 // For MPEG audio stream in MSE, if seeking occurred, before appending new buffer 11063 // We need explicitly set timestampOffset to the desired point in timeline for mpeg SourceBuffer. 11064 segment.timestampOffset = firstDts; 11065 } 11066 11067 this._onMediaSegment('audio', segment); 11068 } 11069 }, { 11070 key: '_remuxVideo', 11071 value: function _remuxVideo(videoTrack, force) { 11072 if (this._videoMeta == null) { 11073 return; 11074 } 11075 11076 var track = videoTrack; 11077 var samples = track.samples; 11078 var dtsCorrection = undefined; 11079 var firstDts = -1,
vendor: 7,675 bytes, lines 11080-11264
11080 lastDts = -1; 11081 var firstPts = -1, 11082 lastPts = -1; 11083 11084 if (!samples || samples.length === 0) { 11085 return; 11086 } 11087 if (samples.length === 1 && !force) { 11088 // If [sample count in current batch] === 1 && (force != true) 11089 // Ignore and keep in demuxer's queue 11090 return; 11091 } // else if (force === true) do remux 11092 11093 var offset = 8; 11094 var mdatbox = null; 11095 var mdatBytes = 8 + videoTrack.length; 11096 11097 var lastSample = null; 11098 11099 // Pop the lastSample and waiting for stash 11100 if (samples.length > 1) { 11101 lastSample = samples.pop(); 11102 mdatBytes -= lastSample.length; 11103 } 11104 11105 // Insert [stashed lastSample in the previous batch] to the front 11106 if (this._videoStashedLastSample != null) { 11107 var sample = this._videoStashedLastSample; 11108 this._videoStashedLastSample = null; 11109 samples.unshift(sample); 11110 mdatBytes += sample.length; 11111 } 11112 11113 // Stash the lastSample of current batch, waiting for next batch 11114 if (lastSample != null) { 11115 this._videoStashedLastSample = lastSample; 11116 } 11117 11118 var firstSampleOriginalDts = samples[0].dts - this._dtsBase; 11119 11120 // calculate dtsCorrection 11121 if (this._videoNextDts) { 11122 dtsCorrection = firstSampleOriginalDts - this._videoNextDts; 11123 } else { 11124 // this._videoNextDts == undefined 11125 if (this._videoSegmentInfoList.isEmpty()) { 11126 dtsCorrection = 0; 11127 } else { 11128 var _lastSample2 = this._videoSegmentInfoList.getLastSampleBefore(firstSampleOriginalDts); 11129 if (_lastSample2 != null) { 11130 var distance = firstSampleOriginalDts - (_lastSample2.originalDts + _lastSample2.duration); 11131 if (distance <= 3) { 11132 distance = 0; 11133 } 11134 var expectedDts = _lastSample2.dts + _lastSample2.duration + distance; 11135 dtsCorrection = firstSampleOriginalDts - expectedDts; 11136 } else { 11137 // lastSample == null, cannot found 11138 dtsCorrection = 0; 11139 } 11140 } 11141 } 11142 11143 var info = new _mediaSegmentInfo.MediaSegmentInfo(); 11144 var mp4Samples = []; 11145 11146 // Correct dts for each sample, and calculate sample duration. Then output to mp4Samples 11147 for (var i = 0; i < samples.length; i++) { 11148 var _sample2 = samples[i]; 11149 var originalDts = _sample2.dts - this._dtsBase; 11150 var isKeyframe = _sample2.isKeyframe; 11151 var dts = originalDts - dtsCorrection; 11152 var cts = _sample2.cts; 11153 var pts = dts + cts; 11154 11155 if (firstDts === -1) { 11156 firstDts = dts; 11157 firstPts = pts; 11158 } 11159 11160 var sampleDuration = 0; 11161 11162 if (i !== samples.length - 1) { 11163 var nextDts = samples[i + 1].dts - this._dtsBase - dtsCorrection; 11164 sampleDuration = nextDts - dts; 11165 } else { 11166 // the last sample 11167 if (lastSample != null) { 11168 // use stashed sample's dts to calculate sample duration 11169 var _nextDts2 = lastSample.dts - this._dtsBase - dtsCorrection; 11170 sampleDuration = _nextDts2 - dts; 11171 } else if (mp4Samples.length >= 1) { 11172 // use second last sample duration 11173 sampleDuration = mp4Samples[mp4Samples.length - 1].duration; 11174 } else { 11175 // the only one sample, use reference sample duration 11176 sampleDuration = Math.floor(this._videoMeta.refSampleDuration); 11177 } 11178 } 11179 11180 if (isKeyframe) { 11181 var syncPoint = new _mediaSegmentInfo.SampleInfo(dts, pts, sampleDuration, _sample2.dts, true); 11182 syncPoint.fileposition = _sample2.fileposition; 11183 info.appendSyncPoint(syncPoint); 11184 } 11185 11186 mp4Samples.push({ 11187 dts: dts, 11188 pts: pts, 11189 cts: cts, 11190 units: _sample2.units, 11191 size: _sample2.length, 11192 isKeyframe: isKeyframe, 11193 duration: sampleDuration, 11194 originalDts: originalDts, 11195 flags: { 11196 isLeading: 0, 11197 dependsOn: isKeyframe ? 2 : 1, 11198 isDependedOn: isKeyframe ? 1 : 0, 11199 hasRedundancy: 0, 11200 isNonSync: isKeyframe ? 0 : 1 11201 } 11202 }); 11203 } 11204 11205 // allocate mdatbox 11206 mdatbox = new Uint8Array(mdatBytes); 11207 mdatbox[0] = mdatBytes >>> 24 & 0xFF; 11208 mdatbox[1] = mdatBytes >>> 16 & 0xFF; 11209 mdatbox[2] = mdatBytes >>> 8 & 0xFF; 11210 mdatbox[3] = mdatBytes & 0xFF; 11211 mdatbox.set(_mp4Generator2.default.types.mdat, 4); 11212 11213 // Write samples into mdatbox 11214 for (var _i2 = 0; _i2 < mp4Samples.length; _i2++) { 11215 var units = mp4Samples[_i2].units; 11216 while (units.length) { 11217 var unit = units.shift(); 11218 var data = unit.data; 11219 mdatbox.set(data, offset); 11220 offset += data.byteLength; 11221 } 11222 } 11223 11224 var latest = mp4Samples[mp4Samples.length - 1]; 11225 lastDts = latest.dts + latest.duration; 11226 lastPts = latest.pts + latest.duration; 11227 this._videoNextDts = lastDts; 11228 11229 // fill media segment info & add to info list 11230 info.beginDts = firstDts; 11231 info.endDts = lastDts; 11232 info.beginPts = firstPts; 11233 info.endPts = lastPts; 11234 info.originalBeginDts = mp4Samples[0].originalDts; 11235 info.originalEndDts = latest.originalDts + latest.duration; 11236 info.firstSample = new _mediaSegmentInfo.SampleInfo(mp4Samples[0].dts, mp4Samples[0].pts, mp4Samples[0].duration, mp4Samples[0].originalDts, mp4Samples[0].isKeyframe); 11237 info.lastSample = new _mediaSegmentInfo.SampleInfo(latest.dts, latest.pts, latest.duration, latest.originalDts, latest.isKeyframe); 11238 if (!this._isLive) { 11239 this._videoSegmentInfoList.append(info); 11240 } 11241 11242 track.samples = mp4Samples; 11243 track.sequenceNumber++; 11244 11245 // workaround for chrome < 50: force first sample as a random access point 11246 // see https://bugs.chromium.org/p/chromium/issues/detail?id=229412 11247 if (this._forceFirstIDR) { 11248 var flags = mp4Samples[0].flags; 11249 flags.dependsOn = 2; 11250 flags.isNonSync = 0; 11251 } 11252 11253 var moofbox = _mp4Generator2.default.moof(track, firstDts); 11254 track.samples = []; 11255 track.length = 0; 11256 11257 this._onMediaSegment('video', { 11258 type: 'video', 11259 data: this._mergeBoxes(moofbox, mdatbox).buffer, 11260 sampleCount: mp4Samples.length, 11261 info: info 11262 }); 11263 } 11264 }, {
11265 key: '_mergeBoxes', 11266 value: function _mergeBoxes(moof, mdat) { 11267 var result = new Uint8Array(moof.byteLength + mdat.byteLength); 11268 result.set(moof, 0); 11269 result.set(mdat, moof.byteLength); 11270 return result; 11271 } 11272 }, { 11273 key: 'onInitSegment', 11274 get: function get() { 11275 return this._onInitSegment; 11276 }, 11277 set: function set(callback) { 11278 this._onInitSegment = callback; 11279 } 11280 11281 /* prototype: function onMediaSegment(type: string, mediaSegment: MediaSegment): void 11282 MediaSegment: { 11283 type: string, 11284 data: ArrayBuffer, 11285 sampleCount: int32 11286 info: MediaSegmentInfo 11287 } 11288 */ 11289 11290 }, { 11291 key: 'onMediaSegment', 11292 get: function get() { 11293 return this._onMediaSegment; 11294 }, 11295 set: function set(callback) { 11296 this._onMediaSegment = callback; 11297 } 11298 }]); 11299 11300 return MP4Remuxer; 11301}(); 11302 11303exports.default = MP4Remuxer; 11304 11305},{"../core/media-segment-info.js":8,"../utils/browser.js":39,"../utils/exception.js":40,"../utils/logger.js":41,"./aac-silent.js":36,"./mp4-generator.js":37}],39:[function(_dereq_,module,exports){ 11306'use strict'; 11307 11308Object.defineProperty(exports, "__esModule", { 11309 value: true 11310}); 11311/* 11312 * Copyright (C) 2016 Bilibili. All Rights Reserved. 11313 * 11314 * @author zheng qian <[email protected]> 11315 * 11316 * Licensed under the Apache License, Version 2.0 (the "License"); 11317 * you may not use this file except in compliance with the License. 11318 * You may obtain a copy of the License at 11319 * 11320 * http://www.apache.org/licenses/LICENSE-2.0 11321 * 11322 * Unless required by applicable law or agreed to in writing, software 11323 * distributed under the License is distributed on an "AS IS" BASIS, 11324 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11325 * See the License for the specific language governing permissions and 11326 * limitations under the License. 11327 */ 11328 11329var Browser = {}; 11330 11331function detect() { 11332 // modified from jquery-browser-plugin 11333 11334 var ua = self.navigator.userAgent.toLowerCase(); 11335 11336 var match = /(edge)\/([\w.]+)/.exec(ua) || /(opr)[\/]([\w.]+)/.exec(ua) || /(chrome)[ \/]([\w.]+)/.exec(ua) || /(iemobile)[\/]([\w.]+)/.exec(ua) || /(version)(applewebkit)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(ua) || /(webkit)[ \/]([\w.]+).*(version)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(ua) || /(webkit)[ \/]([\w.]+)/.exec(ua) || /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || /(msie) ([\w.]+)/.exec(ua) || ua.indexOf('trident') >= 0 && /(rv)(?::| )([\w.]+)/.exec(ua) || ua.indexOf('compatible') < 0 && /(firefox)[ \/]([\w.]+)/.exec(ua) || []; 11337 11338 var platform_match = /(ipad)/.exec(ua) || /(ipod)/.exec(ua) || /(windows phone)/.exec(ua) || /(iphone)/.exec(ua) || /(kindle)/.exec(ua) || /(android)/.exec(ua) || /(windows)/.exec(ua) || /(mac)/.exec(ua) || /(linux)/.exec(ua) || /(cros)/.exec(ua) || []; 11339 11340 var matched = { 11341 browser: match[5] || match[3] || match[1] || '', 11342 version: match[2] || match[4] || '0', 11343 majorVersion: match[4] || match[2] || '0', 11344 platform: platform_match[0] || '' 11345 }; 11346 11347 var browser = {}; 11348 if (matched.browser) { 11349 browser[matched.browser] = true; 11350 11351 var versionArray = matched.majorVersion.split('.'); 11352 browser.version = { 11353 major: parseInt(matched.majorVersion, 10), 11354 string: matched.version 11355 }; 11356 if (versionArray.length > 1) { 11357 browser.version.minor = parseInt(versionArray[1], 10); 11358 } 11359 if (versionArray.length > 2) { 11360 browser.version.build = parseInt(versionArray[2], 10); 11361 } 11362 } 11363 11364 if (matched.platform) { 11365 browser[matched.platform] = true; 11366 } 11367 11368 if (browser.chrome || browser.opr || browser.safari) { 11369 browser.webkit = true; 11370 } 11371 11372 // MSIE. IE11 has 'rv' identifer 11373 if (browser.rv || browser.iemobile) { 11374 if (browser.rv) { 11375 delete browser.rv; 11376 } 11377 var msie = 'msie'; 11378 matched.browser = msie; 11379 browser[msie] = true; 11380 } 11381 11382 // Microsoft Edge 11383 if (browser.edge) { 11384 delete browser.edge; 11385 var msedge = 'msedge'; 11386 matched.browser = msedge; 11387 browser[msedge] = true; 11388 } 11389 11390 // Opera 15+ 11391 if (browser.opr) { 11392 var opera = 'opera'; 11393 matched.browser = opera; 11394 browser[opera] = true; 11395 } 11396 11397 // Stock android browsers are marked as Safari 11398 if (browser.safari && browser.android) { 11399 var android = 'android'; 11400 matched.browser = android; 11401 browser[android] = true; 11402 } 11403 11404 browser.name = matched.browser; 11405 browser.platform = matched.platform; 11406 11407 for (var key in Browser) { 11408 if (Browser.hasOwnProperty(key)) { 11409 delete Browser[key]; 11410 } 11411 } 11412 Object.assign(Browser, browser); 11413} 11414 11415detect(); 11416 11417exports.default = Browser; 11418 11419},{}],40:[function(_dereq_,module,exports){ 11420'use strict'; 11421 11422Object.defineProperty(exports, "__esModule", { 11423 value: true 11424}); 11425 11426var _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; }; }(); 11427 11428function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 11429 11430function _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
11430onstructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 11431 11432function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 11433 11434/* 11435 * Copyright (C) 2016 Bilibili. All Rights Reserved. 11436 * 11437 * @author zheng qian <[email protected]> 11438 * 11439 * Licensed under the Apache License, Version 2.0 (the "License"); 11440 * you may not use this file except in compliance with the License. 11441 * You may obtain a copy of the License at 11442 * 11443 * http://www.apache.org/licenses/LICENSE-2.0 11444 * 11445 * Unless required by applicable law or agreed to in writing, software 11446 * distributed under the License is distributed on an "AS IS" BASIS, 11447 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11448 * See the License for the specific language governing permissions and 11449 * limitations under the License. 11450 */ 11451 11452var RuntimeException = exports.RuntimeException = function () { 11453 function RuntimeException(message) { 11454 _classCallCheck(this, RuntimeException); 11455 11456 this._message = message; 11457 } 11458 11459 _createClass(RuntimeException, [{ 11460 key: 'toString', 11461 value: function toString() { 11462 return this.name + ': ' + this.message; 11463 } 11464 }, { 11465 key: 'name', 11466 get: function get() { 11467 return 'RuntimeException'; 11468 } 11469 }, { 11470 key: 'message', 11471 get: function get() { 11472 return this._message; 11473 } 11474 }]); 11475 11476 return RuntimeException; 11477}(); 11478 11479var IllegalStateException = exports.IllegalStateException = function (_RuntimeException) { 11480 _inherits(IllegalStateException, _RuntimeException); 11481 11482 function IllegalStateException(message) { 11483 _classCallCheck(this, IllegalStateException); 11484 11485 return _possibleConstructorReturn(this, (IllegalStateException.__proto__ || Object.getPrototypeOf(IllegalStateException)).call(this, message)); 11486 } 11487 11488 _createClass(IllegalStateException, [{ 11489 key: 'name', 11490 get: function get() { 11491 return 'IllegalStateException'; 11492 } 11493 }]); 11494 11495 return IllegalStateException; 11496}(RuntimeException); 11497 11498var InvalidArgumentException = exports.InvalidArgumentException = function (_RuntimeException2) { 11499 _inherits(InvalidArgumentException, _RuntimeException2); 11500 11501 function InvalidArgumentException(message) { 11502 _classCallCheck(this, InvalidArgumentException); 11503 11504 return _possibleConstructorReturn(this, (InvalidArgumentException.__proto__ || Object.getPrototypeOf(InvalidArgumentException)).call(this, message)); 11505 } 11506 11507 _createClass(InvalidArgumentException, [{ 11508 key: 'name', 11509 get: function get() { 11510 return 'InvalidArgumentException'; 11511 } 11512 }]); 11513 11514 return InvalidArgumentException; 11515}(RuntimeException); 11516 11517var NotImplementedException = exports.NotImplementedException = function (_RuntimeException3) { 11518 _inherits(NotImplementedException, _RuntimeException3); 11519 11520 function NotImplementedException(message) { 11521 _classCallCheck(this, NotImplementedException); 11522 11523 return _possibleConstructorReturn(this, (NotImplementedException.__proto__ || Object.getPrototypeOf(NotImplementedException)).call(this, message)); 11524 } 11525 11526 _createClass(NotImplementedException, [{ 11527 key: 'name', 11528 get: function get() { 11529 return 'NotImplementedException'; 11530 } 11531 }]); 11532 11533 return NotImplementedException; 11534}(RuntimeException); 11535 11536},{}],41:[function(_dereq_,module,exports){ 11537'use strict'; 11538 11539Object.defineProperty(exports, "__esModule", { 11540 value: true 11541}); 11542 11543var _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; }; }(); /* 11544 * Copyright (C) 2016 Bilibili. All Rights Reserved. 11545 * 11546 * @author zheng qian <[email protected]> 11547 * 11548 * Licensed under the Apache License, Version 2.0 (the "License"); 11549 * you may
11549not use this file except in compliance with the License. 11550 * You may obtain a copy of the License at 11551 * 11552 * http://www.apache.org/licenses/LICENSE-2.0 11553 * 11554 * Unless required by applicable law or agreed to in writing, software 11555 * distributed under the License is distributed on an "AS IS" BASIS, 11556 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11557 * See the License for the specific language governing permissions and 11558 * limitations under the License. 11559 */ 11560 11561var _events = _dereq_('events'); 11562 11563var _events2 = _interopRequireDefault(_events); 11564 11565function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 11566 11567function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 11568 11569var Log = function () { 11570 function Log() { 11571 _classCallCheck(this, Log); 11572 } 11573 11574 _createClass(Log, null, [{ 11575 key: 'e', 11576 value: function e(tag, msg) {
11577 if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG; 11578 11579 var str = '[' + tag + '] > ' + msg; 11580 11581 if (Log.ENABLE_CALLBACK) { 11582 Log.emitter.emit('log', 'error', str); 11583 } 11584 11585 if (!Log.ENABLE_ERROR) { 11586 return; 11587 } 11588 11589 if (console.error) { 11590 console.error(str); 11591 } else if (console.warn) { 11592 console.warn(str); 11593 } else { 11594 console.log(str); 11595 } 11596 } 11597 }, { 11598 key: 'i', 11599 value: function i(tag, msg) { 11600 if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG; 11601 11602 var str = '[' + tag + '] > ' + msg; 11603 11604 if (Log.ENABLE_CALLBACK) { 11605 Log.emitter.emit('log', 'info', str); 11606 } 11607 11608 if (!Log.ENABLE_INFO) { 11609 return; 11610 } 11611 11612 if (console.info) { 11613 console.info(str); 11614 } else { 11615 console.log(str); 11616 } 11617 } 11618 }, { 11619 key: 'w', 11620 value: function w(tag, msg) {
11621 if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG; 11622 11623 var str = '[' + tag + '] > ' + msg; 11624 11625 if (Log.ENABLE_CALLBACK) { 11626 Log.emitter.emit('log', 'warn', str); 11627 } 11628 11629 if (!Log.ENABLE_WARN) { 11630 return; 11631 } 11632 11633 if (console.warn) { 11634 console.warn(str); 11635 } else { 11636 console.log(str); 11637 } 11638 } 11639 }, { 11640 key: 'd', 11641 value: function d(tag, msg) { 11642 if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG; 11643 11644 var str = '[' + tag + '] > ' + msg; 11645 11646 if (Log.ENABLE_CALLBACK) { 11647 Log.emitter.emit('log', 'debug', str); 11648 } 11649 11650 if (!Log.ENABLE_DEBUG) { 11651 return; 11652 } 11653 11654 if (console.debug) { 11655 console.debug(str); 11656 } else { 11657 console.log(str); 11658 } 11659 } 11660 }, { 11661 key: 'v', 11662 value: function v(tag, msg) {
11663 if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG; 11664 11665 var str = '[' + tag + '] > ' + msg; 11666 11667 if (Log.ENABLE_CALLBACK) { 11668 Log.emitter.emit('log', 'verbose', str); 11669 } 11670 11671 if (!Log.ENABLE_VERBOSE) { 11672 return; 11673 } 11674 11675 console.log(str); 11676 } 11677 }]); 11678 11679 return Log; 11680}(); 11681 11682Log.GLOBAL_TAG = 'flv.js'; 11683Log.FORCE_GLOBAL_TAG = false; 11684Log.ENABLE_ERROR = false; //Edited By BuddyBoss 11685Log.ENABLE_INFO = false; //Edited By BuddyBoss 11686Log.ENABLE_WARN = false; //Edited By BuddyBoss 11687Log.ENABLE_DEBUG = false; //Edited By BuddyBoss 11688Log.ENABLE_VERBOSE = false; //Edited By BuddyBoss 11689 11690Log.ENABLE_CALLBACK = false; 11691 11692Log.emitter = new _events2.default(); 11693 11694exports.default = Log; 11695 11696},{"events":2}],42:[function(_dereq_,module,exports){ 11697'use strict'; 11698 11699Object.defineProperty(exports, "__esModule", { 11700 value: true 11701}); 11702 11703var _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; }; }(); /* 11704 * Copyright (C) 2016 Bilibili. All Rights Reserved. 11705 * 11706 * @author zheng qian <[email protected]> 11707 * 11708 * Licensed under the Apache License, Version 2.0 (the "License"); 11709 * you may
11709not use this file except in compliance with the License. 11710 * You may obtain a copy of the License at 11711 * 11712 * http://www.apache.org/licenses/LICENSE-2.0 11713 * 11714 * Unless required by applicable law or agreed to in writing, software 11715 * distributed under the License is distributed on an "AS IS" BASIS, 11716 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11717 * See the License for the specific language governing permissions and 11718 * limitations under the License. 11719 */ 11720 11721var _events = _dereq_('events'); 11722 11723var _events2 = _interopRequireDefault(_events); 11724 11725var _logger = _dereq_('./logger.js'); 11726 11727var _logger2 = _interopRequireDefault(_logger); 11728 11729function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 11730 11731function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 11732 11733var LoggingControl = function () { 11734 function LoggingControl() { 11735 _classCallCheck(this, LoggingControl); 11736 } 11737 11738 _createClass(LoggingControl, null, [{ 11739 key: 'getConfig', 11740 value: function getConfig() { 11741 return { 11742 globalTag: _logger2.default.GLOBAL_TAG, 11743 forceGlobalTag: _logger2.default.FORCE_GLOBAL_TAG, 11744 enableVerbose: _logger2.default.ENABLE_VERBOSE, 11745 enableDebug: _logger2.default.ENABLE_DEBUG, 11746 enableInfo: _logger2.default.ENABLE_INFO, 11747 enableWarn: _logger2.default.ENABLE_WARN, 11748 enableError: _logger2.default.ENABLE_ERROR, 11749 enableCallback: _logger2.default.ENABLE_CALLBACK 11750 }; 11751 } 11752 }, {
11753 key: 'applyConfig', 11754 value: function applyConfig(config) { 11755 _logger2.default.GLOBAL_TAG = config.globalTag; 11756 _logger2.default.FORCE_GLOBAL_TAG = config.forceGlobalTag; 11757 _logger2.default.ENABLE_VERBOSE = config.enableVerbose; 11758 _logger2.default.ENABLE_DEBUG = config.enableDebug; 11759 _logger2.default.ENABLE_INFO = config.enableInfo; 11760 _logger2.default.ENABLE_WARN = config.enableWarn; 11761 _logger2.default.ENABLE_ERROR = config.enableError; 11762 _logger2.default.ENABLE_CALLBACK = config.enableCallback; 11763 } 11764 }, { 11765 key: '_notifyChange', 11766 value: function _notifyChange() { 11767 var emitter = LoggingControl.emitter; 11768 11769 if (emitter.listenerCount('change') > 0) { 11770 var config = LoggingControl.getConfig(); 11771 emitter.emit('change', config); 11772 } 11773 } 11774 }, { 11775 key: 'registerListener', 11776 value: function registerListener(listener) { 11777 LoggingControl.emitter.addListener('change', listener); 11778 } 11779 }, { 11780 key: 'removeListener', 11781 value: function removeListener(listener) { 11782 LoggingControl.emitter.removeListener('change', listener); 11783 } 11784 }, { 11785 key: 'addLogListener', 11786 value: function addLogListener(listener) { 11787 _logger2.default.emitter.addListener('log', listener); 11788 if (_logger2.default.emitter.listenerCount('log') > 0) { 11789 _logger2.default.ENABLE_CALLBACK = true; 11790 LoggingControl._notifyChange(); 11791 } 11792 } 11793 }, { 11794 key: 'removeLogListener', 11795 value: function removeLogListener(listener) { 11796 _logger2.default.emitter.removeListener('log', listener); 11797 if (_logger2.default.emitter.listenerCount('log') === 0) { 11798 _logger2.default.ENABLE_CALLBACK = false; 11799 LoggingControl._notifyChange(); 11800 } 11801 } 11802 }, { 11803 key: 'forceGlobalTag', 11804 get: function get() { 11805 return _logger2.default.FORCE_GLOBAL_TAG; 11806 }, 11807 set: function set(enable) { 11808 _logger2.default.FORCE_GLOBAL_TAG = enable; 11809 LoggingControl._notifyChange(); 11810 } 11811 }, { 11812 key: 'globalTag', 11813 get: function get() { 11814 return _logger2.default.GLOBAL_TAG; 11815 }, 11816 set: function set(tag) { 11817 _logger2.default.GLOBAL_TAG = tag; 11818 LoggingControl._notifyChange(); 11819 } 11820 }, { 11821 key: 'enableAll', 11822 get: function get() { 11823 return _logger2.default.ENABLE_VERBOSE && _logger2.default.ENABLE_DEBUG && _logger2.default.ENABLE_INFO && _logger2.default.ENABLE_WARN && _logger2.default.ENABLE_ERROR; 11824 }, 11825 set: function set(enable) { 11826 _logger2.default.ENABLE_VERBOSE = enable; 11827 _logger2.default.ENABLE_DEBUG = enable; 11828 _logger2.default.ENABLE_INFO = enable; 11829 _logger2.default.ENABLE_WARN = enable; 11830 _logger2.default.ENABLE_ERROR = enable; 11831 LoggingControl._notifyChange(); 11832 } 11833 }, { 11834 key: 'enableDebug', 11835 get: function get() { 11836 return _logger2.default.ENABLE_DEBUG; 11837 }, 11838 set: function set(enable) { 11839 _logger2.default.ENABLE_DEBUG = enable; 11840 LoggingControl._notifyChange(); 11841 } 11842 }, { 11843 key: 'enableVerbose', 11844 get: function get() { 11845 return _logger2.default.ENABLE_VERBOSE; 11846 }, 11847 set: function set(enable) { 11848 _logger2.default.ENABLE_VERBOSE = enable; 11849 LoggingControl._notifyChange(); 11850 } 11851 }, { 11852 key: 'enableInfo', 11853 get: function get() { 11854 return _logger2.default.ENABLE_INFO; 11855 }, 11856 set: function set(enable) { 11857 _logger2.default.ENABLE_INFO = enable; 11858 LoggingControl._notifyChange(); 11859 } 11860 }, { 11861 key: 'enableWarn', 11862 get: function get() { 11863 return _logger2.default.ENABLE_WARN; 11864 }, 11865 set: function set(enable) { 11866 _logger2.default.ENABLE_WARN = enable; 11867 LoggingControl._notifyChange(); 11868 } 11869 }, {
11870 key: 'enableError', 11871 get: function get() { 11872 return _logger2.default.ENABLE_ERROR; 11873 }, 11874 set: function set(enable) { 11875 _logger2.default.ENABLE_ERROR = enable; 11876 LoggingControl._notifyChange(); 11877 } 11878 }]); 11879 11880 return LoggingControl; 11881}(); 11882 11883LoggingControl.emitter = new _events2.default(); 11884 11885exports.default = LoggingControl; 11886 11887},{"./logger.js":41,"events":2}],43:[function(_dereq_,module,exports){ 11888'use strict'; 11889 11890Object.defineProperty(exports, "__esModule", { 11891 value: true 11892}); 11893 11894var _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; }; }(); 11895 11896function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 11897 11898/* 11899 * Copyright (C) 2016 Bilibili. All Rights Reserved. 11900 * 11901 * @author zheng qian <[email protected]> 11902 * 11903 * Licensed under the Apache License, Version 2.0 (the "License"); 11904 * you may not use this file except in compliance with the License. 11905 * You may obtain a copy of the License at 11906 * 11907 * http://www.apache.org/licenses/LICENSE-2.0 11908 * 11909 * Unless required by applicable law or agreed to in writing, software 11910 * distributed under the License is distributed on an "AS IS" BASIS, 11911 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11912 * See the License for the specific language governing permissions and 11913 * limitations under the License. 11914 */ 11915 11916var Polyfill = function () { 11917 function Polyfill() { 11918 _classCallCheck(this, Polyfill); 11919 } 11920 11921 _createClass(Polyfill, null, [{ 11922 key: 'install', 11923 value: function install() { 11924 // ES6 Object.setPrototypeOf 11925 Object.setPrototypeOf = Object.setPrototypeOf || function (obj, proto) { 11926 obj.__proto__ = proto; 11927 return obj; 11928 }; 11929 11930 // ES6 Object.assign 11931 Object.assign = Object.assign || function (target) { 11932 if (target === undefined || target === null) { 11933 throw new TypeError('Cannot convert undefined or null to object'); 11934 } 11935 11936 var output = Object(target); 11937 for (var i = 1; i < arguments.length; i++) { 11938 var source = arguments[i]; 11939 if (source !== undefined && source !== null) { 11940 for (var key in source) { 11941 if (source.hasOwnProperty(key)) { 11942 output[key] = source[key]; 11943 } 11944 } 11945 } 11946 } 11947 return output; 11948 }; 11949 11950 // ES6 Promise (missing support in IE11) 11951 if (typeof self.Promise !== 'function') { 11952 _dereq_('es6-promise').polyfill(); 11953 } 11954 } 11955 }]); 11956 11957 return Polyfill; 11958}(); 11959 11960Polyfill.install(); 11961 11962exports.default = Polyfill; 11963 11964},{"es6-promise":1}],44:[function(_dereq_,module,exports){ 11965'use strict'; 11966 11967Object.defineProperty(exports, "__esModule", { 11968 value: true 11969}); 11970/* 11971 * Copyright (C) 2016 Bilibili. All Rights Reserved. 11972 * 11973 * This file is derived from C++ project libWinTF8 (https://github.com/m13253/libWinTF8) 11974 * @author zheng qian <[email protected]> 11975 * 11976 * Licensed under the Apache License, Version 2.0 (the "License"); 11977 * you may not use this file except in compliance with the License. 11978 * You may obtain a copy of the License at 11979 * 11980 * http://www.apache.org/licenses/LICENSE-2.0 11981 * 11982 * Unless required by applicable law or agreed to in writing, software 11983 * distributed under the License is distributed on an "AS IS" BASIS, 11984 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11985 * See the License for the specific language governing permissions and 11986 * limitations under the License. 11987 */ 11988 11989function checkContinuation(uint8array, start, checkLength) { 11990 var array = uint8array; 11991 if (start + checkLength < array.length) { 11992 while (checkLength--) { 11993 if ((array[++start] & 0xC0) !== 0x80) return false;
11994 } 11995 return true; 11996 } else { 11997 return false; 11998 } 11999} 12000 12001function decodeUTF8(uint8array) { 12002 var out = []; 12003 var input = uint8array; 12004 var i = 0; 12005 var length = uint8array.length; 12006 12007 while (i < length) { 12008 if (input[i] < 0x80) { 12009 out.push(String.fromCharCode(input[i])); 12010 ++i; 12011 continue; 12012 } else if (input[i] < 0xC0) { 12013 // fallthrough 12014 } else if (input[i] < 0xE0) { 12015 if (checkContinuation(input, i, 1)) { 12016 var ucs4 = (input[i] & 0x1F) << 6 | input[i + 1] & 0x3F; 12017 if (ucs4 >= 0x80) { 12018 out.push(String.fromCharCode(ucs4 & 0xFFFF)); 12019 i += 2; 12020 continue; 12021 } 12022 } 12023 } else if (input[i] < 0xF0) { 12024 if (checkContinuation(input, i, 2)) { 12025 var _ucs = (input[i] & 0xF) << 12 | (input[i + 1] & 0x3F) << 6 | input[i + 2] & 0x3F; 12026 if (_ucs >= 0x800 && (_ucs & 0xF800) !== 0xD800) { 12027 out.push(String.fromCharCode(_ucs & 0xFFFF)); 12028 i += 3; 12029 continue; 12030 } 12031 } 12032 } else if (input[i] < 0xF8) { 12033 if (checkContinuation(input, i, 3)) { 12034 var _ucs2 = (input[i] & 0x7) << 18 | (input[i + 1] & 0x3F) << 12 | (input[i + 2] & 0x3F) << 6 | input[i + 3] & 0x3F; 12035 if (_ucs2 > 0x10000 && _ucs2 < 0x110000) { 12036 _ucs2 -= 0x10000; 12037 out.push(String.fromCharCode(_ucs2 >>> 10 | 0xD800)); 12038 out.push(String.fromCharCode(_ucs2 & 0x3FF | 0xDC00)); 12039 i += 4; 12040 continue; 12041 } 12042 } 12043 } 12044 out.push(String.fromCharCode(0xFFFD)); 12045 ++i; 12046 } 12047 12048 return out.join(''); 12049} 12050 12051exports.default = decodeUTF8; 12052 12053},{}]},{},[21])(21) 12054});
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.