diff --git a/src/assets/image/SodaMusic-v2.1.0-official-win32_x64.exe b/src/assets/image/SodaMusic-v2.1.0-official-win32_x64.exe deleted file mode 100644 index 4a5a616..0000000 Binary files a/src/assets/image/SodaMusic-v2.1.0-official-win32_x64.exe and /dev/null differ diff --git a/src/assets/image/icon-fullscreen-close.png b/src/assets/image/icon-fullscreen-close.png new file mode 100644 index 0000000..e274164 Binary files /dev/null and b/src/assets/image/icon-fullscreen-close.png differ diff --git a/src/assets/image/icon-fullscreen.png b/src/assets/image/icon-fullscreen.png new file mode 100644 index 0000000..45a4e59 Binary files /dev/null and b/src/assets/image/icon-fullscreen.png differ diff --git a/src/assets/image/videoNull2.png b/src/assets/image/videoNull2.png new file mode 100644 index 0000000..d1eba2e Binary files /dev/null and b/src/assets/image/videoNull2.png differ diff --git a/src/assets/image/videoNull3.png b/src/assets/image/videoNull3.png new file mode 100644 index 0000000..2ad20f7 Binary files /dev/null and b/src/assets/image/videoNull3.png differ diff --git a/src/vendors/flv.js b/src/vendors/flv.js new file mode 100644 index 0000000..e820732 --- /dev/null +++ b/src/vendors/flv.js @@ -0,0 +1,16224 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if (typeof exports === "object" && typeof module === "object") { + console.log("11111"); + module.exports = factory(); + } else if (typeof define === "function" && define.amd) define([], factory); + else if (typeof exports === "object") exports["flvjs"] = factory(); + else root["flvjs"] = factory(); +})(self, function () { + return /******/ (function () { + // webpackBootstrap + /******/ var __webpack_modules__ = { + /***/ "./node_modules/es6-promise/dist/es6-promise.js": + /*!******************************************************!*\ + !*** ./node_modules/es6-promise/dist/es6-promise.js ***! + \******************************************************/ + /***/ function (module, __unused_webpack_exports, __webpack_require__) { + /*! + * @overview es6-promise - a tiny implementation of Promises/A+. + * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) + * @license Licensed under MIT license + * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE + * @version v4.2.8+1e68dce6 + */ + (function (global, factory) { + true ? (module.exports = factory()) : 0; + })(this, function () { + "use strict"; + function objectOrFunction(x) { + var type = typeof x; + return x !== null && (type === "object" || type === "function"); + } + function isFunction(x) { + return typeof x === "function"; + } + var _isArray = void 0; + if (Array.isArray) { + _isArray = Array.isArray; + } else { + _isArray = function (x) { + return Object.prototype.toString.call(x) === "[object Array]"; + }; + } + var isArray = _isArray; + var len = 0; + var vertxNext = void 0; + var customSchedulerFn = void 0; + var asap = function asap(callback, arg) { + queue[len] = callback; + queue[len + 1] = arg; + len += 2; + if (len === 2) { + // If len is 2, that means that we need to schedule an async flush. + // If additional callbacks are queued before the queue is flushed, they + // will be processed by this flush that we are scheduling. + if (customSchedulerFn) { + customSchedulerFn(flush); + } else { + scheduleFlush(); + } + } + }; + function setScheduler(scheduleFn) { + customSchedulerFn = scheduleFn; + } + function setAsap(asapFn) { + asap = asapFn; + } + var browserWindow = + typeof window !== "undefined" ? window : undefined; + var browserGlobal = browserWindow || {}; + var BrowserMutationObserver = + browserGlobal.MutationObserver || + browserGlobal.WebKitMutationObserver; + var isNode = + typeof self === "undefined" && + typeof process !== "undefined" && + {}.toString.call(process) === "[object process]"; + // test for web worker but not in IE10 + var isWorker = + typeof Uint8ClampedArray !== "undefined" && + typeof importScripts !== "undefined" && + typeof MessageChannel !== "undefined"; + // node + function useNextTick() { + // node version 0.10.x displays a deprecation warning when nextTick is used recursively + // see https://github.com/cujojs/when/issues/410 for details + return function () { + return process.nextTick(flush); + }; + } + // vertx + function useVertxTimer() { + if (typeof vertxNext !== "undefined") { + return function () { + vertxNext(flush); + }; + } + return useSetTimeout(); + } + function useMutationObserver() { + var iterations = 0; + var observer = new BrowserMutationObserver(flush); + var node = document.createTextNode(""); + observer.observe(node, { characterData: true }); + return function () { + node.data = iterations = ++iterations % 2; + }; + } + // web worker + function useMessageChannel() { + var channel = new MessageChannel(); + channel.port1.onmessage = flush; + return function () { + return channel.port2.postMessage(0); + }; + } + function useSetTimeout() { + // Store setTimeout reference so es6-promise will be unaffected by + // other code modifying setTimeout (like sinon.useFakeTimers()) + var globalSetTimeout = setTimeout; + return function () { + return globalSetTimeout(flush, 1); + }; + } + var queue = new Array(1000); + function flush() { + for (var i = 0; i < len; i += 2) { + var callback = queue[i]; + var arg = queue[i + 1]; + callback(arg); + queue[i] = undefined; + queue[i + 1] = undefined; + } + len = 0; + } + function attemptVertx() { + try { + var vertx = Function("return this")().require("vertx"); + vertxNext = vertx.runOnLoop || vertx.runOnContext; + return useVertxTimer(); + } catch (e) { + return useSetTimeout(); + } + } + var scheduleFlush = void 0; + // Decide what async method to use to triggering processing of queued callbacks: + if (isNode) { + scheduleFlush = useNextTick(); + } else if (BrowserMutationObserver) { + scheduleFlush = useMutationObserver(); + } else if (isWorker) { + scheduleFlush = useMessageChannel(); + } else if ( + browserWindow === undefined && + "function" === "function" + ) { + scheduleFlush = attemptVertx(); + } else { + scheduleFlush = useSetTimeout(); + } + function then(onFulfillment, onRejection) { + var parent = this; + var child = new this.constructor(noop); + if (child[PROMISE_ID] === undefined) { + makePromise(child); + } + var _state = parent._state; + if (_state) { + var callback = arguments[_state - 1]; + asap(function () { + return invokeCallback( + _state, + child, + callback, + parent._result + ); + }); + } else { + subscribe(parent, child, onFulfillment, onRejection); + } + return child; + } + /** + `Promise.resolve` returns a promise that will become resolved with the + passed `value`. It is shorthand for the following: + + ```javascript + let promise = new Promise(function(resolve, reject){ + resolve(1); + }); + + promise.then(function(value){ + // value === 1 + }); + ``` + + Instead of writing the above, your code now simply becomes the following: + + ```javascript + let promise = Promise.resolve(1); + + promise.then(function(value){ + // value === 1 + }); + ``` + + @method resolve + @static + @param {Any} value value that the returned promise will be resolved with + Useful for tooling. + @return {Promise} a promise that will become fulfilled with the given + `value` + */ + function resolve$1(object) { + /*jshint validthis:true */ + var Constructor = this; + if ( + object && + typeof object === "object" && + object.constructor === Constructor + ) { + return object; + } + var promise = new Constructor(noop); + resolve(promise, object); + return promise; + } + var PROMISE_ID = Math.random().toString(36).substring(2); + function noop() {} + var PENDING = void 0; + var FULFILLED = 1; + var REJECTED = 2; + function selfFulfillment() { + return new TypeError("You cannot resolve a promise with itself"); + } + function cannotReturnOwn() { + return new TypeError( + "A promises callback cannot return that same promise." + ); + } + function tryThen( + then$$1, + value, + fulfillmentHandler, + rejectionHandler + ) { + try { + then$$1.call(value, fulfillmentHandler, rejectionHandler); + } catch (e) { + return e; + } + } + function handleForeignThenable(promise, thenable, then$$1) { + asap(function (promise) { + var sealed = false; + var error = tryThen( + then$$1, + thenable, + function (value) { + if (sealed) { + return; + } + sealed = true; + if (thenable !== value) { + resolve(promise, value); + } else { + fulfill(promise, value); + } + }, + function (reason) { + if (sealed) { + return; + } + sealed = true; + reject(promise, reason); + }, + "Settle: " + (promise._label || " unknown promise") + ); + if (!sealed && error) { + sealed = true; + reject(promise, error); + } + }, promise); + } + function handleOwnThenable(promise, thenable) { + if (thenable._state === FULFILLED) { + fulfill(promise, thenable._result); + } else if (thenable._state === REJECTED) { + reject(promise, thenable._result); + } else { + subscribe( + thenable, + undefined, + function (value) { + return resolve(promise, value); + }, + function (reason) { + return reject(promise, reason); + } + ); + } + } + function handleMaybeThenable(promise, maybeThenable, then$$1) { + if ( + maybeThenable.constructor === promise.constructor && + then$$1 === then && + maybeThenable.constructor.resolve === resolve$1 + ) { + handleOwnThenable(promise, maybeThenable); + } else { + if (then$$1 === undefined) { + fulfill(promise, maybeThenable); + } else if (isFunction(then$$1)) { + handleForeignThenable(promise, maybeThenable, then$$1); + } else { + fulfill(promise, maybeThenable); + } + } + } + function resolve(promise, value) { + if (promise === value) { + reject(promise, selfFulfillment()); + } else if (objectOrFunction(value)) { + var then$$1 = void 0; + try { + then$$1 = value.then; + } catch (error) { + reject(promise, error); + return; + } + handleMaybeThenable(promise, value, then$$1); + } else { + fulfill(promise, value); + } + } + function publishRejection(promise) { + if (promise._onerror) { + promise._onerror(promise._result); + } + publish(promise); + } + function fulfill(promise, value) { + if (promise._state !== PENDING) { + return; + } + promise._result = value; + promise._state = FULFILLED; + if (promise._subscribers.length !== 0) { + asap(publish, promise); + } + } + function reject(promise, reason) { + if (promise._state !== PENDING) { + return; + } + promise._state = REJECTED; + promise._result = reason; + asap(publishRejection, promise); + } + function subscribe(parent, child, onFulfillment, onRejection) { + var _subscribers = parent._subscribers; + var length = _subscribers.length; + parent._onerror = null; + _subscribers[length] = child; + _subscribers[length + FULFILLED] = onFulfillment; + _subscribers[length + REJECTED] = onRejection; + if (length === 0 && parent._state) { + asap(publish, parent); + } + } + function publish(promise) { + var subscribers = promise._subscribers; + var settled = promise._state; + if (subscribers.length === 0) { + return; + } + var child = void 0, + callback = void 0, + detail = promise._result; + for (var i = 0; i < subscribers.length; i += 3) { + child = subscribers[i]; + callback = subscribers[i + settled]; + if (child) { + invokeCallback(settled, child, callback, detail); + } else { + callback(detail); + } + } + promise._subscribers.length = 0; + } + function invokeCallback(settled, promise, callback, detail) { + var hasCallback = isFunction(callback), + value = void 0, + error = void 0, + succeeded = true; + if (hasCallback) { + try { + value = callback(detail); + } catch (e) { + succeeded = false; + error = e; + } + if (promise === value) { + reject(promise, cannotReturnOwn()); + return; + } + } else { + value = detail; + } + if (promise._state !== PENDING) { + // noop + } else if (hasCallback && succeeded) { + resolve(promise, value); + } else if (succeeded === false) { + reject(promise, error); + } else if (settled === FULFILLED) { + fulfill(promise, value); + } else if (settled === REJECTED) { + reject(promise, value); + } + } + function initializePromise(promise, resolver) { + try { + resolver( + function resolvePromise(value) { + resolve(promise, value); + }, + function rejectPromise(reason) { + reject(promise, reason); + } + ); + } catch (e) { + reject(promise, e); + } + } + var id = 0; + function nextId() { + return id++; + } + function makePromise(promise) { + promise[PROMISE_ID] = id++; + promise._state = undefined; + promise._result = undefined; + promise._subscribers = []; + } + function validationError() { + return new Error("Array Methods must be provided an Array"); + } + var Enumerator = (function () { + function Enumerator(Constructor, input) { + this._instanceConstructor = Constructor; + this.promise = new Constructor(noop); + if (!this.promise[PROMISE_ID]) { + makePromise(this.promise); + } + if (isArray(input)) { + this.length = input.length; + this._remaining = input.length; + this._result = new Array(this.length); + if (this.length === 0) { + fulfill(this.promise, this._result); + } else { + this.length = this.length || 0; + this._enumerate(input); + if (this._remaining === 0) { + fulfill(this.promise, this._result); + } + } + } else { + reject(this.promise, validationError()); + } + } + Enumerator.prototype._enumerate = function _enumerate(input) { + for ( + var i = 0; + this._state === PENDING && i < input.length; + i++ + ) { + this._eachEntry(input[i], i); + } + }; + Enumerator.prototype._eachEntry = function _eachEntry(entry, i) { + var c = this._instanceConstructor; + var resolve$$1 = c.resolve; + if (resolve$$1 === resolve$1) { + var _then = void 0; + var error = void 0; + var didError = false; + try { + _then = entry.then; + } catch (e) { + didError = true; + error = e; + } + if (_then === then && entry._state !== PENDING) { + this._settledAt(entry._state, i, entry._result); + } else if (typeof _then !== "function") { + this._remaining--; + this._result[i] = entry; + } else if (c === Promise$1) { + var promise = new c(noop); + if (didError) { + reject(promise, error); + } else { + handleMaybeThenable(promise, entry, _then); + } + this._willSettleAt(promise, i); + } else { + this._willSettleAt( + new c(function (resolve$$1) { + return resolve$$1(entry); + }), + i + ); + } + } else { + this._willSettleAt(resolve$$1(entry), i); + } + }; + Enumerator.prototype._settledAt = function _settledAt( + state, + i, + value + ) { + var promise = this.promise; + if (promise._state === PENDING) { + this._remaining--; + if (state === REJECTED) { + reject(promise, value); + } else { + this._result[i] = value; + } + } + if (this._remaining === 0) { + fulfill(promise, this._result); + } + }; + Enumerator.prototype._willSettleAt = function _willSettleAt( + promise, + i + ) { + var enumerator = this; + subscribe( + promise, + undefined, + function (value) { + return enumerator._settledAt(FULFILLED, i, value); + }, + function (reason) { + return enumerator._settledAt(REJECTED, i, reason); + } + ); + }; + return Enumerator; + })(); + /** + `Promise.all` accepts an array of promises, and returns a new promise which + is fulfilled with an array of fulfillment values for the passed promises, or + rejected with the reason of the first passed promise to be rejected. It casts all + elements of the passed iterable to promises as it runs this algorithm. + + Example: + + ```javascript + let promise1 = resolve(1); + let promise2 = resolve(2); + let promise3 = resolve(3); + let promises = [ promise1, promise2, promise3 ]; + + Promise.all(promises).then(function(array){ + // The array here would be [ 1, 2, 3 ]; + }); + ``` + + If any of the `promises` given to `all` are rejected, the first promise + that is rejected will be given as an argument to the returned promises's + rejection handler. For example: + + Example: + + ```javascript + let promise1 = resolve(1); + let promise2 = reject(new Error("2")); + let promise3 = reject(new Error("3")); + let promises = [ promise1, promise2, promise3 ]; + + Promise.all(promises).then(function(array){ + // Code here never runs because there are rejected promises! + }, function(error) { + // error.message === "2" + }); + ``` + + @method all + @static + @param {Array} entries array of promises + @param {String} label optional string for labeling the promise. + Useful for tooling. + @return {Promise} promise that is fulfilled when all `promises` have been + fulfilled, or rejected if any of them become rejected. + @static + */ + function all(entries) { + return new Enumerator(this, entries).promise; + } + /** + `Promise.race` returns a new promise which is settled in the same way as the + first passed promise to settle. + + Example: + + ```javascript + let promise1 = new Promise(function(resolve, reject){ + setTimeout(function(){ + resolve('promise 1'); + }, 200); + }); + + let promise2 = new Promise(function(resolve, reject){ + setTimeout(function(){ + resolve('promise 2'); + }, 100); + }); + + Promise.race([promise1, promise2]).then(function(result){ + // result === 'promise 2' because it was resolved before promise1 + // was resolved. + }); + ``` + + `Promise.race` is deterministic in that only the state of the first + settled promise matters. For example, even if other promises given to the + `promises` array argument are resolved, but the first settled promise has + become rejected before the other promises became fulfilled, the returned + promise will become rejected: + + ```javascript + let promise1 = new Promise(function(resolve, reject){ + setTimeout(function(){ + resolve('promise 1'); + }, 200); + }); + + let promise2 = new Promise(function(resolve, reject){ + setTimeout(function(){ + reject(new Error('promise 2')); + }, 100); + }); + + Promise.race([promise1, promise2]).then(function(result){ + // Code here never runs + }, function(reason){ + // reason.message === 'promise 2' because promise 2 became rejected before + // promise 1 became fulfilled + }); + ``` + + An example real-world use case is implementing timeouts: + + ```javascript + Promise.race([ajax('foo.json'), timeout(5000)]) + ``` + + @method race + @static + @param {Array} promises array of promises to observe + Useful for tooling. + @return {Promise} a promise which settles in the same way as the first passed + promise to settle. + */ + function race(entries) { + /*jshint validthis:true */ + var Constructor = this; + if (!isArray(entries)) { + return new Constructor(function (_, reject) { + return reject( + new TypeError("You must pass an array to race.") + ); + }); + } else { + return new Constructor(function (resolve, reject) { + var length = entries.length; + for (var i = 0; i < length; i++) { + Constructor.resolve(entries[i]).then(resolve, reject); + } + }); + } + } + /** + `Promise.reject` returns a promise rejected with the passed `reason`. + It is shorthand for the following: + + ```javascript + let promise = new Promise(function(resolve, reject){ + reject(new Error('WHOOPS')); + }); + + promise.then(function(value){ + // Code here doesn't run because the promise is rejected! + }, function(reason){ + // reason.message === 'WHOOPS' + }); + ``` + + Instead of writing the above, your code now simply becomes the following: + + ```javascript + let promise = Promise.reject(new Error('WHOOPS')); + + promise.then(function(value){ + // Code here doesn't run because the promise is rejected! + }, function(reason){ + // reason.message === 'WHOOPS' + }); + ``` + + @method reject + @static + @param {Any} reason value that the returned promise will be rejected with. + Useful for tooling. + @return {Promise} a promise rejected with the given `reason`. + */ + function reject$1(reason) { + /*jshint validthis:true */ + var Constructor = this; + var promise = new Constructor(noop); + reject(promise, reason); + return promise; + } + function needsResolver() { + throw new TypeError( + "You must pass a resolver function as the first argument to the promise constructor" + ); + } + function needsNew() { + throw new TypeError( + "Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function." + ); + } + /** + Promise objects represent the eventual result of an asynchronous operation. The + primary way of interacting with a promise is through its `then` method, which + registers callbacks to receive either a promise's eventual value or the reason + why the promise cannot be fulfilled. + + Terminology + ----------- + + - `promise` is an object or function with a `then` method whose behavior conforms to this specification. + - `thenable` is an object or function that defines a `then` method. + - `value` is any legal JavaScript value (including undefined, a thenable, or a promise). + - `exception` is a value that is thrown using the throw statement. + - `reason` is a value that indicates why a promise was rejected. + - `settled` the final resting state of a promise, fulfilled or rejected. + + A promise can be in one of three states: pending, fulfilled, or rejected. + + Promises that are fulfilled have a fulfillment value and are in the fulfilled + state. Promises that are rejected have a rejection reason and are in the + rejected state. A fulfillment value is never a thenable. + + Promises can also be said to *resolve* a value. If this value is also a + promise, then the original promise's settled state will match the value's + settled state. So a promise that *resolves* a promise that rejects will + itself reject, and a promise that *resolves* a promise that fulfills will + itself fulfill. + + + Basic Usage: + ------------ + + ```js + let promise = new Promise(function(resolve, reject) { + // on success + resolve(value); + + // on failure + reject(reason); + }); + + promise.then(function(value) { + // on fulfillment + }, function(reason) { + // on rejection + }); + ``` + + Advanced Usage: + --------------- + + Promises shine when abstracting away asynchronous interactions such as + `XMLHttpRequest`s. + + ```js + function getJSON(url) { + return new Promise(function(resolve, reject){ + let xhr = new XMLHttpRequest(); + + xhr.open('GET', url); + xhr.onreadystatechange = handler; + xhr.responseType = 'json'; + xhr.setRequestHeader('Accept', 'application/json'); + xhr.send(); + + function handler() { + if (this.readyState === this.DONE) { + if (this.status === 200) { + resolve(this.response); + } else { + reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']')); + } + } + }; + }); + } + + getJSON('/posts.json').then(function(json) { + // on fulfillment + }, function(reason) { + // on rejection + }); + ``` + + Unlike callbacks, promises are great composable primitives. + + ```js + Promise.all([ + getJSON('/posts'), + getJSON('/comments') + ]).then(function(values){ + values[0] // => postsJSON + values[1] // => commentsJSON + + return values; + }); + ``` + + @class Promise + @param {Function} resolver + Useful for tooling. + @constructor + */ + var Promise$1 = (function () { + function Promise(resolver) { + this[PROMISE_ID] = nextId(); + this._result = this._state = undefined; + this._subscribers = []; + if (noop !== resolver) { + typeof resolver !== "function" && needsResolver(); + this instanceof Promise + ? initializePromise(this, resolver) + : needsNew(); + } + } + /** + The primary way of interacting with a promise is through its `then` method, + which registers callbacks to receive either a promise's eventual value or the + reason why the promise cannot be fulfilled. + ```js + findUser().then(function(user){ + // user is available + }, function(reason){ + // user is unavailable, and you are given the reason why + }); + ``` + Chaining + -------- + The return value of `then` is itself a promise. This second, 'downstream' + promise is resolved with the return value of the first promise's fulfillment + or rejection handler, or rejected if the handler throws an exception. + ```js + findUser().then(function (user) { + return user.name; + }, function (reason) { + return 'default name'; + }).then(function (userName) { + // If `findUser` fulfilled, `userName` will be the user's name, otherwise it + // will be `'default name'` + }); + findUser().then(function (user) { + throw new Error('Found user, but still unhappy'); + }, function (reason) { + throw new Error('`findUser` rejected and we're unhappy'); + }).then(function (value) { + // never reached + }, function (reason) { + // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'. + // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'. + }); + ``` + If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream. + ```js + findUser().then(function (user) { + throw new PedagogicalException('Upstream error'); + }).then(function (value) { + // never reached + }).then(function (value) { + // never reached + }, function (reason) { + // The `PedgagocialException` is propagated all the way down to here + }); + ``` + Assimilation + ------------ + Sometimes the value you want to propagate to a downstream promise can only be + retrieved asynchronously. This can be achieved by returning a promise in the + fulfillment or rejection handler. The downstream promise will then be pending + until the returned promise is settled. This is called *assimilation*. + ```js + findUser().then(function (user) { + return findCommentsByAuthor(user); + }).then(function (comments) { + // The user's comments are now available + }); + ``` + If the assimliated promise rejects, then the downstream promise will also reject. + ```js + findUser().then(function (user) { + return findCommentsByAuthor(user); + }).then(function (comments) { + // If `findCommentsByAuthor` fulfills, we'll have the value here + }, function (reason) { + // If `findCommentsByAuthor` rejects, we'll have the reason here + }); + ``` + Simple Example + -------------- + Synchronous Example + ```javascript + let result; + try { + result = findResult(); + // success + } catch(reason) { + // failure + } + ``` + Errback Example + ```js + findResult(function(result, err){ + if (err) { + // failure + } else { + // success + } + }); + ``` + Promise Example; + ```javascript + findResult().then(function(result){ + // success + }, function(reason){ + // failure + }); + ``` + Advanced Example + -------------- + Synchronous Example + ```javascript + let author, books; + try { + author = findAuthor(); + books = findBooksByAuthor(author); + // success + } catch(reason) { + // failure + } + ``` + Errback Example + ```js + function foundBooks(books) { + } + function failure(reason) { + } + findAuthor(function(author, err){ + if (err) { + failure(err); + // failure + } else { + try { + findBoooksByAuthor(author, function(books, err) { + if (err) { + failure(err); + } else { + try { + foundBooks(books); + } catch(reason) { + failure(reason); + } + } + }); + } catch(error) { + failure(err); + } + // success + } + }); + ``` + Promise Example; + ```javascript + findAuthor(). + then(findBooksByAuthor). + then(function(books){ + // found books + }).catch(function(reason){ + // something went wrong + }); + ``` + @method then + @param {Function} onFulfilled + @param {Function} onRejected + Useful for tooling. + @return {Promise} + */ + /** + `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same + as the catch block of a try/catch statement. + ```js + function findAuthor(){ + throw new Error('couldn't find that author'); + } + // synchronous + try { + findAuthor(); + } catch(reason) { + // something went wrong + } + // async with promises + findAuthor().catch(function(reason){ + // something went wrong + }); + ``` + @method catch + @param {Function} onRejection + Useful for tooling. + @return {Promise} + */ + Promise.prototype.catch = function _catch(onRejection) { + return this.then(null, onRejection); + }; + /** + `finally` will be invoked regardless of the promise's fate just as native + try/catch/finally behaves + + Synchronous example: + + ```js + findAuthor() { + if (Math.random() > 0.5) { + throw new Error(); + } + return new Author(); + } + + try { + return findAuthor(); // succeed or fail + } catch(error) { + return findOtherAuther(); + } finally { + // always runs + // doesn't affect the return value + } + ``` + + Asynchronous example: + + ```js + findAuthor().catch(function(reason){ + return findOtherAuther(); + }).finally(function(){ + // author was either found, or not + }); + ``` + + @method finally + @param {Function} callback + @return {Promise} + */ + Promise.prototype.finally = function _finally(callback) { + var promise = this; + var constructor = promise.constructor; + if (isFunction(callback)) { + return promise.then( + function (value) { + return constructor.resolve(callback()).then(function () { + return value; + }); + }, + function (reason) { + return constructor.resolve(callback()).then(function () { + throw reason; + }); + } + ); + } + return promise.then(callback, callback); + }; + return Promise; + })(); + Promise$1.prototype.then = then; + Promise$1.all = all; + Promise$1.race = race; + Promise$1.resolve = resolve$1; + Promise$1.reject = reject$1; + Promise$1._setScheduler = setScheduler; + Promise$1._setAsap = setAsap; + Promise$1._asap = asap; + /*global self*/ + function polyfill() { + var local = void 0; + if (typeof __webpack_require__.g !== "undefined") { + local = __webpack_require__.g; + } else if (typeof self !== "undefined") { + local = self; + } else { + try { + local = Function("return this")(); + } catch (e) { + throw new Error( + "polyfill failed because global object is unavailable in this environment" + ); + } + } + var P = local.Promise; + if (P) { + var promiseToString = null; + try { + promiseToString = Object.prototype.toString.call(P.resolve()); + } catch (e) { + // silently ignored + } + if (promiseToString === "[object Promise]" && !P.cast) { + return; + } + } + local.Promise = Promise$1; + } + // Strange compat.. + Promise$1.polyfill = polyfill; + Promise$1.Promise = Promise$1; + return Promise$1; + }); + + /***/ + }, + + /***/ "./node_modules/events/events.js": + /*!***************************************!*\ + !*** ./node_modules/events/events.js ***! + \***************************************/ + /***/ function (module) { + "use strict"; + // Copyright Joyent, Inc. and other Node contributors. + // + // Permission is hereby granted, free of charge, to any person obtaining a + // copy of this software and associated documentation files (the + // "Software"), to deal in the Software without restriction, including + // without limitation the rights to use, copy, modify, merge, publish, + // distribute, sublicense, and/or sell copies of the Software, and to permit + // persons to whom the Software is furnished to do so, subject to the + // following conditions: + // + // The above copyright notice and this permission notice shall be included + // in all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + var R = typeof Reflect === "object" ? Reflect : null; + var ReflectApply = + R && typeof R.apply === "function" + ? R.apply + : function ReflectApply(target, receiver, args) { + return Function.prototype.apply.call(target, receiver, args); + }; + var ReflectOwnKeys; + if (R && typeof R.ownKeys === "function") { + ReflectOwnKeys = R.ownKeys; + } else if (Object.getOwnPropertySymbols) { + ReflectOwnKeys = function ReflectOwnKeys(target) { + return Object.getOwnPropertyNames(target).concat( + Object.getOwnPropertySymbols(target) + ); + }; + } else { + ReflectOwnKeys = function ReflectOwnKeys(target) { + return Object.getOwnPropertyNames(target); + }; + } + function ProcessEmitWarning(warning) { + if (console && console.warn) console.warn(warning); + } + var NumberIsNaN = + Number.isNaN || + function NumberIsNaN(value) { + return value !== value; + }; + function EventEmitter() { + EventEmitter.init.call(this); + } + module.exports = EventEmitter; + module.exports.once = once; + // Backwards-compat with node 0.10.x + EventEmitter.EventEmitter = EventEmitter; + EventEmitter.prototype._events = undefined; + EventEmitter.prototype._eventsCount = 0; + EventEmitter.prototype._maxListeners = undefined; + // By default EventEmitters will print a warning if more than 10 listeners are + // added to it. This is a useful default which helps finding memory leaks. + var defaultMaxListeners = 10; + function checkListener(listener) { + if (typeof listener !== "function") { + throw new TypeError( + 'The "listener" argument must be of type Function. Received type ' + + typeof listener + ); + } + } + Object.defineProperty(EventEmitter, "defaultMaxListeners", { + enumerable: true, + get: function () { + return defaultMaxListeners; + }, + set: function (arg) { + if (typeof arg !== "number" || arg < 0 || NumberIsNaN(arg)) { + throw new RangeError( + 'The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + + arg + + "." + ); + } + defaultMaxListeners = arg; + }, + }); + EventEmitter.init = function () { + if ( + this._events === undefined || + this._events === Object.getPrototypeOf(this)._events + ) { + this._events = Object.create(null); + this._eventsCount = 0; + } + this._maxListeners = this._maxListeners || undefined; + }; + // Obviously not all Emitters should be limited to 10. This function allows + // that to be increased. Set to zero for unlimited. + EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { + if (typeof n !== "number" || n < 0 || NumberIsNaN(n)) { + throw new RangeError( + 'The value of "n" is out of range. It must be a non-negative number. Received ' + + n + + "." + ); + } + this._maxListeners = n; + return this; + }; + function _getMaxListeners(that) { + if (that._maxListeners === undefined) + return EventEmitter.defaultMaxListeners; + return that._maxListeners; + } + EventEmitter.prototype.getMaxListeners = function getMaxListeners() { + return _getMaxListeners(this); + }; + EventEmitter.prototype.emit = function emit(type) { + var args = []; + for (var i = 1; i < arguments.length; i++) args.push(arguments[i]); + var doError = type === "error"; + var events = this._events; + if (events !== undefined) + doError = doError && events.error === undefined; + else if (!doError) return false; + // If there is no 'error' event listener then throw. + if (doError) { + var er; + if (args.length > 0) er = args[0]; + if (er instanceof Error) { + // Note: The comments on the `throw` lines are intentional, they show + // up in Node's output if this results in an unhandled exception. + throw er; // Unhandled 'error' event + } + // At least give some kind of context to the user + var err = new Error( + "Unhandled error." + (er ? " (" + er.message + ")" : "") + ); + err.context = er; + throw err; // Unhandled 'error' event + } + var handler = events[type]; + if (handler === undefined) return false; + if (typeof handler === "function") { + ReflectApply(handler, this, args); + } else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + ReflectApply(listeners[i], this, args); + } + return true; + }; + function _addListener(target, type, listener, prepend) { + var m; + var events; + var existing; + checkListener(listener); + events = target._events; + if (events === undefined) { + events = target._events = Object.create(null); + target._eventsCount = 0; + } else { + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (events.newListener !== undefined) { + target.emit( + "newListener", + type, + listener.listener ? listener.listener : listener + ); + // Re-assign `events` because a newListener handler could have caused the + // this._events to be assigned to a new object + events = target._events; + } + existing = events[type]; + } + if (existing === undefined) { + // Optimize the case of one listener. Don't need the extra array object. + existing = events[type] = listener; + ++target._eventsCount; + } else { + if (typeof existing === "function") { + // Adding the second element, need to change to array. + existing = events[type] = prepend + ? [listener, existing] + : [existing, listener]; + // If we've already got an array, just append. + } else if (prepend) { + existing.unshift(listener); + } else { + existing.push(listener); + } + // Check for listener leak + m = _getMaxListeners(target); + if (m > 0 && existing.length > m && !existing.warned) { + existing.warned = true; + // No error code for this since it is a Warning + // eslint-disable-next-line no-restricted-syntax + var w = new Error( + "Possible EventEmitter memory leak detected. " + + existing.length + + " " + + String(type) + + " listeners " + + "added. Use emitter.setMaxListeners() to " + + "increase limit" + ); + w.name = "MaxListenersExceededWarning"; + w.emitter = target; + w.type = type; + w.count = existing.length; + ProcessEmitWarning(w); + } + } + return target; + } + EventEmitter.prototype.addListener = function addListener( + type, + listener + ) { + return _addListener(this, type, listener, false); + }; + EventEmitter.prototype.on = EventEmitter.prototype.addListener; + EventEmitter.prototype.prependListener = function prependListener( + type, + listener + ) { + return _addListener(this, type, listener, true); + }; + function onceWrapper() { + if (!this.fired) { + this.target.removeListener(this.type, this.wrapFn); + this.fired = true; + if (arguments.length === 0) + return this.listener.call(this.target); + return this.listener.apply(this.target, arguments); + } + } + function _onceWrap(target, type, listener) { + var state = { + fired: false, + wrapFn: undefined, + target: target, + type: type, + listener: listener, + }; + var wrapped = onceWrapper.bind(state); + wrapped.listener = listener; + state.wrapFn = wrapped; + return wrapped; + } + EventEmitter.prototype.once = function once(type, listener) { + checkListener(listener); + this.on(type, _onceWrap(this, type, listener)); + return this; + }; + EventEmitter.prototype.prependOnceListener = + function prependOnceListener(type, listener) { + checkListener(listener); + this.prependListener(type, _onceWrap(this, type, listener)); + return this; + }; + // Emits a 'removeListener' event if and only if the listener was removed. + EventEmitter.prototype.removeListener = function removeListener( + type, + listener + ) { + var list, events, position, i, originalListener; + checkListener(listener); + events = this._events; + if (events === undefined) return this; + list = events[type]; + if (list === undefined) return this; + if (list === listener || list.listener === listener) { + if (--this._eventsCount === 0) this._events = Object.create(null); + else { + delete events[type]; + if (events.removeListener) + this.emit("removeListener", type, list.listener || listener); + } + } else if (typeof list !== "function") { + position = -1; + for (i = list.length - 1; i >= 0; i--) { + if (list[i] === listener || list[i].listener === listener) { + originalListener = list[i].listener; + position = i; + break; + } + } + if (position < 0) return this; + if (position === 0) list.shift(); + else { + spliceOne(list, position); + } + if (list.length === 1) events[type] = list[0]; + if (events.removeListener !== undefined) + this.emit("removeListener", type, originalListener || listener); + } + return this; + }; + EventEmitter.prototype.off = EventEmitter.prototype.removeListener; + EventEmitter.prototype.removeAllListeners = + function removeAllListeners(type) { + var listeners, events, i; + events = this._events; + if (events === undefined) return this; + // not listening for removeListener, no need to emit + if (events.removeListener === undefined) { + if (arguments.length === 0) { + this._events = Object.create(null); + this._eventsCount = 0; + } else if (events[type] !== undefined) { + if (--this._eventsCount === 0) + this._events = Object.create(null); + else delete events[type]; + } + return this; + } + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + var keys = Object.keys(events); + var key; + for (i = 0; i < keys.length; ++i) { + key = keys[i]; + if (key === "removeListener") continue; + this.removeAllListeners(key); + } + this.removeAllListeners("removeListener"); + this._events = Object.create(null); + this._eventsCount = 0; + return this; + } + listeners = events[type]; + if (typeof listeners === "function") { + this.removeListener(type, listeners); + } else if (listeners !== undefined) { + // LIFO order + for (i = listeners.length - 1; i >= 0; i--) { + this.removeListener(type, listeners[i]); + } + } + return this; + }; + function _listeners(target, type, unwrap) { + var events = target._events; + if (events === undefined) return []; + var evlistener = events[type]; + if (evlistener === undefined) return []; + if (typeof evlistener === "function") + return unwrap + ? [evlistener.listener || evlistener] + : [evlistener]; + return unwrap + ? unwrapListeners(evlistener) + : arrayClone(evlistener, evlistener.length); + } + EventEmitter.prototype.listeners = function listeners(type) { + return _listeners(this, type, true); + }; + EventEmitter.prototype.rawListeners = function rawListeners(type) { + return _listeners(this, type, false); + }; + EventEmitter.listenerCount = function (emitter, type) { + if (typeof emitter.listenerCount === "function") { + return emitter.listenerCount(type); + } else { + return listenerCount.call(emitter, type); + } + }; + EventEmitter.prototype.listenerCount = listenerCount; + function listenerCount(type) { + var events = this._events; + if (events !== undefined) { + var evlistener = events[type]; + if (typeof evlistener === "function") { + return 1; + } else if (evlistener !== undefined) { + return evlistener.length; + } + } + return 0; + } + EventEmitter.prototype.eventNames = function eventNames() { + return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : []; + }; + function arrayClone(arr, n) { + var copy = new Array(n); + for (var i = 0; i < n; ++i) copy[i] = arr[i]; + return copy; + } + function spliceOne(list, index) { + for (; index + 1 < list.length; index++) + list[index] = list[index + 1]; + list.pop(); + } + function unwrapListeners(arr) { + var ret = new Array(arr.length); + for (var i = 0; i < ret.length; ++i) { + ret[i] = arr[i].listener || arr[i]; + } + return ret; + } + function once(emitter, name) { + return new Promise(function (resolve, reject) { + function errorListener(err) { + emitter.removeListener(name, resolver); + reject(err); + } + function resolver() { + if (typeof emitter.removeListener === "function") { + emitter.removeListener("error", errorListener); + } + resolve([].slice.call(arguments)); + } + eventTargetAgnosticAddListener(emitter, name, resolver, { + once: true, + }); + if (name !== "error") { + addErrorHandlerIfEventEmitter(emitter, errorListener, { + once: true, + }); + } + }); + } + function addErrorHandlerIfEventEmitter(emitter, handler, flags) { + if (typeof emitter.on === "function") { + eventTargetAgnosticAddListener(emitter, "error", handler, flags); + } + } + function eventTargetAgnosticAddListener( + emitter, + name, + listener, + flags + ) { + if (typeof emitter.on === "function") { + if (flags.once) { + emitter.once(name, listener); + } else { + emitter.on(name, listener); + } + } else if (typeof emitter.addEventListener === "function") { + // EventTarget does not have `error` event semantics like Node + // EventEmitters, we do not listen for `error` events here. + emitter.addEventListener(name, function wrapListener(arg) { + // IE does not have builtin `{ once: true }` support so we + // have to do it manually. + if (flags.once) { + emitter.removeEventListener(name, wrapListener); + } + listener(arg); + }); + } else { + throw new TypeError( + 'The "emitter" argument must be of type EventEmitter. Received type ' + + typeof emitter + ); + } + } + + /***/ + }, + + /***/ "./node_modules/webworkify-webpack/index.js": + /*!**************************************************!*\ + !*** ./node_modules/webworkify-webpack/index.js ***! + \**************************************************/ + /***/ function (module, __unused_webpack_exports, __webpack_require__) { + function webpackBootstrapFunc(modules) { + /******/ // The module cache + /******/ var installedModules = {}; + /******/ // The require function + /******/ function __nested_webpack_require_164__(moduleId) { + /******/ // Check if module is in cache + /******/ if (installedModules[moduleId]) + /******/ return installedModules[moduleId].exports; + /******/ // Create a new module (and put it into the cache) + /******/ var module = (installedModules[moduleId] = { + /******/ i: moduleId, + /******/ l: false, + /******/ exports: {}, + /******/ + }); + /******/ // Execute the module function + /******/ modules[moduleId].call( + module.exports, + module, + module.exports, + __nested_webpack_require_164__ + ); + /******/ // Flag the module as loaded + /******/ module.l = true; + /******/ // Return the exports of the module + /******/ return module.exports; + /******/ + } + /******/ // expose the modules object (__webpack_modules__) + /******/ __nested_webpack_require_164__.m = modules; + /******/ // expose the module cache + /******/ __nested_webpack_require_164__.c = installedModules; + /******/ // identity function for calling harmony imports with the correct context + /******/ __nested_webpack_require_164__.i = function (value) { + return value; + }; + /******/ // define getter function for harmony exports + /******/ __nested_webpack_require_164__.d = function ( + exports, + name, + getter + ) { + /******/ if (!__nested_webpack_require_164__.o(exports, name)) { + /******/ Object.defineProperty(exports, name, { + /******/ configurable: false, + /******/ enumerable: true, + /******/ get: getter, + /******/ + }); + /******/ + } + /******/ + }; + /******/ // define __esModule on exports + /******/ __nested_webpack_require_164__.r = function (exports) { + /******/ Object.defineProperty(exports, "__esModule", { + value: true, + }); + /******/ + }; + /******/ // getDefaultExport function for compatibility with non-harmony modules + /******/ __nested_webpack_require_164__.n = function (module) { + /******/ var getter = + module && module.__esModule + ? /******/ function getDefault() { + return module["default"]; + } + : /******/ function getModuleExports() { + return module; + }; + /******/ __nested_webpack_require_164__.d(getter, "a", getter); + /******/ return getter; + /******/ + }; + /******/ // Object.prototype.hasOwnProperty.call + /******/ __nested_webpack_require_164__.o = function ( + object, + property + ) { + return Object.prototype.hasOwnProperty.call(object, property); + }; + /******/ // __webpack_public_path__ + /******/ __nested_webpack_require_164__.p = "/"; + /******/ // on error function for async loading + /******/ __nested_webpack_require_164__.oe = function (err) { + console.error(err); + throw err; + }; + var f = __nested_webpack_require_164__( + (__nested_webpack_require_164__.s = ENTRY_MODULE) + ); + return f.default || f; // try to call default if defined to also support babel esmodule exports + } + var moduleNameReqExp = "[\\.|\\-|\\+|\\w|/|@]+"; + var dependencyRegExp = + "\\(\\s*(/\\*.*?\\*/)?\\s*.*?(" + moduleNameReqExp + ").*?\\)"; // additional chars when output.pathinfo is true + // http://stackoverflow.com/a/2593661/130442 + function quoteRegExp(str) { + return (str + "").replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&"); + } + function isNumeric(n) { + return !isNaN(1 * n); // 1 * n converts integers, integers as string ("123"), 1e3 and "1e3" to integers and strings to NaN + } + function getModuleDependencies(sources, module, queueName) { + var retval = {}; + retval[queueName] = []; + var fnString = module.toString(); + var wrapperSignature = fnString.match( + /^function\s?\w*\(\w+,\s*\w+,\s*(\w+)\)/ + ); + if (!wrapperSignature) return retval; + var webpackRequireName = wrapperSignature[1]; + // main bundle deps + var re = new RegExp( + "(\\\\n|\\W)" + + quoteRegExp(webpackRequireName) + + dependencyRegExp, + "g" + ); + var match; + while ((match = re.exec(fnString))) { + if (match[3] === "dll-reference") continue; + retval[queueName].push(match[3]); + } + // dll deps + re = new RegExp( + "\\(" + + quoteRegExp(webpackRequireName) + + '\\("(dll-reference\\s(' + + moduleNameReqExp + + '))"\\)\\)' + + dependencyRegExp, + "g" + ); + while ((match = re.exec(fnString))) { + if (!sources[match[2]]) { + retval[queueName].push(match[1]); + sources[match[2]] = __webpack_require__(match[1]).m; + } + retval[match[2]] = retval[match[2]] || []; + retval[match[2]].push(match[4]); + } + // convert 1e3 back to 1000 - this can be important after uglify-js converted 1000 to 1e3 + var keys = Object.keys(retval); + for (var i = 0; i < keys.length; i++) { + for (var j = 0; j < retval[keys[i]].length; j++) { + if (isNumeric(retval[keys[i]][j])) { + retval[keys[i]][j] = 1 * retval[keys[i]][j]; + } + } + } + return retval; + } + function hasValuesInQueues(queues) { + var keys = Object.keys(queues); + return keys.reduce(function (hasValues, key) { + return hasValues || queues[key].length > 0; + }, false); + } + function getRequiredModules(sources, moduleId) { + var modulesQueue = { + main: [moduleId], + }; + var requiredModules = { + main: [], + }; + var seenModules = { + main: {}, + }; + while (hasValuesInQueues(modulesQueue)) { + var queues = Object.keys(modulesQueue); + for (var i = 0; i < queues.length; i++) { + var queueName = queues[i]; + var queue = modulesQueue[queueName]; + var moduleToCheck = queue.pop(); + seenModules[queueName] = seenModules[queueName] || {}; + if ( + seenModules[queueName][moduleToCheck] || + !sources[queueName][moduleToCheck] + ) + continue; + seenModules[queueName][moduleToCheck] = true; + requiredModules[queueName] = requiredModules[queueName] || []; + requiredModules[queueName].push(moduleToCheck); + var newModules = getModuleDependencies( + sources, + sources[queueName][moduleToCheck], + queueName + ); + var newModulesKeys = Object.keys(newModules); + for (var j = 0; j < newModulesKeys.length; j++) { + modulesQueue[newModulesKeys[j]] = + modulesQueue[newModulesKeys[j]] || []; + modulesQueue[newModulesKeys[j]] = modulesQueue[ + newModulesKeys[j] + ].concat(newModules[newModulesKeys[j]]); + } + } + } + return requiredModules; + } + module.exports = function (moduleId, options) { + options = options || {}; + var sources = { + main: __webpack_require__.m, + }; + var requiredModules = options.all + ? { main: Object.keys(sources.main) } + : getRequiredModules(sources, moduleId); + var src = ""; + Object.keys(requiredModules) + .filter(function (m) { + return m !== "main"; + }) + .forEach(function (module) { + var entryModule = 0; + while (requiredModules[module][entryModule]) { + entryModule++; + } + requiredModules[module].push(entryModule); + sources[module][entryModule] = + "(function(module, exports, __webpack_require__) { module.exports = __webpack_require__; })"; + src = + src + + "var " + + module + + " = (" + + webpackBootstrapFunc + .toString() + .replace("ENTRY_MODULE", JSON.stringify(entryModule)) + + ")({" + + requiredModules[module] + .map(function (id) { + return ( + "" + + JSON.stringify(id) + + ": " + + sources[module][id].toString() + ); + }) + .join(",") + + "});\n"; + }); + src = + src + + "new ((" + + webpackBootstrapFunc + .toString() + .replace("ENTRY_MODULE", JSON.stringify(moduleId)) + + ")({" + + requiredModules.main + .map(function (id) { + return ( + "" + JSON.stringify(id) + ": " + sources.main[id].toString() + ); + }) + .join(",") + + "}))(self);"; + var blob = new window.Blob([src], { type: "text/javascript" }); + if (options.bare) { + return blob; + } + var URL = + window.URL || window.webkitURL || window.mozURL || window.msURL; + var workerUrl = URL.createObjectURL(blob); + var worker = new window.Worker(workerUrl); + worker.objectURL = workerUrl; + return worker; + }; + + /***/ + }, + + /***/ "./src/config.js": + /*!***********************!*\ + !*** ./src/config.js ***! + \***********************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ defaultConfig: function () { + return /* binding */ defaultConfig; + }, + /* harmony export */ createDefaultConfig: function () { + return /* binding */ createDefaultConfig; + }, + /* harmony export */ + }); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + var defaultConfig = { + enableWorker: false, + enableStashBuffer: true, + stashInitialSize: undefined, + isLive: false, + lazyLoad: true, + lazyLoadMaxDuration: 3 * 60, + lazyLoadRecoverDuration: 30, + deferLoadAfterSourceOpen: true, + // autoCleanupSourceBuffer: default as false, leave unspecified + autoCleanupMaxBackwardDuration: 3 * 60, + autoCleanupMinBackwardDuration: 2 * 60, + statisticsInfoReportInterval: 600, + fixAudioTimestampGap: true, + accurateSeek: false, + seekType: "range", + seekParamStart: "bstart", + seekParamEnd: "bend", + rangeLoadZeroStart: false, + customSeekHandler: undefined, + reuseRedirectedURL: false, + // referrerPolicy: leave as unspecified + headers: undefined, + customLoader: undefined, + }; + function createDefaultConfig() { + return Object.assign({}, defaultConfig); + } + + /***/ + }, + + /***/ "./src/core/features.js": + /*!******************************!*\ + !*** ./src/core/features.js ***! + \******************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony import */ var _io_io_controller_js__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__( + /*! ../io/io-controller.js */ "./src/io/io-controller.js" + ); + /* harmony import */ var _config_js__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__(/*! ../config.js */ "./src/config.js"); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + var Features = /** @class */ (function () { + function Features() {} + Features.supportMSEH264Playback = function () { + var avc_aac_mime_type = + 'video/mp4; codecs="avc1.42E01E,mp4a.40.2"'; + var support_w3c_mse = + self.MediaSource && + self.MediaSource.isTypeSupported(avc_aac_mime_type); + var support_apple_mme = + self.ManagedMediaSource && + self.ManagedMediaSource.isTypeSupported(avc_aac_mime_type); + return support_w3c_mse || support_apple_mme; + }; + Features.supportMSEH265Playback = function () { + var hevc_mime_type = 'video/mp4; codecs="hvc1.1.6.L93.B0"'; + var support_w3c_mse = + self.MediaSource && + self.MediaSource.isTypeSupported(hevc_mime_type); + var support_apple_mme = + self.ManagedMediaSource && + self.ManagedMediaSource.isTypeSupported(hevc_mime_type); + return support_w3c_mse || support_apple_mme; + }; + Features.supportNetworkStreamIO = function () { + var ioctl = + new _io_io_controller_js__WEBPACK_IMPORTED_MODULE_0__.default( + {}, + (0, + _config_js__WEBPACK_IMPORTED_MODULE_1__.createDefaultConfig)() + ); + var loaderType = ioctl.loaderType; + ioctl.destroy(); + return ( + loaderType == "fetch-stream-loader" || + loaderType == "xhr-moz-chunked-loader" + ); + }; + Features.getNetworkLoaderTypeName = function () { + var ioctl = + new _io_io_controller_js__WEBPACK_IMPORTED_MODULE_0__.default( + {}, + (0, + _config_js__WEBPACK_IMPORTED_MODULE_1__.createDefaultConfig)() + ); + var loaderType = ioctl.loaderType; + ioctl.destroy(); + return loaderType; + }; + Features.supportNativeMediaPlayback = function (mimeType) { + if (Features.videoElement == undefined) { + Features.videoElement = window.document.createElement("video"); + } + var canPlay = Features.videoElement.canPlayType(mimeType); + return canPlay === "probably" || canPlay == "maybe"; + }; + Features.getFeatureList = function () { + var features = { + mseFlvPlayback: false, + mseLiveFlvPlayback: false, + networkStreamIO: false, + networkLoaderName: "", + nativeMP4H264Playback: false, + nativeMP4H265Playback: false, + nativeWebmVP8Playback: false, + nativeWebmVP9Playback: false, + }; + features.mseFlvPlayback = Features.supportMSEH264Playback(); + features.networkStreamIO = Features.supportNetworkStreamIO(); + features.networkLoaderName = Features.getNetworkLoaderTypeName(); + features.mseLiveFlvPlayback = + features.mseFlvPlayback && features.networkStreamIO; + features.nativeMP4H264Playback = + Features.supportNativeMediaPlayback( + 'video/mp4; codecs="avc1.42001E, mp4a.40.2"' + ); + features.nativeMP4H265Playback = + Features.supportNativeMediaPlayback( + 'video/mp4; codecs="hvc1.1.6.L93.B0"' + ); + features.nativeWebmVP8Playback = + Features.supportNativeMediaPlayback( + 'video/webm; codecs="vp8.0, vorbis"' + ); + features.nativeWebmVP9Playback = + Features.supportNativeMediaPlayback('video/webm; codecs="vp9"'); + return features; + }; + return Features; + })(); + /* harmony default export */ __webpack_exports__["default"] = + Features; + + /***/ + }, + + /***/ "./src/core/media-info.js": + /*!********************************!*\ + !*** ./src/core/media-info.js ***! + \********************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + var MediaInfo = /** @class */ (function () { + function MediaInfo() { + this.mimeType = null; + this.duration = null; + this.hasAudio = null; + this.hasVideo = null; + this.audioCodec = null; + this.videoCodec = null; + this.audioDataRate = null; + this.videoDataRate = null; + this.audioSampleRate = null; + this.audioChannelCount = 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; + this.metadata = null; + this.segments = null; // MediaInfo[] + this.segmentCount = null; + this.hasKeyframesIndex = null; + this.keyframesIndex = null; + } + MediaInfo.prototype.isComplete = function () { + var audioInfoComplete = + this.hasAudio === false || + (this.hasAudio === true && + this.audioCodec != null && + this.audioSampleRate != null && + this.audioChannelCount != null); + 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); + // keyframesIndex may not be present + return ( + this.mimeType != null && audioInfoComplete && videoInfoComplete + ); + }; + MediaInfo.prototype.isSeekable = function () { + return this.hasKeyframesIndex === true; + }; + MediaInfo.prototype.getNearestKeyframe = function (milliseconds) { + if (this.keyframesIndex == null) { + return null; + } + var table = this.keyframesIndex; + var keyframeIdx = this._search(table.times, milliseconds); + return { + index: keyframeIdx, + milliseconds: table.times[keyframeIdx], + fileposition: table.filepositions[keyframeIdx], + }; + }; + MediaInfo.prototype._search = function (list, value) { + var idx = 0; + var last = list.length - 1; + var mid = 0; + var lbound = 0; + var ubound = last; + if (value < list[0]) { + idx = 0; + lbound = ubound + 1; // skip search + } + while (lbound <= ubound) { + mid = lbound + Math.floor((ubound - lbound) / 2); + if ( + mid === last || + (value >= list[mid] && value < list[mid + 1]) + ) { + idx = mid; + break; + } else if (list[mid] < value) { + lbound = mid + 1; + } else { + ubound = mid - 1; + } + } + return idx; + }; + return MediaInfo; + })(); + /* harmony default export */ __webpack_exports__["default"] = + MediaInfo; + + /***/ + }, + + /***/ "./src/core/media-segment-info.js": + /*!****************************************!*\ + !*** ./src/core/media-segment-info.js ***! + \****************************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ SampleInfo: function () { + return /* binding */ SampleInfo; + }, + /* harmony export */ MediaSegmentInfo: function () { + return /* binding */ MediaSegmentInfo; + }, + /* harmony export */ IDRSampleList: function () { + return /* binding */ IDRSampleList; + }, + /* harmony export */ MediaSegmentInfoList: function () { + return /* binding */ MediaSegmentInfoList; + }, + /* harmony export */ + }); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + // Represents an media sample (audio / video) + var SampleInfo = /** @class */ (function () { + function SampleInfo(dts, pts, duration, originalDts, isSync) { + this.dts = dts; + this.pts = pts; + this.duration = duration; + this.originalDts = originalDts; + this.isSyncPoint = isSync; + this.fileposition = null; + } + return SampleInfo; + })(); + + // Media Segment concept is defined in Media Source Extensions spec. + // Particularly in ISO BMFF format, an Media Segment contains a moof box followed by a mdat box. + var MediaSegmentInfo = /** @class */ (function () { + function MediaSegmentInfo() { + this.beginDts = 0; + this.endDts = 0; + this.beginPts = 0; + this.endPts = 0; + this.originalBeginDts = 0; + this.originalEndDts = 0; + this.syncPoints = []; // SampleInfo[n], for video IDR frames only + this.firstSample = null; // SampleInfo + this.lastSample = null; // SampleInfo + } + MediaSegmentInfo.prototype.appendSyncPoint = function (sampleInfo) { + sampleInfo.isSyncPoint = true; + this.syncPoints.push(sampleInfo); + }; + return MediaSegmentInfo; + })(); + + // Ordered list for recording video IDR frames, sorted by originalDts + var IDRSampleList = /** @class */ (function () { + function IDRSampleList() { + this._list = []; + } + IDRSampleList.prototype.clear = function () { + this._list = []; + }; + IDRSampleList.prototype.appendArray = function (syncPoints) { + var list = this._list; + if (syncPoints.length === 0) { + return; + } + if ( + list.length > 0 && + syncPoints[0].originalDts < list[list.length - 1].originalDts + ) { + this.clear(); + } + Array.prototype.push.apply(list, syncPoints); + }; + IDRSampleList.prototype.getLastSyncPointBeforeDts = function (dts) { + if (this._list.length == 0) { + return null; + } + var list = this._list; + var idx = 0; + var last = list.length - 1; + var mid = 0; + var lbound = 0; + var ubound = last; + if (dts < list[0].dts) { + idx = 0; + lbound = ubound + 1; + } + while (lbound <= ubound) { + mid = lbound + Math.floor((ubound - lbound) / 2); + if ( + mid === last || + (dts >= list[mid].dts && dts < list[mid + 1].dts) + ) { + idx = mid; + break; + } else if (list[mid].dts < dts) { + lbound = mid + 1; + } else { + ubound = mid - 1; + } + } + return this._list[idx]; + }; + return IDRSampleList; + })(); + + // Data structure for recording information of media segments in single track. + var MediaSegmentInfoList = /** @class */ (function () { + function MediaSegmentInfoList(type) { + this._type = type; + this._list = []; + this._lastAppendLocation = -1; // cached last insert location + } + Object.defineProperty(MediaSegmentInfoList.prototype, "type", { + get: function () { + return this._type; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(MediaSegmentInfoList.prototype, "length", { + get: function () { + return this._list.length; + }, + enumerable: false, + configurable: true, + }); + MediaSegmentInfoList.prototype.isEmpty = function () { + return this._list.length === 0; + }; + MediaSegmentInfoList.prototype.clear = function () { + this._list = []; + this._lastAppendLocation = -1; + }; + MediaSegmentInfoList.prototype._searchNearestSegmentBefore = + function (originalBeginDts) { + var list = this._list; + if (list.length === 0) { + return -2; + } + var last = list.length - 1; + var mid = 0; + var lbound = 0; + var ubound = last; + var idx = 0; + if (originalBeginDts < list[0].originalBeginDts) { + idx = -1; + return idx; + } + while (lbound <= ubound) { + mid = lbound + Math.floor((ubound - lbound) / 2); + if ( + mid === last || + (originalBeginDts > list[mid].lastSample.originalDts && + originalBeginDts < list[mid + 1].originalBeginDts) + ) { + idx = mid; + break; + } else if (list[mid].originalBeginDts < originalBeginDts) { + lbound = mid + 1; + } else { + ubound = mid - 1; + } + } + return idx; + }; + MediaSegmentInfoList.prototype._searchNearestSegmentAfter = + function (originalBeginDts) { + return this._searchNearestSegmentBefore(originalBeginDts) + 1; + }; + MediaSegmentInfoList.prototype.append = function ( + mediaSegmentInfo + ) { + var list = this._list; + var msi = mediaSegmentInfo; + var lastAppendIdx = this._lastAppendLocation; + var insertIdx = 0; + 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)) + ) { + insertIdx = lastAppendIdx + 1; // use cached location idx + } else { + if (list.length > 0) { + insertIdx = + this._searchNearestSegmentBefore(msi.originalBeginDts) + 1; + } + } + this._lastAppendLocation = insertIdx; + this._list.splice(insertIdx, 0, msi); + }; + MediaSegmentInfoList.prototype.getLastSegmentBefore = function ( + originalBeginDts + ) { + var idx = this._searchNearestSegmentBefore(originalBeginDts); + if (idx >= 0) { + return this._list[idx]; + } else { + // -1 + return null; + } + }; + MediaSegmentInfoList.prototype.getLastSampleBefore = function ( + originalBeginDts + ) { + var segment = this.getLastSegmentBefore(originalBeginDts); + if (segment != null) { + return segment.lastSample; + } else { + return null; + } + }; + MediaSegmentInfoList.prototype.getLastSyncPointBefore = function ( + originalBeginDts + ) { + var segmentIdx = + this._searchNearestSegmentBefore(originalBeginDts); + var syncPoints = this._list[segmentIdx].syncPoints; + while (syncPoints.length === 0 && segmentIdx > 0) { + segmentIdx--; + syncPoints = this._list[segmentIdx].syncPoints; + } + if (syncPoints.length > 0) { + return syncPoints[syncPoints.length - 1]; + } else { + return null; + } + }; + return MediaSegmentInfoList; + })(); + + /***/ + }, + + /***/ "./src/core/mse-controller.js": + /*!************************************!*\ + !*** ./src/core/mse-controller.js ***! + \************************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony import */ var events__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__( + /*! events */ "./node_modules/events/events.js" + ); + /* harmony import */ var events__WEBPACK_IMPORTED_MODULE_0___default = + /*#__PURE__*/ __webpack_require__.n( + events__WEBPACK_IMPORTED_MODULE_0__ + ); + /* harmony import */ var _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__( + /*! ../utils/logger.js */ "./src/utils/logger.js" + ); + /* harmony import */ var _utils_browser_js__WEBPACK_IMPORTED_MODULE_2__ = + __webpack_require__( + /*! ../utils/browser.js */ "./src/utils/browser.js" + ); + /* harmony import */ var _mse_events_js__WEBPACK_IMPORTED_MODULE_3__ = + __webpack_require__( + /*! ./mse-events.js */ "./src/core/mse-events.js" + ); + /* harmony import */ var _media_segment_info_js__WEBPACK_IMPORTED_MODULE_4__ = + __webpack_require__( + /*! ./media-segment-info.js */ "./src/core/media-segment-info.js" + ); + /* harmony import */ var _utils_exception_js__WEBPACK_IMPORTED_MODULE_5__ = + __webpack_require__( + /*! ../utils/exception.js */ "./src/utils/exception.js" + ); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + // Media Source Extensions controller + var MSEController = /** @class */ (function () { + function MSEController(config) { + this.TAG = "MSEController"; + this._config = config; + this._emitter = + new (events__WEBPACK_IMPORTED_MODULE_0___default())(); + if ( + this._config.isLive && + this._config.autoCleanupSourceBuffer == undefined + ) { + // For live stream, do auto cleanup by default + this._config.autoCleanupSourceBuffer = true; + } + this.e = { + onSourceOpen: this._onSourceOpen.bind(this), + onSourceEnded: this._onSourceEnded.bind(this), + onSourceClose: this._onSourceClose.bind(this), + onStartStreaming: this._onStartStreaming.bind(this), + onEndStreaming: this._onEndStreaming.bind(this), + onQualityChange: this._onQualityChange.bind(this), + onSourceBufferError: this._onSourceBufferError.bind(this), + onSourceBufferUpdateEnd: + this._onSourceBufferUpdateEnd.bind(this), + }; + // Use ManagedMediaSource only if w3c MediaSource is not available (e.g. iOS Safari) + this._useManagedMediaSource = + "ManagedMediaSource" in self && !("MediaSource" in self); + this._mediaSource = null; + this._mediaSourceObjectURL = null; + this._mediaElementProxy = null; + this._isBufferFull = false; + this._hasPendingEos = false; + this._requireSetMediaDuration = false; + this._pendingMediaDuration = 0; + this._pendingSourceBufferInit = []; + this._mimeTypes = { + video: null, + audio: null, + }; + this._sourceBuffers = { + video: null, + audio: null, + }; + this._lastInitSegments = { + video: null, + audio: null, + }; + this._pendingSegments = { + video: [], + audio: [], + }; + this._pendingRemoveRanges = { + video: [], + audio: [], + }; + this._idrList = + new _media_segment_info_js__WEBPACK_IMPORTED_MODULE_4__.IDRSampleList(); + } + MSEController.prototype.destroy = function () { + if (this._mediaElementProxy || this._mediaSource) { + this.detachMediaElement(); + } + this.e = null; + this._emitter.removeAllListeners(); + this._emitter = null; + }; + MSEController.prototype.on = function (event, listener) { + this._emitter.addListener(event, listener); + }; + MSEController.prototype.off = function (event, listener) { + this._emitter.removeListener(event, listener); + }; + MSEController.prototype.attachMediaElement = function ( + mediaElementProxy + ) { + if (this._mediaSource) { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_5__.IllegalStateException( + "MediaSource has been attached to an HTMLMediaElement!" + ); + } + if (this._useManagedMediaSource) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.v( + this.TAG, + "Using ManagedMediaSource" + ); + } + var ms = (this._mediaSource = this._useManagedMediaSource + ? new self.ManagedMediaSource() + : new self.MediaSource()); + ms.addEventListener("sourceopen", this.e.onSourceOpen); + ms.addEventListener("sourceended", this.e.onSourceEnded); + ms.addEventListener("sourceclose", this.e.onSourceClose); + if (this._useManagedMediaSource) { + ms.addEventListener("startstreaming", this.e.onStartStreaming); + ms.addEventListener("endstreaming", this.e.onEndStreaming); + ms.addEventListener("qualitychange", this.e.onQualityChange); + } + this._mediaElementProxy = mediaElementProxy; + this._mediaSourceObjectURL = window.URL.createObjectURL( + this._mediaSource + ); + mediaElementProxy.src = this._mediaSourceObjectURL; + }; + MSEController.prototype.detachMediaElement = function () { + if (this._mediaSource) { + var ms = this._mediaSource; + for (var type in this._sourceBuffers) { + // pending segments should be discard + var ps = this._pendingSegments[type]; + ps.splice(0, ps.length); + this._pendingSegments[type] = null; + this._pendingRemoveRanges[type] = null; + this._lastInitSegments[type] = null; + // remove all sourcebuffers + var sb = this._sourceBuffers[type]; + if (sb) { + if (ms.readyState !== "closed") { + // ms edge can throw an error: Unexpected call to method or property access + try { + ms.removeSourceBuffer(sb); + } catch (error) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.e( + this.TAG, + error.message + ); + } + sb.removeEventListener( + "error", + this.e.onSourceBufferError + ); + sb.removeEventListener( + "updateend", + this.e.onSourceBufferUpdateEnd + ); + } + this._mimeTypes[type] = null; + this._sourceBuffers[type] = null; + } + } + if (ms.readyState === "open") { + try { + ms.endOfStream(); + } catch (error) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.e( + this.TAG, + error.message + ); + } + } + ms.removeEventListener("sourceopen", this.e.onSourceOpen); + ms.removeEventListener("sourceended", this.e.onSourceEnded); + ms.removeEventListener("sourceclose", this.e.onSourceClose); + if (this._useManagedMediaSource) { + ms.removeEventListener( + "startstraming", + this.e.onStartStreaming + ); + ms.removeEventListener("endstreaming", this.e.onEndStreaming); + ms.removeEventListener( + "qualitychange", + this.e.onQualityChange + ); + } + this._pendingSourceBufferInit = []; + this._isBufferFull = false; + this._idrList.clear(); + this._mediaSource = null; + } + if (this._mediaElementProxy) { + this._mediaElementProxy.src = ""; + this._mediaElementProxy.removeAttribute("src"); + this._mediaElementProxy = null; + } + if (this._mediaSourceObjectURL) { + window.URL.revokeObjectURL(this._mediaSourceObjectURL); + this._mediaSourceObjectURL = null; + } + }; + MSEController.prototype.isManagedMediaSource = function () { + return this._useManagedMediaSource; + }; + MSEController.prototype.getObject = function () { + if (!this._mediaSource) { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_5__.IllegalStateException( + "MediaSource has not been initialized yet!" + ); + } + return this._mediaSource; + }; + MSEController.prototype.getHandle = function () { + if (!this._mediaSource) { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_5__.IllegalStateException( + "MediaSource has not been initialized yet!" + ); + } + return this._mediaSource.handle; + }; + MSEController.prototype.getObjectURL = function () { + if (!this._mediaSource) { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_5__.IllegalStateException( + "MediaSource has not been initialized yet!" + ); + } + if (this._mediaSourceObjectURL == null) { + this._mediaSourceObjectURL = URL.createObjectURL( + this._mediaSource + ); + } + return this._mediaSourceObjectURL; + }; + MSEController.prototype.revokeObjectURL = function () { + if (this._mediaSourceObjectURL) { + URL.revokeObjectURL(this._mediaSourceObjectURL); + this._mediaSourceObjectURL = null; + } + }; + MSEController.prototype.appendInitSegment = function ( + initSegment, + deferred + ) { + if (deferred === void 0) { + deferred = undefined; + } + if ( + !this._mediaSource || + this._mediaSource.readyState !== "open" || + this._mediaSource.streaming === false + ) { + // sourcebuffer creation requires mediaSource.readyState === 'open' + // so we defer the sourcebuffer creation, until sourceopen event triggered + this._pendingSourceBufferInit.push(initSegment); + // make sure that this InitSegment is in the front of pending segments queue + this._pendingSegments[initSegment.type].push(initSegment); + return; + } + var is = initSegment; + var mimeType = "" + is.container; + if (is.codec && is.codec.length > 0) { + if ( + is.codec === "opus" && + _utils_browser_js__WEBPACK_IMPORTED_MODULE_2__.default.safari + ) { + is.codec = "Opus"; + } + mimeType += ";codecs=" + is.codec; + } + var firstInitSegment = false; + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.v( + this.TAG, + "Received Initialization Segment, mimeType: " + mimeType + ); + this._lastInitSegments[is.type] = is; + if (mimeType !== this._mimeTypes[is.type]) { + if (!this._mimeTypes[is.type]) { + // empty, first chance create sourcebuffer + firstInitSegment = true; + try { + var sb = (this._sourceBuffers[is.type] = + this._mediaSource.addSourceBuffer(mimeType)); + sb.addEventListener("error", this.e.onSourceBufferError); + sb.addEventListener( + "updateend", + this.e.onSourceBufferUpdateEnd + ); + } catch (error) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.e( + this.TAG, + error.message + ); + this._emitter.emit( + _mse_events_js__WEBPACK_IMPORTED_MODULE_3__.default.ERROR, + { code: error.code, msg: error.message } + ); + return; + } + } else { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.v( + this.TAG, + "Notice: " + + is.type + + " mimeType changed, origin: " + + this._mimeTypes[is.type] + + ", target: " + + mimeType + ); + } + this._mimeTypes[is.type] = mimeType; + } + if (!deferred) { + // deferred means this InitSegment has been pushed to pendingSegments queue + this._pendingSegments[is.type].push(is); + } + if (!firstInitSegment) { + // append immediately only if init segment in subsequence + if ( + this._sourceBuffers[is.type] && + !this._sourceBuffers[is.type].updating + ) { + this._doAppendSegments(); + } + } + if ( + _utils_browser_js__WEBPACK_IMPORTED_MODULE_2__.default.safari && + is.container === "audio/mpeg" && + is.mediaDuration > 0 + ) { + // 'audio/mpeg' track under Safari may cause MediaElement's duration to be NaN + // Manually correct MediaSource.duration to make progress bar seekable, and report right duration + this._requireSetMediaDuration = true; + this._pendingMediaDuration = is.mediaDuration / 1000; // in seconds + this._updateMediaSourceDuration(); + } + }; + MSEController.prototype.appendMediaSegment = function ( + mediaSegment + ) { + var ms = mediaSegment; + this._pendingSegments[ms.type].push(ms); + if ( + this._config.autoCleanupSourceBuffer && + this._needCleanupSourceBuffer() + ) { + this._doCleanupSourceBuffer(); + } + var sb = this._sourceBuffers[ms.type]; + if (sb && !sb.updating && !this._hasPendingRemoveRanges()) { + this._doAppendSegments(); + } + }; + MSEController.prototype.seek = function (seconds) { + // remove all appended buffers + for (var type in this._sourceBuffers) { + if (!this._sourceBuffers[type]) { + continue; + } + // abort current buffer append algorithm + var sb = this._sourceBuffers[type]; + if (this._mediaSource.readyState === "open") { + try { + // If range removal algorithm is running, InvalidStateError will be throwed + // Ignore it. + sb.abort(); + } catch (error) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.e( + this.TAG, + error.message + ); + } + } + // IDRList should be clear + this._idrList.clear(); + // pending segments should be discard + var ps = this._pendingSegments[type]; + ps.splice(0, ps.length); + if (this._mediaSource.readyState === "closed") { + // Parent MediaSource object has been detached from HTMLMediaElement + continue; + } + // record ranges to be remove from SourceBuffer + for (var i = 0; i < sb.buffered.length; i++) { + var start = sb.buffered.start(i); + var end = sb.buffered.end(i); + this._pendingRemoveRanges[type].push({ + start: start, + end: end, + }); + } + // if sb is not updating, let's remove ranges now! + if (!sb.updating) { + this._doRemoveRanges(); + } + // Safari 10 may get InvalidStateError in the later appendBuffer() after SourceBuffer.remove() call + // Internal parser's state may be invalid at this time. Re-append last InitSegment to workaround. + // Related issue: https://bugs.webkit.org/show_bug.cgi?id=159230 + if ( + _utils_browser_js__WEBPACK_IMPORTED_MODULE_2__.default.safari + ) { + var lastInitSegment = this._lastInitSegments[type]; + if (lastInitSegment) { + this._pendingSegments[type].push(lastInitSegment); + if (!sb.updating) { + this._doAppendSegments(); + } + } + } + } + }; + MSEController.prototype.endOfStream = function () { + var ms = this._mediaSource; + var sb = this._sourceBuffers; + if (!ms || ms.readyState !== "open") { + if ( + ms && + ms.readyState === "closed" && + this._hasPendingSegments() + ) { + // If MediaSource hasn't turned into open state, and there're pending segments + // Mark pending endOfStream, defer call until all pending segments appended complete + this._hasPendingEos = true; + } + return; + } + if ( + (sb.video && sb.video.updating) || + (sb.audio && sb.audio.updating) + ) { + // If any sourcebuffer is updating, defer endOfStream operation + // See _onSourceBufferUpdateEnd() + this._hasPendingEos = true; + } else { + this._hasPendingEos = false; + // Notify media data loading complete + // This is helpful for correcting total duration to match last media segment + // Otherwise MediaElement's ended event may not be triggered + ms.endOfStream(); + } + }; + MSEController.prototype.getNearestKeyframe = function (dts) { + return this._idrList.getLastSyncPointBeforeDts(dts); + }; + MSEController.prototype._needCleanupSourceBuffer = function () { + if (!this._config.autoCleanupSourceBuffer) { + return false; + } + // var currentTime = this._mediaElementProxy.getCurrentTime(); + var currentTime = this._mediaElementProxy.currentTime; + for (var type in this._sourceBuffers) { + var sb = this._sourceBuffers[type]; + if (sb) { + var buffered = sb.buffered; + if (buffered.length >= 1) { + if ( + currentTime - buffered.start(0) >= + this._config.autoCleanupMaxBackwardDuration + ) { + return true; + } + } + } + } + return false; + }; + MSEController.prototype._doCleanupSourceBuffer = function () { + // var currentTime = this._mediaElementProxy.getCurrentTime(); + var currentTime = this._mediaElementProxy.currentTime; + for (var type in this._sourceBuffers) { + var sb = this._sourceBuffers[type]; + if (sb) { + var buffered = sb.buffered; + var doRemove = false; + for (var i = 0; i < buffered.length; i++) { + var start = buffered.start(i); + var end = buffered.end(i); + if (start <= currentTime && currentTime < end + 3) { + // padding 3 seconds + if ( + currentTime - start >= + this._config.autoCleanupMaxBackwardDuration + ) { + doRemove = true; + var removeEnd = + currentTime - + this._config.autoCleanupMinBackwardDuration; + this._pendingRemoveRanges[type].push({ + start: start, + end: removeEnd, + }); + } + } else if (end < currentTime) { + doRemove = true; + this._pendingRemoveRanges[type].push({ + start: start, + end: end, + }); + } + } + if (doRemove && !sb.updating) { + this._doRemoveRanges(); + } + } + } + }; + MSEController.prototype._updateMediaSourceDuration = function () { + var sb = this._sourceBuffers; + if ( + this._mediaElementProxy.getReadyState() === 0 || + this._mediaSource.readyState !== "open" + ) { + return; + } + if ( + (sb.video && sb.video.updating) || + (sb.audio && sb.audio.updating) + ) { + return; + } + var current = this._mediaSource.duration; + var target = this._pendingMediaDuration; + if (target > 0 && (isNaN(current) || target > current)) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.v( + this.TAG, + "Update MediaSource duration from " + + current + + " to " + + target + ); + this._mediaSource.duration = target; + } + this._requireSetMediaDuration = false; + this._pendingMediaDuration = 0; + }; + MSEController.prototype._doRemoveRanges = function () { + for (var type in this._pendingRemoveRanges) { + if ( + !this._sourceBuffers[type] || + this._sourceBuffers[type].updating + ) { + continue; + } + var sb = this._sourceBuffers[type]; + var ranges = this._pendingRemoveRanges[type]; + while (ranges.length && !sb.updating) { + var range = ranges.shift(); + sb.remove(range.start, range.end); + } + } + }; + MSEController.prototype._doAppendSegments = function () { + var pendingSegments = this._pendingSegments; + for (var type in pendingSegments) { + if ( + !this._sourceBuffers[type] || + this._sourceBuffers[type].updating || + this._mediaSource.streaming === false + ) { + continue; + } + if (pendingSegments[type].length > 0) { + var segment = pendingSegments[type].shift(); + if ( + typeof segment.timestampOffset === "number" && + isFinite(segment.timestampOffset) + ) { + // For MPEG audio stream in MSE, if unbuffered-seeking occurred + // We need explicitly set timestampOffset to the desired point in timeline for mpeg SourceBuffer. + var currentOffset = + this._sourceBuffers[type].timestampOffset; + var targetOffset = segment.timestampOffset / 1000; // in seconds + var delta = Math.abs(currentOffset - targetOffset); + if (delta > 0.1) { + // If time delta > 100ms + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.v( + this.TAG, + "Update MPEG audio timestampOffset from " + + currentOffset + + " to " + + targetOffset + ); + this._sourceBuffers[type].timestampOffset = targetOffset; + } + delete segment.timestampOffset; + } + if (!segment.data || segment.data.byteLength === 0) { + // Ignore empty buffer + continue; + } + try { + this._sourceBuffers[type].appendBuffer(segment.data); + this._isBufferFull = false; + if (type === "video" && segment.hasOwnProperty("info")) { + this._idrList.appendArray(segment.info.syncPoints); + } + } catch (error) { + this._pendingSegments[type].unshift(segment); + if (error.code === 22) { + // QuotaExceededError + /* Notice that FireFox may not throw QuotaExceededError if SourceBuffer is full + * Currently we can only do lazy-load to avoid SourceBuffer become scattered. + * SourceBuffer eviction policy may be changed in future version of FireFox. + * + * Related issues: + * https://bugzilla.mozilla.org/show_bug.cgi?id=1279885 + * https://bugzilla.mozilla.org/show_bug.cgi?id=1280023 + */ + // report buffer full, abort network IO + if (!this._isBufferFull) { + this._emitter.emit( + _mse_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .BUFFER_FULL + ); + } + this._isBufferFull = true; + } else { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.e( + this.TAG, + type, + error.message + ); + this._emitter.emit( + _mse_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .ERROR, + { code: error.code, msg: error.message } + ); + } + } + } + } + }; + MSEController.prototype._onSourceOpen = function () { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.v( + this.TAG, + "MediaSource onSourceOpen" + ); + this._mediaSource.removeEventListener( + "sourceopen", + this.e.onSourceOpen + ); + // deferred sourcebuffer creation / initialization + if (this._pendingSourceBufferInit.length > 0) { + var pendings = this._pendingSourceBufferInit; + while (pendings.length) { + var segment = pendings.shift(); + this.appendInitSegment(segment, true); + } + } + // there may be some pending media segments, append them + if (this._hasPendingSegments()) { + this._doAppendSegments(); + } + this._emitter.emit( + _mse_events_js__WEBPACK_IMPORTED_MODULE_3__.default.SOURCE_OPEN + ); + }; + MSEController.prototype._onStartStreaming = function () { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.v( + this.TAG, + "ManagedMediaSource onStartStreaming" + ); + this._emitter.emit( + _mse_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .START_STREAMING + ); + }; + MSEController.prototype._onEndStreaming = function () { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.v( + this.TAG, + "ManagedMediaSource onEndStreaming" + ); + this._emitter.emit( + _mse_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .END_STREAMING + ); + }; + MSEController.prototype._onQualityChange = function () { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.v( + this.TAG, + "ManagedMediaSource onQualityChange" + ); + }; + MSEController.prototype._onSourceEnded = function () { + // fired on endOfStream + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.v( + this.TAG, + "MediaSource onSourceEnded" + ); + }; + MSEController.prototype._onSourceClose = function () { + // fired on detaching from media element + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.v( + this.TAG, + "MediaSource onSourceClose" + ); + if (this._mediaSource && this.e != null) { + this._mediaSource.removeEventListener( + "sourceopen", + this.e.onSourceOpen + ); + this._mediaSource.removeEventListener( + "sourceended", + this.e.onSourceEnded + ); + this._mediaSource.removeEventListener( + "sourceclose", + this.e.onSourceClose + ); + if (this._useManagedMediaSource) { + this._mediaSource.removeEventListener( + "startstraming", + this.e.onStartStreaming + ); + this._mediaSource.removeEventListener( + "endstreaming", + this.e.onEndStreaming + ); + this._mediaSource.removeEventListener( + "qualitychange", + this.e.onQualityChange + ); + } + } + }; + MSEController.prototype._hasPendingSegments = function () { + var ps = this._pendingSegments; + return ( + (ps.video && ps.video.length) > 0 || + (ps.audio && ps.audio.length > 0) + ); + }; + MSEController.prototype._hasPendingRemoveRanges = function () { + var prr = this._pendingRemoveRanges; + return ( + (prr.video && prr.video.length) > 0 || + (prr.audio && prr.audio.length > 0) + ); + }; + MSEController.prototype._onSourceBufferUpdateEnd = function () { + if (this._requireSetMediaDuration) { + this._updateMediaSourceDuration(); + } else if (this._hasPendingRemoveRanges()) { + this._doRemoveRanges(); + } else if (this._hasPendingSegments()) { + this._doAppendSegments(); + } else if (this._hasPendingEos) { + this.endOfStream(); + } + this._emitter.emit( + _mse_events_js__WEBPACK_IMPORTED_MODULE_3__.default.UPDATE_END + ); + }; + MSEController.prototype._onSourceBufferError = function (e) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.e( + this.TAG, + "SourceBuffer Error: " + e + ); + // this error might not always be fatal, just ignore it + }; + return MSEController; + })(); + /* harmony default export */ __webpack_exports__["default"] = + MSEController; + + /***/ + }, + + /***/ "./src/core/mse-events.js": + /*!********************************!*\ + !*** ./src/core/mse-events.js ***! + \********************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + var MSEEvents = { + ERROR: "error", + SOURCE_OPEN: "source_open", + UPDATE_END: "update_end", + BUFFER_FULL: "buffer_full", + START_STREAMING: "start_streaming", + END_STREAMING: "end_streaming", + }; + /* harmony default export */ __webpack_exports__["default"] = + MSEEvents; + + /***/ + }, + + /***/ "./src/core/transmuxer.js": + /*!********************************!*\ + !*** ./src/core/transmuxer.js ***! + \********************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony import */ var events__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__( + /*! events */ "./node_modules/events/events.js" + ); + /* harmony import */ var events__WEBPACK_IMPORTED_MODULE_0___default = + /*#__PURE__*/ __webpack_require__.n( + events__WEBPACK_IMPORTED_MODULE_0__ + ); + /* harmony import */ var webworkify_webpack__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__( + /*! webworkify-webpack */ "./node_modules/webworkify-webpack/index.js" + ); + /* harmony import */ var webworkify_webpack__WEBPACK_IMPORTED_MODULE_1___default = + /*#__PURE__*/ __webpack_require__.n( + webworkify_webpack__WEBPACK_IMPORTED_MODULE_1__ + ); + /* harmony import */ var _utils_logger_js__WEBPACK_IMPORTED_MODULE_2__ = + __webpack_require__( + /*! ../utils/logger.js */ "./src/utils/logger.js" + ); + /* harmony import */ var _utils_logging_control_js__WEBPACK_IMPORTED_MODULE_3__ = + __webpack_require__( + /*! ../utils/logging-control.js */ "./src/utils/logging-control.js" + ); + /* harmony import */ var _transmuxing_controller_js__WEBPACK_IMPORTED_MODULE_4__ = + __webpack_require__( + /*! ./transmuxing-controller.js */ "./src/core/transmuxing-controller.js" + ); + /* harmony import */ var _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__ = + __webpack_require__( + /*! ./transmuxing-events.js */ "./src/core/transmuxing-events.js" + ); + /* harmony import */ var _media_info_js__WEBPACK_IMPORTED_MODULE_6__ = + __webpack_require__( + /*! ./media-info.js */ "./src/core/media-info.js" + ); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + var Transmuxer = /** @class */ (function () { + function Transmuxer(mediaDataSource, config) { + this.TAG = "Transmuxer"; + this._emitter = + new (events__WEBPACK_IMPORTED_MODULE_0___default())(); + if (config.enableWorker && typeof Worker !== "undefined") { + try { + this._worker = + webworkify_webpack__WEBPACK_IMPORTED_MODULE_1___default()( + /*require.resolve*/ /*! ./transmuxing-worker */ "./src/core/transmuxing-worker.js" + ); + this._workerDestroying = false; + this._worker.addEventListener( + "message", + this._onWorkerMessage.bind(this) + ); + this._worker.postMessage({ + cmd: "init", + param: [mediaDataSource, config], + }); + this.e = { + onLoggingConfigChanged: + this._onLoggingConfigChanged.bind(this), + }; + _utils_logging_control_js__WEBPACK_IMPORTED_MODULE_3__.default.registerListener( + this.e.onLoggingConfigChanged + ); + this._worker.postMessage({ + cmd: "logging_config", + param: + _utils_logging_control_js__WEBPACK_IMPORTED_MODULE_3__.default.getConfig(), + }); + } catch (error) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_2__.default.e( + this.TAG, + "Error while initialize transmuxing worker, fallback to inline transmuxing" + ); + this._worker = null; + this._controller = + new _transmuxing_controller_js__WEBPACK_IMPORTED_MODULE_4__.default( + mediaDataSource, + config + ); + } + } else { + this._controller = + new _transmuxing_controller_js__WEBPACK_IMPORTED_MODULE_4__.default( + mediaDataSource, + config + ); + } + if (this._controller) { + var ctl = this._controller; + ctl.on( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .IO_ERROR, + this._onIOError.bind(this) + ); + ctl.on( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .DEMUX_ERROR, + this._onDemuxError.bind(this) + ); + ctl.on( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .INIT_SEGMENT, + this._onInitSegment.bind(this) + ); + ctl.on( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .MEDIA_SEGMENT, + this._onMediaSegment.bind(this) + ); + ctl.on( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .LOADING_COMPLETE, + this._onLoadingComplete.bind(this) + ); + ctl.on( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .RECOVERED_EARLY_EOF, + this._onRecoveredEarlyEof.bind(this) + ); + ctl.on( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .MEDIA_INFO, + this._onMediaInfo.bind(this) + ); + ctl.on( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .METADATA_ARRIVED, + this._onMetaDataArrived.bind(this) + ); + ctl.on( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .SCRIPTDATA_ARRIVED, + this._onScriptDataArrived.bind(this) + ); + ctl.on( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .STATISTICS_INFO, + this._onStatisticsInfo.bind(this) + ); + ctl.on( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .RECOMMEND_SEEKPOINT, + this._onRecommendSeekpoint.bind(this) + ); + } + } + Transmuxer.prototype.destroy = function () { + if (this._worker) { + if (!this._workerDestroying) { + this._workerDestroying = true; + this._worker.postMessage({ cmd: "destroy" }); + _utils_logging_control_js__WEBPACK_IMPORTED_MODULE_3__.default.removeListener( + this.e.onLoggingConfigChanged + ); + this.e = null; + } + } else { + this._controller.destroy(); + this._controller = null; + } + this._emitter.removeAllListeners(); + this._emitter = null; + }; + Transmuxer.prototype.on = function (event, listener) { + this._emitter.addListener(event, listener); + }; + Transmuxer.prototype.off = function (event, listener) { + this._emitter.removeListener(event, listener); + }; + Transmuxer.prototype.hasWorker = function () { + return this._worker != null; + }; + Transmuxer.prototype.open = function () { + if (this._worker) { + this._worker.postMessage({ cmd: "start" }); + } else { + this._controller.start(); + } + }; + Transmuxer.prototype.close = function () { + if (this._worker) { + this._worker.postMessage({ cmd: "stop" }); + } else { + this._controller.stop(); + } + }; + Transmuxer.prototype.seek = function (milliseconds) { + if (this._worker) { + this._worker.postMessage({ cmd: "seek", param: milliseconds }); + } else { + this._controller.seek(milliseconds); + } + }; + Transmuxer.prototype.pause = function () { + if (this._worker) { + this._worker.postMessage({ cmd: "pause" }); + } else { + this._controller.pause(); + } + }; + Transmuxer.prototype.resume = function () { + if (this._worker) { + this._worker.postMessage({ cmd: "resume" }); + } else { + this._controller.resume(); + } + }; + Transmuxer.prototype._onInitSegment = function (type, initSegment) { + var _this = this; + // do async invoke + Promise.resolve().then(function () { + _this._emitter.emit( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .INIT_SEGMENT, + type, + initSegment + ); + }); + }; + Transmuxer.prototype._onMediaSegment = function ( + type, + mediaSegment + ) { + var _this = this; + Promise.resolve().then(function () { + _this._emitter.emit( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .MEDIA_SEGMENT, + type, + mediaSegment + ); + }); + }; + Transmuxer.prototype._onLoadingComplete = function () { + var _this = this; + Promise.resolve().then(function () { + _this._emitter.emit( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .LOADING_COMPLETE + ); + }); + }; + Transmuxer.prototype._onRecoveredEarlyEof = function () { + var _this = this; + Promise.resolve().then(function () { + _this._emitter.emit( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .RECOVERED_EARLY_EOF + ); + }); + }; + Transmuxer.prototype._onMediaInfo = function (mediaInfo) { + var _this = this; + Promise.resolve().then(function () { + _this._emitter.emit( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .MEDIA_INFO, + mediaInfo + ); + }); + }; + Transmuxer.prototype._onMetaDataArrived = function (metadata) { + var _this = this; + Promise.resolve().then(function () { + _this._emitter.emit( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .METADATA_ARRIVED, + metadata + ); + }); + }; + Transmuxer.prototype._onScriptDataArrived = function (data) { + var _this = this; + Promise.resolve().then(function () { + _this._emitter.emit( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .SCRIPTDATA_ARRIVED, + data + ); + }); + }; + Transmuxer.prototype._onStatisticsInfo = function (statisticsInfo) { + var _this = this; + Promise.resolve().then(function () { + _this._emitter.emit( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .STATISTICS_INFO, + statisticsInfo + ); + }); + }; + Transmuxer.prototype._onIOError = function (type, info) { + var _this = this; + Promise.resolve().then(function () { + _this._emitter.emit( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .IO_ERROR, + type, + info + ); + }); + }; + Transmuxer.prototype._onDemuxError = function (type, info) { + var _this = this; + Promise.resolve().then(function () { + _this._emitter.emit( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .DEMUX_ERROR, + type, + info + ); + }); + }; + Transmuxer.prototype._onRecommendSeekpoint = function ( + milliseconds + ) { + var _this = this; + Promise.resolve().then(function () { + _this._emitter.emit( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .RECOMMEND_SEEKPOINT, + milliseconds + ); + }); + }; + Transmuxer.prototype._onLoggingConfigChanged = function (config) { + if (this._worker) { + this._worker.postMessage({ + cmd: "logging_config", + param: config, + }); + } + }; + Transmuxer.prototype._onWorkerMessage = function (e) { + var message = e.data; + var data = message.data; + if (message.msg === "destroyed" || this._workerDestroying) { + this._workerDestroying = false; + this._worker.terminate(); + this._worker = null; + return; + } + switch (message.msg) { + case _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .INIT_SEGMENT: + case _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .MEDIA_SEGMENT: + this._emitter.emit(message.msg, data.type, data.data); + break; + case _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .LOADING_COMPLETE: + case _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .RECOVERED_EARLY_EOF: + this._emitter.emit(message.msg); + break; + case _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .MEDIA_INFO: + Object.setPrototypeOf( + data, + _media_info_js__WEBPACK_IMPORTED_MODULE_6__.default + .prototype + ); + this._emitter.emit(message.msg, data); + break; + case _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .METADATA_ARRIVED: + case _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .SCRIPTDATA_ARRIVED: + case _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .STATISTICS_INFO: + this._emitter.emit(message.msg, data); + break; + case _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .IO_ERROR: + case _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .DEMUX_ERROR: + this._emitter.emit(message.msg, data.type, data.info); + break; + case _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .RECOMMEND_SEEKPOINT: + this._emitter.emit(message.msg, data); + break; + case "logcat_callback": + _utils_logger_js__WEBPACK_IMPORTED_MODULE_2__.default.emitter.emit( + "log", + data.type, + data.logcat + ); + break; + default: + break; + } + }; + return Transmuxer; + })(); + /* harmony default export */ __webpack_exports__["default"] = + Transmuxer; + + /***/ + }, + + /***/ "./src/core/transmuxing-controller.js": + /*!********************************************!*\ + !*** ./src/core/transmuxing-controller.js ***! + \********************************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony import */ var events__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__( + /*! events */ "./node_modules/events/events.js" + ); + /* harmony import */ var events__WEBPACK_IMPORTED_MODULE_0___default = + /*#__PURE__*/ __webpack_require__.n( + events__WEBPACK_IMPORTED_MODULE_0__ + ); + /* harmony import */ var _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__( + /*! ../utils/logger.js */ "./src/utils/logger.js" + ); + /* harmony import */ var _utils_browser_js__WEBPACK_IMPORTED_MODULE_2__ = + __webpack_require__( + /*! ../utils/browser.js */ "./src/utils/browser.js" + ); + /* harmony import */ var _media_info_js__WEBPACK_IMPORTED_MODULE_3__ = + __webpack_require__( + /*! ./media-info.js */ "./src/core/media-info.js" + ); + /* harmony import */ var _demux_flv_demuxer_js__WEBPACK_IMPORTED_MODULE_4__ = + __webpack_require__( + /*! ../demux/flv-demuxer.js */ "./src/demux/flv-demuxer.js" + ); + /* harmony import */ var _remux_mp4_remuxer_js__WEBPACK_IMPORTED_MODULE_5__ = + __webpack_require__( + /*! ../remux/mp4-remuxer.js */ "./src/remux/mp4-remuxer.js" + ); + /* harmony import */ var _demux_demux_errors_js__WEBPACK_IMPORTED_MODULE_6__ = + __webpack_require__( + /*! ../demux/demux-errors.js */ "./src/demux/demux-errors.js" + ); + /* harmony import */ var _io_io_controller_js__WEBPACK_IMPORTED_MODULE_7__ = + __webpack_require__( + /*! ../io/io-controller.js */ "./src/io/io-controller.js" + ); + /* harmony import */ var _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_8__ = + __webpack_require__( + /*! ./transmuxing-events.js */ "./src/core/transmuxing-events.js" + ); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + // Transmuxing (IO, Demuxing, Remuxing) controller, with multipart support + var TransmuxingController = /** @class */ (function () { + function TransmuxingController(mediaDataSource, config) { + this.TAG = "TransmuxingController"; + this._emitter = + new (events__WEBPACK_IMPORTED_MODULE_0___default())(); + this._config = config; + // treat single part media as multipart media, which has only one segment + if (!mediaDataSource.segments) { + mediaDataSource.segments = [ + { + duration: mediaDataSource.duration, + filesize: mediaDataSource.filesize, + url: mediaDataSource.url, + }, + ]; + } + // fill in default IO params if not exists + if (typeof mediaDataSource.cors !== "boolean") { + mediaDataSource.cors = true; + } + if (typeof mediaDataSource.withCredentials !== "boolean") { + mediaDataSource.withCredentials = false; + } + this._mediaDataSource = mediaDataSource; + this._currentSegmentIndex = 0; + var totalDuration = 0; + this._mediaDataSource.segments.forEach(function (segment) { + // timestampBase for each segment, and calculate total duration + segment.timestampBase = totalDuration; + totalDuration += segment.duration; + // params needed by IOController + segment.cors = mediaDataSource.cors; + segment.withCredentials = mediaDataSource.withCredentials; + // referrer policy control, if exist + if (config.referrerPolicy) { + segment.referrerPolicy = config.referrerPolicy; + } + }); + if ( + !isNaN(totalDuration) && + this._mediaDataSource.duration !== totalDuration + ) { + this._mediaDataSource.duration = totalDuration; + } + this._mediaInfo = null; + this._demuxer = null; + this._remuxer = null; + this._ioctl = null; + this._pendingSeekTime = null; + this._pendingResolveSeekPoint = null; + this._statisticsReporter = null; + } + TransmuxingController.prototype.destroy = function () { + this._mediaInfo = null; + this._mediaDataSource = null; + if (this._statisticsReporter) { + this._disableStatisticsReporter(); + } + if (this._ioctl) { + this._ioctl.destroy(); + this._ioctl = null; + } + if (this._demuxer) { + this._demuxer.destroy(); + this._demuxer = null; + } + if (this._remuxer) { + this._remuxer.destroy(); + this._remuxer = null; + } + this._emitter.removeAllListeners(); + this._emitter = null; + }; + TransmuxingController.prototype.on = function (event, listener) { + this._emitter.addListener(event, listener); + }; + TransmuxingController.prototype.off = function (event, listener) { + this._emitter.removeListener(event, listener); + }; + TransmuxingController.prototype.start = function () { + this._loadSegment(0); + this._enableStatisticsReporter(); + }; + TransmuxingController.prototype._loadSegment = function ( + segmentIndex, + optionalFrom + ) { + this._currentSegmentIndex = segmentIndex; + var dataSource = this._mediaDataSource.segments[segmentIndex]; + var ioctl = (this._ioctl = + new _io_io_controller_js__WEBPACK_IMPORTED_MODULE_7__.default( + dataSource, + this._config, + segmentIndex + )); + ioctl.onError = this._onIOException.bind(this); + ioctl.onSeeked = this._onIOSeeked.bind(this); + ioctl.onComplete = this._onIOComplete.bind(this); + ioctl.onRedirect = this._onIORedirect.bind(this); + ioctl.onRecoveredEarlyEof = + this._onIORecoveredEarlyEof.bind(this); + if (optionalFrom) { + this._demuxer.bindDataSource(this._ioctl); + } else { + ioctl.onDataArrival = this._onInitChunkArrival.bind(this); + } + ioctl.open(optionalFrom); + }; + TransmuxingController.prototype.stop = function () { + this._internalAbort(); + this._disableStatisticsReporter(); + }; + TransmuxingController.prototype._internalAbort = function () { + if (this._ioctl) { + this._ioctl.destroy(); + this._ioctl = null; + } + }; + TransmuxingController.prototype.pause = function () { + if (this._ioctl && this._ioctl.isWorking()) { + this._ioctl.pause(); + this._disableStatisticsReporter(); + } + }; + TransmuxingController.prototype.resume = function () { + if (this._ioctl && this._ioctl.isPaused()) { + this._ioctl.resume(); + this._enableStatisticsReporter(); + } + }; + TransmuxingController.prototype.seek = function (milliseconds) { + if (this._mediaInfo == null || !this._mediaInfo.isSeekable()) { + return; + } + var targetSegmentIndex = + this._searchSegmentIndexContains(milliseconds); + if (targetSegmentIndex === this._currentSegmentIndex) { + // intra-segment seeking + var segmentInfo = this._mediaInfo.segments[targetSegmentIndex]; + if (segmentInfo == undefined) { + // current segment loading started, but mediainfo hasn't received yet + // wait for the metadata loaded, then seek to expected position + this._pendingSeekTime = milliseconds; + } else { + var keyframe = segmentInfo.getNearestKeyframe(milliseconds); + this._remuxer.seek(keyframe.milliseconds); + this._ioctl.seek(keyframe.fileposition); + // Will be resolved in _onRemuxerMediaSegmentArrival() + this._pendingResolveSeekPoint = keyframe.milliseconds; + } + } else { + // cross-segment seeking + var targetSegmentInfo = + this._mediaInfo.segments[targetSegmentIndex]; + if (targetSegmentInfo == undefined) { + // target segment hasn't been loaded. We need metadata then seek to expected time + this._pendingSeekTime = milliseconds; + this._internalAbort(); + this._remuxer.seek(); + this._remuxer.insertDiscontinuity(); + this._loadSegment(targetSegmentIndex); + // Here we wait for the metadata loaded, then seek to expected position + } else { + // We have target segment's metadata, direct seek to target position + var keyframe = + targetSegmentInfo.getNearestKeyframe(milliseconds); + this._internalAbort(); + this._remuxer.seek(milliseconds); + this._remuxer.insertDiscontinuity(); + this._demuxer.resetMediaInfo(); + this._demuxer.timestampBase = + this._mediaDataSource.segments[ + targetSegmentIndex + ].timestampBase; + this._loadSegment(targetSegmentIndex, keyframe.fileposition); + this._pendingResolveSeekPoint = keyframe.milliseconds; + this._reportSegmentMediaInfo(targetSegmentIndex); + } + } + this._enableStatisticsReporter(); + }; + TransmuxingController.prototype._searchSegmentIndexContains = + function (milliseconds) { + var segments = this._mediaDataSource.segments; + var idx = segments.length - 1; + for (var i = 0; i < segments.length; i++) { + if (milliseconds < segments[i].timestampBase) { + idx = i - 1; + break; + } + } + return idx; + }; + TransmuxingController.prototype._onInitChunkArrival = function ( + data, + byteStart + ) { + var _this = this; + var probeData = null; + var consumed = 0; + if (byteStart > 0) { + // IOController seeked immediately after opened, byteStart > 0 callback may received + this._demuxer.bindDataSource(this._ioctl); + this._demuxer.timestampBase = + this._mediaDataSource.segments[ + this._currentSegmentIndex + ].timestampBase; + consumed = this._demuxer.parseChunks(data, byteStart); + } else if ( + (probeData = + _demux_flv_demuxer_js__WEBPACK_IMPORTED_MODULE_4__.default.probe( + data + )).match + ) { + // Always create new FLVDemuxer + this._demuxer = + new _demux_flv_demuxer_js__WEBPACK_IMPORTED_MODULE_4__.default( + probeData, + this._config + ); + if (!this._remuxer) { + this._remuxer = + new _remux_mp4_remuxer_js__WEBPACK_IMPORTED_MODULE_5__.default( + this._config + ); + } + var mds = this._mediaDataSource; + if (mds.duration != undefined && !isNaN(mds.duration)) { + this._demuxer.overridedDuration = mds.duration; + } + if (typeof mds.hasAudio === "boolean") { + this._demuxer.overridedHasAudio = mds.hasAudio; + } + if (typeof mds.hasVideo === "boolean") { + this._demuxer.overridedHasVideo = mds.hasVideo; + } + this._demuxer.timestampBase = + mds.segments[this._currentSegmentIndex].timestampBase; + this._demuxer.onError = this._onDemuxException.bind(this); + this._demuxer.onMediaInfo = this._onMediaInfo.bind(this); + this._demuxer.onMetaDataArrived = + this._onMetaDataArrived.bind(this); + this._demuxer.onScriptDataArrived = + this._onScriptDataArrived.bind(this); + this._remuxer.bindDataSource( + this._demuxer.bindDataSource(this._ioctl) + ); + this._remuxer.onInitSegment = + this._onRemuxerInitSegmentArrival.bind(this); + this._remuxer.onMediaSegment = + this._onRemuxerMediaSegmentArrival.bind(this); + consumed = this._demuxer.parseChunks(data, byteStart); + } else { + probeData = null; + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.e( + this.TAG, + "Non-FLV, Unsupported media type!" + ); + Promise.resolve().then(function () { + _this._internalAbort(); + }); + this._emitter.emit( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_8__.default + .DEMUX_ERROR, + _demux_demux_errors_js__WEBPACK_IMPORTED_MODULE_6__.default + .FORMAT_UNSUPPORTED, + "Non-FLV, Unsupported media type" + ); + consumed = 0; + } + return consumed; + }; + TransmuxingController.prototype._onMediaInfo = function ( + mediaInfo + ) { + var _this = this; + if (this._mediaInfo == null) { + // Store first segment's mediainfo as global mediaInfo + this._mediaInfo = Object.assign({}, mediaInfo); + this._mediaInfo.keyframesIndex = null; + this._mediaInfo.segments = []; + this._mediaInfo.segmentCount = + this._mediaDataSource.segments.length; + Object.setPrototypeOf( + this._mediaInfo, + _media_info_js__WEBPACK_IMPORTED_MODULE_3__.default.prototype + ); + } + var segmentInfo = Object.assign({}, mediaInfo); + Object.setPrototypeOf( + segmentInfo, + _media_info_js__WEBPACK_IMPORTED_MODULE_3__.default.prototype + ); + this._mediaInfo.segments[this._currentSegmentIndex] = segmentInfo; + // notify mediaInfo update + this._reportSegmentMediaInfo(this._currentSegmentIndex); + if (this._pendingSeekTime != null) { + Promise.resolve().then(function () { + var target = _this._pendingSeekTime; + _this._pendingSeekTime = null; + _this.seek(target); + }); + } + }; + TransmuxingController.prototype._onMetaDataArrived = function ( + metadata + ) { + this._emitter.emit( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_8__.default + .METADATA_ARRIVED, + metadata + ); + }; + TransmuxingController.prototype._onScriptDataArrived = function ( + data + ) { + this._emitter.emit( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_8__.default + .SCRIPTDATA_ARRIVED, + data + ); + }; + TransmuxingController.prototype._onIOSeeked = function () { + this._remuxer.insertDiscontinuity(); + }; + TransmuxingController.prototype._onIOComplete = function ( + extraData + ) { + var segmentIndex = extraData; + var nextSegmentIndex = segmentIndex + 1; + if (nextSegmentIndex < this._mediaDataSource.segments.length) { + this._internalAbort(); + if (this._remuxer) { + this._remuxer.flushStashedSamples(); + } + this._loadSegment(nextSegmentIndex); + } else { + if (this._remuxer) { + this._remuxer.flushStashedSamples(); + } + this._emitter.emit( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_8__.default + .LOADING_COMPLETE + ); + this._disableStatisticsReporter(); + } + }; + TransmuxingController.prototype._onIORedirect = function ( + redirectedURL + ) { + var segmentIndex = this._ioctl.extraData; + this._mediaDataSource.segments[segmentIndex].redirectedURL = + redirectedURL; + }; + TransmuxingController.prototype._onIORecoveredEarlyEof = + function () { + this._emitter.emit( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_8__.default + .RECOVERED_EARLY_EOF + ); + }; + TransmuxingController.prototype._onIOException = function ( + type, + info + ) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.e( + this.TAG, + "IOException: type = " + + type + + ", code = " + + info.code + + ", msg = " + + info.msg + ); + this._emitter.emit( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_8__.default + .IO_ERROR, + type, + info + ); + this._disableStatisticsReporter(); + }; + TransmuxingController.prototype._onDemuxException = function ( + type, + info + ) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.e( + this.TAG, + "DemuxException: type = " + type + ", info = " + info + ); + this._emitter.emit( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_8__.default + .DEMUX_ERROR, + type, + info + ); + }; + TransmuxingController.prototype._onRemuxerInitSegmentArrival = + function (type, initSegment) { + this._emitter.emit( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_8__.default + .INIT_SEGMENT, + type, + initSegment + ); + }; + TransmuxingController.prototype._onRemuxerMediaSegmentArrival = + function (type, mediaSegment) { + if (this._pendingSeekTime != null) { + // Media segments after new-segment cross-seeking should be dropped. + return; + } + this._emitter.emit( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_8__.default + .MEDIA_SEGMENT, + type, + mediaSegment + ); + // Resolve pending seekPoint + if (this._pendingResolveSeekPoint != null && type === "video") { + var syncPoints = mediaSegment.info.syncPoints; + var seekpoint = this._pendingResolveSeekPoint; + this._pendingResolveSeekPoint = null; + // Safari: Pass PTS for recommend_seekpoint + if ( + _utils_browser_js__WEBPACK_IMPORTED_MODULE_2__.default + .safari && + syncPoints.length > 0 && + syncPoints[0].originalDts === seekpoint + ) { + seekpoint = syncPoints[0].pts; + } + // else: use original DTS (keyframe.milliseconds) + this._emitter.emit( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_8__.default + .RECOMMEND_SEEKPOINT, + seekpoint + ); + } + }; + TransmuxingController.prototype._enableStatisticsReporter = + function () { + if (this._statisticsReporter == null) { + this._statisticsReporter = self.setInterval( + this._reportStatisticsInfo.bind(this), + this._config.statisticsInfoReportInterval + ); + } + }; + TransmuxingController.prototype._disableStatisticsReporter = + function () { + if (this._statisticsReporter) { + self.clearInterval(this._statisticsReporter); + this._statisticsReporter = null; + } + }; + TransmuxingController.prototype._reportSegmentMediaInfo = function ( + segmentIndex + ) { + var segmentInfo = this._mediaInfo.segments[segmentIndex]; + var exportInfo = Object.assign({}, segmentInfo); + exportInfo.duration = this._mediaInfo.duration; + exportInfo.segmentCount = this._mediaInfo.segmentCount; + delete exportInfo.segments; + delete exportInfo.keyframesIndex; + this._emitter.emit( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_8__.default + .MEDIA_INFO, + exportInfo + ); + }; + TransmuxingController.prototype._reportStatisticsInfo = + function () { + var info = {}; + info.url = this._ioctl.currentURL; + info.hasRedirect = this._ioctl.hasRedirect; + if (info.hasRedirect) { + info.redirectedURL = this._ioctl.currentRedirectedURL; + } + info.speed = this._ioctl.currentSpeed; + info.loaderType = this._ioctl.loaderType; + info.currentSegmentIndex = this._currentSegmentIndex; + info.totalSegmentCount = this._mediaDataSource.segments.length; + this._emitter.emit( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_8__.default + .STATISTICS_INFO, + info + ); + }; + return TransmuxingController; + })(); + /* harmony default export */ __webpack_exports__["default"] = + TransmuxingController; + + /***/ + }, + + /***/ "./src/core/transmuxing-events.js": + /*!****************************************!*\ + !*** ./src/core/transmuxing-events.js ***! + \****************************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + var TransmuxingEvents = { + IO_ERROR: "io_error", + DEMUX_ERROR: "demux_error", + INIT_SEGMENT: "init_segment", + MEDIA_SEGMENT: "media_segment", + LOADING_COMPLETE: "loading_complete", + RECOVERED_EARLY_EOF: "recovered_early_eof", + MEDIA_INFO: "media_info", + METADATA_ARRIVED: "metadata_arrived", + SCRIPTDATA_ARRIVED: "scriptdata_arrived", + STATISTICS_INFO: "statistics_info", + RECOMMEND_SEEKPOINT: "recommend_seekpoint", + }; + /* harmony default export */ __webpack_exports__["default"] = + TransmuxingEvents; + + /***/ + }, + + /***/ "./src/core/transmuxing-worker.js": + /*!****************************************!*\ + !*** ./src/core/transmuxing-worker.js ***! + \****************************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony import */ var _utils_logging_control_js__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__( + /*! ../utils/logging-control.js */ "./src/utils/logging-control.js" + ); + /* harmony import */ var _utils_polyfill_js__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__( + /*! ../utils/polyfill.js */ "./src/utils/polyfill.js" + ); + /* harmony import */ var _transmuxing_controller_js__WEBPACK_IMPORTED_MODULE_2__ = + __webpack_require__( + /*! ./transmuxing-controller.js */ "./src/core/transmuxing-controller.js" + ); + /* harmony import */ var _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_3__ = + __webpack_require__( + /*! ./transmuxing-events.js */ "./src/core/transmuxing-events.js" + ); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + /* post message to worker: + data: { + cmd: string + param: any + } + + receive message from worker: + data: { + msg: string, + data: any + } + */ + var TransmuxingWorker = function (self) { + var TAG = "TransmuxingWorker"; + var controller = null; + var logcatListener = onLogcatCallback.bind(this); + _utils_polyfill_js__WEBPACK_IMPORTED_MODULE_1__.default.install(); + self.addEventListener("message", function (e) { + switch (e.data.cmd) { + case "init": + controller = + new _transmuxing_controller_js__WEBPACK_IMPORTED_MODULE_2__.default( + e.data.param[0], + e.data.param[1] + ); + controller.on( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .IO_ERROR, + onIOError.bind(this) + ); + controller.on( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .DEMUX_ERROR, + onDemuxError.bind(this) + ); + controller.on( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .INIT_SEGMENT, + onInitSegment.bind(this) + ); + controller.on( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .MEDIA_SEGMENT, + onMediaSegment.bind(this) + ); + controller.on( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .LOADING_COMPLETE, + onLoadingComplete.bind(this) + ); + controller.on( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .RECOVERED_EARLY_EOF, + onRecoveredEarlyEof.bind(this) + ); + controller.on( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .MEDIA_INFO, + onMediaInfo.bind(this) + ); + controller.on( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .METADATA_ARRIVED, + onMetaDataArrived.bind(this) + ); + controller.on( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .SCRIPTDATA_ARRIVED, + onScriptDataArrived.bind(this) + ); + controller.on( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .STATISTICS_INFO, + onStatisticsInfo.bind(this) + ); + controller.on( + _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .RECOMMEND_SEEKPOINT, + onRecommendSeekpoint.bind(this) + ); + break; + case "destroy": + if (controller) { + controller.destroy(); + controller = null; + } + self.postMessage({ msg: "destroyed" }); + break; + case "start": + controller.start(); + break; + case "stop": + controller.stop(); + break; + case "seek": + controller.seek(e.data.param); + break; + case "pause": + controller.pause(); + break; + case "resume": + controller.resume(); + break; + case "logging_config": { + var config = e.data.param; + _utils_logging_control_js__WEBPACK_IMPORTED_MODULE_0__.default.applyConfig( + config + ); + if (config.enableCallback === true) { + _utils_logging_control_js__WEBPACK_IMPORTED_MODULE_0__.default.addLogListener( + logcatListener + ); + } else { + _utils_logging_control_js__WEBPACK_IMPORTED_MODULE_0__.default.removeLogListener( + logcatListener + ); + } + break; + } + } + }); + function onInitSegment(type, initSegment) { + var obj = { + msg: _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .INIT_SEGMENT, + data: { + type: type, + data: initSegment, + }, + }; + self.postMessage(obj, [initSegment.data]); // data: ArrayBuffer + } + function onMediaSegment(type, mediaSegment) { + var obj = { + msg: _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .MEDIA_SEGMENT, + data: { + type: type, + data: mediaSegment, + }, + }; + self.postMessage(obj, [mediaSegment.data]); // data: ArrayBuffer + } + function onLoadingComplete() { + var obj = { + msg: _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .LOADING_COMPLETE, + }; + self.postMessage(obj); + } + function onRecoveredEarlyEof() { + var obj = { + msg: _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .RECOVERED_EARLY_EOF, + }; + self.postMessage(obj); + } + function onMediaInfo(mediaInfo) { + var obj = { + msg: _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .MEDIA_INFO, + data: mediaInfo, + }; + self.postMessage(obj); + } + function onMetaDataArrived(metadata) { + var obj = { + msg: _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .METADATA_ARRIVED, + data: metadata, + }; + self.postMessage(obj); + } + function onScriptDataArrived(data) { + var obj = { + msg: _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .SCRIPTDATA_ARRIVED, + data: data, + }; + self.postMessage(obj); + } + function onStatisticsInfo(statInfo) { + var obj = { + msg: _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .STATISTICS_INFO, + data: statInfo, + }; + self.postMessage(obj); + } + function onIOError(type, info) { + self.postMessage({ + msg: _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .IO_ERROR, + data: { + type: type, + info: info, + }, + }); + } + function onDemuxError(type, info) { + self.postMessage({ + msg: _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .DEMUX_ERROR, + data: { + type: type, + info: info, + }, + }); + } + function onRecommendSeekpoint(milliseconds) { + self.postMessage({ + msg: _transmuxing_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .RECOMMEND_SEEKPOINT, + data: milliseconds, + }); + } + function onLogcatCallback(type, str) { + self.postMessage({ + msg: "logcat_callback", + data: { + type: type, + logcat: str, + }, + }); + } + }; + /* harmony default export */ __webpack_exports__["default"] = + TransmuxingWorker; + + /***/ + }, + + /***/ "./src/demux/amf-parser.js": + /*!*********************************!*\ + !*** ./src/demux/amf-parser.js ***! + \*********************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony import */ var _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__( + /*! ../utils/logger.js */ "./src/utils/logger.js" + ); + /* harmony import */ var _utils_utf8_conv_js__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__( + /*! ../utils/utf8-conv.js */ "./src/utils/utf8-conv.js" + ); + /* harmony import */ var _utils_exception_js__WEBPACK_IMPORTED_MODULE_2__ = + __webpack_require__( + /*! ../utils/exception.js */ "./src/utils/exception.js" + ); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + var le = (function () { + var buf = new ArrayBuffer(2); + new DataView(buf).setInt16(0, 256, true); // little-endian write + return new Int16Array(buf)[0] === 256; // platform-spec read, if equal then LE + })(); + var AMF = /** @class */ (function () { + function AMF() {} + AMF.parseScriptData = function (arrayBuffer, dataOffset, dataSize) { + var data = {}; + try { + var name_1 = AMF.parseValue(arrayBuffer, dataOffset, dataSize); + var value = AMF.parseValue( + arrayBuffer, + dataOffset + name_1.size, + dataSize - name_1.size + ); + data[name_1.data] = value.data; + } catch (e) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.e( + "AMF", + e.toString() + ); + } + return data; + }; + AMF.parseObject = function (arrayBuffer, dataOffset, dataSize) { + if (dataSize < 3) { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_2__.IllegalStateException( + "Data not enough when parse ScriptDataObject" + ); + } + var name = AMF.parseString(arrayBuffer, dataOffset, dataSize); + var value = AMF.parseValue( + arrayBuffer, + dataOffset + name.size, + dataSize - name.size + ); + var isObjectEnd = value.objectEnd; + return { + data: { + name: name.data, + value: value.data, + }, + size: name.size + value.size, + objectEnd: isObjectEnd, + }; + }; + AMF.parseVariable = function (arrayBuffer, dataOffset, dataSize) { + return AMF.parseObject(arrayBuffer, dataOffset, dataSize); + }; + AMF.parseString = function (arrayBuffer, dataOffset, dataSize) { + if (dataSize < 2) { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_2__.IllegalStateException( + "Data not enough when parse String" + ); + } + var v = new DataView(arrayBuffer, dataOffset, dataSize); + var length = v.getUint16(0, !le); + var str; + if (length > 0) { + str = (0, + _utils_utf8_conv_js__WEBPACK_IMPORTED_MODULE_1__.default)( + new Uint8Array(arrayBuffer, dataOffset + 2, length) + ); + } else { + str = ""; + } + return { + data: str, + size: 2 + length, + }; + }; + AMF.parseLongString = function (arrayBuffer, dataOffset, dataSize) { + if (dataSize < 4) { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_2__.IllegalStateException( + "Data not enough when parse LongString" + ); + } + var v = new DataView(arrayBuffer, dataOffset, dataSize); + var length = v.getUint32(0, !le); + var str; + if (length > 0) { + str = (0, + _utils_utf8_conv_js__WEBPACK_IMPORTED_MODULE_1__.default)( + new Uint8Array(arrayBuffer, dataOffset + 4, length) + ); + } else { + str = ""; + } + return { + data: str, + size: 4 + length, + }; + }; + AMF.parseDate = function (arrayBuffer, dataOffset, dataSize) { + if (dataSize < 10) { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_2__.IllegalStateException( + "Data size invalid when parse Date" + ); + } + var v = new DataView(arrayBuffer, dataOffset, dataSize); + var timestamp = v.getFloat64(0, !le); + var localTimeOffset = v.getInt16(8, !le); + timestamp += localTimeOffset * 60 * 1000; // get UTC time + return { + data: new Date(timestamp), + size: 8 + 2, + }; + }; + AMF.parseValue = function (arrayBuffer, dataOffset, dataSize) { + if (dataSize < 1) { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_2__.IllegalStateException( + "Data not enough when parse Value" + ); + } + var v = new DataView(arrayBuffer, dataOffset, dataSize); + var offset = 1; + var type = v.getUint8(0); + var value; + var objectEnd = false; + try { + switch (type) { + case 0: // Number(Double) type + value = v.getFloat64(1, !le); + offset += 8; + break; + case 1: { + // Boolean type + var b = v.getUint8(1); + value = b ? true : false; + offset += 1; + break; + } + case 2: { + // String type + var amfstr = AMF.parseString( + arrayBuffer, + dataOffset + 1, + dataSize - 1 + ); + value = amfstr.data; + offset += amfstr.size; + break; + } + case 3: { + // Object(s) type + value = {}; + var terminal = 0; // workaround for malformed Objects which has missing ScriptDataObjectEnd + if ((v.getUint32(dataSize - 4, !le) & 0x00ffffff) === 9) { + terminal = 3; + } + while (offset < dataSize - 4) { + // 4 === type(UI8) + ScriptDataObjectEnd(UI24) + var amfobj = AMF.parseObject( + arrayBuffer, + dataOffset + offset, + dataSize - offset - terminal + ); + if (amfobj.objectEnd) break; + value[amfobj.data.name] = amfobj.data.value; + offset += amfobj.size; + } + if (offset <= dataSize - 3) { + var marker = v.getUint32(offset - 1, !le) & 0x00ffffff; + if (marker === 9) { + offset += 3; + } + } + break; + } + case 8: { + // ECMA array type (Mixed array) + value = {}; + offset += 4; // ECMAArrayLength(UI32) + var terminal = 0; // workaround for malformed MixedArrays which has missing ScriptDataObjectEnd + if ((v.getUint32(dataSize - 4, !le) & 0x00ffffff) === 9) { + terminal = 3; + } + while (offset < dataSize - 8) { + // 8 === type(UI8) + ECMAArrayLength(UI32) + ScriptDataVariableEnd(UI24) + var amfvar = AMF.parseVariable( + arrayBuffer, + dataOffset + offset, + dataSize - offset - terminal + ); + if (amfvar.objectEnd) break; + value[amfvar.data.name] = amfvar.data.value; + offset += amfvar.size; + } + if (offset <= dataSize - 3) { + var marker = v.getUint32(offset - 1, !le) & 0x00ffffff; + if (marker === 9) { + offset += 3; + } + } + break; + } + case 9: // ScriptDataObjectEnd + value = undefined; + offset = 1; + objectEnd = true; + break; + case 10: { + // Strict array type + // ScriptDataValue[n]. NOTE: according to video_file_format_spec_v10_1.pdf + value = []; + var strictArrayLength = v.getUint32(1, !le); + offset += 4; + for (var i = 0; i < strictArrayLength; i++) { + var val = AMF.parseValue( + arrayBuffer, + dataOffset + offset, + dataSize - offset + ); + value.push(val.data); + offset += val.size; + } + break; + } + case 11: { + // Date type + var date = AMF.parseDate( + arrayBuffer, + dataOffset + 1, + dataSize - 1 + ); + value = date.data; + offset += date.size; + break; + } + case 12: { + // Long string type + var amfLongStr = AMF.parseString( + arrayBuffer, + dataOffset + 1, + dataSize - 1 + ); + value = amfLongStr.data; + offset += amfLongStr.size; + break; + } + default: + // ignore and skip + offset = dataSize; + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + "AMF", + "Unsupported AMF value type " + type + ); + } + } catch (e) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.e( + "AMF", + e.toString() + ); + } + return { + data: value, + size: offset, + objectEnd: objectEnd, + }; + }; + return AMF; + })(); + /* harmony default export */ __webpack_exports__["default"] = AMF; + + /***/ + }, + + /***/ "./src/demux/av1-parser.js": + /*!*********************************!*\ + !*** ./src/demux/av1-parser.js ***! + \*********************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony import */ var _exp_golomb_js__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__( + /*! ./exp-golomb.js */ "./src/demux/exp-golomb.js" + ); + /* + * Copyright (C) 2022 もにょてっく. All Rights Reserved. + * + * @author もにょ〜ん + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + // type OperatingPoint = { + // operating_point_idc: number, + // level: number, + // tier: number, + // }; + var AV1OBUParser = /** @class */ (function () { + function AV1OBUParser() {} + AV1OBUParser.parseOBUs = function (uint8array) { + var meta = null; + for (var i = 0; i < uint8array.byteLength; ) { + var forbidden_bit = (uint8array[i] & 0x80) >> 7; + var type = (uint8array[i] & 0x78) >> 3; + var extension_flag = (uint8array[i] & 0x04) !== 0; + var has_size_field = (uint8array[i] & 0x02) !== 0; + var reserved_1bit = (uint8array[i] & 0x01) !== 0; + i += 1; + if (extension_flag) { + i += 1; + } + var size = Number.POSITIVE_INFINITY; + if (has_size_field) { + size = 0; + for (var j = 0; ; j++) { + size |= (uint8array[i] & 0x7f) << (j * 7); + i += 1; + if ((uint8array[i] & 0x80) === 0) { + break; + } + } + } + if (type === 1) { + // OBU_SEQUENCE_HEADER + meta = AV1OBUParser.parseSeuqneceHeader( + uint8array.subarray(i, i + size) + ); + } + i += size; + } + return meta; + }; + AV1OBUParser.parseSeuqneceHeader = function (uint8array) { + var gb = new _exp_golomb_js__WEBPACK_IMPORTED_MODULE_0__.default( + uint8array + ); + var seq_profile = gb.readBits(3); + var still_picture = gb.readBool(); + var reduced_still_picture_header = gb.readBool(); + var fps = 0, + fps_fixed = true, + fps_num = 0, + fps_den = 0; + var operating_points /*: OperatingPoint[]*/ = []; + if (reduced_still_picture_header) { + operating_points.push({ + operating_point_idc: 0, + level: gb.readBits(5), + tier: 0, + }); + } else { + var timing_info_present_flag = gb.readBool(); + var decoder_model_info_present_flag = false; + var buffer_delay_length_minus_1 = 0; + if (timing_info_present_flag) { + // timing_info + var num_units_in_display_tick = gb.readBits(32); + var time_scale = gb.readBits(32); + var equal_picture_interval = gb.readBool(); + var num_ticks_per_picture_minus_1 = 0; + if (equal_picture_interval) { + var leading = 0; + while (true) { + var value = gb.readBits(1); + if (value !== 0) { + break; + } + leading += 1; + } + if (leading >= 32) { + num_ticks_per_picture_minus_1 = 0xffffffff; + } else { + num_ticks_per_picture_minus_1 = + (1 << leading) - 1 + gb.readBits(leading); + } + } + fps_den = num_units_in_display_tick; + fps_num = time_scale; + fps = fps_num / fps_den; + fps_fixed = equal_picture_interval; + var decoder_model_info_present_flag_1 = gb.readBool(); + if (decoder_model_info_present_flag_1) { + // decoder_model_info + buffer_delay_length_minus_1 = gb.readBits(5); + var num_units_in_decoding_tick = gb.readBits(32); + var buffer_removal_time_length_minus_1 = gb.readBits(5); + var frame_presentation_time_length_minus_1 = gb.readBits(5); + } + } + var initial_display_delay_present_flag = gb.readBool(); + var operating_points_cnt_minus_1 = gb.readBits(5); + for (var i = 0; i <= operating_points_cnt_minus_1; i++) { + var operating_point_idc = gb.readBits(12); + var level_1 = gb.readBits(5); + var tier_1 = level_1 > 7 ? gb.readBits(1) : 0; + operating_points.push({ + operating_point_idc: operating_point_idc, + level: level_1, + tier: tier_1, + }); + if (decoder_model_info_present_flag) { + var decoder_model_present_for_this_op = gb.readBool(); + if (decoder_model_present_for_this_op) { + // operating_parameters_info + var decoder_buffer_delay = gb.readBits( + buffer_delay_length_minus_1 + 1 + ); + var encoder_buffer_delay = gb.readBits( + buffer_delay_length_minus_1 + 1 + ); + var low_delay_mode_flag = gb.readBool(); + } + } + if (initial_display_delay_present_flag) { + var initial_display_delay_present_for_this_op = + gb.readBool(); + if (initial_display_delay_present_for_this_op) { + var initial_display_delay_minus_1 = gb.readBits(4); + } + } + } + } + var operating_point = 0; + var _a = operating_points[operating_point], + level = _a.level, + tier = _a.tier; + var frame_width_bits_minus_1 = gb.readBits(4); + var frame_height_bits_minus_1 = gb.readBits(4); + var max_frame_width = + gb.readBits(frame_width_bits_minus_1 + 1) + 1; + var max_frame_height = + gb.readBits(frame_height_bits_minus_1 + 1) + 1; + var frame_id_numbers_present_flag = false; + if (!reduced_still_picture_header) { + frame_id_numbers_present_flag = gb.readBool(); + } + if (frame_id_numbers_present_flag) { + var delta_frame_id_length_minus_2 = gb.readBits(4); + var additional_frame_id_length_minus_1 = gb.readBits(4); + } + var SELECT_SCREEN_CONTENT_TOOLS = 2; + var SELECT_INTEGER_MV = 2; + var use_128x128_superblock = gb.readBool(); + var enable_filter_intra = gb.readBool(); + var enable_intra_edge_filter = gb.readBool(); + var enable_interintra_compound = false; + var enable_masked_compound = false; + var enable_warped_motion = false; + var enable_dual_filter = false; + var enable_order_hint = false; + var enable_jnt_comp = false; + var enable_ref_frame_mvs = false; + var seq_force_screen_content_tools = SELECT_SCREEN_CONTENT_TOOLS; + var seq_force_integer_mv = SELECT_INTEGER_MV; + var OrderHintBits = 0; + if (!reduced_still_picture_header) { + enable_interintra_compound = gb.readBool(); + enable_masked_compound = gb.readBool(); + enable_warped_motion = gb.readBool(); + enable_dual_filter = gb.readBool(); + enable_order_hint = gb.readBool(); + if (enable_order_hint) { + var enable_jnt_comp_1 = gb.readBool(); + var enable_ref_frame_mvs_1 = gb.readBool(); + } + var seq_choose_screen_content_tools = gb.readBool(); + if (seq_choose_screen_content_tools) { + seq_force_screen_content_tools = SELECT_SCREEN_CONTENT_TOOLS; + } else { + seq_force_screen_content_tools = gb.readBits(1); + } + if (seq_force_screen_content_tools) { + var seq_choose_integer_mv = gb.readBool(); + if (seq_choose_integer_mv) { + seq_force_integer_mv = SELECT_INTEGER_MV; + } else { + seq_force_integer_mv = gb.readBits(1); + } + } else { + seq_force_integer_mv = SELECT_INTEGER_MV; + } + if (enable_order_hint) { + var order_hint_bits_minus_1 = gb.readBits(3); + OrderHintBits = order_hint_bits_minus_1 + 1; + } else { + OrderHintBits = 0; + } + } + var enable_superres = gb.readBool(); + var enable_cdef = gb.readBool(); + var enable_restoration = gb.readBool(); + // color_config + var high_bitdepth = gb.readBool(); + var bitDepth = 8; + if (seq_profile === 2 && high_bitdepth) { + var twelve_bit = gb.readBool(); + bitDepth = twelve_bit ? 12 : 10; + } else { + bitDepth = high_bitdepth ? 10 : 8; + } + var mono_chrome = false; + if (seq_profile !== 1) { + mono_chrome = gb.readBool(); + } + var numPlanes = mono_chrome ? 1 : 3; + var color_description_present_flag = gb.readBool(); + var CP_BT_709 = 1, + CP_UNSPECIFIED = 2; + var TC_UNSPECIFIED = 2, + TC_SRGB = 13; + var MC_UNSPECIFIED = 2, + MC_IDENTITY = 0; + var color_primaries = CP_UNSPECIFIED; + var transfer_characteristics = TC_UNSPECIFIED; + var matrix_coefficients = MC_UNSPECIFIED; + if (color_description_present_flag) { + var color_primaries_1 = gb.readBits(8); + var transfer_characteristics_1 = gb.readBits(8); + var matrix_coefficients_1 = gb.readBits(8); + } + var color_range = 1; + var subsampling_x = 1; + var subsampling_y = 1; + if (mono_chrome) { + color_range = gb.readBits(1); + subsampling_x = 1; + subsampling_y = 1; + var chroma_sample_position = 0; /* CSP_UNKNOWN */ + var separate_uv_delta_q = 0; + } else { + var color_range_1 = 1; + if ( + color_primaries === CP_BT_709 && + transfer_characteristics === TC_SRGB && + matrix_coefficients === MC_IDENTITY + ) { + color_range_1 = 1; + subsampling_x = 1; + subsampling_y = 1; + } else { + color_range_1 = gb.readBits(1); + if (seq_profile == 0) { + subsampling_x = 1; + subsampling_y = 1; + } else if (seq_profile == 1) { + subsampling_x = 0; + subsampling_y = 0; + } else { + if (bitDepth == 12) { + var subsampling_x_1 = gb.readBits(1); + if (subsampling_x_1) { + var subsampling_y_1 = gb.readBits(1); + } else { + var subsampling_y_2 = 0; + } + } else { + subsampling_x = 1; + subsampling_y = 0; + } + } + if (subsampling_x && subsampling_y) { + var chroma_sample_position = gb.readBits(2); + } + var separate_uv_delta_q = gb.readBits(1); + } + } + // + var film_grain_params_present = gb.readBool(); + gb.destroy(); + gb = null; + var codec_mimetype = + "av01." + + seq_profile + + "." + + AV1OBUParser.getLevelString(level, tier) + + "." + + bitDepth.toString(10).padStart(2, "0"); + var sar_width = 1, + sar_height = 1, + sar_scale = 1; + return { + codec_mimetype: codec_mimetype, + level: level, + tier: tier, + level_string: AV1OBUParser.getLevelString(level, tier), + profile_idc: seq_profile, + profile_string: "" + seq_profile, + bit_depth: bitDepth, + ref_frames: 1, + chroma_format: AV1OBUParser.getChromaFormat( + mono_chrome, + subsampling_x, + subsampling_y + ), + chroma_format_string: AV1OBUParser.getChromaFormatString( + mono_chrome, + subsampling_x, + subsampling_y + ), + frame_rate: { + fixed: fps_fixed, + fps: fps_num / fps_den, + fps_den: fps_den, + fps_num: fps_num, + }, + sar_ratio: { + width: sar_width, + height: sar_height, + }, + codec_size: { + width: max_frame_width, + height: max_frame_height, + }, + present_size: { + width: max_frame_width * sar_scale, + height: max_frame_height, + }, + }; + }; + AV1OBUParser.getLevelString = function ( + level /*: number*/, + tier /*: number*/ + ) { + return ( + "" + + level.toString(10).padStart(2, "0") + + (tier === 0 ? "M" : "H") + ); + }; + AV1OBUParser.getChromaFormat = function ( + mono_chrome /*: boolean*/, + subsampling_x /*: number*/, + subsampling_y /*: number*/ + ) { + if (mono_chrome) { + return 0; + } else if (subsampling_x === 0 && subsampling_y === 0) { + return 3; + } else if (subsampling_x === 1 && subsampling_y === 0) { + return 2; + } else if (subsampling_x === 1 && subsampling_y === 1) { + return 1; + } else { + return Number.NaN; + } + }; + AV1OBUParser.getChromaFormatString = function ( + mono_chrome /*: boolean*/, + subsampling_x /*: number*/, + subsampling_y /*: number*/ + ) { + if (mono_chrome) { + return "4:0:0"; + } else if (subsampling_x === 0 && subsampling_y === 0) { + return "4:4:4"; + } else if (subsampling_x === 1 && subsampling_y === 0) { + return "4:2:2"; + } else if (subsampling_x === 1 && subsampling_y === 1) { + return "4:2:0"; + } else { + return "Unknown"; + } + }; + return AV1OBUParser; + })(); + /* harmony default export */ __webpack_exports__["default"] = + AV1OBUParser; + + /***/ + }, + + /***/ "./src/demux/demux-errors.js": + /*!***********************************!*\ + !*** ./src/demux/demux-errors.js ***! + \***********************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + var DemuxErrors = { + OK: "OK", + FORMAT_ERROR: "FormatError", + FORMAT_UNSUPPORTED: "FormatUnsupported", + CODEC_UNSUPPORTED: "CodecUnsupported", + }; + /* harmony default export */ __webpack_exports__["default"] = + DemuxErrors; + + /***/ + }, + + /***/ "./src/demux/exp-golomb.js": + /*!*********************************!*\ + !*** ./src/demux/exp-golomb.js ***! + \*********************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony import */ var _utils_exception_js__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__( + /*! ../utils/exception.js */ "./src/utils/exception.js" + ); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + // Exponential-Golomb buffer decoder + var ExpGolomb = /** @class */ (function () { + function ExpGolomb(uint8array) { + this.TAG = "ExpGolomb"; + this._buffer = uint8array; + this._buffer_index = 0; + this._total_bytes = uint8array.byteLength; + this._total_bits = uint8array.byteLength * 8; + this._current_word = 0; + this._current_word_bits_left = 0; + } + ExpGolomb.prototype.destroy = function () { + this._buffer = null; + }; + ExpGolomb.prototype._fillCurrentWord = function () { + var buffer_bytes_left = this._total_bytes - this._buffer_index; + if (buffer_bytes_left <= 0) + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_0__.IllegalStateException( + "ExpGolomb: _fillCurrentWord() but no bytes available" + ); + var bytes_read = Math.min(4, buffer_bytes_left); + var word = new Uint8Array(4); + word.set( + this._buffer.subarray( + this._buffer_index, + this._buffer_index + bytes_read + ) + ); + this._current_word = new DataView(word.buffer).getUint32( + 0, + false + ); + this._buffer_index += bytes_read; + this._current_word_bits_left = bytes_read * 8; + }; + ExpGolomb.prototype.readBits = function (bits) { + if (bits > 32) + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_0__.InvalidArgumentException( + "ExpGolomb: readBits() bits exceeded max 32bits!" + ); + if (bits <= this._current_word_bits_left) { + var result_1 = this._current_word >>> (32 - bits); + this._current_word <<= bits; + this._current_word_bits_left -= bits; + return result_1; + } + var result = this._current_word_bits_left + ? this._current_word + : 0; + result = result >>> (32 - this._current_word_bits_left); + var bits_need_left = bits - this._current_word_bits_left; + this._fillCurrentWord(); + var bits_read_next = Math.min( + bits_need_left, + this._current_word_bits_left + ); + var result2 = this._current_word >>> (32 - bits_read_next); + this._current_word <<= bits_read_next; + this._current_word_bits_left -= bits_read_next; + result = (result << bits_read_next) | result2; + return result; + }; + ExpGolomb.prototype.readBool = function () { + return this.readBits(1) === 1; + }; + ExpGolomb.prototype.readByte = function () { + return this.readBits(8); + }; + ExpGolomb.prototype._skipLeadingZero = function () { + var zero_count; + for ( + zero_count = 0; + zero_count < this._current_word_bits_left; + zero_count++ + ) { + if (0 !== (this._current_word & (0x80000000 >>> zero_count))) { + this._current_word <<= zero_count; + this._current_word_bits_left -= zero_count; + return zero_count; + } + } + this._fillCurrentWord(); + return zero_count + this._skipLeadingZero(); + }; + ExpGolomb.prototype.readUEG = function () { + var leading_zeros = this._skipLeadingZero(); + return this.readBits(leading_zeros + 1) - 1; + }; + ExpGolomb.prototype.readSEG = function () { + var value = this.readUEG(); + if (value & 0x01) { + return (value + 1) >>> 1; + } else { + return -1 * (value >>> 1); + } + }; + ExpGolomb.prototype.getBitsLeft = function () { + return ( + (this._total_bytes - this._buffer_index) * 8 + + this._current_word_bits_left + ); + }; + return ExpGolomb; + })(); + /* harmony default export */ __webpack_exports__["default"] = + ExpGolomb; + + /***/ + }, + + /***/ "./src/demux/flv-demuxer.js": + /*!**********************************!*\ + !*** ./src/demux/flv-demuxer.js ***! + \**********************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony import */ var _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__( + /*! ../utils/logger.js */ "./src/utils/logger.js" + ); + /* harmony import */ var _amf_parser_js__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__( + /*! ./amf-parser.js */ "./src/demux/amf-parser.js" + ); + /* harmony import */ var _sps_parser_js__WEBPACK_IMPORTED_MODULE_2__ = + __webpack_require__( + /*! ./sps-parser.js */ "./src/demux/sps-parser.js" + ); + /* harmony import */ var _hevc_sps_parser_js__WEBPACK_IMPORTED_MODULE_3__ = + __webpack_require__( + /*! ./hevc-sps-parser.js */ "./src/demux/hevc-sps-parser.js" + ); + /* harmony import */ var _av1_parser_js__WEBPACK_IMPORTED_MODULE_4__ = + __webpack_require__( + /*! ./av1-parser.js */ "./src/demux/av1-parser.js" + ); + /* harmony import */ var _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__ = + __webpack_require__( + /*! ./demux-errors.js */ "./src/demux/demux-errors.js" + ); + /* harmony import */ var _core_media_info_js__WEBPACK_IMPORTED_MODULE_6__ = + __webpack_require__( + /*! ../core/media-info.js */ "./src/core/media-info.js" + ); + /* harmony import */ var _utils_exception_js__WEBPACK_IMPORTED_MODULE_7__ = + __webpack_require__( + /*! ../utils/exception.js */ "./src/utils/exception.js" + ); + /* harmony import */ var _utils_typedarray_equality_js__WEBPACK_IMPORTED_MODULE_8__ = + __webpack_require__( + /*! ../utils/typedarray-equality.js */ "./src/utils/typedarray-equality.js" + ); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + function Swap16(src) { + return ((src >>> 8) & 0xff) | ((src & 0xff) << 8); + } + function Swap32(src) { + return ( + ((src & 0xff000000) >>> 24) | + ((src & 0x00ff0000) >>> 8) | + ((src & 0x0000ff00) << 8) | + ((src & 0x000000ff) << 24) + ); + } + function ReadBig32(array, index) { + return ( + (array[index] << 24) | + (array[index + 1] << 16) | + (array[index + 2] << 8) | + array[index + 3] + ); + } + var FLVDemuxer = /** @class */ (function () { + function FLVDemuxer(probeData, config) { + this.TAG = "FLVDemuxer"; + this._config = config; + this._onError = null; + this._onMediaInfo = null; + this._onMetaDataArrived = null; + this._onScriptDataArrived = null; + this._onTrackMetadata = null; + this._onDataAvailable = null; + this._dataOffset = probeData.dataOffset; + this._firstParse = true; + this._dispatch = false; + this._hasAudio = probeData.hasAudioTrack; + this._hasVideo = probeData.hasVideoTrack; + this._hasAudioFlagOverrided = false; + this._hasVideoFlagOverrided = false; + this._audioInitialMetadataDispatched = false; + this._videoInitialMetadataDispatched = false; + this._mediaInfo = + new _core_media_info_js__WEBPACK_IMPORTED_MODULE_6__.default(); + this._mediaInfo.hasAudio = this._hasAudio; + this._mediaInfo.hasVideo = this._hasVideo; + this._metadata = null; + this._audioMetadata = null; + this._videoMetadata = null; + this._naluLengthSize = 4; + this._timestampBase = 0; // int32, in milliseconds + this._timescale = 1000; + this._duration = 0; // int32, in milliseconds + this._durationOverrided = false; + this._referenceFrameRate = { + fixed: true, + fps: 23.976, + fps_num: 23976, + fps_den: 1000, + }; + this._flvSoundRateTable = [5500, 11025, 22050, 44100, 48000]; + this._mpegSamplingRates = [ + 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, + 12000, 11025, 8000, 7350, + ]; + this._mpegAudioV10SampleRateTable = [44100, 48000, 32000, 0]; + this._mpegAudioV20SampleRateTable = [22050, 24000, 16000, 0]; + this._mpegAudioV25SampleRateTable = [11025, 12000, 8000, 0]; + this._mpegAudioL1BitRateTable = [ + 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, + 448, -1, + ]; + this._mpegAudioL2BitRateTable = [ + 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, + 384, -1, + ]; + this._mpegAudioL3BitRateTable = [ + 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, + 320, -1, + ]; + this._videoTrack = { + type: "video", + id: 1, + sequenceNumber: 0, + samples: [], + length: 0, + }; + this._audioTrack = { + type: "audio", + id: 2, + sequenceNumber: 0, + samples: [], + length: 0, + }; + this._littleEndian = (function () { + var buf = new ArrayBuffer(2); + new DataView(buf).setInt16(0, 256, true); // little-endian write + return new Int16Array(buf)[0] === 256; // platform-spec read, if equal then LE + })(); + } + FLVDemuxer.prototype.destroy = function () { + this._mediaInfo = null; + this._metadata = null; + this._audioMetadata = null; + this._videoMetadata = null; + this._videoTrack = null; + this._audioTrack = null; + this._onError = null; + this._onMediaInfo = null; + this._onMetaDataArrived = null; + this._onScriptDataArrived = null; + this._onTrackMetadata = null; + this._onDataAvailable = null; + }; + FLVDemuxer.probe = function (buffer) { + var data = new Uint8Array(buffer); + if (data.byteLength < 9) { + return { needMoreData: true }; + } + var mismatch = { match: false }; + if ( + data[0] !== 0x46 || + data[1] !== 0x4c || + data[2] !== 0x56 || + data[3] !== 0x01 + ) { + return mismatch; + } + var hasAudio = (data[4] & 4) >>> 2 !== 0; + var hasVideo = (data[4] & 1) !== 0; + var offset = ReadBig32(data, 5); + if (offset < 9) { + return mismatch; + } + return { + match: true, + consumed: offset, + dataOffset: offset, + hasAudioTrack: hasAudio, + hasVideoTrack: hasVideo, + }; + }; + FLVDemuxer.prototype.bindDataSource = function (loader) { + loader.onDataArrival = this.parseChunks.bind(this); + return this; + }; + Object.defineProperty(FLVDemuxer.prototype, "onTrackMetadata", { + // prototype: function(type: string, metadata: any): void + get: function () { + return this._onTrackMetadata; + }, + set: function (callback) { + this._onTrackMetadata = callback; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(FLVDemuxer.prototype, "onMediaInfo", { + // prototype: function(mediaInfo: MediaInfo): void + get: function () { + return this._onMediaInfo; + }, + set: function (callback) { + this._onMediaInfo = callback; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(FLVDemuxer.prototype, "onMetaDataArrived", { + get: function () { + return this._onMetaDataArrived; + }, + set: function (callback) { + this._onMetaDataArrived = callback; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(FLVDemuxer.prototype, "onScriptDataArrived", { + get: function () { + return this._onScriptDataArrived; + }, + set: function (callback) { + this._onScriptDataArrived = callback; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(FLVDemuxer.prototype, "onError", { + // prototype: function(type: number, info: string): void + get: function () { + return this._onError; + }, + set: function (callback) { + this._onError = callback; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(FLVDemuxer.prototype, "onDataAvailable", { + // prototype: function(videoTrack: any, audioTrack: any): void + get: function () { + return this._onDataAvailable; + }, + set: function (callback) { + this._onDataAvailable = callback; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(FLVDemuxer.prototype, "timestampBase", { + // timestamp base for output samples, must be in milliseconds + get: function () { + return this._timestampBase; + }, + set: function (base) { + this._timestampBase = base; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(FLVDemuxer.prototype, "overridedDuration", { + get: function () { + return this._duration; + }, + // Force-override media duration. Must be in milliseconds, int32 + set: function (duration) { + this._durationOverrided = true; + this._duration = duration; + this._mediaInfo.duration = duration; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(FLVDemuxer.prototype, "overridedHasAudio", { + // Force-override audio track present flag, boolean + set: function (hasAudio) { + this._hasAudioFlagOverrided = true; + this._hasAudio = hasAudio; + this._mediaInfo.hasAudio = hasAudio; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(FLVDemuxer.prototype, "overridedHasVideo", { + // Force-override video track present flag, boolean + set: function (hasVideo) { + this._hasVideoFlagOverrided = true; + this._hasVideo = hasVideo; + this._mediaInfo.hasVideo = hasVideo; + }, + enumerable: false, + configurable: true, + }); + FLVDemuxer.prototype.resetMediaInfo = function () { + this._mediaInfo = + new _core_media_info_js__WEBPACK_IMPORTED_MODULE_6__.default(); + }; + FLVDemuxer.prototype._isInitialMetadataDispatched = function () { + if (this._hasAudio && this._hasVideo) { + // both audio & video + return ( + this._audioInitialMetadataDispatched && + this._videoInitialMetadataDispatched + ); + } + if (this._hasAudio && !this._hasVideo) { + // audio only + return this._audioInitialMetadataDispatched; + } + if (!this._hasAudio && this._hasVideo) { + // video only + return this._videoInitialMetadataDispatched; + } + return false; + }; + // function parseChunks(chunk: ArrayBuffer, byteStart: number): number; + FLVDemuxer.prototype.parseChunks = function (chunk, byteStart) { + if ( + !this._onError || + !this._onMediaInfo || + !this._onTrackMetadata || + !this._onDataAvailable + ) { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_7__.IllegalStateException( + "Flv: onError & onMediaInfo & onTrackMetadata & onDataAvailable callback must be specified" + ); + } + var offset = 0; + var le = this._littleEndian; + if (byteStart === 0) { + // buffer with FLV header + if (chunk.byteLength > 13) { + var probeData = FLVDemuxer.probe(chunk); + offset = probeData.dataOffset; + } else { + return 0; + } + } + if (this._firstParse) { + // handle PreviousTagSize0 before Tag1 + this._firstParse = false; + if (byteStart + offset !== this._dataOffset) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "First time parsing but chunk byteStart invalid!" + ); + } + var v = new DataView(chunk, offset); + var prevTagSize0 = v.getUint32(0, !le); + if (prevTagSize0 !== 0) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "PrevTagSize0 !== 0 !!!" + ); + } + offset += 4; + } + while (offset < chunk.byteLength) { + this._dispatch = true; + var v = new DataView(chunk, offset); + if (offset + 11 + 4 > chunk.byteLength) { + // data not enough for parsing an flv tag + break; + } + var tagType = v.getUint8(0); + var dataSize = v.getUint32(0, !le) & 0x00ffffff; + if (offset + 11 + dataSize + 4 > chunk.byteLength) { + // data not enough for parsing actual data body + break; + } + if (tagType !== 8 && tagType !== 9 && tagType !== 18) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Unsupported tag type " + tagType + ", skipped" + ); + // consume the whole tag (skip it) + offset += 11 + dataSize + 4; + continue; + } + var ts2 = v.getUint8(4); + var ts1 = v.getUint8(5); + var ts0 = v.getUint8(6); + var ts3 = v.getUint8(7); + var timestamp = ts0 | (ts1 << 8) | (ts2 << 16) | (ts3 << 24); + var streamId = v.getUint32(7, !le) & 0x00ffffff; + if (streamId !== 0) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Meet tag which has StreamID != 0!" + ); + } + var dataOffset = offset + 11; + switch (tagType) { + case 8: // Audio + this._parseAudioData( + chunk, + dataOffset, + dataSize, + timestamp + ); + break; + case 9: // Video + this._parseVideoData( + chunk, + dataOffset, + dataSize, + timestamp, + byteStart + offset + ); + break; + case 18: // ScriptDataObject + this._parseScriptData(chunk, dataOffset, dataSize); + break; + } + var prevTagSize = v.getUint32(11 + dataSize, !le); + if (prevTagSize !== 11 + dataSize) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Invalid PrevTagSize " + prevTagSize + ); + } + offset += 11 + dataSize + 4; // tagBody + dataSize + prevTagSize + } + // dispatch parsed frames to consumer (typically, the remuxer) + if (this._isInitialMetadataDispatched()) { + if ( + this._dispatch && + (this._audioTrack.length || this._videoTrack.length) + ) { + this._onDataAvailable(this._audioTrack, this._videoTrack); + } + } + return offset; // consumed bytes, just equals latest offset index + }; + FLVDemuxer.prototype._parseScriptData = function ( + arrayBuffer, + dataOffset, + dataSize + ) { + var scriptData = + _amf_parser_js__WEBPACK_IMPORTED_MODULE_1__.default.parseScriptData( + arrayBuffer, + dataOffset, + dataSize + ); + if (scriptData.hasOwnProperty("onMetaData")) { + if ( + scriptData.onMetaData == null || + typeof scriptData.onMetaData !== "object" + ) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Invalid onMetaData structure!" + ); + return; + } + if (this._metadata) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Found another onMetaData tag!" + ); + } + this._metadata = scriptData; + var onMetaData = this._metadata.onMetaData; + if (this._onMetaDataArrived) { + this._onMetaDataArrived(Object.assign({}, onMetaData)); + } + if (typeof onMetaData.hasAudio === "boolean") { + // hasAudio + if (this._hasAudioFlagOverrided === false) { + this._hasAudio = onMetaData.hasAudio; + this._mediaInfo.hasAudio = this._hasAudio; + } + } + if (typeof onMetaData.hasVideo === "boolean") { + // hasVideo + if (this._hasVideoFlagOverrided === false) { + this._hasVideo = onMetaData.hasVideo; + this._mediaInfo.hasVideo = this._hasVideo; + } + } + if (typeof onMetaData.audiodatarate === "number") { + // audiodatarate + this._mediaInfo.audioDataRate = onMetaData.audiodatarate; + } + if (typeof onMetaData.videodatarate === "number") { + // videodatarate + this._mediaInfo.videoDataRate = onMetaData.videodatarate; + } + if (typeof onMetaData.width === "number") { + // width + this._mediaInfo.width = onMetaData.width; + } + if (typeof onMetaData.height === "number") { + // height + this._mediaInfo.height = onMetaData.height; + } + if (typeof onMetaData.duration === "number") { + // duration + if (!this._durationOverrided) { + var duration = Math.floor( + onMetaData.duration * this._timescale + ); + this._duration = duration; + this._mediaInfo.duration = duration; + } + } else { + this._mediaInfo.duration = 0; + } + if (typeof onMetaData.framerate === "number") { + // framerate + var fps_num = Math.floor(onMetaData.framerate * 1000); + if (fps_num > 0) { + var fps = fps_num / 1000; + this._referenceFrameRate.fixed = true; + this._referenceFrameRate.fps = fps; + this._referenceFrameRate.fps_num = fps_num; + this._referenceFrameRate.fps_den = 1000; + this._mediaInfo.fps = fps; + } + } + if (typeof onMetaData.keyframes === "object") { + // keyframes + this._mediaInfo.hasKeyframesIndex = true; + var keyframes = onMetaData.keyframes; + this._mediaInfo.keyframesIndex = + this._parseKeyframesIndex(keyframes); + onMetaData.keyframes = null; // keyframes has been extracted, remove it + } else { + this._mediaInfo.hasKeyframesIndex = false; + } + this._dispatch = false; + this._mediaInfo.metadata = onMetaData; + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.v( + this.TAG, + "Parsed onMetaData" + ); + if (this._mediaInfo.isComplete()) { + this._onMediaInfo(this._mediaInfo); + } + } + if (Object.keys(scriptData).length > 0) { + if (this._onScriptDataArrived) { + this._onScriptDataArrived(Object.assign({}, scriptData)); + } + } + }; + FLVDemuxer.prototype._parseKeyframesIndex = function (keyframes) { + var times = []; + var filepositions = []; + // ignore first keyframe which is actually AVC/HEVC Sequence Header (AVCDecoderConfigurationRecord or HEVCDecoderConfigurationRecord) + for (var i = 1; i < keyframes.times.length; i++) { + var time = + this._timestampBase + Math.floor(keyframes.times[i] * 1000); + times.push(time); + filepositions.push(keyframes.filepositions[i]); + } + return { + times: times, + filepositions: filepositions, + }; + }; + FLVDemuxer.prototype._parseAudioData = function ( + arrayBuffer, + dataOffset, + dataSize, + tagTimestamp + ) { + if (dataSize <= 1) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Flv: Invalid audio packet, missing SoundData payload!" + ); + return; + } + if ( + this._hasAudioFlagOverrided === true && + this._hasAudio === false + ) { + // If hasAudio: false indicated explicitly in MediaDataSource, + // Ignore all the audio packets + return; + } + var le = this._littleEndian; + var v = new DataView(arrayBuffer, dataOffset, dataSize); + var soundSpec = v.getUint8(0); + var soundFormat = soundSpec >>> 4; + if (soundFormat === 9) { + // Enhanced FLV + if (dataSize <= 5) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Flv: Invalid audio packet, missing AudioFourCC in Ehnanced FLV payload!" + ); + return; + } + var packetType = soundSpec & 0x0f; + var fourcc = String.fromCharCode.apply( + String, + new Uint8Array(arrayBuffer, dataOffset, dataSize).slice(1, 5) + ); + switch (fourcc) { + case "Opus": + this._parseOpusAudioPacket( + arrayBuffer, + dataOffset + 5, + dataSize - 5, + tagTimestamp, + packetType + ); + break; + default: + this._onError( + _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__.default + .CODEC_UNSUPPORTED, + "Flv: Unsupported audio codec: " + fourcc + ); + } + return; + } + // Legacy FLV + if (soundFormat !== 2 && soundFormat !== 10) { + // MP3 or AAC + this._onError( + _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__.default + .CODEC_UNSUPPORTED, + "Flv: Unsupported audio codec idx: " + soundFormat + ); + return; + } + var soundRate = 0; + var soundRateIndex = (soundSpec & 12) >>> 2; + if (soundRateIndex >= 0 && soundRateIndex <= 4) { + soundRate = this._flvSoundRateTable[soundRateIndex]; + } else { + this._onError( + _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__.default + .FORMAT_ERROR, + "Flv: Invalid audio sample rate idx: " + soundRateIndex + ); + return; + } + var soundSize = (soundSpec & 2) >>> 1; // unused + var soundType = soundSpec & 1; + var meta = this._audioMetadata; + var track = this._audioTrack; + if (!meta) { + if ( + this._hasAudio === false && + this._hasAudioFlagOverrided === false + ) { + this._hasAudio = true; + this._mediaInfo.hasAudio = true; + } + // initial metadata + meta = this._audioMetadata = {}; + meta.type = "audio"; + meta.id = track.id; + meta.timescale = this._timescale; + meta.duration = this._duration; + meta.audioSampleRate = soundRate; + meta.channelCount = soundType === 0 ? 1 : 2; + } + if (soundFormat === 10) { + // AAC + var aacData = this._parseAACAudioData( + arrayBuffer, + dataOffset + 1, + dataSize - 1 + ); + if (aacData == undefined) { + return; + } + if (aacData.packetType === 0) { + // AAC sequence header (AudioSpecificConfig) + if (meta.config) { + if ( + (0, + _utils_typedarray_equality_js__WEBPACK_IMPORTED_MODULE_8__.default)( + aacData.data.config, + meta.config + ) + ) { + // If AudioSpecificConfig is not changed, ignore it to avoid generating initialization segment repeatedly + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Found another AudioSpecificConfig!" + ); + return; + } else { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "AudioSpecificConfig has been changed, re-generate initialization segment" + ); + } + } + var misc = aacData.data; + meta.audioSampleRate = misc.samplingRate; + meta.channelCount = misc.channelCount; + meta.codec = misc.codec; + meta.originalCodec = misc.originalCodec; + meta.config = misc.config; + // The decode result of an aac sample is 1024 PCM samples + meta.refSampleDuration = + (1024 / meta.audioSampleRate) * meta.timescale; + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.v( + this.TAG, + "Parsed AudioSpecificConfig" + ); + if (this._isInitialMetadataDispatched()) { + // Non-initial metadata, force dispatch (or flush) parsed frames to remuxer + if ( + this._dispatch && + (this._audioTrack.length || this._videoTrack.length) + ) { + this._onDataAvailable(this._audioTrack, this._videoTrack); + } + } else { + this._audioInitialMetadataDispatched = true; + } + // then notify new metadata + this._dispatch = false; + this._onTrackMetadata("audio", meta); + var mi = this._mediaInfo; + mi.audioCodec = meta.originalCodec; + mi.audioSampleRate = meta.audioSampleRate; + mi.audioChannelCount = meta.channelCount; + if (mi.hasVideo) { + if (mi.videoCodec != null) { + mi.mimeType = + 'video/x-flv; codecs="' + + mi.videoCodec + + "," + + mi.audioCodec + + '"'; + } + } else { + mi.mimeType = 'video/x-flv; codecs="' + mi.audioCodec + '"'; + } + if (mi.isComplete()) { + this._onMediaInfo(mi); + } + } else if (aacData.packetType === 1) { + // AAC raw frame data + var dts = this._timestampBase + tagTimestamp; + var aacSample = { + unit: aacData.data, + length: aacData.data.byteLength, + dts: dts, + pts: dts, + }; + track.samples.push(aacSample); + track.length += aacData.data.length; + } else { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.e( + this.TAG, + "Flv: Unsupported AAC data type " + aacData.packetType + ); + } + } else if (soundFormat === 2) { + // MP3 + if (!meta.codec) { + // We need metadata for mp3 audio track, extract info from frame header + var misc = this._parseMP3AudioData( + arrayBuffer, + dataOffset + 1, + dataSize - 1, + true + ); + if (misc == undefined) { + return; + } + meta.audioSampleRate = misc.samplingRate; + meta.channelCount = misc.channelCount; + meta.codec = misc.codec; + meta.originalCodec = misc.originalCodec; + // The decode result of an mp3 sample is 1152 PCM samples + meta.refSampleDuration = + (1152 / meta.audioSampleRate) * meta.timescale; + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.v( + this.TAG, + "Parsed MPEG Audio Frame Header" + ); + this._audioInitialMetadataDispatched = true; + this._onTrackMetadata("audio", meta); + var mi = this._mediaInfo; + mi.audioCodec = meta.codec; + mi.audioSampleRate = meta.audioSampleRate; + mi.audioChannelCount = meta.channelCount; + mi.audioDataRate = misc.bitRate; + if (mi.hasVideo) { + if (mi.videoCodec != null) { + mi.mimeType = + 'video/x-flv; codecs="' + + mi.videoCodec + + "," + + mi.audioCodec + + '"'; + } + } else { + mi.mimeType = 'video/x-flv; codecs="' + mi.audioCodec + '"'; + } + if (mi.isComplete()) { + this._onMediaInfo(mi); + } + } + // This packet is always a valid audio packet, extract it + var data = this._parseMP3AudioData( + arrayBuffer, + dataOffset + 1, + dataSize - 1, + false + ); + if (data == undefined) { + return; + } + var dts = this._timestampBase + tagTimestamp; + var mp3Sample = { + unit: data, + length: data.byteLength, + dts: dts, + pts: dts, + }; + track.samples.push(mp3Sample); + track.length += data.length; + } + }; + FLVDemuxer.prototype._parseAACAudioData = function ( + arrayBuffer, + dataOffset, + dataSize + ) { + if (dataSize <= 1) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Flv: Invalid AAC packet, missing AACPacketType or/and Data!" + ); + return; + } + var result = {}; + var array = new Uint8Array(arrayBuffer, dataOffset, dataSize); + result.packetType = array[0]; + if (array[0] === 0) { + result.data = this._parseAACAudioSpecificConfig( + arrayBuffer, + dataOffset + 1, + dataSize - 1 + ); + } else { + result.data = array.subarray(1); + } + return result; + }; + FLVDemuxer.prototype._parseAACAudioSpecificConfig = function ( + arrayBuffer, + dataOffset, + dataSize + ) { + var array = new Uint8Array(arrayBuffer, dataOffset, dataSize); + var config = null; + /* Audio Object Type: + 0: Null + 1: AAC Main + 2: AAC LC + 3: AAC SSR (Scalable Sample Rate) + 4: AAC LTP (Long Term Prediction) + 5: HE-AAC / SBR (Spectral Band Replication) + 6: AAC Scalable + */ + var audioObjectType = 0; + var originalAudioObjectType = 0; + var audioExtensionObjectType = null; + var samplingIndex = 0; + var extensionSamplingIndex = null; + // 5 bits + audioObjectType = originalAudioObjectType = array[0] >>> 3; + // 4 bits + samplingIndex = ((array[0] & 0x07) << 1) | (array[1] >>> 7); + if ( + samplingIndex < 0 || + samplingIndex >= this._mpegSamplingRates.length + ) { + this._onError( + _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__.default + .FORMAT_ERROR, + "Flv: AAC invalid sampling frequency index!" + ); + return; + } + var samplingFrequence = this._mpegSamplingRates[samplingIndex]; + // 4 bits + var channelConfig = (array[1] & 0x78) >>> 3; + if (channelConfig < 0 || channelConfig >= 8) { + this._onError( + _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__.default + .FORMAT_ERROR, + "Flv: AAC invalid channel configuration" + ); + return; + } + if (audioObjectType === 5) { + // HE-AAC? + // 4 bits + extensionSamplingIndex = + ((array[1] & 0x07) << 1) | (array[2] >>> 7); + // 5 bits + audioExtensionObjectType = (array[2] & 0x7c) >>> 2; + } + // workarounds for various browsers + var userAgent = self.navigator.userAgent.toLowerCase(); + if (userAgent.indexOf("firefox") !== -1) { + // firefox: use SBR (HE-AAC) if freq less than 24kHz + if (samplingIndex >= 6) { + audioObjectType = 5; + config = new Array(4); + extensionSamplingIndex = samplingIndex - 3; + } else { + // use LC-AAC + audioObjectType = 2; + config = new Array(2); + extensionSamplingIndex = samplingIndex; + } + } else if (userAgent.indexOf("android") !== -1) { + // android: always use LC-AAC + audioObjectType = 2; + config = new Array(2); + extensionSamplingIndex = samplingIndex; + } else { + // for other browsers, e.g. chrome... + // Always use HE-AAC to make it easier to switch aac codec profile + audioObjectType = 5; + extensionSamplingIndex = samplingIndex; + config = new Array(4); + if (samplingIndex >= 6) { + extensionSamplingIndex = samplingIndex - 3; + } else if (channelConfig === 1) { + // Mono channel + audioObjectType = 2; + config = new Array(2); + extensionSamplingIndex = samplingIndex; + } + } + config[0] = audioObjectType << 3; + config[0] |= (samplingIndex & 0x0f) >>> 1; + config[1] = (samplingIndex & 0x0f) << 7; + config[1] |= (channelConfig & 0x0f) << 3; + if (audioObjectType === 5) { + config[1] |= (extensionSamplingIndex & 0x0f) >>> 1; + config[2] = (extensionSamplingIndex & 0x01) << 7; + // extended audio object type: force to 2 (LC-AAC) + config[2] |= 2 << 2; + config[3] = 0; + } + return { + config: config, + samplingRate: samplingFrequence, + channelCount: channelConfig, + codec: "mp4a.40." + audioObjectType, + originalCodec: "mp4a.40." + originalAudioObjectType, + }; + }; + FLVDemuxer.prototype._parseMP3AudioData = function ( + arrayBuffer, + dataOffset, + dataSize, + requestHeader + ) { + if (dataSize < 4) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Flv: Invalid MP3 packet, header missing!" + ); + return; + } + var le = this._littleEndian; + var array = new Uint8Array(arrayBuffer, dataOffset, dataSize); + var result = null; + if (requestHeader) { + if (array[0] !== 0xff) { + return; + } + var ver = (array[1] >>> 3) & 0x03; + var layer = (array[1] & 0x06) >> 1; + var bitrate_index = (array[2] & 0xf0) >>> 4; + var sampling_freq_index = (array[2] & 0x0c) >>> 2; + var channel_mode = (array[3] >>> 6) & 0x03; + var channel_count = channel_mode !== 3 ? 2 : 1; + var sample_rate = 0; + var bit_rate = 0; + var object_type = 34; // Layer-3, listed in MPEG-4 Audio Object Types + var codec = "mp3"; + switch (ver) { + case 0: // MPEG 2.5 + sample_rate = + this._mpegAudioV25SampleRateTable[sampling_freq_index]; + break; + case 2: // MPEG 2 + sample_rate = + this._mpegAudioV20SampleRateTable[sampling_freq_index]; + break; + case 3: // MPEG 1 + sample_rate = + this._mpegAudioV10SampleRateTable[sampling_freq_index]; + break; + } + switch (layer) { + case 1: // Layer 3 + object_type = 34; + if (bitrate_index < this._mpegAudioL3BitRateTable.length) { + bit_rate = this._mpegAudioL3BitRateTable[bitrate_index]; + } + break; + case 2: // Layer 2 + object_type = 33; + if (bitrate_index < this._mpegAudioL2BitRateTable.length) { + bit_rate = this._mpegAudioL2BitRateTable[bitrate_index]; + } + break; + case 3: // Layer 1 + object_type = 32; + if (bitrate_index < this._mpegAudioL1BitRateTable.length) { + bit_rate = this._mpegAudioL1BitRateTable[bitrate_index]; + } + break; + } + result = { + bitRate: bit_rate, + samplingRate: sample_rate, + channelCount: channel_count, + codec: codec, + originalCodec: codec, + }; + } else { + result = array; + } + return result; + }; + FLVDemuxer.prototype._parseOpusAudioPacket = function ( + arrayBuffer, + dataOffset, + dataSize, + tagTimestamp, + packetType + ) { + if (packetType === 0) { + // OpusSequenceHeader + this._parseOpusSequenceHeader( + arrayBuffer, + dataOffset, + dataSize + ); + } else if (packetType === 1) { + // OpusCodedData + this._parseOpusAudioData( + arrayBuffer, + dataOffset, + dataSize, + tagTimestamp + ); + } else if (packetType === 2) { + // empty, Opus end of sequence + } else { + this._onError( + _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__.default + .FORMAT_ERROR, + "Flv: Invalid video packet type " + packetType + ); + return; + } + }; + FLVDemuxer.prototype._parseOpusSequenceHeader = function ( + arrayBuffer, + dataOffset, + dataSize + ) { + if (dataSize <= 16) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Flv: Invalid OpusSequenceHeader, lack of data!" + ); + return; + } + var meta = this._audioMetadata; + var track = this._audioTrack; + if (!meta) { + if ( + this._hasAudio === false && + this._hasAudioFlagOverrided === false + ) { + this._hasAudio = true; + this._mediaInfo.hasAudio = true; + } + // initial metadata + meta = this._audioMetadata = {}; + meta.type = "audio"; + meta.id = track.id; + meta.timescale = this._timescale; + meta.duration = this._duration; + } + // Identification Header + var v = new DataView(arrayBuffer, dataOffset, dataSize); + v.setUint8(8 + 0, 0); // set version to 0 + var channelCount = v.getUint8(8 + 1); // Opus Header + 1 + v.setUint16(8 + 2, v.getUint16(8 + 2, true), false); // Big Endian to Little Endian for Pre-skip + var samplingFrequence = v.getUint32(8 + 4, true); // Opus Header + 4 + v.setUint32(8 + 4, v.getUint32(8 + 4, true), false); // Big Endian to Little Endian for Input Sample Rate + var config = new Uint8Array( + arrayBuffer, + dataOffset + 8, + dataSize - 8 + ); + var misc = { + config: config, + channelCount: channelCount, + samplingFrequence: samplingFrequence, + codec: "opus", + originalCodec: "opus", + }; + if (meta.config) { + if ( + (0, + _utils_typedarray_equality_js__WEBPACK_IMPORTED_MODULE_8__.default)( + misc.config, + meta.config + ) + ) { + // If OpusSequenceHeader is not changed, ignore it to avoid generating initialization segment repeatedly + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Found another OpusSequenceHeader!" + ); + return; + } else { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "OpusSequenceHeader has been changed, re-generate initialization segment" + ); + } + } + meta.audioSampleRate = misc.samplingFrequence; + meta.channelCount = misc.channelCount; + meta.codec = misc.codec; + meta.originalCodec = misc.originalCodec; + meta.config = misc.config; + // The decode result of an opus sample is 20ms + meta.refSampleDuration = 20; + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.v( + this.TAG, + "Parsed OpusSequenceHeader" + ); + if (this._isInitialMetadataDispatched()) { + // Non-initial metadata, force dispatch (or flush) parsed frames to remuxer + if ( + this._dispatch && + (this._audioTrack.length || this._videoTrack.length) + ) { + this._onDataAvailable(this._audioTrack, this._videoTrack); + } + } else { + this._audioInitialMetadataDispatched = true; + } + // then notify new metadata + this._dispatch = false; + this._onTrackMetadata("audio", meta); + var mi = this._mediaInfo; + mi.audioCodec = meta.originalCodec; + mi.audioSampleRate = meta.audioSampleRate; + mi.audioChannelCount = meta.channelCount; + if (mi.hasVideo) { + if (mi.videoCodec != null) { + mi.mimeType = + 'video/x-flv; codecs="' + + mi.videoCodec + + "," + + mi.audioCodec + + '"'; + } + } else { + mi.mimeType = 'video/x-flv; codecs="' + mi.audioCodec + '"'; + } + if (mi.isComplete()) { + this._onMediaInfo(mi); + } + }; + FLVDemuxer.prototype._parseOpusAudioData = function ( + arrayBuffer, + dataOffset, + dataSize, + tagTimestamp + ) { + var track = this._audioTrack; + var data = new Uint8Array(arrayBuffer, dataOffset, dataSize); + var dts = this._timestampBase + tagTimestamp; + var opusSample = { + unit: data, + length: data.byteLength, + dts: dts, + pts: dts, + }; + track.samples.push(opusSample); + track.length += data.length; + }; + FLVDemuxer.prototype._parseVideoData = function ( + arrayBuffer, + dataOffset, + dataSize, + tagTimestamp, + tagPosition + ) { + if (dataSize <= 1) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Flv: Invalid video packet, missing VideoData payload!" + ); + return; + } + if ( + this._hasVideoFlagOverrided === true && + this._hasVideo === false + ) { + // If hasVideo: false indicated explicitly in MediaDataSource, + // Ignore all the video packets + return; + } + var spec = new Uint8Array(arrayBuffer, dataOffset, dataSize)[0]; + var isExHeader = (spec & 128) !== 0; + var frameType = (spec & 112) >>> 4; + if (!isExHeader) { + var codecId = spec & 15; + if (codecId === 7) { + // AVC + this._parseAVCVideoPacket( + arrayBuffer, + dataOffset + 1, + dataSize - 1, + tagTimestamp, + tagPosition, + frameType + ); + } else if (codecId === 12) { + // HEVC + this._parseHEVCVideoPacket( + arrayBuffer, + dataOffset + 1, + dataSize - 1, + tagTimestamp, + tagPosition, + frameType + ); + } else { + this._onError( + _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__.default + .CODEC_UNSUPPORTED, + "Flv: Unsupported codec in video frame: " + codecId + ); + return; + } + } else { + var packetType = spec & 15; + var fourcc = String.fromCharCode.apply( + String, + new Uint8Array(arrayBuffer, dataOffset, dataSize).slice(1, 5) + ); + if (fourcc === "hvc1") { + // HEVC + this._parseEnhancedHEVCVideoPacket( + arrayBuffer, + dataOffset + 5, + dataSize - 5, + tagTimestamp, + tagPosition, + frameType, + packetType + ); + } else if (fourcc === "av01") { + // AV1 + this._parseEnhancedAV1VideoPacket( + arrayBuffer, + dataOffset + 5, + dataSize - 5, + tagTimestamp, + tagPosition, + frameType, + packetType + ); + } else { + this._onError( + _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__.default + .CODEC_UNSUPPORTED, + "Flv: Unsupported codec in video frame: " + fourcc + ); + return; + } + } + }; + FLVDemuxer.prototype._parseAVCVideoPacket = function ( + arrayBuffer, + dataOffset, + dataSize, + tagTimestamp, + tagPosition, + frameType + ) { + if (dataSize < 4) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Flv: Invalid AVC packet, missing AVCPacketType or/and CompositionTime" + ); + return; + } + var le = this._littleEndian; + var v = new DataView(arrayBuffer, dataOffset, dataSize); + var packetType = v.getUint8(0); + var cts_unsigned = v.getUint32(0, !le) & 0x00ffffff; + var cts = (cts_unsigned << 8) >> 8; // convert to 24-bit signed int + if (packetType === 0) { + // AVCDecoderConfigurationRecord + this._parseAVCDecoderConfigurationRecord( + arrayBuffer, + dataOffset + 4, + dataSize - 4 + ); + } else if (packetType === 1) { + // One or more Nalus + this._parseAVCVideoData( + arrayBuffer, + dataOffset + 4, + dataSize - 4, + tagTimestamp, + tagPosition, + frameType, + cts + ); + } else if (packetType === 2) { + // empty, AVC end of sequence + } else { + this._onError( + _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__.default + .FORMAT_ERROR, + "Flv: Invalid video packet type " + packetType + ); + return; + } + }; + FLVDemuxer.prototype._parseAVCDecoderConfigurationRecord = + function (arrayBuffer, dataOffset, dataSize) { + if (dataSize < 7) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Flv: Invalid AVCDecoderConfigurationRecord, lack of data!" + ); + return; + } + var meta = this._videoMetadata; + var track = this._videoTrack; + var le = this._littleEndian; + var v = new DataView(arrayBuffer, dataOffset, dataSize); + if (!meta) { + if ( + this._hasVideo === false && + this._hasVideoFlagOverrided === false + ) { + this._hasVideo = true; + this._mediaInfo.hasVideo = true; + } + meta = this._videoMetadata = {}; + meta.type = "video"; + meta.id = track.id; + meta.timescale = this._timescale; + meta.duration = this._duration; + } else { + if (typeof meta.avcc !== "undefined") { + var new_avcc = new Uint8Array( + arrayBuffer, + dataOffset, + dataSize + ); + if ( + (0, + _utils_typedarray_equality_js__WEBPACK_IMPORTED_MODULE_8__.default)( + new_avcc, + meta.avcc + ) + ) { + // AVCDecoderConfigurationRecord is not changed, ignore it to avoid generating initialization segment repeatedly + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Found another AVCDecoderConfigurationRecord!" + ); + return; + } else { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "AVCDecoderConfigurationRecord has been changed, re-generate initialization segment" + ); + } + } + } + var version = v.getUint8(0); // configurationVersion + var avcProfile = v.getUint8(1); // avcProfileIndication + var profileCompatibility = v.getUint8(2); // profile_compatibility + var avcLevel = v.getUint8(3); // AVCLevelIndication + if (version !== 1 || avcProfile === 0) { + this._onError( + _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__.default + .FORMAT_ERROR, + "Flv: Invalid AVCDecoderConfigurationRecord" + ); + return; + } + this._naluLengthSize = (v.getUint8(4) & 3) + 1; // lengthSizeMinusOne + if (this._naluLengthSize !== 3 && this._naluLengthSize !== 4) { + // holy shit!!! + this._onError( + _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__.default + .FORMAT_ERROR, + "Flv: Strange NaluLengthSizeMinusOne: " + + (this._naluLengthSize - 1) + ); + return; + } + var spsCount = v.getUint8(5) & 31; // numOfSequenceParameterSets + if (spsCount === 0) { + this._onError( + _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__.default + .FORMAT_ERROR, + "Flv: Invalid AVCDecoderConfigurationRecord: No SPS" + ); + return; + } else if (spsCount > 1) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Flv: Strange AVCDecoderConfigurationRecord: SPS Count = " + + spsCount + ); + } + var offset = 6; + for (var i = 0; i < spsCount; i++) { + var len = v.getUint16(offset, !le); // sequenceParameterSetLength + offset += 2; + if (len === 0) { + continue; + } + // Notice: Nalu without startcode header (00 00 00 01) + var sps = new Uint8Array( + arrayBuffer, + dataOffset + offset, + len + ); + offset += len; + var config = + _sps_parser_js__WEBPACK_IMPORTED_MODULE_2__.default.parseSPS( + sps + ); + if (i !== 0) { + // ignore other sps's config + continue; + } + meta.codecWidth = config.codec_size.width; + meta.codecHeight = config.codec_size.height; + meta.presentWidth = config.present_size.width; + meta.presentHeight = config.present_size.height; + meta.profile = config.profile_string; + meta.level = config.level_string; + meta.bitDepth = config.bit_depth; + meta.chromaFormat = config.chroma_format; + meta.sarRatio = config.sar_ratio; + meta.frameRate = config.frame_rate; + if ( + config.frame_rate.fixed === false || + config.frame_rate.fps_num === 0 || + config.frame_rate.fps_den === 0 + ) { + meta.frameRate = this._referenceFrameRate; + } + var fps_den = meta.frameRate.fps_den; + var fps_num = meta.frameRate.fps_num; + meta.refSampleDuration = meta.timescale * (fps_den / fps_num); + var codecArray = sps.subarray(1, 4); + var codecString = "avc1."; + for (var j = 0; j < 3; j++) { + var h = codecArray[j].toString(16); + if (h.length < 2) { + h = "0" + h; + } + codecString += h; + } + meta.codec = codecString; + var mi = this._mediaInfo; + mi.width = meta.codecWidth; + mi.height = meta.codecHeight; + mi.fps = meta.frameRate.fps; + mi.profile = meta.profile; + mi.level = meta.level; + mi.refFrames = config.ref_frames; + mi.chromaFormat = config.chroma_format_string; + mi.sarNum = meta.sarRatio.width; + mi.sarDen = meta.sarRatio.height; + mi.videoCodec = codecString; + if (mi.hasAudio) { + if (mi.audioCodec != null) { + mi.mimeType = + 'video/x-flv; codecs="' + + mi.videoCodec + + "," + + mi.audioCodec + + '"'; + } + } else { + mi.mimeType = 'video/x-flv; codecs="' + mi.videoCodec + '"'; + } + if (mi.isComplete()) { + this._onMediaInfo(mi); + } + } + var ppsCount = v.getUint8(offset); // numOfPictureParameterSets + if (ppsCount === 0) { + this._onError( + _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__.default + .FORMAT_ERROR, + "Flv: Invalid AVCDecoderConfigurationRecord: No PPS" + ); + return; + } else if (ppsCount > 1) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Flv: Strange AVCDecoderConfigurationRecord: PPS Count = " + + ppsCount + ); + } + offset++; + for (var i = 0; i < ppsCount; i++) { + var len = v.getUint16(offset, !le); // pictureParameterSetLength + offset += 2; + if (len === 0) { + continue; + } + // pps is useless for extracting video information + offset += len; + } + meta.avcc = new Uint8Array(dataSize); + meta.avcc.set( + new Uint8Array(arrayBuffer, dataOffset, dataSize), + 0 + ); + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.v( + this.TAG, + "Parsed AVCDecoderConfigurationRecord" + ); + if (this._isInitialMetadataDispatched()) { + // flush parsed frames + if ( + this._dispatch && + (this._audioTrack.length || this._videoTrack.length) + ) { + this._onDataAvailable(this._audioTrack, this._videoTrack); + } + } else { + this._videoInitialMetadataDispatched = true; + } + // notify new metadata + this._dispatch = false; + this._onTrackMetadata("video", meta); + }; + FLVDemuxer.prototype._parseAVCVideoData = function ( + arrayBuffer, + dataOffset, + dataSize, + tagTimestamp, + tagPosition, + frameType, + cts + ) { + var le = this._littleEndian; + var v = new DataView(arrayBuffer, dataOffset, dataSize); + var units = [], + length = 0; + var offset = 0; + var lengthSize = this._naluLengthSize; + var dts = this._timestampBase + tagTimestamp; + var keyframe = frameType === 1; // from FLV Frame Type constants + while (offset < dataSize) { + if (offset + 4 >= dataSize) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Malformed Nalu near timestamp " + + dts + + ", offset = " + + offset + + ", dataSize = " + + dataSize + ); + break; // data not enough for next Nalu + } + // Nalu with length-header (AVC1) + var naluSize = v.getUint32(offset, !le); // Big-Endian read + if (lengthSize === 3) { + naluSize >>>= 8; + } + if (naluSize > dataSize - lengthSize) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Malformed Nalus near timestamp " + + dts + + ", NaluSize > DataSize!" + ); + return; + } + var unitType = v.getUint8(offset + lengthSize) & 0x1f; + if (unitType === 5) { + // IDR + keyframe = true; + } + var data = new Uint8Array( + arrayBuffer, + dataOffset + offset, + lengthSize + naluSize + ); + var unit = { type: unitType, data: data }; + units.push(unit); + length += data.byteLength; + offset += lengthSize + naluSize; + } + if (units.length) { + var track = this._videoTrack; + var avcSample = { + units: units, + length: length, + isKeyframe: keyframe, + dts: dts, + cts: cts, + pts: dts + cts, + }; + if (keyframe) { + avcSample.fileposition = tagPosition; + } + track.samples.push(avcSample); + track.length += length; + } + }; + FLVDemuxer.prototype._parseHEVCVideoPacket = function ( + arrayBuffer, + dataOffset, + dataSize, + tagTimestamp, + tagPosition, + frameType + ) { + if (dataSize < 4) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Flv: Invalid HEVC packet, missing HEVCPacketType or/and CompositionTime" + ); + return; + } + var le = this._littleEndian; + var v = new DataView(arrayBuffer, dataOffset, dataSize); + var packetType = v.getUint8(0); + var cts_unsigned = v.getUint32(0, !le) & 0x00ffffff; + var cts = (cts_unsigned << 8) >> 8; // convert to 24-bit signed int + if (packetType === 0) { + // HEVCDecoderConfigurationRecord + this._parseHEVCDecoderConfigurationRecord( + arrayBuffer, + dataOffset + 4, + dataSize - 4 + ); + } else if (packetType === 1) { + // One or more Nalus + this._parseHEVCVideoData( + arrayBuffer, + dataOffset + 4, + dataSize - 4, + tagTimestamp, + tagPosition, + frameType, + cts + ); + } else if (packetType === 2) { + // empty, HEVC end of sequence + } else { + this._onError( + _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__.default + .FORMAT_ERROR, + "Flv: Invalid video packet type " + packetType + ); + return; + } + }; + FLVDemuxer.prototype._parseEnhancedHEVCVideoPacket = function ( + arrayBuffer, + dataOffset, + dataSize, + tagTimestamp, + tagPosition, + frameType, + packetType + ) { + var le = this._littleEndian; + var v = new DataView(arrayBuffer, dataOffset, dataSize); + if (packetType === 0) { + // HEVCDecoderConfigurationRecord + this._parseHEVCDecoderConfigurationRecord( + arrayBuffer, + dataOffset, + dataSize + ); + } else if (packetType === 1) { + // One or more Nalus + var cts_unsigned = v.getUint32(0, !le) & 0xffffff00; + var cts = cts_unsigned >> 8; // convert to 24-bit signed int + this._parseHEVCVideoData( + arrayBuffer, + dataOffset + 3, + dataSize - 3, + tagTimestamp, + tagPosition, + frameType, + cts + ); + } else if (packetType === 3) { + this._parseHEVCVideoData( + arrayBuffer, + dataOffset, + dataSize, + tagTimestamp, + tagPosition, + frameType, + 0 + ); + } else if (packetType === 2) { + // empty, HEVC end of sequence + } else { + this._onError( + _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__.default + .FORMAT_ERROR, + "Flv: Invalid video packet type " + packetType + ); + return; + } + }; + FLVDemuxer.prototype._parseHEVCDecoderConfigurationRecord = + function (arrayBuffer, dataOffset, dataSize) { + if (dataSize < 23) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Flv: Invalid HEVCDecoderConfigurationRecord, lack of data!" + ); + return; + } + var meta = this._videoMetadata; + var track = this._videoTrack; + var le = this._littleEndian; + var v = new DataView(arrayBuffer, dataOffset, dataSize); + if (!meta) { + if ( + this._hasVideo === false && + this._hasVideoFlagOverrided === false + ) { + this._hasVideo = true; + this._mediaInfo.hasVideo = true; + } + meta = this._videoMetadata = {}; + meta.type = "video"; + meta.id = track.id; + meta.timescale = this._timescale; + meta.duration = this._duration; + } else { + if (typeof meta.hvcc !== "undefined") { + var new_hvcc = new Uint8Array( + arrayBuffer, + dataOffset, + dataSize + ); + if ( + (0, + _utils_typedarray_equality_js__WEBPACK_IMPORTED_MODULE_8__.default)( + new_hvcc, + meta.hvcc + ) + ) { + // HEVCDecoderConfigurationRecord not changed, ignore it to avoid generating initialization segment repeatedly + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Found another HEVCDecoderConfigurationRecord!" + ); + return; + } else { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "HEVCDecoderConfigurationRecord has been changed, re-generate initialization segment" + ); + } + } + } + var version = v.getUint8(0); // configurationVersion + var hevcProfile = v.getUint8(1) & 0x1f; // hevcProfileIndication + if ((version !== 0 && version !== 1) || hevcProfile === 0) { + this._onError( + _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__.default + .FORMAT_ERROR, + "Flv: Invalid HEVCDecoderConfigurationRecord" + ); + return; + } + this._naluLengthSize = (v.getUint8(21) & 3) + 1; // lengthSizeMinusOne + if (this._naluLengthSize !== 3 && this._naluLengthSize !== 4) { + // holy shit!!! + this._onError( + _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__.default + .FORMAT_ERROR, + "Flv: Strange NaluLengthSizeMinusOne: " + + (this._naluLengthSize - 1) + ); + return; + } + var numOfArrays = v.getUint8(22); + var vpsCount, spsCount, ppsCount; + var spss = []; + for (var i = 0, offset = 23; i < numOfArrays; i++) { + var unitType = v.getUint8(offset++) & 0x3f; + var numNalus = v.getUint16(offset, !le); + offset += 2; + if (numNalus === 0) { + continue; + } + switch (unitType) { + case 32: + vpsCount += numNalus; + break; + case 33: + spsCount += numNalus; + break; + case 34: + ppsCount += numNalus; + break; + default: + break; + } + for (var j = 0; j < numNalus; j++) { + var nauUnitLength = v.getUint16(offset, !le); + offset += 2; + if (nauUnitLength === 0) { + continue; + } + if (unitType === 33) { + // Notice: Nalu without startcode header (00 00 00 01) + var sps_1 = new Uint8Array( + arrayBuffer, + dataOffset + offset, + nauUnitLength + ); + spss.push(sps_1); + } + offset += nauUnitLength; + } + } + if (vpsCount === 0) { + this._onError( + _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__.default + .FORMAT_ERROR, + "Flv: Invalid HEVCDecoderConfigurationRecord: No VPS" + ); + return; + } else if (vpsCount > 1) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Flv: Strange HEVCDecoderConfigurationRecord: VPS Count = " + + vpsCount + ); + } + if (spsCount === 0) { + this._onError( + _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__.default + .FORMAT_ERROR, + "Flv: Invalid HEVCDecoderConfigurationRecord: No SPS" + ); + return; + } else if (spsCount > 1) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Flv: Strange HEVCDecoderConfigurationRecord: SPS Count = " + + spsCount + ); + } + if (ppsCount === 0) { + this._onError( + _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__.default + .FORMAT_ERROR, + "Flv: Invalid HEVCDecoderConfigurationRecord: No PPS" + ); + return; + } else if (ppsCount > 1) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Flv: Strange HEVCDecoderConfigurationRecord: PPS Count = " + + spsCount + ); + } + var sps = spss[0]; // ignore other sps's config + var config = + _hevc_sps_parser_js__WEBPACK_IMPORTED_MODULE_3__.default.parseSPS( + sps + ); + meta.codecWidth = config.codec_size.width; + meta.codecHeight = config.codec_size.height; + meta.presentWidth = config.present_size.width; + meta.presentHeight = config.present_size.height; + meta.profile = config.profile_string; + meta.level = config.level_string; + meta.profile_idc = config.profile_idc; + meta.level_idc = config.level_idc; + meta.bitDepth = config.bit_depth; + meta.chromaFormat = config.chroma_format; + meta.sarRatio = config.sar_ratio; + meta.frameRate = config.frame_rate; + if ( + config.frame_rate.fixed === false || + config.frame_rate.fps_num === 0 || + config.frame_rate.fps_den === 0 + ) { + meta.frameRate = this._referenceFrameRate; + } + var fps_den = meta.frameRate.fps_den; + var fps_num = meta.frameRate.fps_num; + meta.refSampleDuration = meta.timescale * (fps_den / fps_num); + meta.codec = config.codec_mimetype; + var mi = this._mediaInfo; + mi.width = meta.codecWidth; + mi.height = meta.codecHeight; + mi.fps = meta.frameRate.fps; + mi.profile = meta.profile; + mi.level = meta.level; + mi.refFrames = config.ref_frames; + mi.chromaFormat = config.chroma_format_string; + mi.sarNum = meta.sarRatio.width; + mi.sarDen = meta.sarRatio.height; + mi.videoCodec = config.codec_mimetype; + if (mi.hasAudio) { + if (mi.audioCodec != null) { + mi.mimeType = + 'video/x-flv; codecs="' + + mi.videoCodec + + "," + + mi.audioCodec + + '"'; + } + } else { + mi.mimeType = 'video/x-flv; codecs="' + mi.videoCodec + '"'; + } + if (mi.isComplete()) { + this._onMediaInfo(mi); + } + meta.hvcc = new Uint8Array(dataSize); + meta.hvcc.set( + new Uint8Array(arrayBuffer, dataOffset, dataSize), + 0 + ); + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.v( + this.TAG, + "Parsed HEVCDecoderConfigurationRecord" + ); + if (this._isInitialMetadataDispatched()) { + // flush parsed frames + if ( + this._dispatch && + (this._audioTrack.length || this._videoTrack.length) + ) { + this._onDataAvailable(this._audioTrack, this._videoTrack); + } + } else { + this._videoInitialMetadataDispatched = true; + } + // notify new metadata + this._dispatch = false; + this._onTrackMetadata("video", meta); + }; + FLVDemuxer.prototype._parseHEVCVideoData = function ( + arrayBuffer, + dataOffset, + dataSize, + tagTimestamp, + tagPosition, + frameType, + cts + ) { + var le = this._littleEndian; + var v = new DataView(arrayBuffer, dataOffset, dataSize); + var units = [], + length = 0; + var offset = 0; + var lengthSize = this._naluLengthSize; + var dts = this._timestampBase + tagTimestamp; + var keyframe = frameType === 1; // from FLV Frame Type constants + while (offset < dataSize) { + if (offset + 4 >= dataSize) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Malformed Nalu near timestamp " + + dts + + ", offset = " + + offset + + ", dataSize = " + + dataSize + ); + break; // data not enough for next Nalu + } + // Nalu with length-header (HVC1) + var naluSize = v.getUint32(offset, !le); // Big-Endian read + if (lengthSize === 3) { + naluSize >>>= 8; + } + if (naluSize > dataSize - lengthSize) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Malformed Nalus near timestamp " + + dts + + ", NaluSize > DataSize!" + ); + return; + } + var unitType = (v.getUint8(offset + lengthSize) >> 1) & 0x3f; + if (unitType >= 16 && unitType <= 23) { + // IRAP + keyframe = true; + } + var data = new Uint8Array( + arrayBuffer, + dataOffset + offset, + lengthSize + naluSize + ); + var unit = { type: unitType, data: data }; + units.push(unit); + length += data.byteLength; + offset += lengthSize + naluSize; + } + if (units.length) { + var track = this._videoTrack; + var hevcSample = { + units: units, + length: length, + isKeyframe: keyframe, + dts: dts, + cts: cts, + pts: dts + cts, + }; + if (keyframe) { + hevcSample.fileposition = tagPosition; + } + track.samples.push(hevcSample); + track.length += length; + } + }; + FLVDemuxer.prototype._parseAV1CodecConfigurationRecord = function ( + arrayBuffer, + dataOffset, + dataSize + ) { + if (dataSize < 4) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Flv: Invalid AV1CodecConfigurationRecord, lack of data!" + ); + return; + } + var meta = this._videoMetadata; + var track = this._videoTrack; + var le = this._littleEndian; + var v = new DataView(arrayBuffer, dataOffset, dataSize); + if (!meta) { + if ( + this._hasVideo === false && + this._hasVideoFlagOverrided === false + ) { + this._hasVideo = true; + this._mediaInfo.hasVideo = true; + } + meta = this._videoMetadata = {}; + meta.type = "video"; + meta.id = track.id; + meta.timescale = this._timescale; + meta.duration = this._duration; + } else { + if (typeof meta.av1c !== "undefined") { + var new_av1c = new Uint8Array( + arrayBuffer, + dataOffset, + dataSize + ); + if ( + (0, + _utils_typedarray_equality_js__WEBPACK_IMPORTED_MODULE_8__.default)( + new_av1c, + meta.av1c + ) + ) { + // AV1CodecConfigurationRecord is not changed, ignore it to avoid generating initialization segment repeatedly + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Found another AV1CodecConfigurationRecord!" + ); + return; + } else { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "AV1CodecConfigurationRecord has been changed, re-generate initialization segment" + ); + } + } + } + var version = v.getUint8(0) & 0x7f; + var seq_profile = (v.getUint8(1) & 0xe0) >> 5; + var seq_level_idx = (v.getUint8(1) & 0x8f) >> 0; + var seq_tier = (v.getUint8(2) & 0x80) >> 7; + if (version !== 1) { + this._onError( + _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__.default + .FORMAT_ERROR, + "Flv: Invalid AV1CodecConfigurationRecord" + ); + return; + } + var config = + _av1_parser_js__WEBPACK_IMPORTED_MODULE_4__.default.parseOBUs( + new Uint8Array(arrayBuffer, dataOffset + 4, dataSize - 4) + ); + if (config == null) { + this._onError( + _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__.default + .FORMAT_ERROR, + "Flv: Invalid AV1CodecConfigurationRecord" + ); + return; + } + meta.codecWidth = config.codec_size.width; + meta.codecHeight = config.codec_size.height; + meta.presentWidth = config.present_size.width; + meta.presentHeight = config.present_size.height; + meta.profile = config.profile_string; + meta.level = config.level_string; + meta.bitDepth = config.bit_depth; + meta.chromaFormat = config.chroma_format; + meta.sarRatio = config.sar_ratio; + meta.frameRate = config.frame_rate; + if ( + config.frame_rate.fixed === false || + config.frame_rate.fps_num === 0 || + config.frame_rate.fps_den === 0 + ) { + meta.frameRate = this._referenceFrameRate; + } + var fps_den = meta.frameRate.fps_den; + var fps_num = meta.frameRate.fps_num; + meta.refSampleDuration = meta.timescale * (fps_den / fps_num); + meta.codec = config.codec_mimetype; + var mi = this._mediaInfo; + mi.width = meta.codecWidth; + mi.height = meta.codecHeight; + mi.fps = meta.frameRate.fps; + mi.profile = meta.profile; + mi.level = meta.level; + mi.refFrames = config.ref_frames; + mi.chromaFormat = config.chroma_format_string; + mi.sarNum = meta.sarRatio.width; + mi.sarDen = meta.sarRatio.height; + mi.videoCodec = config.codec_mimetype; + if (mi.hasAudio) { + if (mi.audioCodec != null) { + mi.mimeType = + 'video/x-flv; codecs="' + + mi.videoCodec + + "," + + mi.audioCodec + + '"'; + } + } else { + mi.mimeType = 'video/x-flv; codecs="' + mi.videoCodec + '"'; + } + if (mi.isComplete()) { + this._onMediaInfo(mi); + } + meta.av1c = new Uint8Array(dataSize); + meta.av1c.set( + new Uint8Array(arrayBuffer, dataOffset, dataSize), + 0 + ); + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.v( + this.TAG, + "Parsed AV1CodecConfigurationRecord" + ); + if (this._isInitialMetadataDispatched()) { + // flush parsed frames + if ( + this._dispatch && + (this._audioTrack.length || this._videoTrack.length) + ) { + this._onDataAvailable(this._audioTrack, this._videoTrack); + } + } else { + this._videoInitialMetadataDispatched = true; + } + // notify new metadata + this._dispatch = false; + this._onTrackMetadata("video", meta); + }; + FLVDemuxer.prototype._parseAV1VideoData = function ( + arrayBuffer, + dataOffset, + dataSize, + tagTimestamp, + tagPosition, + frameType, + cts + ) { + var le = this._littleEndian; + //let v = new DataView(arrayBuffer, dataOffset, dataSize); + var units = [], + length = 0; + var offset = 0; + var dts = this._timestampBase + tagTimestamp; + var keyframe = frameType === 1; // from FLV Frame Type constants + /* FIXME: NEEDS Inspect Per OBUs */ + length = dataSize; + units.push({ + unitType: 0, + data: new Uint8Array( + arrayBuffer, + dataOffset + offset, + dataSize + ), + }); + if (units.length) { + var track = this._videoTrack; + var av1Sample = { + units: units, + length: length, + isKeyframe: keyframe, + dts: dts, + cts: cts, + pts: dts + cts, + }; + if (keyframe) { + av1Sample.fileposition = tagPosition; + } + track.samples.push(av1Sample); + track.length += length; + } + }; + FLVDemuxer.prototype._parseEnhancedAV1VideoPacket = function ( + arrayBuffer, + dataOffset, + dataSize, + tagTimestamp, + tagPosition, + frameType, + packetType + ) { + var le = this._littleEndian; + var v = new DataView(arrayBuffer, dataOffset, dataSize); + if (packetType === 0) { + // AV1CodecConfigurationRecord + this._parseAV1CodecConfigurationRecord( + arrayBuffer, + dataOffset, + dataSize + ); + } else if (packetType === 1) { + // One or more OBUs + this._parseAV1VideoData( + arrayBuffer, + dataOffset, + dataSize, + tagTimestamp, + tagPosition, + frameType, + 0 + ); + } else if (packetType === 5) { + this._onError( + _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__.default + .FORMAT_ERROR, + "Flv: Not Supported MP2T AV1 video packet type " + packetType + ); + return; + } else if (packetType === 2) { + // empty, AV1 end of sequence + } else { + this._onError( + _demux_errors_js__WEBPACK_IMPORTED_MODULE_5__.default + .FORMAT_ERROR, + "Flv: Invalid video packet type " + packetType + ); + return; + } + }; + return FLVDemuxer; + })(); + /* harmony default export */ __webpack_exports__["default"] = + FLVDemuxer; + + /***/ + }, + + /***/ "./src/demux/hevc-sps-parser.js": + /*!**************************************!*\ + !*** ./src/demux/hevc-sps-parser.js ***! + \**************************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony import */ var _exp_golomb_js__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__( + /*! ./exp-golomb.js */ "./src/demux/exp-golomb.js" + ); + /* harmony import */ var _sps_parser_js__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__( + /*! ./sps-parser.js */ "./src/demux/sps-parser.js" + ); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * Copyright (C) 2022 Nanuns. All Rights Reserved. + * + * @author zheng qian + * @author nanuns + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + var HevcSPSParser = /** @class */ (function () { + function HevcSPSParser() {} + HevcSPSParser.parseSPS = function (uint8array) { + var rbsp = + _sps_parser_js__WEBPACK_IMPORTED_MODULE_1__.default._ebsp2rbsp( + uint8array + ); + var gb = new _exp_golomb_js__WEBPACK_IMPORTED_MODULE_0__.default( + rbsp + ); + var hvcc = {}; + gb.readBits(16); // nal_unit_header + gb.readBits(4); // sps_video_parameter_set_id + var max_sub_layers_minus1 = gb.readBits(3); // sps_max_sub_layers_minus1 + gb.readBits(1); // sps_temporal_id_nesting_flag + HevcSPSParser._hvcc_parse_ptl(gb, hvcc, max_sub_layers_minus1); + gb.readUEG(); // seq_parameter_set_id + var separate_colour_plane_flag = 0; + var chroma_format = gb.readUEG(); // chroma_format_idc + if (chroma_format == 3) { + separate_colour_plane_flag = gb.readBits(1); // separate_colour_plane_flag + } + hvcc.sar_width = hvcc.sar_height = 1; + hvcc.conf_win_left_offset = + hvcc.conf_win_right_offset = + hvcc.conf_win_top_offset = + hvcc.conf_win_bottom_offset = + 0; + hvcc.def_disp_win_left_offset = + hvcc.def_disp_win_right_offset = + hvcc.def_disp_win_top_offset = + hvcc.def_disp_win_bottom_offset = + 0; + var pic_width_in_luma_samples = gb.readUEG(); // pic_width_in_luma_samples + var pic_height_in_luma_samples = gb.readUEG(); // pic_height_in_luma_samples + var left_offset = 0, + right_offset = 0, + top_offset = 0, + bottom_offset = 0; + var conformance_window_flag = gb.readBits(1); + if (conformance_window_flag) { + hvcc.conf_win_left_offset = gb.readUEG(); // conf_win_left_offset + hvcc.conf_win_right_offset = gb.readUEG(); // conf_win_right_offset + hvcc.conf_win_top_offset = gb.readUEG(); // conf_win_top_offset + hvcc.conf_win_bottom_offset = gb.readUEG(); // conf_win_bottom_offset + if (hvcc.default_display_window_flag === 1) { + left_offset = + hvcc.conf_win_left_offset + hvcc.def_disp_win_left_offset; + right_offset = + hvcc.conf_win_right_offset + hvcc.def_disp_win_right_offset; + top_offset = + hvcc.conf_win_top_offset + hvcc.def_disp_win_top_offset; + bottom_offset = + hvcc.conf_win_bottom_offset + + hvcc.def_disp_win_bottom_offset; + } + } + var bit_depth = gb.readUEG() + 8; // bit_depth_luma_minus8 + gb.readUEG(); // bit_depth_chroma_minus8 + var log2_max_pic_order_cnt_lsb_minus4 = gb.readUEG(); + /* sps_sub_layer_ordering_info_present_flag */ + var sub_layer_ordering_info_present_flag = gb.readBits(1); + var i = sub_layer_ordering_info_present_flag + ? 0 + : max_sub_layers_minus1; + for (; i <= max_sub_layers_minus1; i++) { + HevcSPSParser._skip_sub_layer_ordering_info(gb); + } + gb.readUEG(); // log2_min_luma_coding_block_size_minus3 + gb.readUEG(); // log2_diff_max_min_luma_coding_block_size + gb.readUEG(); // log2_min_transform_block_size_minus2 + gb.readUEG(); // log2_diff_max_min_transform_block_size + gb.readUEG(); // max_transform_hierarchy_depth_inter + gb.readUEG(); // max_transform_hierarchy_depth_intra + if ( + gb.readBits(1) && // scaling_list_enabled_flag + gb.readBits(1) + ) { + // sps_scaling_list_data_present_flag + HevcSPSParser._skip_scaling_list_data(gb); + } + gb.readBits(1); // amp_enabled_flag + gb.readBits(1); // sample_adaptive_offset_enabled_flag + if (gb.readBits(1)) { + // pcm_enabled_flag + gb.readBits(4); // pcm_sample_bit_depth_luma_minus1 + gb.readBits(4); // pcm_sample_bit_depth_chroma_minus1 + gb.readUEG(); // log2_min_pcm_luma_coding_block_size_minus3 + gb.readUEG(); // log2_diff_max_min_pcm_luma_coding_block_size + gb.readBits(1); // pcm_loop_filter_disabled_flag + } + var num_delta_pocs = []; + var num_short_term_ref_pic_sets = gb.readUEG(); + for (i = 0; i < num_short_term_ref_pic_sets; i++) { + var ret = HevcSPSParser._parse_rps( + gb, + i, + num_short_term_ref_pic_sets, + num_delta_pocs + ); + if (ret < 0) return null; + } + if (gb.readBits(1)) { + // long_term_ref_pics_present_flag + var num_long_term_ref_pics_sps = gb.readUEG(); + if (num_long_term_ref_pics_sps > 31) return null; + for (i = 0; i < num_long_term_ref_pics_sps; i++) { + // num_long_term_ref_pics_sps + var len = Math.min(log2_max_pic_order_cnt_lsb_minus4 + 4, 16); + // lt_ref_pic_poc_lsb_sps[i] + if (len > 32) { + var d = len / 32; + var t = len % 32; + for (var j = 0; j < d; j++) { + gb.readBits(32); + } + gb.readBits(t); + } else { + gb.readBits(len); + } + gb.readBits(1); // used_by_curr_pic_lt_sps_flag[i] + } + } + var ref_frames = 1; // TODO + gb.readBits(1); // sps_temporal_mvp_enabled_flag + gb.readBits(1); // strong_intra_smoothing_enabled_flag + if (gb.readBits(1)) { + // vui_parameters_present_flag + HevcSPSParser._hvcc_parse_vui(gb, hvcc, max_sub_layers_minus1); + } + /** + * https://tools.axinom.com/capabilities/media + * video Profile + * + * Main: `hvc1.1.6.L93.B0` + * Main 10: `hvc1.2.4.L93.B0` + * Main still-picture: `hvc1.3.E.L93.B0` + * Range extensions: `hvc1.4.10.L93.B0` + */ + var codec_mimetype = + "hvc1." + hvcc.profile_idc + ".1.L" + hvcc.level_idc + ".B0"; + var profile_string = HevcSPSParser.getProfileString( + hvcc.profile_idc + ); + var level_string = HevcSPSParser.getLevelString(hvcc.level_idc); + var sarScale = 1; + if (hvcc.sar_width !== 1 || hvcc.sar_height !== 1) { + sarScale = hvcc.sar_width / hvcc.sar_height; + } + var codec_width = pic_width_in_luma_samples, + codec_height = pic_height_in_luma_samples; + var sub_wc = + (1 === chroma_format || 2 == chroma_format) && + 0 === separate_colour_plane_flag + ? 2 + : 1; + var sub_hc = + 1 === chroma_format && 0 === separate_colour_plane_flag ? 2 : 1; + codec_width -= + sub_wc * + (hvcc.conf_win_left_offset + hvcc.conf_win_right_offset); + codec_height -= + sub_hc * + (hvcc.conf_win_top_offset + hvcc.conf_win_bottom_offset); + var present_width = Math.ceil(codec_width * sarScale); + gb.destroy(); + gb = null; + return { + codec_mimetype: codec_mimetype, + profile_string: profile_string, + level_string: level_string, + profile_idc: hvcc.profile_idc, + level_idc: hvcc.level_idc, + bit_depth: bit_depth, + ref_frames: ref_frames, + chroma_format: chroma_format, + chroma_format_string: + HevcSPSParser.getChromaFormatString(chroma_format), + frame_rate: { + fixed: hvcc.fps_fixed, + fps: hvcc.fps, + fps_den: hvcc.fps_den, + fps_num: hvcc.fps_num, + }, + sar_ratio: { + width: hvcc.sar_width, + height: hvcc.sar_height, + }, + codec_size: { + width: codec_width, + height: codec_height, + }, + present_size: { + width: present_width, + height: codec_height, + }, + }; + }; + HevcSPSParser._hvcc_parse_ptl = function ( + gb, + hvcc, + max_sub_layers_minus1 + ) { + gb.readBits(2); // profile_space + var tier_flag = gb.readBits(1); + var profile_idc = gb.readBits(5); // profile_idc + gb.readBits(32); // profile_compatibility_flags + gb.readBits(32); // constraint_indicator_flags + gb.readBits(16); + var level_idc = gb.readByte(); // level_idc + if ( + hvcc.tier_flag === undefined || + hvcc.level_idc === undefined || + hvcc.tier_flag < tier_flag + ) { + hvcc.level_idc = level_idc; + } else { + hvcc.level_idc = Math.max(hvcc.level_idc, level_idc); + } + hvcc.profile_idc = Math.max( + hvcc.profile_idc === undefined ? 0 : hvcc.profile_idc, + profile_idc + ); + var sub_layer_profile_present_flag = []; + var sub_layer_level_present_flag = []; + for (var i = 0; i < max_sub_layers_minus1; i++) { + sub_layer_profile_present_flag.push(gb.readBits(1)); + sub_layer_level_present_flag.push(gb.readBits(1)); + } + if (max_sub_layers_minus1 > 0) { + for (var i = max_sub_layers_minus1; i < 8; i++) { + gb.readBits(2); // reserved_zero_2bits[i] + } + } + for (var i = 0; i < max_sub_layers_minus1; i++) { + if (sub_layer_profile_present_flag[i]) { + /* + * sub_layer_profile_space[i] u(2) + * sub_layer_tier_flag[i] u(1) + * sub_layer_profile_idc[i] u(5) + * sub_layer_profile_compatibility_flag[i][0..31] u(32) + * sub_layer_progressive_source_flag[i] u(1) + * sub_layer_interlaced_source_flag[i] u(1) + * sub_layer_non_packed_constraint_flag[i] u(1) + * sub_layer_frame_only_constraint_flag[i] u(1) + * sub_layer_reserved_zero_44bits[i] u(44) + */ + gb.readBits(32); + gb.readBits(32); + gb.readBits(24); + } + if (sub_layer_level_present_flag[i]) { + gb.readByte(); + } + } + }; + HevcSPSParser._parse_rps = function ( + gb, + rps_idx, + num_rps, + num_delta_pocs + ) { + if (rps_idx && gb.readBits(1)) { + // inter_ref_pic_set_prediction_flag + /* this should only happen for slice headers, and this isn't one */ + if (rps_idx >= num_rps) return -1; + gb.readBits(1); // delta_rps_sign + gb.readUEG(); // abs_delta_rps_minus1 + num_delta_pocs[rps_idx] = 0; + for (var i = 0; i <= num_delta_pocs[rps_idx - 1]; i++) { + var use_delta_flag = 0; + var used_by_curr_pic_flag = gb.readBits(1); + if (!used_by_curr_pic_flag) { + use_delta_flag = gb.readBits(1); + } + if (used_by_curr_pic_flag || use_delta_flag) { + num_delta_pocs[rps_idx]++; + } + } + } else { + var num_negative_pics = gb.readUEG(); + var num_positive_pics = gb.readUEG(); + if ( + (num_positive_pics + num_negative_pics) * 2 > + gb.getBitsLeft() + ) + return -1; + num_delta_pocs[rps_idx] = num_negative_pics + num_positive_pics; + for (var i = 0; i < num_negative_pics; i++) { + gb.readUEG(); // delta_poc_s0_minus1[rps_idx] + gb.readBits(1); // used_by_curr_pic_s0_flag[rps_idx] + } + for (var i = 0; i < num_positive_pics; i++) { + gb.readUEG(); // delta_poc_s1_minus1[rps_idx] + gb.readBits(1); // used_by_curr_pic_s1_flag[rps_idx] + } + } + return 0; + }; + HevcSPSParser._hvcc_parse_vui = function ( + gb, + hvcc, + max_sub_layers_minus1 + ) { + var min_spatial_segmentation_idc; + if (gb.readBits(1)) { + // aspect_ratio_info_present_flag + if (gb.readByte() == 255) { + // aspect_ratio_idc + hvcc.sar_width = gb.readBits(16); // sar_width u(16) + hvcc.sar_height = gb.readBits(16); // sar_height u(16) + } + } + if (gb.readBits(1)) { + // overscan_info_present_flag + gb.readBits(1); // overscan_appropriate_flag + } + if (gb.readBits(1)) { + // video_signal_type_present_flag + gb.readBits(4); // video_format u(3), video_full_range_flag u(1) + if (gb.readBits(1)) { + // colour_description_present_flag + /* + * colour_primaries u(8) + * transfer_characteristics u(8) + * matrix_coeffs u(8) + */ + gb.readBits(24); + } + } + if (gb.readBits(1)) { + // chroma_loc_info_present_flag + gb.readUEG(); // chroma_sample_loc_type_top_field + gb.readUEG(); // chroma_sample_loc_type_bottom_field + } + /* + * neutral_chroma_indication_flag u(1) + * field_seq_flag u(1) + * frame_field_info_present_flag u(1) + */ + gb.readBits(3); + hvcc.default_display_window_flag = gb.readBits(1); // default_display_window_flag + if (hvcc.default_display_window_flag) { + hvcc.def_disp_win_left_offset = gb.readUEG(); // def_disp_win_left_offset + hvcc.def_disp_win_right_offset = gb.readUEG(); // def_disp_win_right_offset + hvcc.def_disp_win_top_offset = gb.readUEG(); // def_disp_win_top_offset + hvcc.def_disp_win_bottom_offset = gb.readUEG(); // def_disp_win_bottom_offset + } + if (gb.readBits(1)) { + // vui_timing_info_present_flag + HevcSPSParser._skip_timing_info(gb, hvcc); + if (gb.readBits(1)) { + // vui_hrd_parameters_present_flag + HevcSPSParser._skip_hrd_parameters( + gb, + hvcc, + 1, + max_sub_layers_minus1 + ); + } + } + if (gb.readBits(1)) { + // bitstream_restriction_flag + /* + * tiles_fixed_structure_flag u(1) + * motion_vectors_over_pic_boundaries_flag u(1) + * restricted_ref_pic_lists_flag u(1) + */ + gb.readBits(3); + min_spatial_segmentation_idc = gb.readUEG(); // min_spatial_segmentation_idc + /* + * unsigned int(12) min_spatial_segmentation_idc; + * + * The min_spatial_segmentation_idc indication must indicate a level of + * spatial segmentation equal to or less than the lowest level of + * spatial segmentation indicated in all the parameter sets. + */ + hvcc.min_spatial_segmentation_idc = Math.min( + hvcc.min_spatial_segmentation_idc, + min_spatial_segmentation_idc + ); + gb.readUEG(); // max_bytes_per_pic_denom + gb.readUEG(); // max_bits_per_min_cu_denom + gb.readUEG(); // log2_max_mv_length_horizontal + gb.readUEG(); // log2_max_mv_length_vertical + } + }; + HevcSPSParser._skip_sub_layer_ordering_info = function (gb, hvcc) { + gb.readUEG(); // max_dec_pic_buffering_minus1 + gb.readUEG(); // max_num_reorder_pics + gb.readUEG(); // max_latency_increase_plus1 + }; + HevcSPSParser._skip_scaling_list_data = function (gb) { + for (var i = 0; i < 4; i++) { + for (var j = 0; j < (i == 3 ? 2 : 6); j++) { + if (!gb.readBits(1)) { + // scaling_list_pred_mode_flag[i][j] + gb.readUEG(); // scaling_list_pred_matrix_id_delta[i][j] + } else { + var num_coeffs = Math.min(64, 1 << (4 + (i << 1))); + if (i > 1) { + gb.readSEG(); // scaling_list_dc_coef_minus8[i-2][j] + } + for (var k = 0; k < num_coeffs; k++) { + gb.readSEG(); // scaling_list_delta_coef + } + } + } + } + }; + HevcSPSParser._skip_sub_layer_hrd_parameters = function ( + gb, + cpb_cnt_minus1, + sub_pic_hrd_params_present_flag + ) { + for (var i = 0; i <= cpb_cnt_minus1; i++) { + gb.readUEG(); // bit_rate_value_minus1 + gb.readUEG(); // cpb_size_value_minus1 + if (sub_pic_hrd_params_present_flag) { + gb.readUEG(); // cpb_size_du_value_minus1 + gb.readUEG(); // bit_rate_du_value_minus1 + } + gb.readBits(1); // cbr_flag + } + }; + HevcSPSParser._skip_timing_info = function (gb, hvcc) { + hvcc.fps_den = gb.readBits(32); // num_units_in_tick + hvcc.fps_num = gb.readBits(32); // time_scale + if (hvcc.fps_den > 0) { + hvcc.fps = hvcc.fps_num / hvcc.fps_den; + } + var num_ticks_poc_diff_one_minus1 = 0; + if (gb.readBits(1)) { + // poc_proportional_to_timing_flag + num_ticks_poc_diff_one_minus1 = gb.readUEG(); // num_ticks_poc_diff_one_minus1 + if (num_ticks_poc_diff_one_minus1 >= 0) { + hvcc.fps /= num_ticks_poc_diff_one_minus1 + 1; + } + } + }; + HevcSPSParser._skip_hrd_parameters = function ( + gb, + hvcc, + cprms_present_flag, + max_sub_layers_minus1 + ) { + var sub_pic_hrd_params_present_flag = 0; + var nal_hrd_parameters_present_flag = 0; + var vcl_hrd_parameters_present_flag = 0; + if (cprms_present_flag) { + nal_hrd_parameters_present_flag = gb.readBits(1); + vcl_hrd_parameters_present_flag = gb.readBits(1); + if ( + nal_hrd_parameters_present_flag || + vcl_hrd_parameters_present_flag + ) { + var sub_pic_hrd_params_present_flag_1 = gb.readBits(1); + if (sub_pic_hrd_params_present_flag_1) { + /* + * tick_divisor_minus2 u(8) + * du_cpb_removal_delay_increment_length_minus1 u(5) + * sub_pic_cpb_params_in_pic_timing_sei_flag u(1) + * dpb_output_delay_du_length_minus1 u(5) + */ + gb.readBits(19); + } + /* + * bit_rate_scale u(4) + * cpb_size_scale u(4) + */ + gb.readByte(); + if (sub_pic_hrd_params_present_flag_1) { + gb.readBits(4); // cpb_size_du_scale + } + /* + * initial_cpb_removal_delay_length_minus1 u(5) + * au_cpb_removal_delay_length_minus1 u(5) + * dpb_output_delay_length_minus1 u(5) + */ + gb.readBits(15); + } + } + for (var i = 0; i <= max_sub_layers_minus1; i++) { + var cpb_cnt_minus1 = 0; + var low_delay_hrd_flag = 0; + var fixed_pic_rate_within_cvs_flag = 0; + var fixed_pic_rate_general_flag = gb.readBits(1); + hvcc.fps_fixed = fixed_pic_rate_general_flag; + if (!fixed_pic_rate_general_flag) { + fixed_pic_rate_within_cvs_flag = gb.readBits(1); + } + if (fixed_pic_rate_within_cvs_flag) { + gb.readUEG(); // elemental_duration_in_tc_minus1 + } else { + low_delay_hrd_flag = gb.readBits(1); + } + if (!low_delay_hrd_flag) { + cpb_cnt_minus1 = gb.readUEG(gb); + } + if (nal_hrd_parameters_present_flag) { + HevcSPSParser._skip_sub_layer_hrd_parameters( + gb, + cpb_cnt_minus1, + sub_pic_hrd_params_present_flag + ); + } + if (vcl_hrd_parameters_present_flag) { + HevcSPSParser._skip_sub_layer_hrd_parameters( + gb, + cpb_cnt_minus1, + sub_pic_hrd_params_present_flag + ); + } + } + }; + HevcSPSParser.getProfileString = function (profile_idc) { + switch (profile_idc) { + case 1: + return "Main"; + case 2: + return "Main10"; + case 3: + return "MainSP"; // MainStillPictrue + case 4: + return "Rext"; + case 9: + return "SCC"; + default: + return "Unknown"; + } + }; + HevcSPSParser.getLevelString = function (level_idc) { + return (level_idc / 30).toFixed(1); + }; + HevcSPSParser.getChromaFormatString = function (chroma) { + switch (chroma) { + case 0: + return "4:0:0"; + case 1: + return "4:2:0"; + case 2: + return "4:2:2"; + case 3: + return "4:4:4"; + default: + return "Unknown"; + } + }; + return HevcSPSParser; + })(); + /* harmony default export */ __webpack_exports__["default"] = + HevcSPSParser; + + /***/ + }, + + /***/ "./src/demux/sps-parser.js": + /*!*********************************!*\ + !*** ./src/demux/sps-parser.js ***! + \*********************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony import */ var _exp_golomb_js__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__( + /*! ./exp-golomb.js */ "./src/demux/exp-golomb.js" + ); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + var SPSParser = /** @class */ (function () { + function SPSParser() {} + SPSParser._ebsp2rbsp = function (uint8array) { + var src = uint8array; + var src_length = src.byteLength; + var dst = new Uint8Array(src_length); + var dst_idx = 0; + for (var i = 0; i < src_length; i++) { + if (i >= 2) { + // Unescape: Skip 0x03 after 00 00 + if ( + src[i] === 0x03 && + src[i - 1] === 0x00 && + src[i - 2] === 0x00 + ) { + continue; + } + } + dst[dst_idx] = src[i]; + dst_idx++; + } + return new Uint8Array(dst.buffer, 0, dst_idx); + }; + SPSParser.parseSPS = function (uint8array) { + var codec_array = uint8array.subarray(1, 4); + var codec_mimetype = "avc1."; + for (var j = 0; j < 3; j++) { + var h = codec_array[j].toString(16); + if (h.length < 2) { + h = "0" + h; + } + codec_mimetype += h; + } + var rbsp = SPSParser._ebsp2rbsp(uint8array); + var gb = new _exp_golomb_js__WEBPACK_IMPORTED_MODULE_0__.default( + rbsp + ); + gb.readByte(); + var profile_idc = gb.readByte(); // profile_idc + gb.readByte(); // constraint_set_flags[5] + reserved_zero[3] + var level_idc = gb.readByte(); // level_idc + gb.readUEG(); // seq_parameter_set_id + var profile_string = SPSParser.getProfileString(profile_idc); + var level_string = SPSParser.getLevelString(level_idc); + var chroma_format_idc = 1; + var chroma_format = 420; + var chroma_format_table = [0, 420, 422, 444]; + var bit_depth_luma = 8; + var bit_depth_chroma = 8; + 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 + ) { + chroma_format_idc = gb.readUEG(); + if (chroma_format_idc === 3) { + gb.readBits(1); // separate_colour_plane_flag + } + if (chroma_format_idc <= 3) { + chroma_format = chroma_format_table[chroma_format_idc]; + } + bit_depth_luma = gb.readUEG() + 8; // bit_depth_luma_minus8 + bit_depth_chroma = gb.readUEG() + 8; // bit_depth_chroma_minus8 + gb.readBits(1); // qpprime_y_zero_transform_bypass_flag + if (gb.readBool()) { + // seq_scaling_matrix_present_flag + var scaling_list_count = chroma_format_idc !== 3 ? 8 : 12; + for (var i = 0; i < scaling_list_count; i++) { + if (gb.readBool()) { + // seq_scaling_list_present_flag + if (i < 6) { + SPSParser._skipScalingList(gb, 16); + } else { + SPSParser._skipScalingList(gb, 64); + } + } + } + } + } + gb.readUEG(); // log2_max_frame_num_minus4 + var pic_order_cnt_type = gb.readUEG(); + if (pic_order_cnt_type === 0) { + gb.readUEG(); // log2_max_pic_order_cnt_lsb_minus_4 + } else if (pic_order_cnt_type === 1) { + gb.readBits(1); // delta_pic_order_always_zero_flag + gb.readSEG(); // offset_for_non_ref_pic + gb.readSEG(); // offset_for_top_to_bottom_field + var num_ref_frames_in_pic_order_cnt_cycle = gb.readUEG(); + for ( + var i = 0; + i < num_ref_frames_in_pic_order_cnt_cycle; + i++ + ) { + gb.readSEG(); // offset_for_ref_frame + } + } + var ref_frames = gb.readUEG(); // max_num_ref_frames + gb.readBits(1); // gaps_in_frame_num_value_allowed_flag + var pic_width_in_mbs_minus1 = gb.readUEG(); + var pic_height_in_map_units_minus1 = gb.readUEG(); + var frame_mbs_only_flag = gb.readBits(1); + if (frame_mbs_only_flag === 0) { + gb.readBits(1); // mb_adaptive_frame_field_flag + } + gb.readBits(1); // direct_8x8_inference_flag + var frame_crop_left_offset = 0; + var frame_crop_right_offset = 0; + var frame_crop_top_offset = 0; + var frame_crop_bottom_offset = 0; + var frame_cropping_flag = gb.readBool(); + if (frame_cropping_flag) { + frame_crop_left_offset = gb.readUEG(); + frame_crop_right_offset = gb.readUEG(); + frame_crop_top_offset = gb.readUEG(); + frame_crop_bottom_offset = gb.readUEG(); + } + var sar_width = 1, + sar_height = 1; + var fps = 0, + fps_fixed = true, + fps_num = 0, + fps_den = 0; + var vui_parameters_present_flag = gb.readBool(); + if (vui_parameters_present_flag) { + if (gb.readBool()) { + // aspect_ratio_info_present_flag + var aspect_ratio_idc = gb.readByte(); + var sar_w_table = [ + 1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160, 4, 3, 2, + ]; + var sar_h_table = [ + 1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99, 3, 2, 1, + ]; + if (aspect_ratio_idc > 0 && aspect_ratio_idc < 16) { + sar_width = sar_w_table[aspect_ratio_idc - 1]; + sar_height = sar_h_table[aspect_ratio_idc - 1]; + } else if (aspect_ratio_idc === 255) { + sar_width = (gb.readByte() << 8) | gb.readByte(); + sar_height = (gb.readByte() << 8) | gb.readByte(); + } + } + if (gb.readBool()) { + // overscan_info_present_flag + gb.readBool(); // overscan_appropriate_flag + } + if (gb.readBool()) { + // video_signal_type_present_flag + gb.readBits(4); // video_format & video_full_range_flag + if (gb.readBool()) { + // colour_description_present_flag + gb.readBits(24); // colour_primaries & transfer_characteristics & matrix_coefficients + } + } + if (gb.readBool()) { + // chroma_loc_info_present_flag + gb.readUEG(); // chroma_sample_loc_type_top_field + gb.readUEG(); // chroma_sample_loc_type_bottom_field + } + if (gb.readBool()) { + // timing_info_present_flag + var num_units_in_tick = gb.readBits(32); + var time_scale = gb.readBits(32); + fps_fixed = gb.readBool(); // fixed_frame_rate_flag + fps_num = time_scale; + fps_den = num_units_in_tick * 2; + fps = fps_num / fps_den; + } + } + var sarScale = 1; + if (sar_width !== 1 || sar_height !== 1) { + sarScale = sar_width / sar_height; + } + var crop_unit_x = 0, + crop_unit_y = 0; + if (chroma_format_idc === 0) { + crop_unit_x = 1; + crop_unit_y = 2 - frame_mbs_only_flag; + } else { + var sub_wc = chroma_format_idc === 3 ? 1 : 2; + var sub_hc = chroma_format_idc === 1 ? 2 : 1; + crop_unit_x = sub_wc; + crop_unit_y = sub_hc * (2 - frame_mbs_only_flag); + } + var codec_width = (pic_width_in_mbs_minus1 + 1) * 16; + var codec_height = + (2 - frame_mbs_only_flag) * + ((pic_height_in_map_units_minus1 + 1) * 16); + codec_width -= + (frame_crop_left_offset + frame_crop_right_offset) * + crop_unit_x; + codec_height -= + (frame_crop_top_offset + frame_crop_bottom_offset) * + crop_unit_y; + var present_width = Math.ceil(codec_width * sarScale); + gb.destroy(); + gb = null; + return { + codec_mimetype: codec_mimetype, + profile_idc: profile_idc, + level_idc: level_idc, + profile_string: profile_string, + level_string: level_string, + chroma_format_idc: chroma_format_idc, + bit_depth: bit_depth_luma, + bit_depth_luma: bit_depth_luma, + bit_depth_chroma: bit_depth_chroma, + ref_frames: ref_frames, + chroma_format: chroma_format, + chroma_format_string: + SPSParser.getChromaFormatString(chroma_format), + frame_rate: { + fixed: fps_fixed, + fps: fps, + fps_den: fps_den, + fps_num: fps_num, + }, + sar_ratio: { + width: sar_width, + height: sar_height, + }, + codec_size: { + width: codec_width, + height: codec_height, + }, + present_size: { + width: present_width, + height: codec_height, + }, + }; + }; + SPSParser._skipScalingList = function (gb, count) { + var last_scale = 8, + next_scale = 8; + var delta_scale = 0; + for (var i = 0; i < count; i++) { + if (next_scale !== 0) { + delta_scale = gb.readSEG(); + next_scale = (last_scale + delta_scale + 256) % 256; + } + last_scale = next_scale === 0 ? last_scale : next_scale; + } + }; + SPSParser.getProfileString = function (profile_idc) { + switch (profile_idc) { + case 66: + return "Baseline"; + case 77: + return "Main"; + case 88: + return "Extended"; + case 100: + return "High"; + case 110: + return "High10"; + case 122: + return "High422"; + case 244: + return "High444"; + default: + return "Unknown"; + } + }; + SPSParser.getLevelString = function (level_idc) { + return (level_idc / 10).toFixed(1); + }; + SPSParser.getChromaFormatString = function (chroma) { + switch (chroma) { + case 420: + return "4:2:0"; + case 422: + return "4:2:2"; + case 444: + return "4:4:4"; + default: + return "Unknown"; + } + }; + return SPSParser; + })(); + /* harmony default export */ __webpack_exports__["default"] = + SPSParser; + + /***/ + }, + + /***/ "./src/flv.js": + /*!********************!*\ + !*** ./src/flv.js ***! + \********************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony import */ var _utils_polyfill_js__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__( + /*! ./utils/polyfill.js */ "./src/utils/polyfill.js" + ); + /* harmony import */ var _core_features_js__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__( + /*! ./core/features.js */ "./src/core/features.js" + ); + /* harmony import */ var _io_loader_js__WEBPACK_IMPORTED_MODULE_2__ = + __webpack_require__(/*! ./io/loader.js */ "./src/io/loader.js"); + /* harmony import */ var _player_flv_player_js__WEBPACK_IMPORTED_MODULE_3__ = + __webpack_require__( + /*! ./player/flv-player.js */ "./src/player/flv-player.js" + ); + /* harmony import */ var _player_native_player_js__WEBPACK_IMPORTED_MODULE_4__ = + __webpack_require__( + /*! ./player/native-player.js */ "./src/player/native-player.js" + ); + /* harmony import */ var _player_player_events_js__WEBPACK_IMPORTED_MODULE_5__ = + __webpack_require__( + /*! ./player/player-events.js */ "./src/player/player-events.js" + ); + /* harmony import */ var _player_player_errors_js__WEBPACK_IMPORTED_MODULE_6__ = + __webpack_require__( + /*! ./player/player-errors.js */ "./src/player/player-errors.js" + ); + /* harmony import */ var _utils_logging_control_js__WEBPACK_IMPORTED_MODULE_7__ = + __webpack_require__( + /*! ./utils/logging-control.js */ "./src/utils/logging-control.js" + ); + /* harmony import */ var _utils_exception_js__WEBPACK_IMPORTED_MODULE_8__ = + __webpack_require__( + /*! ./utils/exception.js */ "./src/utils/exception.js" + ); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + // here are all the interfaces + // install polyfills + _utils_polyfill_js__WEBPACK_IMPORTED_MODULE_0__.default.install(); + // factory method + function createPlayer(mediaDataSource, optionalConfig) { + var mds = mediaDataSource; + if (mds == null || typeof mds !== "object") { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_8__.InvalidArgumentException( + "MediaDataSource must be an javascript object!" + ); + } + if (!mds.hasOwnProperty("type")) { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_8__.InvalidArgumentException( + "MediaDataSource must has type field to indicate video file type!" + ); + } + switch (mds.type) { + case "flv": + return new _player_flv_player_js__WEBPACK_IMPORTED_MODULE_3__.default( + mds, + optionalConfig + ); + default: + return new _player_native_player_js__WEBPACK_IMPORTED_MODULE_4__.default( + mds, + optionalConfig + ); + } + } + // feature detection + function isSupported() { + return _core_features_js__WEBPACK_IMPORTED_MODULE_1__.default.supportMSEH264Playback(); + } + function getFeatureList() { + return _core_features_js__WEBPACK_IMPORTED_MODULE_1__.default.getFeatureList(); + } + // interfaces + var flvjs = {}; + flvjs.createPlayer = createPlayer; + flvjs.isSupported = isSupported; + flvjs.getFeatureList = getFeatureList; + flvjs.BaseLoader = + _io_loader_js__WEBPACK_IMPORTED_MODULE_2__.BaseLoader; + flvjs.LoaderStatus = + _io_loader_js__WEBPACK_IMPORTED_MODULE_2__.LoaderStatus; + flvjs.LoaderErrors = + _io_loader_js__WEBPACK_IMPORTED_MODULE_2__.LoaderErrors; + flvjs.Events = + _player_player_events_js__WEBPACK_IMPORTED_MODULE_5__.default; + flvjs.ErrorTypes = + _player_player_errors_js__WEBPACK_IMPORTED_MODULE_6__.ErrorTypes; + flvjs.ErrorDetails = + _player_player_errors_js__WEBPACK_IMPORTED_MODULE_6__.ErrorDetails; + flvjs.FlvPlayer = + _player_flv_player_js__WEBPACK_IMPORTED_MODULE_3__.default; + flvjs.NativePlayer = + _player_native_player_js__WEBPACK_IMPORTED_MODULE_4__.default; + flvjs.LoggingControl = + _utils_logging_control_js__WEBPACK_IMPORTED_MODULE_7__.default; + Object.defineProperty(flvjs, "version", { + enumerable: true, + get: function () { + // replace by webpack.DefinePlugin + return "1.7.8"; + }, + }); + /* harmony default export */ __webpack_exports__["default"] = flvjs; + + /***/ + }, + + /***/ "./src/index.js": + /*!**********************!*\ + !*** ./src/index.js ***! + \**********************/ + /***/ function (module, __unused_webpack_exports, __webpack_require__) { + // entry/index file + // make it compatible with browserify's umd wrapper + module.exports = __webpack_require__( + /*! ./flv.js */ "./src/flv.js" + ).default; + + /***/ + }, + + /***/ "./src/io/fetch-stream-loader.js": + /*!***************************************!*\ + !*** ./src/io/fetch-stream-loader.js ***! + \***************************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony import */ var _utils_browser_js__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__( + /*! ../utils/browser.js */ "./src/utils/browser.js" + ); + /* harmony import */ var _loader_js__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__(/*! ./loader.js */ "./src/io/loader.js"); + /* harmony import */ var _utils_exception_js__WEBPACK_IMPORTED_MODULE_2__ = + __webpack_require__( + /*! ../utils/exception.js */ "./src/utils/exception.js" + ); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + var __extends = + (undefined && undefined.__extends) || + (function () { + var extendStatics = function (d, b) { + extendStatics = + Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && + function (d, b) { + d.__proto__ = b; + }) || + function (d, b) { + for (var p in b) + if (Object.prototype.hasOwnProperty.call(b, p)) + d[p] = b[p]; + }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError( + "Class extends value " + + String(b) + + " is not a constructor or null" + ); + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = + b === null + ? Object.create(b) + : ((__.prototype = b.prototype), new __()); + }; + })(); + + /* fetch + stream IO loader. Currently working on chrome 43+. + * fetch provides a better alternative http API to XMLHttpRequest + * + * fetch spec https://fetch.spec.whatwg.org/ + * stream spec https://streams.spec.whatwg.org/ + */ + var FetchStreamLoader = /** @class */ (function (_super) { + __extends(FetchStreamLoader, _super); + function FetchStreamLoader(seekHandler, config) { + var _this = _super.call(this, "fetch-stream-loader") || this; + _this.TAG = "FetchStreamLoader"; + _this._seekHandler = seekHandler; + _this._config = config; + _this._needStash = true; + _this._requestAbort = false; + _this._abortController = null; + _this._contentLength = null; + _this._receivedLength = 0; + return _this; + } + FetchStreamLoader.isSupported = function () { + try { + // fetch + stream is broken on Microsoft Edge. Disable before build 15048. + // see https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/8196907/ + // Fixed in Jan 10, 2017. Build 15048+ removed from blacklist. + var isWorkWellEdge = + _utils_browser_js__WEBPACK_IMPORTED_MODULE_0__.default + .msedge && + _utils_browser_js__WEBPACK_IMPORTED_MODULE_0__.default.version + .minor >= 15048; + var browserNotBlacklisted = + _utils_browser_js__WEBPACK_IMPORTED_MODULE_0__.default.msedge + ? isWorkWellEdge + : true; + return ( + self.fetch && self.ReadableStream && browserNotBlacklisted + ); + } catch (e) { + return false; + } + }; + FetchStreamLoader.prototype.destroy = function () { + if (this.isWorking()) { + this.abort(); + } + _super.prototype.destroy.call(this); + }; + FetchStreamLoader.prototype.open = function (dataSource, range) { + var _this = this; + this._dataSource = dataSource; + this._range = range; + var sourceURL = dataSource.url; + if ( + this._config.reuseRedirectedURL && + dataSource.redirectedURL != undefined + ) { + sourceURL = dataSource.redirectedURL; + } + var seekConfig = this._seekHandler.getConfig(sourceURL, range); + var headers = new self.Headers(); + if (typeof seekConfig.headers === "object") { + var configHeaders = seekConfig.headers; + for (var key in configHeaders) { + if (configHeaders.hasOwnProperty(key)) { + headers.append(key, configHeaders[key]); + } + } + } + var params = { + method: "GET", + headers: headers, + mode: "cors", + cache: "default", + // The default policy of Fetch API in the whatwg standard + // Safari incorrectly indicates 'no-referrer' as default policy, fuck it + referrerPolicy: "no-referrer-when-downgrade", + }; + // add additional headers + if (typeof this._config.headers === "object") { + for (var key in this._config.headers) { + headers.append(key, this._config.headers[key]); + } + } + // cors is enabled by default + if (dataSource.cors === false) { + // no-cors means 'disregard cors policy', which can only be used in ServiceWorker + params.mode = "same-origin"; + } + // withCredentials is disabled by default + if (dataSource.withCredentials) { + params.credentials = "include"; + } + // referrerPolicy from config + if (dataSource.referrerPolicy) { + params.referrerPolicy = dataSource.referrerPolicy; + } + if (self.AbortController) { + this._abortController = new self.AbortController(); + params.signal = this._abortController.signal; + } + this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderStatus.kConnecting; + self + .fetch(seekConfig.url, params) + .then(function (res) { + if (_this._requestAbort) { + _this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderStatus.kIdle; + res.body.cancel(); + return; + } + if (res.ok && res.status >= 200 && res.status <= 299) { + if (res.url !== seekConfig.url) { + if (_this._onURLRedirect) { + var redirectedURL = + _this._seekHandler.removeURLParameters(res.url); + _this._onURLRedirect(redirectedURL); + } + } + var lengthHeader = res.headers.get("Content-Length"); + if (lengthHeader != null) { + _this._contentLength = parseInt(lengthHeader); + if (_this._contentLength !== 0) { + if (_this._onContentLengthKnown) { + _this._onContentLengthKnown(_this._contentLength); + } + } + } + return _this._pump.call(_this, res.body.getReader()); + } else { + _this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderStatus.kError; + if (_this._onError) { + _this._onError( + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderErrors + .HTTP_STATUS_CODE_INVALID, + { code: res.status, msg: res.statusText } + ); + } else { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_2__.RuntimeException( + "FetchStreamLoader: Http code invalid, " + + res.status + + " " + + res.statusText + ); + } + } + }) + .catch(function (e) { + if ( + _this._abortController && + _this._abortController.signal.aborted + ) { + return; + } + _this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderStatus.kError; + if (_this._onError) { + _this._onError( + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderErrors + .EXCEPTION, + { code: -1, msg: e.message } + ); + } else { + throw e; + } + }); + }; + FetchStreamLoader.prototype.abort = function () { + this._requestAbort = true; + if ( + this._status !== + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderStatus + .kBuffering || + !_utils_browser_js__WEBPACK_IMPORTED_MODULE_0__.default.chrome + ) { + // Chrome may throw Exception-like things here, avoid using if is buffering + if (this._abortController) { + try { + this._abortController.abort(); + } catch (e) {} + } + } + }; + FetchStreamLoader.prototype._pump = function (reader) { + var _this = this; + return reader + .read() + .then(function (result) { + if (result.done) { + // First check received length + if ( + _this._contentLength !== null && + _this._receivedLength < _this._contentLength + ) { + // Report Early-EOF + _this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderStatus.kError; + var type = + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderErrors + .EARLY_EOF; + var info = { + code: -1, + msg: "Fetch stream meet Early-EOF", + }; + if (_this._onError) { + _this._onError(type, info); + } else { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_2__.RuntimeException( + info.msg + ); + } + } else { + // OK. Download complete + _this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderStatus.kComplete; + if (_this._onComplete) { + _this._onComplete( + _this._range.from, + _this._range.from + _this._receivedLength - 1 + ); + } + } + } else { + if ( + _this._abortController && + _this._abortController.signal.aborted + ) { + _this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderStatus.kComplete; + return; + } else if (_this._requestAbort === true) { + _this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderStatus.kComplete; + return reader.cancel(); + } + _this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderStatus.kBuffering; + var chunk = result.value.buffer; + var byteStart = _this._range.from + _this._receivedLength; + _this._receivedLength += chunk.byteLength; + if (_this._onDataArrival) { + _this._onDataArrival( + chunk, + byteStart, + _this._receivedLength + ); + } + _this._pump(reader); + } + }) + .catch(function (e) { + if ( + _this._abortController && + _this._abortController.signal.aborted + ) { + _this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderStatus.kComplete; + return; + } + if ( + e.code === 11 && + _utils_browser_js__WEBPACK_IMPORTED_MODULE_0__.default + .msedge + ) { + // InvalidStateError on Microsoft Edge + // Workaround: Edge may throw InvalidStateError after ReadableStreamReader.cancel() call + // Ignore the unknown exception. + // Related issue: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/11265202/ + return; + } + _this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderStatus.kError; + var type = 0; + var info = null; + if ( + (e.code === 19 || e.message === "network error") && // NETWORK_ERR + (_this._contentLength === null || + (_this._contentLength !== null && + _this._receivedLength < _this._contentLength)) + ) { + type = + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderErrors + .EARLY_EOF; + info = { code: e.code, msg: "Fetch stream meet Early-EOF" }; + } else { + type = + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderErrors + .EXCEPTION; + info = { code: e.code, msg: e.message }; + } + if (_this._onError) { + _this._onError(type, info); + } else { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_2__.RuntimeException( + info.msg + ); + } + }); + }; + return FetchStreamLoader; + })(_loader_js__WEBPACK_IMPORTED_MODULE_1__.BaseLoader); + /* harmony default export */ __webpack_exports__["default"] = + FetchStreamLoader; + + /***/ + }, + + /***/ "./src/io/io-controller.js": + /*!*********************************!*\ + !*** ./src/io/io-controller.js ***! + \*********************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony import */ var _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__( + /*! ../utils/logger.js */ "./src/utils/logger.js" + ); + /* harmony import */ var _speed_sampler_js__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__( + /*! ./speed-sampler.js */ "./src/io/speed-sampler.js" + ); + /* harmony import */ var _loader_js__WEBPACK_IMPORTED_MODULE_2__ = + __webpack_require__(/*! ./loader.js */ "./src/io/loader.js"); + /* harmony import */ var _fetch_stream_loader_js__WEBPACK_IMPORTED_MODULE_3__ = + __webpack_require__( + /*! ./fetch-stream-loader.js */ "./src/io/fetch-stream-loader.js" + ); + /* harmony import */ var _xhr_moz_chunked_loader_js__WEBPACK_IMPORTED_MODULE_4__ = + __webpack_require__( + /*! ./xhr-moz-chunked-loader.js */ "./src/io/xhr-moz-chunked-loader.js" + ); + /* harmony import */ var _xhr_range_loader_js__WEBPACK_IMPORTED_MODULE_5__ = + __webpack_require__( + /*! ./xhr-range-loader.js */ "./src/io/xhr-range-loader.js" + ); + /* harmony import */ var _websocket_loader_js__WEBPACK_IMPORTED_MODULE_6__ = + __webpack_require__( + /*! ./websocket-loader.js */ "./src/io/websocket-loader.js" + ); + /* harmony import */ var _range_seek_handler_js__WEBPACK_IMPORTED_MODULE_7__ = + __webpack_require__( + /*! ./range-seek-handler.js */ "./src/io/range-seek-handler.js" + ); + /* harmony import */ var _param_seek_handler_js__WEBPACK_IMPORTED_MODULE_8__ = + __webpack_require__( + /*! ./param-seek-handler.js */ "./src/io/param-seek-handler.js" + ); + /* harmony import */ var _utils_exception_js__WEBPACK_IMPORTED_MODULE_9__ = + __webpack_require__( + /*! ../utils/exception.js */ "./src/utils/exception.js" + ); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + /** + * DataSource: { + * url: string, + * filesize: number, + * cors: boolean, + * withCredentials: boolean + * } + * + */ + // Manage IO Loaders + var IOController = /** @class */ (function () { + function IOController(dataSource, config, extraData) { + this.TAG = "IOController"; + this._config = config; + this._extraData = extraData; + this._stashInitialSize = 64 * 1024; // default initial size: 64KB + if ( + config.stashInitialSize != undefined && + config.stashInitialSize > 0 + ) { + // apply from config + this._stashInitialSize = config.stashInitialSize; + } + this._stashUsed = 0; + this._stashSize = this._stashInitialSize; + this._bufferSize = Math.max(this._stashSize, 1024 * 1024 * 3); // initial size: 3MB at least + this._stashBuffer = new ArrayBuffer(this._bufferSize); + this._stashByteStart = 0; + this._enableStash = true; + if (config.enableStashBuffer === false) { + this._enableStash = false; + } + this._loader = null; + this._loaderClass = null; + this._seekHandler = null; + this._dataSource = dataSource; + this._isWebSocketURL = /wss?:\/\/(.+?)/.test(dataSource.url); + this._refTotalLength = dataSource.filesize + ? dataSource.filesize + : null; + this._totalLength = this._refTotalLength; + this._fullRequestFlag = false; + this._currentRange = null; + this._redirectedURL = null; + this._speedNormalized = 0; + this._speedSampler = + new _speed_sampler_js__WEBPACK_IMPORTED_MODULE_1__.default(); + this._speedNormalizeList = [ + 32, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, + 3072, 4096, + ]; + this._isEarlyEofReconnecting = false; + this._paused = false; + this._resumeFrom = 0; + this._onDataArrival = null; + this._onSeeked = null; + this._onError = null; + this._onComplete = null; + this._onRedirect = null; + this._onRecoveredEarlyEof = null; + this._selectSeekHandler(); + this._selectLoader(); + this._createLoader(); + } + IOController.prototype.destroy = function () { + if (this._loader.isWorking()) { + this._loader.abort(); + } + this._loader.destroy(); + this._loader = null; + this._loaderClass = null; + this._dataSource = null; + this._stashBuffer = null; + this._stashUsed = + this._stashSize = + this._bufferSize = + this._stashByteStart = + 0; + this._currentRange = null; + this._speedSampler = null; + this._isEarlyEofReconnecting = false; + this._onDataArrival = null; + this._onSeeked = null; + this._onError = null; + this._onComplete = null; + this._onRedirect = null; + this._onRecoveredEarlyEof = null; + this._extraData = null; + }; + IOController.prototype.isWorking = function () { + return this._loader && this._loader.isWorking() && !this._paused; + }; + IOController.prototype.isPaused = function () { + return this._paused; + }; + Object.defineProperty(IOController.prototype, "status", { + get: function () { + return this._loader.status; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(IOController.prototype, "extraData", { + get: function () { + return this._extraData; + }, + set: function (data) { + this._extraData = data; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(IOController.prototype, "onDataArrival", { + // prototype: function onDataArrival(chunks: ArrayBuffer, byteStart: number): number + get: function () { + return this._onDataArrival; + }, + set: function (callback) { + this._onDataArrival = callback; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(IOController.prototype, "onSeeked", { + get: function () { + return this._onSeeked; + }, + set: function (callback) { + this._onSeeked = callback; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(IOController.prototype, "onError", { + // prototype: function onError(type: number, info: {code: number, msg: string}): void + get: function () { + return this._onError; + }, + set: function (callback) { + this._onError = callback; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(IOController.prototype, "onComplete", { + get: function () { + return this._onComplete; + }, + set: function (callback) { + this._onComplete = callback; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(IOController.prototype, "onRedirect", { + get: function () { + return this._onRedirect; + }, + set: function (callback) { + this._onRedirect = callback; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty( + IOController.prototype, + "onRecoveredEarlyEof", + { + get: function () { + return this._onRecoveredEarlyEof; + }, + set: function (callback) { + this._onRecoveredEarlyEof = callback; + }, + enumerable: false, + configurable: true, + } + ); + Object.defineProperty(IOController.prototype, "currentURL", { + get: function () { + return this._dataSource.url; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(IOController.prototype, "hasRedirect", { + get: function () { + return ( + this._redirectedURL != null || + this._dataSource.redirectedURL != undefined + ); + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty( + IOController.prototype, + "currentRedirectedURL", + { + get: function () { + return this._redirectedURL || this._dataSource.redirectedURL; + }, + enumerable: false, + configurable: true, + } + ); + Object.defineProperty(IOController.prototype, "currentSpeed", { + // in KB/s + get: function () { + if ( + this._loaderClass === + _xhr_range_loader_js__WEBPACK_IMPORTED_MODULE_5__.default + ) { + // SpeedSampler is inaccuracy if loader is RangeLoader + return this._loader.currentSpeed; + } + return this._speedSampler.lastSecondKBps; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(IOController.prototype, "loaderType", { + get: function () { + return this._loader.type; + }, + enumerable: false, + configurable: true, + }); + IOController.prototype._selectSeekHandler = function () { + var config = this._config; + if (config.seekType === "range") { + this._seekHandler = + new _range_seek_handler_js__WEBPACK_IMPORTED_MODULE_7__.default( + this._config.rangeLoadZeroStart + ); + } else if (config.seekType === "param") { + var paramStart = config.seekParamStart || "bstart"; + var paramEnd = config.seekParamEnd || "bend"; + this._seekHandler = + new _param_seek_handler_js__WEBPACK_IMPORTED_MODULE_8__.default( + paramStart, + paramEnd + ); + } else if (config.seekType === "custom") { + if (typeof config.customSeekHandler !== "function") { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_9__.InvalidArgumentException( + "Custom seekType specified in config but invalid customSeekHandler!" + ); + } + this._seekHandler = new config.customSeekHandler(); + } else { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_9__.InvalidArgumentException( + "Invalid seekType in config: " + config.seekType + ); + } + }; + IOController.prototype._selectLoader = function () { + if (this._config.customLoader != null) { + this._loaderClass = this._config.customLoader; + } else if (this._isWebSocketURL) { + this._loaderClass = + _websocket_loader_js__WEBPACK_IMPORTED_MODULE_6__.default; + } else if ( + _fetch_stream_loader_js__WEBPACK_IMPORTED_MODULE_3__.default.isSupported() + ) { + this._loaderClass = + _fetch_stream_loader_js__WEBPACK_IMPORTED_MODULE_3__.default; + } else if ( + _xhr_moz_chunked_loader_js__WEBPACK_IMPORTED_MODULE_4__.default.isSupported() + ) { + this._loaderClass = + _xhr_moz_chunked_loader_js__WEBPACK_IMPORTED_MODULE_4__.default; + } else if ( + _xhr_range_loader_js__WEBPACK_IMPORTED_MODULE_5__.default.isSupported() + ) { + this._loaderClass = + _xhr_range_loader_js__WEBPACK_IMPORTED_MODULE_5__.default; + } else { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_9__.RuntimeException( + "Your browser doesn't support xhr with arraybuffer responseType!" + ); + } + }; + IOController.prototype._createLoader = function () { + this._loader = new this._loaderClass( + this._seekHandler, + this._config + ); + if (this._loader.needStashBuffer === false) { + this._enableStash = false; + } + this._loader.onContentLengthKnown = + this._onContentLengthKnown.bind(this); + this._loader.onURLRedirect = this._onURLRedirect.bind(this); + this._loader.onDataArrival = + this._onLoaderChunkArrival.bind(this); + this._loader.onComplete = this._onLoaderComplete.bind(this); + this._loader.onError = this._onLoaderError.bind(this); + }; + IOController.prototype.open = function (optionalFrom) { + this._currentRange = { from: 0, to: -1 }; + if (optionalFrom) { + this._currentRange.from = optionalFrom; + } + this._speedSampler.reset(); + if (!optionalFrom) { + this._fullRequestFlag = true; + } + this._loader.open( + this._dataSource, + Object.assign({}, this._currentRange) + ); + }; + IOController.prototype.abort = function () { + this._loader.abort(); + if (this._paused) { + this._paused = false; + this._resumeFrom = 0; + } + }; + IOController.prototype.pause = function () { + if (this.isWorking()) { + this._loader.abort(); + if (this._stashUsed !== 0) { + this._resumeFrom = this._stashByteStart; + this._currentRange.to = this._stashByteStart - 1; + } else { + this._resumeFrom = this._currentRange.to + 1; + } + this._stashUsed = 0; + this._stashByteStart = 0; + this._paused = true; + } + }; + IOController.prototype.resume = function () { + if (this._paused) { + this._paused = false; + var bytes = this._resumeFrom; + this._resumeFrom = 0; + this._internalSeek(bytes, true); + } + }; + IOController.prototype.seek = function (bytes) { + this._paused = false; + this._stashUsed = 0; + this._stashByteStart = 0; + this._internalSeek(bytes, true); + }; + /** + * When seeking request is from media seeking, unconsumed stash data should be dropped + * However, stash data shouldn't be dropped if seeking requested from http reconnection + * + * @dropUnconsumed: Ignore and discard all unconsumed data in stash buffer + */ + IOController.prototype._internalSeek = function ( + bytes, + dropUnconsumed + ) { + if (this._loader.isWorking()) { + this._loader.abort(); + } + // dispatch & flush stash buffer before seek + this._flushStashBuffer(dropUnconsumed); + this._loader.destroy(); + this._loader = null; + var requestRange = { from: bytes, to: -1 }; + this._currentRange = { from: requestRange.from, to: -1 }; + this._speedSampler.reset(); + this._stashSize = this._stashInitialSize; + this._createLoader(); + this._loader.open(this._dataSource, requestRange); + if (this._onSeeked) { + this._onSeeked(); + } + }; + IOController.prototype.updateUrl = function (url) { + if (!url || typeof url !== "string" || url.length === 0) { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_9__.InvalidArgumentException( + "Url must be a non-empty string!" + ); + } + this._dataSource.url = url; + // TODO: replace with new url + }; + IOController.prototype._expandBuffer = function (expectedBytes) { + var bufferNewSize = this._stashSize; + while (bufferNewSize + 1024 * 1024 * 1 < expectedBytes) { + bufferNewSize *= 2; + } + bufferNewSize += 1024 * 1024 * 1; // bufferSize = stashSize + 1MB + if (bufferNewSize === this._bufferSize) { + return; + } + var newBuffer = new ArrayBuffer(bufferNewSize); + if (this._stashUsed > 0) { + // copy existing data into new buffer + var stashOldArray = new Uint8Array( + this._stashBuffer, + 0, + this._stashUsed + ); + var stashNewArray = new Uint8Array(newBuffer, 0, bufferNewSize); + stashNewArray.set(stashOldArray, 0); + } + this._stashBuffer = newBuffer; + this._bufferSize = bufferNewSize; + }; + IOController.prototype._normalizeSpeed = function (input) { + var list = this._speedNormalizeList; + var last = list.length - 1; + var mid = 0; + var lbound = 0; + var ubound = last; + if (input < list[0]) { + return list[0]; + } + // binary search + while (lbound <= ubound) { + mid = lbound + Math.floor((ubound - lbound) / 2); + if ( + mid === last || + (input >= list[mid] && input < list[mid + 1]) + ) { + return list[mid]; + } else if (list[mid] < input) { + lbound = mid + 1; + } else { + ubound = mid - 1; + } + } + }; + IOController.prototype._adjustStashSize = function (normalized) { + var stashSizeKB = 0; + if (this._config.isLive) { + // live stream: always use 1/8 normalized speed for size of stashSizeKB + stashSizeKB = normalized / 8; + } else { + if (normalized < 512) { + stashSizeKB = normalized; + } else if (normalized >= 512 && normalized <= 1024) { + stashSizeKB = Math.floor(normalized * 1.5); + } else { + stashSizeKB = normalized * 2; + } + } + if (stashSizeKB > 8192) { + stashSizeKB = 8192; + } + var bufferSize = stashSizeKB * 1024 + 1024 * 1024 * 1; // stashSize + 1MB + if (this._bufferSize < bufferSize) { + this._expandBuffer(bufferSize); + } + this._stashSize = stashSizeKB * 1024; + }; + IOController.prototype._dispatchChunks = function ( + chunks, + byteStart + ) { + this._currentRange.to = byteStart + chunks.byteLength - 1; + return this._onDataArrival(chunks, byteStart); + }; + IOController.prototype._onURLRedirect = function (redirectedURL) { + this._redirectedURL = redirectedURL; + if (this._onRedirect) { + this._onRedirect(redirectedURL); + } + }; + IOController.prototype._onContentLengthKnown = function ( + contentLength + ) { + if (contentLength && this._fullRequestFlag) { + this._totalLength = contentLength; + this._fullRequestFlag = false; + } + }; + IOController.prototype._onLoaderChunkArrival = function ( + chunk, + byteStart, + receivedLength + ) { + if (!this._onDataArrival) { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_9__.IllegalStateException( + "IOController: No existing consumer (onDataArrival) callback!" + ); + } + if (this._paused) { + return; + } + if (this._isEarlyEofReconnecting) { + // Auto-reconnect for EarlyEof succeed, notify to upper-layer by callback + this._isEarlyEofReconnecting = false; + if (this._onRecoveredEarlyEof) { + this._onRecoveredEarlyEof(); + } + } + this._speedSampler.addBytes(chunk.byteLength); + // adjust stash buffer size according to network speed dynamically + var KBps = this._speedSampler.lastSecondKBps; + if (KBps !== 0) { + var normalized = this._normalizeSpeed(KBps); + if (this._speedNormalized !== normalized) { + this._speedNormalized = normalized; + this._adjustStashSize(normalized); + } + } + if (!this._enableStash) { + // disable stash + if (this._stashUsed === 0) { + // dispatch chunk directly to consumer; + // check ret value (consumed bytes) and stash unconsumed to stashBuffer + var consumed = this._dispatchChunks(chunk, byteStart); + if (consumed < chunk.byteLength) { + // unconsumed data remain. + var remain = chunk.byteLength - consumed; + if (remain > this._bufferSize) { + this._expandBuffer(remain); + } + var stashArray = new Uint8Array( + this._stashBuffer, + 0, + this._bufferSize + ); + stashArray.set(new Uint8Array(chunk, consumed), 0); + this._stashUsed += remain; + this._stashByteStart = byteStart + consumed; + } + } else { + // else: Merge chunk into stashBuffer, and dispatch stashBuffer to consumer. + if (this._stashUsed + chunk.byteLength > this._bufferSize) { + this._expandBuffer(this._stashUsed + chunk.byteLength); + } + var stashArray = new Uint8Array( + this._stashBuffer, + 0, + this._bufferSize + ); + stashArray.set(new Uint8Array(chunk), this._stashUsed); + this._stashUsed += chunk.byteLength; + var consumed = this._dispatchChunks( + this._stashBuffer.slice(0, this._stashUsed), + this._stashByteStart + ); + if (consumed < this._stashUsed && consumed > 0) { + // unconsumed data remain + var remainArray = new Uint8Array( + this._stashBuffer, + consumed + ); + stashArray.set(remainArray, 0); + } + this._stashUsed -= consumed; + this._stashByteStart += consumed; + } + } else { + // enable stash + if (this._stashUsed === 0 && this._stashByteStart === 0) { + // seeked? or init chunk? + // This is the first chunk after seek action + this._stashByteStart = byteStart; + } + if (this._stashUsed + chunk.byteLength <= this._stashSize) { + // just stash + var stashArray = new Uint8Array( + this._stashBuffer, + 0, + this._stashSize + ); + stashArray.set(new Uint8Array(chunk), this._stashUsed); + this._stashUsed += chunk.byteLength; + } else { + // stashUsed + chunkSize > stashSize, size limit exceeded + var stashArray = new Uint8Array( + this._stashBuffer, + 0, + this._bufferSize + ); + if (this._stashUsed > 0) { + // There're stash datas in buffer + // dispatch the whole stashBuffer, and stash remain data + // then append chunk to stashBuffer (stash) + var buffer = this._stashBuffer.slice(0, this._stashUsed); + var consumed = this._dispatchChunks( + buffer, + this._stashByteStart + ); + if (consumed < buffer.byteLength) { + if (consumed > 0) { + var remainArray = new Uint8Array(buffer, consumed); + stashArray.set(remainArray, 0); + this._stashUsed = remainArray.byteLength; + this._stashByteStart += consumed; + } + } else { + this._stashUsed = 0; + this._stashByteStart += consumed; + } + if (this._stashUsed + chunk.byteLength > this._bufferSize) { + this._expandBuffer(this._stashUsed + chunk.byteLength); + stashArray = new Uint8Array( + this._stashBuffer, + 0, + this._bufferSize + ); + } + stashArray.set(new Uint8Array(chunk), this._stashUsed); + this._stashUsed += chunk.byteLength; + } else { + // stash buffer empty, but chunkSize > stashSize (oh, holy shit) + // dispatch chunk directly and stash remain data + var consumed = this._dispatchChunks(chunk, byteStart); + if (consumed < chunk.byteLength) { + var remain = chunk.byteLength - consumed; + if (remain > this._bufferSize) { + this._expandBuffer(remain); + stashArray = new Uint8Array( + this._stashBuffer, + 0, + this._bufferSize + ); + } + stashArray.set(new Uint8Array(chunk, consumed), 0); + this._stashUsed += remain; + this._stashByteStart = byteStart + consumed; + } + } + } + } + }; + IOController.prototype._flushStashBuffer = function ( + dropUnconsumed + ) { + if (this._stashUsed > 0) { + var buffer = this._stashBuffer.slice(0, this._stashUsed); + var consumed = this._dispatchChunks( + buffer, + this._stashByteStart + ); + var remain = buffer.byteLength - consumed; + if (consumed < buffer.byteLength) { + if (dropUnconsumed) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + remain + + " bytes unconsumed data remain when flush buffer, dropped" + ); + } else { + if (consumed > 0) { + var stashArray = new Uint8Array( + this._stashBuffer, + 0, + this._bufferSize + ); + var remainArray = new Uint8Array(buffer, consumed); + stashArray.set(remainArray, 0); + this._stashUsed = remainArray.byteLength; + this._stashByteStart += consumed; + } + return 0; + } + } + this._stashUsed = 0; + this._stashByteStart = 0; + return remain; + } + return 0; + }; + IOController.prototype._onLoaderComplete = function (from, to) { + // Force-flush stash buffer, and drop unconsumed data + this._flushStashBuffer(true); + if (this._onComplete) { + this._onComplete(this._extraData); + } + }; + IOController.prototype._onLoaderError = function (type, data) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.e( + this.TAG, + "Loader error, code = " + data.code + ", msg = " + data.msg + ); + this._flushStashBuffer(false); + if (this._isEarlyEofReconnecting) { + // Auto-reconnect for EarlyEof failed, throw UnrecoverableEarlyEof error to upper-layer + this._isEarlyEofReconnecting = false; + type = + _loader_js__WEBPACK_IMPORTED_MODULE_2__.LoaderErrors + .UNRECOVERABLE_EARLY_EOF; + } + switch (type) { + case _loader_js__WEBPACK_IMPORTED_MODULE_2__.LoaderErrors + .EARLY_EOF: { + if (!this._config.isLive) { + // Do internal http reconnect if not live stream + if (this._totalLength) { + var nextFrom = this._currentRange.to + 1; + if (nextFrom < this._totalLength) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Connection lost, trying reconnect..." + ); + this._isEarlyEofReconnecting = true; + this._internalSeek(nextFrom, false); + } + return; + } + // else: We don't know totalLength, throw UnrecoverableEarlyEof + } + // live stream: throw UnrecoverableEarlyEof error to upper-layer + type = + _loader_js__WEBPACK_IMPORTED_MODULE_2__.LoaderErrors + .UNRECOVERABLE_EARLY_EOF; + break; + } + case _loader_js__WEBPACK_IMPORTED_MODULE_2__.LoaderErrors + .UNRECOVERABLE_EARLY_EOF: + case _loader_js__WEBPACK_IMPORTED_MODULE_2__.LoaderErrors + .CONNECTING_TIMEOUT: + case _loader_js__WEBPACK_IMPORTED_MODULE_2__.LoaderErrors + .HTTP_STATUS_CODE_INVALID: + case _loader_js__WEBPACK_IMPORTED_MODULE_2__.LoaderErrors + .EXCEPTION: + break; + } + if (this._onError) { + this._onError(type, data); + } else { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_9__.RuntimeException( + "IOException: " + data.msg + ); + } + }; + return IOController; + })(); + /* harmony default export */ __webpack_exports__["default"] = + IOController; + + /***/ + }, + + /***/ "./src/io/loader.js": + /*!**************************!*\ + !*** ./src/io/loader.js ***! + \**************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ LoaderStatus: function () { + return /* binding */ LoaderStatus; + }, + /* harmony export */ LoaderErrors: function () { + return /* binding */ LoaderErrors; + }, + /* harmony export */ BaseLoader: function () { + return /* binding */ BaseLoader; + }, + /* harmony export */ + }); + /* harmony import */ var _utils_exception_js__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__( + /*! ../utils/exception.js */ "./src/utils/exception.js" + ); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + var LoaderStatus = { + kIdle: 0, + kConnecting: 1, + kBuffering: 2, + kError: 3, + kComplete: 4, + }; + var LoaderErrors = { + OK: "OK", + EXCEPTION: "Exception", + HTTP_STATUS_CODE_INVALID: "HttpStatusCodeInvalid", + CONNECTING_TIMEOUT: "ConnectingTimeout", + EARLY_EOF: "EarlyEof", + UNRECOVERABLE_EARLY_EOF: "UnrecoverableEarlyEof", + }; + /* Loader has callbacks which have following prototypes: + * function onContentLengthKnown(contentLength: number): void + * function onURLRedirect(url: string): void + * function onDataArrival(chunk: ArrayBuffer, byteStart: number, receivedLength: number): void + * function onError(errorType: number, errorInfo: {code: number, msg: string}): void + * function onComplete(rangeFrom: number, rangeTo: number): void + */ + var BaseLoader = /** @class */ (function () { + function BaseLoader(typeName) { + this._type = typeName || "undefined"; + this._status = LoaderStatus.kIdle; + this._needStash = false; + // callbacks + this._onContentLengthKnown = null; + this._onURLRedirect = null; + this._onDataArrival = null; + this._onError = null; + this._onComplete = null; + } + BaseLoader.prototype.destroy = function () { + this._status = LoaderStatus.kIdle; + this._onContentLengthKnown = null; + this._onURLRedirect = null; + this._onDataArrival = null; + this._onError = null; + this._onComplete = null; + }; + BaseLoader.prototype.isWorking = function () { + return ( + this._status === LoaderStatus.kConnecting || + this._status === LoaderStatus.kBuffering + ); + }; + Object.defineProperty(BaseLoader.prototype, "type", { + get: function () { + return this._type; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(BaseLoader.prototype, "status", { + get: function () { + return this._status; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(BaseLoader.prototype, "needStashBuffer", { + get: function () { + return this._needStash; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty( + BaseLoader.prototype, + "onContentLengthKnown", + { + get: function () { + return this._onContentLengthKnown; + }, + set: function (callback) { + this._onContentLengthKnown = callback; + }, + enumerable: false, + configurable: true, + } + ); + Object.defineProperty(BaseLoader.prototype, "onURLRedirect", { + get: function () { + return this._onURLRedirect; + }, + set: function (callback) { + this._onURLRedirect = callback; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(BaseLoader.prototype, "onDataArrival", { + get: function () { + return this._onDataArrival; + }, + set: function (callback) { + this._onDataArrival = callback; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(BaseLoader.prototype, "onError", { + get: function () { + return this._onError; + }, + set: function (callback) { + this._onError = callback; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(BaseLoader.prototype, "onComplete", { + get: function () { + return this._onComplete; + }, + set: function (callback) { + this._onComplete = callback; + }, + enumerable: false, + configurable: true, + }); + // pure virtual + BaseLoader.prototype.open = function (dataSource, range) { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_0__.NotImplementedException( + "Unimplemented abstract function!" + ); + }; + BaseLoader.prototype.abort = function () { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_0__.NotImplementedException( + "Unimplemented abstract function!" + ); + }; + return BaseLoader; + })(); + + /***/ + }, + + /***/ "./src/io/param-seek-handler.js": + /*!**************************************!*\ + !*** ./src/io/param-seek-handler.js ***! + \**************************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + var ParamSeekHandler = /** @class */ (function () { + function ParamSeekHandler(paramStart, paramEnd) { + this._startName = paramStart; + this._endName = paramEnd; + } + ParamSeekHandler.prototype.getConfig = function (baseUrl, range) { + var url = baseUrl; + if (range.from !== 0 || range.to !== -1) { + var needAnd = true; + if (url.indexOf("?") === -1) { + url += "?"; + needAnd = false; + } + if (needAnd) { + url += "&"; + } + url += this._startName + "=" + range.from.toString(); + if (range.to !== -1) { + url += "&" + this._endName + "=" + range.to.toString(); + } + } + return { + url: url, + headers: {}, + }; + }; + ParamSeekHandler.prototype.removeURLParameters = function ( + seekedURL + ) { + var baseURL = seekedURL.split("?")[0]; + var params = undefined; + var queryIndex = seekedURL.indexOf("?"); + if (queryIndex !== -1) { + params = seekedURL.substring(queryIndex + 1); + } + var resultParams = ""; + if (params != undefined && params.length > 0) { + var pairs = params.split("&"); + for (var i = 0; i < pairs.length; i++) { + var pair = pairs[i].split("="); + var requireAnd = i > 0; + if ( + pair[0] !== this._startName && + pair[0] !== this._endName + ) { + if (requireAnd) { + resultParams += "&"; + } + resultParams += pairs[i]; + } + } + } + return resultParams.length === 0 + ? baseURL + : baseURL + "?" + resultParams; + }; + return ParamSeekHandler; + })(); + /* harmony default export */ __webpack_exports__["default"] = + ParamSeekHandler; + + /***/ + }, + + /***/ "./src/io/range-seek-handler.js": + /*!**************************************!*\ + !*** ./src/io/range-seek-handler.js ***! + \**************************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + var RangeSeekHandler = /** @class */ (function () { + function RangeSeekHandler(zeroStart) { + this._zeroStart = zeroStart || false; + } + RangeSeekHandler.prototype.getConfig = function (url, range) { + var headers = {}; + if (range.from !== 0 || range.to !== -1) { + var param = void 0; + if (range.to !== -1) { + param = + "bytes=" + + range.from.toString() + + "-" + + range.to.toString(); + } else { + param = "bytes=" + range.from.toString() + "-"; + } + headers["Range"] = param; + } else if (this._zeroStart) { + headers["Range"] = "bytes=0-"; + } + return { + url: url, + headers: headers, + }; + }; + RangeSeekHandler.prototype.removeURLParameters = function ( + seekedURL + ) { + return seekedURL; + }; + return RangeSeekHandler; + })(); + /* harmony default export */ __webpack_exports__["default"] = + RangeSeekHandler; + + /***/ + }, + + /***/ "./src/io/speed-sampler.js": + /*!*********************************!*\ + !*** ./src/io/speed-sampler.js ***! + \*********************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + // Utility class to calculate realtime network I/O speed + var SpeedSampler = /** @class */ (function () { + function SpeedSampler() { + // milliseconds + this._firstCheckpoint = 0; + this._lastCheckpoint = 0; + this._intervalBytes = 0; + this._totalBytes = 0; + this._lastSecondBytes = 0; + // compatibility detection + if (self.performance && self.performance.now) { + this._now = self.performance.now.bind(self.performance); + } else { + this._now = Date.now; + } + } + SpeedSampler.prototype.reset = function () { + this._firstCheckpoint = this._lastCheckpoint = 0; + this._totalBytes = this._intervalBytes = 0; + this._lastSecondBytes = 0; + }; + SpeedSampler.prototype.addBytes = function (bytes) { + if (this._firstCheckpoint === 0) { + this._firstCheckpoint = this._now(); + this._lastCheckpoint = this._firstCheckpoint; + this._intervalBytes += bytes; + this._totalBytes += bytes; + } else if (this._now() - this._lastCheckpoint < 1000) { + this._intervalBytes += bytes; + this._totalBytes += bytes; + } else { + // duration >= 1000 + this._lastSecondBytes = this._intervalBytes; + this._intervalBytes = bytes; + this._totalBytes += bytes; + this._lastCheckpoint = this._now(); + } + }; + Object.defineProperty(SpeedSampler.prototype, "currentKBps", { + get: function () { + this.addBytes(0); + var durationSeconds = + (this._now() - this._lastCheckpoint) / 1000; + if (durationSeconds == 0) durationSeconds = 1; + return this._intervalBytes / durationSeconds / 1024; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(SpeedSampler.prototype, "lastSecondKBps", { + get: function () { + this.addBytes(0); + if (this._lastSecondBytes !== 0) { + return this._lastSecondBytes / 1024; + } else { + // lastSecondBytes === 0 + if (this._now() - this._lastCheckpoint >= 500) { + // if time interval since last checkpoint has exceeded 500ms + // the speed is nearly accurate + return this.currentKBps; + } else { + // We don't know + return 0; + } + } + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(SpeedSampler.prototype, "averageKBps", { + get: function () { + var durationSeconds = + (this._now() - this._firstCheckpoint) / 1000; + return this._totalBytes / durationSeconds / 1024; + }, + enumerable: false, + configurable: true, + }); + return SpeedSampler; + })(); + /* harmony default export */ __webpack_exports__["default"] = + SpeedSampler; + + /***/ + }, + + /***/ "./src/io/websocket-loader.js": + /*!************************************!*\ + !*** ./src/io/websocket-loader.js ***! + \************************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony import */ var _loader_js__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__(/*! ./loader.js */ "./src/io/loader.js"); + /* harmony import */ var _utils_exception_js__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__( + /*! ../utils/exception.js */ "./src/utils/exception.js" + ); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + var __extends = + (undefined && undefined.__extends) || + (function () { + var extendStatics = function (d, b) { + extendStatics = + Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && + function (d, b) { + d.__proto__ = b; + }) || + function (d, b) { + for (var p in b) + if (Object.prototype.hasOwnProperty.call(b, p)) + d[p] = b[p]; + }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError( + "Class extends value " + + String(b) + + " is not a constructor or null" + ); + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = + b === null + ? Object.create(b) + : ((__.prototype = b.prototype), new __()); + }; + })(); + + // For FLV over WebSocket live stream + var WebSocketLoader = /** @class */ (function (_super) { + __extends(WebSocketLoader, _super); + function WebSocketLoader() { + var _this = _super.call(this, "websocket-loader") || this; + _this.TAG = "WebSocketLoader"; + _this._needStash = true; + _this._ws = null; + _this._requestAbort = false; + _this._receivedLength = 0; + return _this; + } + WebSocketLoader.isSupported = function () { + try { + return typeof self.WebSocket !== "undefined"; + } catch (e) { + return false; + } + }; + WebSocketLoader.prototype.destroy = function () { + if (this._ws) { + this.abort(); + } + _super.prototype.destroy.call(this); + }; + WebSocketLoader.prototype.open = function (dataSource) { + try { + var ws = (this._ws = new self.WebSocket(dataSource.url)); + ws.binaryType = "arraybuffer"; + ws.onopen = this._onWebSocketOpen.bind(this); + ws.onclose = this._onWebSocketClose.bind(this); + ws.onmessage = this._onWebSocketMessage.bind(this); + ws.onerror = this._onWebSocketError.bind(this); + this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_0__.LoaderStatus.kConnecting; + } catch (e) { + this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_0__.LoaderStatus.kError; + var info = { code: e.code, msg: e.message }; + if (this._onError) { + this._onError( + _loader_js__WEBPACK_IMPORTED_MODULE_0__.LoaderErrors + .EXCEPTION, + info + ); + } else { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_1__.RuntimeException( + info.msg + ); + } + } + }; + WebSocketLoader.prototype.abort = function () { + var ws = this._ws; + if (ws && (ws.readyState === 0 || ws.readyState === 1)) { + // CONNECTING || OPEN + this._requestAbort = true; + ws.close(); + } + this._ws = null; + this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_0__.LoaderStatus.kComplete; + }; + WebSocketLoader.prototype._onWebSocketOpen = function (e) { + this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_0__.LoaderStatus.kBuffering; + }; + WebSocketLoader.prototype._onWebSocketClose = function (e) { + if (this._requestAbort === true) { + this._requestAbort = false; + return; + } + this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_0__.LoaderStatus.kComplete; + if (this._onComplete) { + this._onComplete(0, this._receivedLength - 1); + } + }; + WebSocketLoader.prototype._onWebSocketMessage = function (e) { + var _this = this; + if (e.data instanceof ArrayBuffer) { + this._dispatchArrayBuffer(e.data); + } else if (e.data instanceof Blob) { + var reader_1 = new FileReader(); + reader_1.onload = function () { + _this._dispatchArrayBuffer(reader_1.result); + }; + reader_1.readAsArrayBuffer(e.data); + } else { + this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_0__.LoaderStatus.kError; + var info = { + code: -1, + msg: + "Unsupported WebSocket message type: " + + e.data.constructor.name, + }; + if (this._onError) { + this._onError( + _loader_js__WEBPACK_IMPORTED_MODULE_0__.LoaderErrors + .EXCEPTION, + info + ); + } else { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_1__.RuntimeException( + info.msg + ); + } + } + }; + WebSocketLoader.prototype._dispatchArrayBuffer = function ( + arraybuffer + ) { + var chunk = arraybuffer; + var byteStart = this._receivedLength; + this._receivedLength += chunk.byteLength; + if (this._onDataArrival) { + this._onDataArrival(chunk, byteStart, this._receivedLength); + } + }; + WebSocketLoader.prototype._onWebSocketError = function (e) { + this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_0__.LoaderStatus.kError; + var info = { + code: e.code, + msg: e.message, + }; + if (this._onError) { + this._onError( + _loader_js__WEBPACK_IMPORTED_MODULE_0__.LoaderErrors + .EXCEPTION, + info + ); + } else { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_1__.RuntimeException( + info.msg + ); + } + }; + return WebSocketLoader; + })(_loader_js__WEBPACK_IMPORTED_MODULE_0__.BaseLoader); + /* harmony default export */ __webpack_exports__["default"] = + WebSocketLoader; + + /***/ + }, + + /***/ "./src/io/xhr-moz-chunked-loader.js": + /*!******************************************!*\ + !*** ./src/io/xhr-moz-chunked-loader.js ***! + \******************************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony import */ var _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__( + /*! ../utils/logger.js */ "./src/utils/logger.js" + ); + /* harmony import */ var _loader_js__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__(/*! ./loader.js */ "./src/io/loader.js"); + /* harmony import */ var _utils_exception_js__WEBPACK_IMPORTED_MODULE_2__ = + __webpack_require__( + /*! ../utils/exception.js */ "./src/utils/exception.js" + ); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + var __extends = + (undefined && undefined.__extends) || + (function () { + var extendStatics = function (d, b) { + extendStatics = + Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && + function (d, b) { + d.__proto__ = b; + }) || + function (d, b) { + for (var p in b) + if (Object.prototype.hasOwnProperty.call(b, p)) + d[p] = b[p]; + }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError( + "Class extends value " + + String(b) + + " is not a constructor or null" + ); + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = + b === null + ? Object.create(b) + : ((__.prototype = b.prototype), new __()); + }; + })(); + + // For FireFox browser which supports `xhr.responseType = 'moz-chunked-arraybuffer'` + var MozChunkedLoader = /** @class */ (function (_super) { + __extends(MozChunkedLoader, _super); + function MozChunkedLoader(seekHandler, config) { + var _this = _super.call(this, "xhr-moz-chunked-loader") || this; + _this.TAG = "MozChunkedLoader"; + _this._seekHandler = seekHandler; + _this._config = config; + _this._needStash = true; + _this._xhr = null; + _this._requestAbort = false; + _this._contentLength = null; + _this._receivedLength = 0; + return _this; + } + MozChunkedLoader.isSupported = function () { + try { + var xhr = new XMLHttpRequest(); + // Firefox 37- requires .open() to be called before setting responseType + xhr.open("GET", "https://example.com", true); + xhr.responseType = "moz-chunked-arraybuffer"; + return xhr.responseType === "moz-chunked-arraybuffer"; + } catch (e) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + "MozChunkedLoader", + e.message + ); + return false; + } + }; + MozChunkedLoader.prototype.destroy = function () { + if (this.isWorking()) { + this.abort(); + } + if (this._xhr) { + this._xhr.onreadystatechange = null; + this._xhr.onprogress = null; + this._xhr.onloadend = null; + this._xhr.onerror = null; + this._xhr = null; + } + _super.prototype.destroy.call(this); + }; + MozChunkedLoader.prototype.open = function (dataSource, range) { + this._dataSource = dataSource; + this._range = range; + var sourceURL = dataSource.url; + if ( + this._config.reuseRedirectedURL && + dataSource.redirectedURL != undefined + ) { + sourceURL = dataSource.redirectedURL; + } + var seekConfig = this._seekHandler.getConfig(sourceURL, range); + this._requestURL = seekConfig.url; + var xhr = (this._xhr = new XMLHttpRequest()); + xhr.open("GET", seekConfig.url, true); + xhr.responseType = "moz-chunked-arraybuffer"; + xhr.onreadystatechange = this._onReadyStateChange.bind(this); + xhr.onprogress = this._onProgress.bind(this); + xhr.onloadend = this._onLoadEnd.bind(this); + xhr.onerror = this._onXhrError.bind(this); + // cors is auto detected and enabled by xhr + // withCredentials is disabled by default + if (dataSource.withCredentials) { + xhr.withCredentials = true; + } + if (typeof seekConfig.headers === "object") { + var headers = seekConfig.headers; + for (var key in headers) { + if (headers.hasOwnProperty(key)) { + xhr.setRequestHeader(key, headers[key]); + } + } + } + // add additional headers + if (typeof this._config.headers === "object") { + var headers = this._config.headers; + for (var key in headers) { + if (headers.hasOwnProperty(key)) { + xhr.setRequestHeader(key, headers[key]); + } + } + } + this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderStatus.kConnecting; + xhr.send(); + }; + MozChunkedLoader.prototype.abort = function () { + this._requestAbort = true; + if (this._xhr) { + this._xhr.abort(); + } + this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderStatus.kComplete; + }; + MozChunkedLoader.prototype._onReadyStateChange = function (e) { + var xhr = e.target; + if (xhr.readyState === 2) { + // HEADERS_RECEIVED + if ( + xhr.responseURL != undefined && + xhr.responseURL !== this._requestURL + ) { + if (this._onURLRedirect) { + var redirectedURL = this._seekHandler.removeURLParameters( + xhr.responseURL + ); + this._onURLRedirect(redirectedURL); + } + } + if ( + xhr.status !== 0 && + (xhr.status < 200 || xhr.status > 299) + ) { + this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderStatus.kError; + if (this._onError) { + this._onError( + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderErrors + .HTTP_STATUS_CODE_INVALID, + { code: xhr.status, msg: xhr.statusText } + ); + } else { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_2__.RuntimeException( + "MozChunkedLoader: Http code invalid, " + + xhr.status + + " " + + xhr.statusText + ); + } + } else { + this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderStatus.kBuffering; + } + } + }; + MozChunkedLoader.prototype._onProgress = function (e) { + if ( + this._status === + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderStatus.kError + ) { + // Ignore error response + return; + } + if (this._contentLength === null) { + if (e.total !== null && e.total !== 0) { + this._contentLength = e.total; + if (this._onContentLengthKnown) { + this._onContentLengthKnown(this._contentLength); + } + } + } + var chunk = e.target.response; + var byteStart = this._range.from + this._receivedLength; + this._receivedLength += chunk.byteLength; + if (this._onDataArrival) { + this._onDataArrival(chunk, byteStart, this._receivedLength); + } + }; + MozChunkedLoader.prototype._onLoadEnd = function (e) { + if (this._requestAbort === true) { + this._requestAbort = false; + return; + } else if ( + this._status === + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderStatus.kError + ) { + return; + } + this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderStatus.kComplete; + if (this._onComplete) { + this._onComplete( + this._range.from, + this._range.from + this._receivedLength - 1 + ); + } + }; + MozChunkedLoader.prototype._onXhrError = function (e) { + this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderStatus.kError; + var type = 0; + var info = null; + if (this._contentLength && e.loaded < this._contentLength) { + type = + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderErrors + .EARLY_EOF; + info = { code: -1, msg: "Moz-Chunked stream meet Early-Eof" }; + } else { + type = + _loader_js__WEBPACK_IMPORTED_MODULE_1__.LoaderErrors + .EXCEPTION; + info = { code: -1, msg: e.constructor.name + " " + e.type }; + } + if (this._onError) { + this._onError(type, info); + } else { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_2__.RuntimeException( + info.msg + ); + } + }; + return MozChunkedLoader; + })(_loader_js__WEBPACK_IMPORTED_MODULE_1__.BaseLoader); + /* harmony default export */ __webpack_exports__["default"] = + MozChunkedLoader; + + /***/ + }, + + /***/ "./src/io/xhr-range-loader.js": + /*!************************************!*\ + !*** ./src/io/xhr-range-loader.js ***! + \************************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony import */ var _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__( + /*! ../utils/logger.js */ "./src/utils/logger.js" + ); + /* harmony import */ var _speed_sampler_js__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__( + /*! ./speed-sampler.js */ "./src/io/speed-sampler.js" + ); + /* harmony import */ var _loader_js__WEBPACK_IMPORTED_MODULE_2__ = + __webpack_require__(/*! ./loader.js */ "./src/io/loader.js"); + /* harmony import */ var _utils_exception_js__WEBPACK_IMPORTED_MODULE_3__ = + __webpack_require__( + /*! ../utils/exception.js */ "./src/utils/exception.js" + ); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + var __extends = + (undefined && undefined.__extends) || + (function () { + var extendStatics = function (d, b) { + extendStatics = + Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && + function (d, b) { + d.__proto__ = b; + }) || + function (d, b) { + for (var p in b) + if (Object.prototype.hasOwnProperty.call(b, p)) + d[p] = b[p]; + }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError( + "Class extends value " + + String(b) + + " is not a constructor or null" + ); + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = + b === null + ? Object.create(b) + : ((__.prototype = b.prototype), new __()); + }; + })(); + + // Universal IO Loader, implemented by adding Range header in xhr's request header + var RangeLoader = /** @class */ (function (_super) { + __extends(RangeLoader, _super); + function RangeLoader(seekHandler, config) { + var _this = _super.call(this, "xhr-range-loader") || this; + _this.TAG = "RangeLoader"; + _this._seekHandler = seekHandler; + _this._config = config; + _this._needStash = false; + _this._chunkSizeKBList = [ + 128, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 5120, + 6144, 7168, 8192, + ]; + _this._currentChunkSizeKB = 384; + _this._currentSpeedNormalized = 0; + _this._zeroSpeedChunkCount = 0; + _this._xhr = null; + _this._speedSampler = + new _speed_sampler_js__WEBPACK_IMPORTED_MODULE_1__.default(); + _this._requestAbort = false; + _this._waitForTotalLength = false; + _this._totalLengthReceived = false; + _this._currentRequestURL = null; + _this._currentRedirectedURL = null; + _this._currentRequestRange = null; + _this._totalLength = null; // size of the entire file + _this._contentLength = null; // Content-Length of entire request range + _this._receivedLength = 0; // total received bytes + _this._lastTimeLoaded = 0; // received bytes of current request sub-range + return _this; + } + RangeLoader.isSupported = function () { + try { + var xhr = new XMLHttpRequest(); + xhr.open("GET", "https://example.com", true); + xhr.responseType = "arraybuffer"; + return xhr.responseType === "arraybuffer"; + } catch (e) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + "RangeLoader", + e.message + ); + return false; + } + }; + RangeLoader.prototype.destroy = function () { + if (this.isWorking()) { + this.abort(); + } + if (this._xhr) { + this._xhr.onreadystatechange = null; + this._xhr.onprogress = null; + this._xhr.onload = null; + this._xhr.onerror = null; + this._xhr = null; + } + _super.prototype.destroy.call(this); + }; + Object.defineProperty(RangeLoader.prototype, "currentSpeed", { + get: function () { + return this._speedSampler.lastSecondKBps; + }, + enumerable: false, + configurable: true, + }); + RangeLoader.prototype.open = function (dataSource, range) { + this._dataSource = dataSource; + this._range = range; + this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_2__.LoaderStatus.kConnecting; + var useRefTotalLength = false; + if ( + this._dataSource.filesize != undefined && + this._dataSource.filesize !== 0 + ) { + useRefTotalLength = true; + this._totalLength = this._dataSource.filesize; + } + if (!this._totalLengthReceived && !useRefTotalLength) { + // We need total filesize + this._waitForTotalLength = true; + this._internalOpen(this._dataSource, { from: 0, to: -1 }); + } else { + // We have filesize, start loading + this._openSubRange(); + } + }; + RangeLoader.prototype._openSubRange = function () { + var chunkSize = this._currentChunkSizeKB * 1024; + var from = this._range.from + this._receivedLength; + var to = from + chunkSize; + if (this._contentLength != null) { + if (to - this._range.from >= this._contentLength) { + to = this._range.from + this._contentLength - 1; + } + } + this._currentRequestRange = { from: from, to: to }; + this._internalOpen(this._dataSource, this._currentRequestRange); + }; + RangeLoader.prototype._internalOpen = function (dataSource, range) { + this._lastTimeLoaded = 0; + var sourceURL = dataSource.url; + if (this._config.reuseRedirectedURL) { + if (this._currentRedirectedURL != undefined) { + sourceURL = this._currentRedirectedURL; + } else if (dataSource.redirectedURL != undefined) { + sourceURL = dataSource.redirectedURL; + } + } + var seekConfig = this._seekHandler.getConfig(sourceURL, range); + this._currentRequestURL = seekConfig.url; + var xhr = (this._xhr = new XMLHttpRequest()); + xhr.open("GET", seekConfig.url, true); + xhr.responseType = "arraybuffer"; + xhr.onreadystatechange = this._onReadyStateChange.bind(this); + xhr.onprogress = this._onProgress.bind(this); + xhr.onload = this._onLoad.bind(this); + xhr.onerror = this._onXhrError.bind(this); + if (dataSource.withCredentials) { + xhr.withCredentials = true; + } + if (typeof seekConfig.headers === "object") { + var headers = seekConfig.headers; + for (var key in headers) { + if (headers.hasOwnProperty(key)) { + xhr.setRequestHeader(key, headers[key]); + } + } + } + // add additional headers + if (typeof this._config.headers === "object") { + var headers = this._config.headers; + for (var key in headers) { + if (headers.hasOwnProperty(key)) { + xhr.setRequestHeader(key, headers[key]); + } + } + } + xhr.send(); + }; + RangeLoader.prototype.abort = function () { + this._requestAbort = true; + this._internalAbort(); + this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_2__.LoaderStatus.kComplete; + }; + RangeLoader.prototype._internalAbort = function () { + if (this._xhr) { + this._xhr.onreadystatechange = null; + this._xhr.onprogress = null; + this._xhr.onload = null; + this._xhr.onerror = null; + this._xhr.abort(); + this._xhr = null; + } + }; + RangeLoader.prototype._onReadyStateChange = function (e) { + var xhr = e.target; + if (xhr.readyState === 2) { + // HEADERS_RECEIVED + if (xhr.responseURL != undefined) { + // if the browser support this property + var redirectedURL = this._seekHandler.removeURLParameters( + xhr.responseURL + ); + if ( + xhr.responseURL !== this._currentRequestURL && + redirectedURL !== this._currentRedirectedURL + ) { + this._currentRedirectedURL = redirectedURL; + if (this._onURLRedirect) { + this._onURLRedirect(redirectedURL); + } + } + } + if (xhr.status >= 200 && xhr.status <= 299) { + if (this._waitForTotalLength) { + return; + } + this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_2__.LoaderStatus.kBuffering; + } else { + this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_2__.LoaderStatus.kError; + if (this._onError) { + this._onError( + _loader_js__WEBPACK_IMPORTED_MODULE_2__.LoaderErrors + .HTTP_STATUS_CODE_INVALID, + { code: xhr.status, msg: xhr.statusText } + ); + } else { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_3__.RuntimeException( + "RangeLoader: Http code invalid, " + + xhr.status + + " " + + xhr.statusText + ); + } + } + } + }; + RangeLoader.prototype._onProgress = function (e) { + if ( + this._status === + _loader_js__WEBPACK_IMPORTED_MODULE_2__.LoaderStatus.kError + ) { + // Ignore error response + return; + } + if (this._contentLength === null) { + var openNextRange = false; + if (this._waitForTotalLength) { + this._waitForTotalLength = false; + this._totalLengthReceived = true; + openNextRange = true; + var total = e.total; + this._internalAbort(); + if ((total != null) & (total !== 0)) { + this._totalLength = total; + } + } + // calculate currrent request range's contentLength + if (this._range.to === -1) { + this._contentLength = this._totalLength - this._range.from; + } else { + // to !== -1 + this._contentLength = this._range.to - this._range.from + 1; + } + if (openNextRange) { + this._openSubRange(); + return; + } + if (this._onContentLengthKnown) { + this._onContentLengthKnown(this._contentLength); + } + } + var delta = e.loaded - this._lastTimeLoaded; + this._lastTimeLoaded = e.loaded; + this._speedSampler.addBytes(delta); + }; + RangeLoader.prototype._normalizeSpeed = function (input) { + var list = this._chunkSizeKBList; + var last = list.length - 1; + var mid = 0; + var lbound = 0; + var ubound = last; + if (input < list[0]) { + return list[0]; + } + while (lbound <= ubound) { + mid = lbound + Math.floor((ubound - lbound) / 2); + if ( + mid === last || + (input >= list[mid] && input < list[mid + 1]) + ) { + return list[mid]; + } else if (list[mid] < input) { + lbound = mid + 1; + } else { + ubound = mid - 1; + } + } + }; + RangeLoader.prototype._onLoad = function (e) { + if ( + this._status === + _loader_js__WEBPACK_IMPORTED_MODULE_2__.LoaderStatus.kError + ) { + // Ignore error response + return; + } + if (this._waitForTotalLength) { + this._waitForTotalLength = false; + return; + } + this._lastTimeLoaded = 0; + var KBps = this._speedSampler.lastSecondKBps; + if (KBps === 0) { + this._zeroSpeedChunkCount++; + if (this._zeroSpeedChunkCount >= 3) { + // Try get currentKBps after 3 chunks + KBps = this._speedSampler.currentKBps; + } + } + if (KBps !== 0) { + var normalized = this._normalizeSpeed(KBps); + if (this._currentSpeedNormalized !== normalized) { + this._currentSpeedNormalized = normalized; + this._currentChunkSizeKB = normalized; + } + } + var chunk = e.target.response; + var byteStart = this._range.from + this._receivedLength; + this._receivedLength += chunk.byteLength; + var reportComplete = false; + if ( + this._contentLength != null && + this._receivedLength < this._contentLength + ) { + // continue load next chunk + this._openSubRange(); + } else { + reportComplete = true; + } + // dispatch received chunk + if (this._onDataArrival) { + this._onDataArrival(chunk, byteStart, this._receivedLength); + } + if (reportComplete) { + this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_2__.LoaderStatus.kComplete; + if (this._onComplete) { + this._onComplete( + this._range.from, + this._range.from + this._receivedLength - 1 + ); + } + } + }; + RangeLoader.prototype._onXhrError = function (e) { + this._status = + _loader_js__WEBPACK_IMPORTED_MODULE_2__.LoaderStatus.kError; + var type = 0; + var info = null; + if ( + this._contentLength && + this._receivedLength > 0 && + this._receivedLength < this._contentLength + ) { + type = + _loader_js__WEBPACK_IMPORTED_MODULE_2__.LoaderErrors + .EARLY_EOF; + info = { code: -1, msg: "RangeLoader meet Early-Eof" }; + } else { + type = + _loader_js__WEBPACK_IMPORTED_MODULE_2__.LoaderErrors + .EXCEPTION; + info = { code: -1, msg: e.constructor.name + " " + e.type }; + } + if (this._onError) { + this._onError(type, info); + } else { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_3__.RuntimeException( + info.msg + ); + } + }; + return RangeLoader; + })(_loader_js__WEBPACK_IMPORTED_MODULE_2__.BaseLoader); + /* harmony default export */ __webpack_exports__["default"] = + RangeLoader; + + /***/ + }, + + /***/ "./src/player/flv-player.js": + /*!**********************************!*\ + !*** ./src/player/flv-player.js ***! + \**********************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony import */ var events__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__( + /*! events */ "./node_modules/events/events.js" + ); + /* harmony import */ var events__WEBPACK_IMPORTED_MODULE_0___default = + /*#__PURE__*/ __webpack_require__.n( + events__WEBPACK_IMPORTED_MODULE_0__ + ); + /* harmony import */ var _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__( + /*! ../utils/logger.js */ "./src/utils/logger.js" + ); + /* harmony import */ var _utils_browser_js__WEBPACK_IMPORTED_MODULE_2__ = + __webpack_require__( + /*! ../utils/browser.js */ "./src/utils/browser.js" + ); + /* harmony import */ var _player_events_js__WEBPACK_IMPORTED_MODULE_3__ = + __webpack_require__( + /*! ./player-events.js */ "./src/player/player-events.js" + ); + /* harmony import */ var _core_transmuxer_js__WEBPACK_IMPORTED_MODULE_4__ = + __webpack_require__( + /*! ../core/transmuxer.js */ "./src/core/transmuxer.js" + ); + /* harmony import */ var _core_transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__ = + __webpack_require__( + /*! ../core/transmuxing-events.js */ "./src/core/transmuxing-events.js" + ); + /* harmony import */ var _core_mse_controller_js__WEBPACK_IMPORTED_MODULE_6__ = + __webpack_require__( + /*! ../core/mse-controller.js */ "./src/core/mse-controller.js" + ); + /* harmony import */ var _core_mse_events_js__WEBPACK_IMPORTED_MODULE_7__ = + __webpack_require__( + /*! ../core/mse-events.js */ "./src/core/mse-events.js" + ); + /* harmony import */ var _player_errors_js__WEBPACK_IMPORTED_MODULE_8__ = + __webpack_require__( + /*! ./player-errors.js */ "./src/player/player-errors.js" + ); + /* harmony import */ var _config_js__WEBPACK_IMPORTED_MODULE_9__ = + __webpack_require__(/*! ../config.js */ "./src/config.js"); + /* harmony import */ var _utils_exception_js__WEBPACK_IMPORTED_MODULE_10__ = + __webpack_require__( + /*! ../utils/exception.js */ "./src/utils/exception.js" + ); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + var FlvPlayer = /** @class */ (function () { + function FlvPlayer(mediaDataSource, config) { + this.TAG = "FlvPlayer"; + this._type = "FlvPlayer"; + this._emitter = + new (events__WEBPACK_IMPORTED_MODULE_0___default())(); + this._config = (0, + _config_js__WEBPACK_IMPORTED_MODULE_9__.createDefaultConfig)(); + if (typeof config === "object") { + Object.assign(this._config, config); + } + if (mediaDataSource.type.toLowerCase() !== "flv") { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_10__.InvalidArgumentException( + "FlvPlayer requires an flv MediaDataSource input!" + ); + } + if (mediaDataSource.isLive === true) { + this._config.isLive = true; + } + this.e = { + onvLoadedMetadata: this._onvLoadedMetadata.bind(this), + onvSeeking: this._onvSeeking.bind(this), + onvCanPlay: this._onvCanPlay.bind(this), + onvStalled: this._onvStalled.bind(this), + onvProgress: this._onvProgress.bind(this), + }; + if (self.performance && self.performance.now) { + this._now = self.performance.now.bind(self.performance); + } else { + this._now = Date.now; + } + this._pendingSeekTime = null; // in seconds + this._requestSetTime = false; + this._seekpointRecord = null; + this._progressChecker = null; + this._mediaDataSource = mediaDataSource; + this._mediaElement = null; + this._msectl = null; + this._transmuxer = null; + this._mseSourceOpened = false; + this._hasPendingLoad = false; + this._receivedCanPlay = false; + this._mediaInfo = null; + this._statisticsInfo = null; + var chromeNeedIDRFix = + _utils_browser_js__WEBPACK_IMPORTED_MODULE_2__.default.chrome && + (_utils_browser_js__WEBPACK_IMPORTED_MODULE_2__.default.version + .major < 50 || + (_utils_browser_js__WEBPACK_IMPORTED_MODULE_2__.default + .version.major === 50 && + _utils_browser_js__WEBPACK_IMPORTED_MODULE_2__.default + .version.build < 2661)); + this._alwaysSeekKeyframe = + chromeNeedIDRFix || + _utils_browser_js__WEBPACK_IMPORTED_MODULE_2__.default.msedge || + _utils_browser_js__WEBPACK_IMPORTED_MODULE_2__.default.msie + ? true + : false; + if (this._alwaysSeekKeyframe) { + this._config.accurateSeek = false; + } + } + FlvPlayer.prototype.destroy = function () { + this._emitter.emit( + _player_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .DESTROYING + ); + if (this._progressChecker != null) { + window.clearInterval(this._progressChecker); + this._progressChecker = null; + } + if (this._transmuxer) { + this.unload(); + } + if (this._mediaElement) { + this.detachMediaElement(); + } + this.e = null; + this._mediaDataSource = null; + this._emitter.removeAllListeners(); + this._emitter = null; + }; + FlvPlayer.prototype.on = function (event, listener) { + var _this = this; + if ( + event === + _player_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .MEDIA_INFO + ) { + if (this._mediaInfo != null) { + Promise.resolve().then(function () { + _this._emitter.emit( + _player_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .MEDIA_INFO, + _this.mediaInfo + ); + }); + } + } else if ( + event === + _player_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .STATISTICS_INFO + ) { + if (this._statisticsInfo != null) { + Promise.resolve().then(function () { + _this._emitter.emit( + _player_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .STATISTICS_INFO, + _this.statisticsInfo + ); + }); + } + } + this._emitter.addListener(event, listener); + }; + FlvPlayer.prototype.off = function (event, listener) { + this._emitter.removeListener(event, listener); + }; + FlvPlayer.prototype.attachMediaElement = function (mediaElement) { + var _this = this; + this._mediaElement = mediaElement; + mediaElement.addEventListener( + "loadedmetadata", + this.e.onvLoadedMetadata + ); + mediaElement.addEventListener("seeking", this.e.onvSeeking); + mediaElement.addEventListener("canplay", this.e.onvCanPlay); + mediaElement.addEventListener("stalled", this.e.onvStalled); + mediaElement.addEventListener("progress", this.e.onvProgress); + this._msectl = + new _core_mse_controller_js__WEBPACK_IMPORTED_MODULE_6__.default( + this._config + ); + this._msectl.on( + _core_mse_events_js__WEBPACK_IMPORTED_MODULE_7__.default + .UPDATE_END, + this._onmseUpdateEnd.bind(this) + ); + this._msectl.on( + _core_mse_events_js__WEBPACK_IMPORTED_MODULE_7__.default + .BUFFER_FULL, + this._onmseBufferFull.bind(this) + ); + this._msectl.on( + _core_mse_events_js__WEBPACK_IMPORTED_MODULE_7__.default + .SOURCE_OPEN, + function () { + _this._mseSourceOpened = true; + if (_this._hasPendingLoad) { + _this._hasPendingLoad = false; + _this.load(); + } + } + ); + this._msectl.on( + _core_mse_events_js__WEBPACK_IMPORTED_MODULE_7__.default.ERROR, + function (info) { + _this._emitter.emit( + _player_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .ERROR, + _player_errors_js__WEBPACK_IMPORTED_MODULE_8__.ErrorTypes + .MEDIA_ERROR, + _player_errors_js__WEBPACK_IMPORTED_MODULE_8__.ErrorDetails + .MEDIA_MSE_ERROR, + info + ); + } + ); + this._msectl.attachMediaElement(mediaElement); + if (this._pendingSeekTime != null) { + try { + mediaElement.currentTime = this._pendingSeekTime; + this._pendingSeekTime = null; + } catch (e) { + // IE11 may throw InvalidStateError if readyState === 0 + // We can defer set currentTime operation after loadedmetadata + } + } + }; + FlvPlayer.prototype.detachMediaElement = function () { + if (this._mediaElement) { + this._msectl.detachMediaElement(); + this._mediaElement.removeEventListener( + "loadedmetadata", + this.e.onvLoadedMetadata + ); + this._mediaElement.removeEventListener( + "seeking", + this.e.onvSeeking + ); + this._mediaElement.removeEventListener( + "canplay", + this.e.onvCanPlay + ); + this._mediaElement.removeEventListener( + "stalled", + this.e.onvStalled + ); + this._mediaElement.removeEventListener( + "progress", + this.e.onvProgress + ); + this._mediaElement = null; + } + if (this._msectl) { + this._msectl.destroy(); + this._msectl = null; + } + }; + FlvPlayer.prototype.load = function () { + var _this = this; + if (!this._mediaElement) { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_10__.IllegalStateException( + "HTMLMediaElement must be attached before load()!" + ); + } + if (this._transmuxer) { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_10__.IllegalStateException( + "FlvPlayer.load() has been called, please call unload() first!" + ); + } + if (this._hasPendingLoad) { + return; + } + if ( + this._config.deferLoadAfterSourceOpen && + this._mseSourceOpened === false + ) { + this._hasPendingLoad = true; + return; + } + if (this._mediaElement.readyState > 0) { + // IE11 may throw InvalidStateError if readyState === 0 + this.directSeek(0); + } + this._transmuxer = + new _core_transmuxer_js__WEBPACK_IMPORTED_MODULE_4__.default( + this._mediaDataSource, + this._config + ); + this._transmuxer.on( + _core_transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .INIT_SEGMENT, + function (type, is) { + _this._msectl.appendInitSegment(is); + } + ); + this._transmuxer.on( + _core_transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .MEDIA_SEGMENT, + function (type, ms) { + _this._msectl.appendMediaSegment(ms); + // lazyLoad check + if (_this._config.lazyLoad && !_this._config.isLive) { + var currentTime = _this._mediaElement.currentTime; + if ( + ms.info.endDts >= + (currentTime + _this._config.lazyLoadMaxDuration) * 1000 + ) { + if (_this._progressChecker == null) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.v( + _this.TAG, + "Maximum buffering duration exceeded, suspend transmuxing task" + ); + _this._suspendTransmuxer(); + } + } + } + } + ); + this._transmuxer.on( + _core_transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .LOADING_COMPLETE, + function () { + _this._msectl.endOfStream(); + _this._emitter.emit( + _player_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .LOADING_COMPLETE + ); + } + ); + this._transmuxer.on( + _core_transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .RECOVERED_EARLY_EOF, + function () { + _this._emitter.emit( + _player_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .RECOVERED_EARLY_EOF + ); + } + ); + this._transmuxer.on( + _core_transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .IO_ERROR, + function (detail, info) { + _this._emitter.emit( + _player_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .ERROR, + _player_errors_js__WEBPACK_IMPORTED_MODULE_8__.ErrorTypes + .NETWORK_ERROR, + detail, + info + ); + } + ); + this._transmuxer.on( + _core_transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .DEMUX_ERROR, + function (detail, info) { + _this._emitter.emit( + _player_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .ERROR, + _player_errors_js__WEBPACK_IMPORTED_MODULE_8__.ErrorTypes + .MEDIA_ERROR, + detail, + { code: -1, msg: info } + ); + } + ); + this._transmuxer.on( + _core_transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .MEDIA_INFO, + function (mediaInfo) { + _this._mediaInfo = mediaInfo; + _this._emitter.emit( + _player_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .MEDIA_INFO, + Object.assign({}, mediaInfo) + ); + } + ); + this._transmuxer.on( + _core_transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .METADATA_ARRIVED, + function (metadata) { + _this._emitter.emit( + _player_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .METADATA_ARRIVED, + metadata + ); + } + ); + this._transmuxer.on( + _core_transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .SCRIPTDATA_ARRIVED, + function (data) { + _this._emitter.emit( + _player_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .SCRIPTDATA_ARRIVED, + data + ); + } + ); + this._transmuxer.on( + _core_transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .STATISTICS_INFO, + function (statInfo) { + _this._statisticsInfo = _this._fillStatisticsInfo(statInfo); + _this._emitter.emit( + _player_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .STATISTICS_INFO, + Object.assign({}, _this._statisticsInfo) + ); + } + ); + this._transmuxer.on( + _core_transmuxing_events_js__WEBPACK_IMPORTED_MODULE_5__.default + .RECOMMEND_SEEKPOINT, + function (milliseconds) { + if (_this._mediaElement && !_this._config.accurateSeek) { + _this.directSeek(milliseconds / 1000); + } + } + ); + this._transmuxer.open(); + }; + FlvPlayer.prototype.unload = function () { + if (this._mediaElement) { + this._mediaElement.pause(); + } + if (this._msectl) { + this._msectl.seek(0); + } + if (this._transmuxer) { + this._transmuxer.close(); + this._transmuxer.destroy(); + this._transmuxer = null; + } + }; + FlvPlayer.prototype.play = function () { + return this._mediaElement.play(); + }; + FlvPlayer.prototype.pause = function () { + this._mediaElement.pause(); + }; + Object.defineProperty(FlvPlayer.prototype, "type", { + get: function () { + return this._type; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(FlvPlayer.prototype, "buffered", { + get: function () { + return this._mediaElement.buffered; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(FlvPlayer.prototype, "duration", { + get: function () { + return this._mediaElement.duration; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(FlvPlayer.prototype, "volume", { + get: function () { + return this._mediaElement.volume; + }, + set: function (value) { + this._mediaElement.volume = value; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(FlvPlayer.prototype, "muted", { + get: function () { + return this._mediaElement.muted; + }, + set: function (muted) { + this._mediaElement.muted = muted; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(FlvPlayer.prototype, "speed", { + get: function () { + return this._mediaElement.playbackRate; + }, + set: function (speed) { + this._mediaElement.playbackRate = speed; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(FlvPlayer.prototype, "currentTime", { + get: function () { + if (this._mediaElement) { + return this._mediaElement.currentTime; + } + return 0; + }, + set: function (seconds) { + if (this._mediaElement) { + this._internalSeek(seconds); + } else { + this._pendingSeekTime = seconds; + } + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(FlvPlayer.prototype, "mediaInfo", { + get: function () { + return Object.assign({}, this._mediaInfo); + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(FlvPlayer.prototype, "statisticsInfo", { + get: function () { + if (this._statisticsInfo == null) { + this._statisticsInfo = {}; + } + this._statisticsInfo = this._fillStatisticsInfo( + this._statisticsInfo + ); + return Object.assign({}, this._statisticsInfo); + }, + enumerable: false, + configurable: true, + }); + FlvPlayer.prototype._fillStatisticsInfo = function (statInfo) { + statInfo.playerType = this._type; + if (!(this._mediaElement instanceof HTMLVideoElement)) { + return statInfo; + } + var hasQualityInfo = true; + var decoded = 0; + var dropped = 0; + if (this._mediaElement.getVideoPlaybackQuality) { + var quality = this._mediaElement.getVideoPlaybackQuality(); + decoded = quality.totalVideoFrames; + dropped = quality.droppedVideoFrames; + } else if ( + this._mediaElement.webkitDecodedFrameCount != undefined + ) { + decoded = this._mediaElement.webkitDecodedFrameCount; + dropped = this._mediaElement.webkitDroppedFrameCount; + } else { + hasQualityInfo = false; + } + if (hasQualityInfo) { + statInfo.decodedFrames = decoded; + statInfo.droppedFrames = dropped; + } + return statInfo; + }; + FlvPlayer.prototype._onmseUpdateEnd = function () { + if (!this._config.lazyLoad || this._config.isLive) { + return; + } + var buffered = this._mediaElement.buffered; + var currentTime = this._mediaElement.currentTime; + var currentRangeStart = 0; + var currentRangeEnd = 0; + for (var i = 0; i < buffered.length; i++) { + var start = buffered.start(i); + var end = buffered.end(i); + if (start <= currentTime && currentTime < end) { + currentRangeStart = start; + currentRangeEnd = end; + break; + } + } + if ( + currentRangeEnd >= + currentTime + this._config.lazyLoadMaxDuration && + this._progressChecker == null + ) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.v( + this.TAG, + "Maximum buffering duration exceeded, suspend transmuxing task" + ); + this._suspendTransmuxer(); + } + }; + FlvPlayer.prototype._onmseBufferFull = function () { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.v( + this.TAG, + "MSE SourceBuffer is full, suspend transmuxing task" + ); + if (this._progressChecker == null) { + this._suspendTransmuxer(); + } + }; + FlvPlayer.prototype._suspendTransmuxer = function () { + if (this._transmuxer) { + this._transmuxer.pause(); + if (this._progressChecker == null) { + this._progressChecker = window.setInterval( + this._checkProgressAndResume.bind(this), + 1000 + ); + } + } + }; + FlvPlayer.prototype._checkProgressAndResume = function () { + var currentTime = this._mediaElement.currentTime; + var buffered = this._mediaElement.buffered; + var needResume = false; + for (var i = 0; i < buffered.length; i++) { + var from = buffered.start(i); + var to = buffered.end(i); + if (currentTime >= from && currentTime < to) { + if ( + currentTime >= + to - this._config.lazyLoadRecoverDuration + ) { + needResume = true; + } + break; + } + } + if (needResume) { + window.clearInterval(this._progressChecker); + this._progressChecker = null; + if (needResume) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.v( + this.TAG, + "Continue loading from paused position" + ); + this._transmuxer.resume(); + } + } + }; + FlvPlayer.prototype._isTimepointBuffered = function (seconds) { + var buffered = this._mediaElement.buffered; + for (var i = 0; i < buffered.length; i++) { + var from = buffered.start(i); + var to = buffered.end(i); + if (seconds >= from && seconds < to) { + return true; + } + } + return false; + }; + FlvPlayer.prototype._internalSeek = function (seconds) { + var directSeek = this._isTimepointBuffered(seconds); + var directSeekBegin = false; + var directSeekBeginTime = 0; + if (seconds < 1.0 && this._mediaElement.buffered.length > 0) { + var videoBeginTime = this._mediaElement.buffered.start(0); + if ( + (videoBeginTime < 1.0 && seconds < videoBeginTime) || + _utils_browser_js__WEBPACK_IMPORTED_MODULE_2__.default.safari + ) { + directSeekBegin = true; + // also workaround for Safari: Seek to 0 may cause video stuck, use 0.1 to avoid + directSeekBeginTime = + _utils_browser_js__WEBPACK_IMPORTED_MODULE_2__.default + .safari + ? 0.1 + : videoBeginTime; + } + } + if (directSeekBegin) { + // seek to video begin, set currentTime directly if beginPTS buffered + this.directSeek(directSeekBeginTime); + } else if (directSeek) { + // buffered position + if (!this._alwaysSeekKeyframe) { + this.directSeek(seconds); + } else { + var idr = this._msectl.getNearestKeyframe( + Math.floor(seconds * 1000) + ); + if (idr != null) { + seconds = idr.dts / 1000; + } + this.directSeek(seconds); + } + if (this._progressChecker != null) { + this._checkProgressAndResume(); + } + } else { + if (this._progressChecker != null) { + window.clearInterval(this._progressChecker); + this._progressChecker = null; + } + this._msectl.seek(seconds); + this._transmuxer.seek(Math.floor(seconds * 1000)); // in milliseconds + // no need to set mediaElement.currentTime if non-accurateSeek, + // just wait for the recommend_seekpoint callback + if (this._config.accurateSeek) { + this.directSeek(seconds); + } + } + }; + FlvPlayer.prototype.directSeek = function (seconds) { + this._requestSetTime = true; + this._mediaElement.currentTime = seconds; + }; + FlvPlayer.prototype._checkAndApplyUnbufferedSeekpoint = + function () { + if (this._seekpointRecord) { + if (this._seekpointRecord.recordTime <= this._now() - 100) { + var target = this._mediaElement.currentTime; + this._seekpointRecord = null; + if (!this._isTimepointBuffered(target)) { + if (this._progressChecker != null) { + window.clearTimeout(this._progressChecker); + this._progressChecker = null; + } + // .currentTime is consists with .buffered timestamp + // Chrome/Edge use DTS, while FireFox/Safari use PTS + this._msectl.seek(target); + this._transmuxer.seek(Math.floor(target * 1000)); + // Update currentTime if using accurateSeek, or wait for recommend_seekpoint callback + if (this._config.accurateSeek) { + this.directSeek(target); + } + } + } else { + window.setTimeout( + this._checkAndApplyUnbufferedSeekpoint.bind(this), + 50 + ); + } + } + }; + FlvPlayer.prototype._checkAndResumeStuckPlayback = function ( + stalled + ) { + var media = this._mediaElement; + if (stalled || !this._receivedCanPlay || media.readyState < 2) { + // HAVE_CURRENT_DATA + var buffered = media.buffered; + if ( + buffered.length > 0 && + media.currentTime < buffered.start(0) + ) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_1__.default.w( + this.TAG, + "Playback seems stuck at " + + media.currentTime + + ", seek to " + + buffered.start(0) + ); + this.directSeek(buffered.start(0)); + //this._mediaElement.removeEventListener('progress', this.e.onvProgress); + } + } else { + // Playback didn't stuck, remove progress event listener + //this._mediaElement.removeEventListener('progress', this.e.onvProgress); + } + }; + FlvPlayer.prototype._onvLoadedMetadata = function (e) { + if (this._pendingSeekTime != null) { + this._mediaElement.currentTime = this._pendingSeekTime; + this._pendingSeekTime = null; + } + }; + // handle seeking request from browser's progress bar or HTMLMediaElement.currentTime setter + FlvPlayer.prototype._onvSeeking = function (e) { + if (this._requestSetTime) { + this._requestSetTime = false; + return; + } + var target = this._mediaElement.currentTime; + var buffered = this._mediaElement.buffered; + // Handle seeking to video begin (near 0.0s) + if (target < 1.0 && buffered.length > 0) { + // seek to video begin, set currentTime directly if beginPTS buffered + var videoBeginTime = buffered.start(0); + if ( + (videoBeginTime < 1.0 && target < videoBeginTime) || + _utils_browser_js__WEBPACK_IMPORTED_MODULE_2__.default.safari + ) { + // Safari may get stuck if currentTime set to 0, use 0.1 to avoid + var target_1 = _utils_browser_js__WEBPACK_IMPORTED_MODULE_2__ + .default.safari + ? 0.1 + : videoBeginTime; + this.directSeek(target_1); + return; + } + } + // Handle in-buffer seeking (usually nothing to do) + if (this._isTimepointBuffered(target)) { + if (this._alwaysSeekKeyframe) { + var idr = this._msectl.getNearestKeyframe( + Math.floor(target * 1000) + ); + if (idr != null) { + target = idr.dts / 1000; + this.directSeek(target); + } + } + if (this._progressChecker != null) { + this._checkProgressAndResume(); + } + return; + } + this._seekpointRecord = { + seekPoint: target, + recordTime: this._now(), + }; + window.setTimeout( + this._checkAndApplyUnbufferedSeekpoint.bind(this), + 50 + ); + }; + FlvPlayer.prototype._onvCanPlay = function (e) { + this._receivedCanPlay = true; + // Remove canplay listener since it will be fired multiple times + this._mediaElement.removeEventListener( + "canplay", + this.e.onvCanPlay + ); + }; + FlvPlayer.prototype._onvStalled = function (e) { + this._checkAndResumeStuckPlayback(true); + }; + FlvPlayer.prototype._onvProgress = function (e) { + var _this = this; + this._checkAndResumeStuckPlayback(); + Promise.resolve().then(function () { + _this._emitter.emit( + _player_events_js__WEBPACK_IMPORTED_MODULE_3__.default + .PROGRESS, + e + ); + }); + }; + return FlvPlayer; + })(); + /* harmony default export */ __webpack_exports__["default"] = + FlvPlayer; + + /***/ + }, + + /***/ "./src/player/native-player.js": + /*!*************************************!*\ + !*** ./src/player/native-player.js ***! + \*************************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony import */ var events__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__( + /*! events */ "./node_modules/events/events.js" + ); + /* harmony import */ var events__WEBPACK_IMPORTED_MODULE_0___default = + /*#__PURE__*/ __webpack_require__.n( + events__WEBPACK_IMPORTED_MODULE_0__ + ); + /* harmony import */ var _player_events_js__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__( + /*! ./player-events.js */ "./src/player/player-events.js" + ); + /* harmony import */ var _config_js__WEBPACK_IMPORTED_MODULE_2__ = + __webpack_require__(/*! ../config.js */ "./src/config.js"); + /* harmony import */ var _utils_exception_js__WEBPACK_IMPORTED_MODULE_3__ = + __webpack_require__( + /*! ../utils/exception.js */ "./src/utils/exception.js" + ); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + // Player wrapper for browser's native player (HTMLVideoElement) without MediaSource src. + var NativePlayer = /** @class */ (function () { + function NativePlayer(mediaDataSource, config) { + this.TAG = "NativePlayer"; + this._type = "NativePlayer"; + this._emitter = + new (events__WEBPACK_IMPORTED_MODULE_0___default())(); + this._config = (0, + _config_js__WEBPACK_IMPORTED_MODULE_2__.createDefaultConfig)(); + if (typeof config === "object") { + Object.assign(this._config, config); + } + if (mediaDataSource.type.toLowerCase() === "flv") { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_3__.InvalidArgumentException( + "NativePlayer does't support flv MediaDataSource input!" + ); + } + if (mediaDataSource.hasOwnProperty("segments")) { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_3__.InvalidArgumentException( + "NativePlayer(" + + mediaDataSource.type + + ") doesn't support multipart playback!" + ); + } + this.e = { + onvLoadedMetadata: this._onvLoadedMetadata.bind(this), + }; + this._pendingSeekTime = null; + this._statisticsReporter = null; + this._mediaDataSource = mediaDataSource; + this._mediaElement = null; + } + NativePlayer.prototype.destroy = function () { + this._emitter.emit( + _player_events_js__WEBPACK_IMPORTED_MODULE_1__.default + .DESTROYING + ); + if (this._mediaElement) { + this.unload(); + this.detachMediaElement(); + } + this.e = null; + this._mediaDataSource = null; + this._emitter.removeAllListeners(); + this._emitter = null; + }; + NativePlayer.prototype.on = function (event, listener) { + var _this = this; + if ( + event === + _player_events_js__WEBPACK_IMPORTED_MODULE_1__.default + .MEDIA_INFO + ) { + if ( + this._mediaElement != null && + this._mediaElement.readyState !== 0 + ) { + // HAVE_NOTHING + Promise.resolve().then(function () { + _this._emitter.emit( + _player_events_js__WEBPACK_IMPORTED_MODULE_1__.default + .MEDIA_INFO, + _this.mediaInfo + ); + }); + } + } else if ( + event === + _player_events_js__WEBPACK_IMPORTED_MODULE_1__.default + .STATISTICS_INFO + ) { + if ( + this._mediaElement != null && + this._mediaElement.readyState !== 0 + ) { + Promise.resolve().then(function () { + _this._emitter.emit( + _player_events_js__WEBPACK_IMPORTED_MODULE_1__.default + .STATISTICS_INFO, + _this.statisticsInfo + ); + }); + } + } + this._emitter.addListener(event, listener); + }; + NativePlayer.prototype.off = function (event, listener) { + this._emitter.removeListener(event, listener); + }; + NativePlayer.prototype.attachMediaElement = function ( + mediaElement + ) { + this._mediaElement = mediaElement; + mediaElement.addEventListener( + "loadedmetadata", + this.e.onvLoadedMetadata + ); + if (this._pendingSeekTime != null) { + try { + mediaElement.currentTime = this._pendingSeekTime; + this._pendingSeekTime = null; + } catch (e) { + // IE11 may throw InvalidStateError if readyState === 0 + // Defer set currentTime operation after loadedmetadata + } + } + }; + NativePlayer.prototype.detachMediaElement = function () { + if (this._mediaElement) { + this._mediaElement.src = ""; + this._mediaElement.removeAttribute("src"); + this._mediaElement.removeEventListener( + "loadedmetadata", + this.e.onvLoadedMetadata + ); + this._mediaElement = null; + } + if (this._statisticsReporter != null) { + window.clearInterval(this._statisticsReporter); + this._statisticsReporter = null; + } + }; + NativePlayer.prototype.load = function () { + if (!this._mediaElement) { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_3__.IllegalStateException( + "HTMLMediaElement must be attached before load()!" + ); + } + this._mediaElement.src = this._mediaDataSource.url; + if (this._mediaElement.readyState > 0) { + this._mediaElement.currentTime = 0; + } + this._mediaElement.preload = "auto"; + this._mediaElement.load(); + this._statisticsReporter = window.setInterval( + this._reportStatisticsInfo.bind(this), + this._config.statisticsInfoReportInterval + ); + }; + NativePlayer.prototype.unload = function () { + if (this._mediaElement) { + this._mediaElement.src = ""; + this._mediaElement.removeAttribute("src"); + } + if (this._statisticsReporter != null) { + window.clearInterval(this._statisticsReporter); + this._statisticsReporter = null; + } + }; + NativePlayer.prototype.play = function () { + return this._mediaElement.play(); + }; + NativePlayer.prototype.pause = function () { + this._mediaElement.pause(); + }; + Object.defineProperty(NativePlayer.prototype, "type", { + get: function () { + return this._type; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(NativePlayer.prototype, "buffered", { + get: function () { + return this._mediaElement.buffered; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(NativePlayer.prototype, "duration", { + get: function () { + return this._mediaElement.duration; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(NativePlayer.prototype, "volume", { + get: function () { + return this._mediaElement.volume; + }, + set: function (value) { + this._mediaElement.volume = value; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(NativePlayer.prototype, "muted", { + get: function () { + return this._mediaElement.muted; + }, + set: function (muted) { + this._mediaElement.muted = muted; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(NativePlayer.prototype, "speed", { + get: function () { + return this._mediaElement.playbackRate; + }, + set: function (speed) { + this._mediaElement.playbackRate = speed; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(NativePlayer.prototype, "currentTime", { + get: function () { + if (this._mediaElement) { + return this._mediaElement.currentTime; + } + return 0; + }, + set: function (seconds) { + if (this._mediaElement) { + this._mediaElement.currentTime = seconds; + } else { + this._pendingSeekTime = seconds; + } + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(NativePlayer.prototype, "mediaInfo", { + get: function () { + var mediaPrefix = + this._mediaElement instanceof HTMLAudioElement + ? "audio/" + : "video/"; + var info = { + mimeType: mediaPrefix + this._mediaDataSource.type, + }; + if (this._mediaElement) { + info.duration = Math.floor( + this._mediaElement.duration * 1000 + ); + if (this._mediaElement instanceof HTMLVideoElement) { + info.width = this._mediaElement.videoWidth; + info.height = this._mediaElement.videoHeight; + } + } + return info; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(NativePlayer.prototype, "statisticsInfo", { + get: function () { + var info = { + playerType: this._type, + url: this._mediaDataSource.url, + }; + if (!(this._mediaElement instanceof HTMLVideoElement)) { + return info; + } + var hasQualityInfo = true; + var decoded = 0; + var dropped = 0; + if (this._mediaElement.getVideoPlaybackQuality) { + var quality = this._mediaElement.getVideoPlaybackQuality(); + decoded = quality.totalVideoFrames; + dropped = quality.droppedVideoFrames; + } else if ( + this._mediaElement.webkitDecodedFrameCount != undefined + ) { + decoded = this._mediaElement.webkitDecodedFrameCount; + dropped = this._mediaElement.webkitDroppedFrameCount; + } else { + hasQualityInfo = false; + } + if (hasQualityInfo) { + info.decodedFrames = decoded; + info.droppedFrames = dropped; + } + return info; + }, + enumerable: false, + configurable: true, + }); + NativePlayer.prototype._onvLoadedMetadata = function (e) { + if (this._pendingSeekTime != null) { + this._mediaElement.currentTime = this._pendingSeekTime; + this._pendingSeekTime = null; + } + this._emitter.emit( + _player_events_js__WEBPACK_IMPORTED_MODULE_1__.default + .MEDIA_INFO, + this.mediaInfo + ); + }; + NativePlayer.prototype._reportStatisticsInfo = function () { + this._emitter.emit( + _player_events_js__WEBPACK_IMPORTED_MODULE_1__.default + .STATISTICS_INFO, + this.statisticsInfo + ); + }; + return NativePlayer; + })(); + /* harmony default export */ __webpack_exports__["default"] = + NativePlayer; + + /***/ + }, + + /***/ "./src/player/player-errors.js": + /*!*************************************!*\ + !*** ./src/player/player-errors.js ***! + \*************************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ ErrorTypes: function () { + return /* binding */ ErrorTypes; + }, + /* harmony export */ ErrorDetails: function () { + return /* binding */ ErrorDetails; + }, + /* harmony export */ + }); + /* harmony import */ var _io_loader_js__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__(/*! ../io/loader.js */ "./src/io/loader.js"); + /* harmony import */ var _demux_demux_errors_js__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__( + /*! ../demux/demux-errors.js */ "./src/demux/demux-errors.js" + ); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + var ErrorTypes = { + NETWORK_ERROR: "NetworkError", + MEDIA_ERROR: "MediaError", + OTHER_ERROR: "OtherError", + }; + var ErrorDetails = { + NETWORK_EXCEPTION: + _io_loader_js__WEBPACK_IMPORTED_MODULE_0__.LoaderErrors.EXCEPTION, + NETWORK_STATUS_CODE_INVALID: + _io_loader_js__WEBPACK_IMPORTED_MODULE_0__.LoaderErrors + .HTTP_STATUS_CODE_INVALID, + NETWORK_TIMEOUT: + _io_loader_js__WEBPACK_IMPORTED_MODULE_0__.LoaderErrors + .CONNECTING_TIMEOUT, + NETWORK_UNRECOVERABLE_EARLY_EOF: + _io_loader_js__WEBPACK_IMPORTED_MODULE_0__.LoaderErrors + .UNRECOVERABLE_EARLY_EOF, + MEDIA_MSE_ERROR: "MediaMSEError", + MEDIA_FORMAT_ERROR: + _demux_demux_errors_js__WEBPACK_IMPORTED_MODULE_1__.default + .FORMAT_ERROR, + MEDIA_FORMAT_UNSUPPORTED: + _demux_demux_errors_js__WEBPACK_IMPORTED_MODULE_1__.default + .FORMAT_UNSUPPORTED, + MEDIA_CODEC_UNSUPPORTED: + _demux_demux_errors_js__WEBPACK_IMPORTED_MODULE_1__.default + .CODEC_UNSUPPORTED, + }; + + /***/ + }, + + /***/ "./src/player/player-events.js": + /*!*************************************!*\ + !*** ./src/player/player-events.js ***! + \*************************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + var PlayerEvents = { + ERROR: "error", + LOADING_COMPLETE: "loading_complete", + RECOVERED_EARLY_EOF: "recovered_early_eof", + MEDIA_INFO: "media_info", + METADATA_ARRIVED: "metadata_arrived", + SCRIPTDATA_ARRIVED: "scriptdata_arrived", + STATISTICS_INFO: "statistics_info", + DESTROYING: "destroying", + PROGRESS: "progress", + }; + /* harmony default export */ __webpack_exports__["default"] = + PlayerEvents; + + /***/ + }, + + /***/ "./src/remux/aac-silent.js": + /*!*********************************!*\ + !*** ./src/remux/aac-silent.js ***! + \*********************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * This file is modified from dailymotion's hls.js library (hls.js/src/helper/aac.js) + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + var AAC = /** @class */ (function () { + function AAC() {} + AAC.getSilentFrame = function (codec, channelCount) { + if (codec === "mp4a.40.2") { + // handle LC-AAC + if (channelCount === 1) { + return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x23, 0x80]); + } else if (channelCount === 2) { + return new Uint8Array([ + 0x21, 0x00, 0x49, 0x90, 0x02, 0x19, 0x00, 0x23, 0x80, + ]); + } else if (channelCount === 3) { + return new Uint8Array([ + 0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, + 0x64, 0x00, 0x8e, + ]); + } else if (channelCount === 4) { + return new Uint8Array([ + 0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, + 0x64, 0x00, 0x80, 0x2c, 0x80, 0x08, 0x02, 0x38, + ]); + } else if (channelCount === 5) { + return new Uint8Array([ + 0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, + 0x64, 0x00, 0x82, 0x30, 0x04, 0x99, 0x00, 0x21, 0x90, 0x02, + 0x38, + ]); + } else if (channelCount === 6) { + 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, + ]); + } + } else { + // handle HE-AAC (mp4a.40.5 / mp4a.40.29) + if (channelCount === 1) { + // 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 + 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, + ]); + } else if (channelCount === 2) { + // 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 + 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, + ]); + } else if (channelCount === 3) { + // 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 + 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, + ]); + } + } + return null; + }; + return AAC; + })(); + /* harmony default export */ __webpack_exports__["default"] = AAC; + + /***/ + }, + + /***/ "./src/remux/mp4-generator.js": + /*!************************************!*\ + !*** ./src/remux/mp4-generator.js ***! + \************************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * This file is derived from dailymotion's hls.js library (hls.js/src/remux/mp4-generator.js) + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + var __spreadArray = + (undefined && undefined.__spreadArray) || + function (to, from) { + for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) + to[j] = from[i]; + return to; + }; + // MP4 boxes generator for ISO BMFF (ISO Base Media File Format, defined in ISO/IEC 14496-12) + var MP4 = /** @class */ (function () { + function MP4() {} + MP4.init = function () { + MP4.types = { + hvc1: [], + hvcC: [], + av01: [], + av1C: [], + avc1: [], + avcC: [], + btrt: [], + dinf: [], + dref: [], + esds: [], + ftyp: [], + hdlr: [], + mdat: [], + mdhd: [], + mdia: [], + mfhd: [], + minf: [], + moof: [], + moov: [], + mp4a: [], + mvex: [], + mvhd: [], + sdtp: [], + stbl: [], + stco: [], + stsc: [], + stsd: [], + stsz: [], + stts: [], + tfdt: [], + tfhd: [], + traf: [], + trak: [], + trun: [], + trex: [], + tkhd: [], + vmhd: [], + smhd: [], + pasp: [], + ".mp3": [], + Opus: [], + dOps: [], + }; + for (var name_1 in MP4.types) { + if (MP4.types.hasOwnProperty(name_1)) { + MP4.types[name_1] = [ + name_1.charCodeAt(0), + name_1.charCodeAt(1), + name_1.charCodeAt(2), + name_1.charCodeAt(3), + ]; + } + } + var constants = (MP4.constants = {}); + constants.FTYP = new Uint8Array([ + 0x69, + 0x73, + 0x6f, + 0x6d, + 0x0, + 0x0, + 0x0, + 0x1, + 0x69, + 0x73, + 0x6f, + 0x6d, + 0x61, + 0x76, + 0x63, + 0x31, // avc1 + ]); + constants.STSD_PREFIX = new Uint8Array([ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, // entry_count + ]); + constants.STTS = new Uint8Array([ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // entry_count + ]); + constants.STSC = constants.STCO = constants.STTS; + constants.STSZ = new Uint8Array([ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // sample_count + ]); + constants.HDLR_VIDEO = new Uint8Array([ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x76, + 0x69, + 0x64, + 0x65, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x56, + 0x69, + 0x64, + 0x65, + 0x6f, + 0x48, + 0x61, + 0x6e, + 0x64, + 0x6c, + 0x65, + 0x72, + 0x00, // name: VideoHandler + ]); + constants.HDLR_AUDIO = new Uint8Array([ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x73, + 0x6f, + 0x75, + 0x6e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x53, + 0x6f, + 0x75, + 0x6e, + 0x64, + 0x48, + 0x61, + 0x6e, + 0x64, + 0x6c, + 0x65, + 0x72, + 0x00, // name: SoundHandler + ]); + constants.DREF = new Uint8Array([ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x75, + 0x72, + 0x6c, + 0x20, + 0x00, + 0x00, + 0x00, + 0x01, // version(0) + flags + ]); + // Sound media header + constants.SMHD = new Uint8Array([ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // balance(2) + reserved(2) + ]); + // video media header + constants.VMHD = new Uint8Array([ + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + ]); + }; + // Generate a box + MP4.box = function (type) { + var size = 8; + var result = null; + var datas = Array.prototype.slice.call(arguments, 1); + var arrayCount = datas.length; + for (var i = 0; i < arrayCount; i++) { + size += datas[i].byteLength; + } + result = new Uint8Array(size); + result[0] = (size >>> 24) & 0xff; // size + result[1] = (size >>> 16) & 0xff; + result[2] = (size >>> 8) & 0xff; + result[3] = size & 0xff; + result.set(type, 4); // type + var offset = 8; + for (var i = 0; i < arrayCount; i++) { + // data body + result.set(datas[i], offset); + offset += datas[i].byteLength; + } + return result; + }; + // emit ftyp & moov + MP4.generateInitSegment = function (meta) { + var ftyp = MP4.box(MP4.types.ftyp, MP4.constants.FTYP); + var moov = MP4.moov(meta); + var result = new Uint8Array(ftyp.byteLength + moov.byteLength); + result.set(ftyp, 0); + result.set(moov, ftyp.byteLength); + return result; + }; + // Movie metadata box + MP4.moov = function (meta) { + var mvhd = MP4.mvhd(meta.timescale, meta.duration); + var trak = MP4.trak(meta); + var mvex = MP4.mvex(meta); + return MP4.box(MP4.types.moov, mvhd, trak, mvex); + }; + // Movie header box + MP4.mvhd = function (timescale, duration) { + return MP4.box( + MP4.types.mvhd, + new Uint8Array([ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + (timescale >>> 24) & 0xff, + (timescale >>> 16) & 0xff, + (timescale >>> 8) & 0xff, + timescale & 0xff, + (duration >>> 24) & 0xff, + (duration >>> 16) & 0xff, + (duration >>> 8) & 0xff, + duration & 0xff, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 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, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0xff, // next_track_ID + ]) + ); + }; + // Track box + MP4.trak = function (meta) { + return MP4.box(MP4.types.trak, MP4.tkhd(meta), MP4.mdia(meta)); + }; + // Track header box + MP4.tkhd = function (meta) { + var trackId = meta.id, + duration = meta.duration; + var width = meta.presentWidth, + height = meta.presentHeight; + return MP4.box( + MP4.types.tkhd, + new Uint8Array([ + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + (trackId >>> 24) & 0xff, + (trackId >>> 16) & 0xff, + (trackId >>> 8) & 0xff, + trackId & 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + (duration >>> 24) & 0xff, + (duration >>> 16) & 0xff, + (duration >>> 8) & 0xff, + duration & 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x00, + (width >>> 8) & 0xff, + width & 0xff, + 0x00, + 0x00, + (height >>> 8) & 0xff, + height & 0xff, + 0x00, + 0x00, + ]) + ); + }; + // Media Box + MP4.mdia = function (meta) { + return MP4.box( + MP4.types.mdia, + MP4.mdhd(meta), + MP4.hdlr(meta), + MP4.minf(meta) + ); + }; + // Media header box + MP4.mdhd = function (meta) { + var timescale = meta.timescale; + var duration = meta.duration; + return MP4.box( + MP4.types.mdhd, + new Uint8Array([ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + (timescale >>> 24) & 0xff, + (timescale >>> 16) & 0xff, + (timescale >>> 8) & 0xff, + timescale & 0xff, + (duration >>> 24) & 0xff, + (duration >>> 16) & 0xff, + (duration >>> 8) & 0xff, + duration & 0xff, + 0x55, + 0xc4, + 0x00, + 0x00, // pre_defined = 0 + ]) + ); + }; + // Media handler reference box + MP4.hdlr = function (meta) { + var data = null; + if (meta.type === "audio") { + data = MP4.constants.HDLR_AUDIO; + } else { + data = MP4.constants.HDLR_VIDEO; + } + return MP4.box(MP4.types.hdlr, data); + }; + // Media infomation box + MP4.minf = function (meta) { + var xmhd = null; + if (meta.type === "audio") { + xmhd = MP4.box(MP4.types.smhd, MP4.constants.SMHD); + } else { + xmhd = MP4.box(MP4.types.vmhd, MP4.constants.VMHD); + } + return MP4.box(MP4.types.minf, xmhd, MP4.dinf(), MP4.stbl(meta)); + }; + // Data infomation box + MP4.dinf = function () { + var result = MP4.box( + MP4.types.dinf, + MP4.box(MP4.types.dref, MP4.constants.DREF) + ); + return result; + }; + // Sample table box + MP4.stbl = function (meta) { + var result = MP4.box( + MP4.types.stbl, // type: stbl + MP4.stsd(meta), // Sample Description Table + MP4.box(MP4.types.stts, MP4.constants.STTS), // Time-To-Sample + MP4.box(MP4.types.stsc, MP4.constants.STSC), // Sample-To-Chunk + MP4.box(MP4.types.stsz, MP4.constants.STSZ), // Sample size + MP4.box(MP4.types.stco, MP4.constants.STCO) // Chunk offset + ); + return result; + }; + // Sample description box + MP4.stsd = function (meta) { + if (meta.type === "audio") { + if (meta.codec === "mp3") { + return MP4.box( + MP4.types.stsd, + MP4.constants.STSD_PREFIX, + MP4.mp3(meta) + ); + } else if (meta.codec === "opus") { + return MP4.box( + MP4.types.stsd, + MP4.constants.STSD_PREFIX, + MP4.Opus(meta) + ); + } + // else: aac -> mp4a + return MP4.box( + MP4.types.stsd, + MP4.constants.STSD_PREFIX, + MP4.mp4a(meta) + ); + } else { + // 'video' + if (meta.codec.startsWith("hvc1")) { + return MP4.box( + MP4.types.stsd, + MP4.constants.STSD_PREFIX, + MP4.hvc1(meta) + ); + } else if (meta.codec.startsWith("av01")) { + return MP4.box( + MP4.types.stsd, + MP4.constants.STSD_PREFIX, + MP4.av01(meta) + ); + } else { + return MP4.box( + MP4.types.stsd, + MP4.constants.STSD_PREFIX, + MP4.avc1(meta) + ); + } + } + }; + MP4.mp3 = function (meta) { + var channelCount = meta.channelCount; + var sampleRate = meta.audioSampleRate; + var data = new Uint8Array([ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + channelCount, + 0x00, + 0x10, + 0x00, + 0x00, + 0x00, + 0x00, + (sampleRate >>> 8) & 0xff, + sampleRate & 0xff, + 0x00, + 0x00, + ]); + return MP4.box(MP4.types[".mp3"], data); + }; + MP4.mp4a = function (meta) { + var channelCount = meta.channelCount; + var sampleRate = meta.audioSampleRate; + var data = new Uint8Array([ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + channelCount, + 0x00, + 0x10, + 0x00, + 0x00, + 0x00, + 0x00, + (sampleRate >>> 8) & 0xff, + sampleRate & 0xff, + 0x00, + 0x00, + ]); + return MP4.box(MP4.types.mp4a, data, MP4.esds(meta)); + }; + MP4.Opus = function (meta) { + var channelCount = meta.channelCount; + var sampleRate = meta.audioSampleRate; + var data = new Uint8Array([ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + channelCount, + 0x00, + 0x10, + 0x00, + 0x00, + 0x00, + 0x00, + (sampleRate >>> 8) & 0xff, + sampleRate & 0xff, + 0x00, + 0x00, + ]); + return MP4.box(MP4.types.Opus, data, MP4.dOps(meta)); + }; + MP4.dOps = function (meta) { + var channelCount = meta.channelCount; + var channelConfigCode = meta.channelConfigCode; + var sampleRate = meta.audioSampleRate; + if (meta.config) { + return MP4.box(MP4.types.dOps, meta.config); + } + var mapping = []; + switch (channelConfigCode) { + case 0x01: + case 0x02: + mapping = [0x0]; + break; + case 0x00: // dualmono + mapping = [0xff, 1, 1, 0, 1]; + break; + case 0x80: // dualmono + mapping = [0xff, 2, 0, 0, 1]; + break; + case 0x03: + mapping = [0x01, 2, 1, 0, 2, 1]; + break; + case 0x04: + mapping = [0x01, 2, 2, 0, 1, 2, 3]; + break; + case 0x05: + mapping = [0x01, 3, 2, 0, 4, 1, 2, 3]; + break; + case 0x06: + mapping = [0x01, 4, 2, 0, 4, 1, 2, 3, 5]; + break; + case 0x07: + mapping = [0x01, 4, 2, 0, 4, 1, 2, 3, 5, 6]; + break; + case 0x08: + mapping = [0x01, 5, 3, 0, 6, 1, 2, 3, 4, 5, 7]; + break; + case 0x82: + mapping = [0x01, 1, 2, 0, 1]; + break; + case 0x83: + mapping = [0x01, 1, 3, 0, 1, 2]; + break; + case 0x84: + mapping = [0x01, 1, 4, 0, 1, 2, 3]; + break; + case 0x85: + mapping = [0x01, 1, 5, 0, 1, 2, 3, 4]; + break; + case 0x86: + mapping = [0x01, 1, 6, 0, 1, 2, 3, 4, 5]; + break; + case 0x87: + mapping = [0x01, 1, 7, 0, 1, 2, 3, 4, 5, 6]; + break; + case 0x88: + mapping = [0x01, 1, 8, 0, 1, 2, 3, 4, 5, 6, 7]; + break; + } + var data = new Uint8Array( + __spreadArray( + [ + 0x00, + channelCount, + 0x00, + 0x00, + (sampleRate >>> 24) & 0xff, + (sampleRate >>> 17) & 0xff, + (sampleRate >>> 8) & 0xff, + (sampleRate >>> 0) & 0xff, + 0x00, + 0x00, + ], + mapping + ) + ); + return MP4.box(MP4.types.dOps, data); + }; + MP4.esds = function (meta) { + var config = meta.config || []; + var configSize = config.length; + var data = new Uint8Array( + [ + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x17 + configSize, + 0x00, + 0x01, + 0x00, + 0x04, + 0x0f + configSize, + 0x40, + 0x15, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x05, // descriptor_type + ] + .concat([configSize]) + .concat(config) + .concat([ + 0x06, + 0x01, + 0x02, // GASpecificConfig + ]) + ); + return MP4.box(MP4.types.esds, data); + }; + MP4.avc1 = function (meta) { + var avcc = meta.avcc; + var width = meta.codecWidth, + height = meta.codecHeight; + var data = new Uint8Array([ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + (width >>> 8) & 0xff, + width & 0xff, + (height >>> 8) & 0xff, + height & 0xff, + 0x00, + 0x48, + 0x00, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x0a, + 0x78, + 0x71, + 0x71, + 0x2f, + 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, + 0xff, + 0xff, // pre_defined = -1 + ]); + return MP4.box( + MP4.types.avc1, + data, + MP4.box(MP4.types.avcC, avcc) + ); + }; + MP4.hvc1 = function (meta) { + var hvcc = meta.hvcc; + var width = meta.codecWidth, + height = meta.codecHeight; + var data = new Uint8Array([ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + (width >>> 8) & 0xff, + width & 0xff, + (height >>> 8) & 0xff, + height & 0xff, + 0x00, + 0x48, + 0x00, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x0a, + 0x78, + 0x71, + 0x71, + 0x2f, + 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, + 0xff, + 0xff, // pre_defined = -1 + ]); + return MP4.box( + MP4.types.hvc1, + data, + MP4.box(MP4.types.hvcC, hvcc) + ); + }; + MP4.av01 = function (meta) { + var av1c = meta.av1c; + var width = meta.codecWidth || 192, + height = meta.codecHeight || 108; + var data = new Uint8Array([ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + (width >>> 8) & 0xff, + width & 0xff, + (height >>> 8) & 0xff, + height & 0xff, + 0x00, + 0x48, + 0x00, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x0a, + 0x78, + 0x71, + 0x71, + 0x2f, + 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, + 0xff, + 0xff, // pre_defined = -1 + ]); + return MP4.box( + MP4.types.av01, + data, + MP4.box(MP4.types.av1C, av1c) + ); + }; + // Movie Extends box + MP4.mvex = function (meta) { + return MP4.box(MP4.types.mvex, MP4.trex(meta)); + }; + // Track Extends box + MP4.trex = function (meta) { + var trackId = meta.id; + var data = new Uint8Array([ + 0x00, + 0x00, + 0x00, + 0x00, + (trackId >>> 24) & 0xff, + (trackId >>> 16) & 0xff, + (trackId >>> 8) & 0xff, + trackId & 0xff, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x01, // default_sample_flags + ]); + return MP4.box(MP4.types.trex, data); + }; + // Movie fragment box + MP4.moof = function (track, baseMediaDecodeTime) { + return MP4.box( + MP4.types.moof, + MP4.mfhd(track.sequenceNumber), + MP4.traf(track, baseMediaDecodeTime) + ); + }; + MP4.mfhd = function (sequenceNumber) { + var data = new Uint8Array([ + 0x00, + 0x00, + 0x00, + 0x00, + (sequenceNumber >>> 24) & 0xff, + (sequenceNumber >>> 16) & 0xff, + (sequenceNumber >>> 8) & 0xff, + sequenceNumber & 0xff, + ]); + return MP4.box(MP4.types.mfhd, data); + }; + // Track fragment box + MP4.traf = function (track, baseMediaDecodeTime) { + var trackId = track.id; + // Track fragment header box + var tfhd = MP4.box( + MP4.types.tfhd, + new Uint8Array([ + 0x00, + 0x00, + 0x00, + 0x00, + (trackId >>> 24) & 0xff, + (trackId >>> 16) & 0xff, + (trackId >>> 8) & 0xff, + trackId & 0xff, + ]) + ); + // Track Fragment Decode Time + var tfdt = MP4.box( + MP4.types.tfdt, + new Uint8Array([ + 0x00, + 0x00, + 0x00, + 0x00, + (baseMediaDecodeTime >>> 24) & 0xff, + (baseMediaDecodeTime >>> 16) & 0xff, + (baseMediaDecodeTime >>> 8) & 0xff, + baseMediaDecodeTime & 0xff, + ]) + ); + var sdtp = MP4.sdtp(track); + var trun = MP4.trun( + track, + sdtp.byteLength + 16 + 16 + 8 + 16 + 8 + 8 + ); + return MP4.box(MP4.types.traf, tfhd, tfdt, trun, sdtp); + }; + // Sample Dependency Type box + MP4.sdtp = function (track) { + var samples = track.samples || []; + var sampleCount = samples.length; + var data = new Uint8Array(4 + sampleCount); + // 0~4 bytes: version(0) & flags + for (var i = 0; i < sampleCount; i++) { + var flags = samples[i].flags; + data[i + 4] = + (flags.isLeading << 6) | // is_leading: 2 (bit) + (flags.dependsOn << 4) | // sample_depends_on + (flags.isDependedOn << 2) | // sample_is_depended_on + flags.hasRedundancy; // sample_has_redundancy + } + return MP4.box(MP4.types.sdtp, data); + }; + // Track fragment run box + MP4.trun = function (track, offset) { + var samples = track.samples || []; + var sampleCount = samples.length; + var dataSize = 12 + 16 * sampleCount; + var data = new Uint8Array(dataSize); + offset += 8 + dataSize; + data.set( + [ + 0x00, + 0x00, + 0x0f, + 0x01, + (sampleCount >>> 24) & 0xff, + (sampleCount >>> 16) & 0xff, + (sampleCount >>> 8) & 0xff, + sampleCount & 0xff, + (offset >>> 24) & 0xff, + (offset >>> 16) & 0xff, + (offset >>> 8) & 0xff, + offset & 0xff, + ], + 0 + ); + for (var i = 0; i < sampleCount; i++) { + var duration = samples[i].duration; + var size = samples[i].size; + var flags = samples[i].flags; + var cts = samples[i].cts; + data.set( + [ + (duration >>> 24) & 0xff, + (duration >>> 16) & 0xff, + (duration >>> 8) & 0xff, + duration & 0xff, + (size >>> 24) & 0xff, + (size >>> 16) & 0xff, + (size >>> 8) & 0xff, + size & 0xff, + (flags.isLeading << 2) | flags.dependsOn, + (flags.isDependedOn << 6) | + (flags.hasRedundancy << 4) | + flags.isNonSync, + 0x00, + 0x00, + (cts >>> 24) & 0xff, + (cts >>> 16) & 0xff, + (cts >>> 8) & 0xff, + cts & 0xff, + ], + 12 + 16 * i + ); + } + return MP4.box(MP4.types.trun, data); + }; + MP4.mdat = function (data) { + return MP4.box(MP4.types.mdat, data); + }; + return MP4; + })(); + MP4.init(); + /* harmony default export */ __webpack_exports__["default"] = MP4; + + /***/ + }, + + /***/ "./src/remux/mp4-remuxer.js": + /*!**********************************!*\ + !*** ./src/remux/mp4-remuxer.js ***! + \**********************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony import */ var _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__( + /*! ../utils/logger.js */ "./src/utils/logger.js" + ); + /* harmony import */ var _mp4_generator_js__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__( + /*! ./mp4-generator.js */ "./src/remux/mp4-generator.js" + ); + /* harmony import */ var _aac_silent_js__WEBPACK_IMPORTED_MODULE_2__ = + __webpack_require__( + /*! ./aac-silent.js */ "./src/remux/aac-silent.js" + ); + /* harmony import */ var _utils_browser_js__WEBPACK_IMPORTED_MODULE_3__ = + __webpack_require__( + /*! ../utils/browser.js */ "./src/utils/browser.js" + ); + /* harmony import */ var _core_media_segment_info_js__WEBPACK_IMPORTED_MODULE_4__ = + __webpack_require__( + /*! ../core/media-segment-info.js */ "./src/core/media-segment-info.js" + ); + /* harmony import */ var _utils_exception_js__WEBPACK_IMPORTED_MODULE_5__ = + __webpack_require__( + /*! ../utils/exception.js */ "./src/utils/exception.js" + ); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + // Fragmented mp4 remuxer + var MP4Remuxer = /** @class */ (function () { + function MP4Remuxer(config) { + this.TAG = "MP4Remuxer"; + this._config = config; + this._isLive = config.isLive === true ? true : false; + this._dtsBase = -1; + this._dtsBaseInited = false; + this._audioDtsBase = Infinity; + this._videoDtsBase = Infinity; + this._audioNextDts = undefined; + this._videoNextDts = undefined; + this._audioStashedLastSample = null; + this._videoStashedLastSample = null; + this._audioMeta = null; + this._videoMeta = null; + this._audioSegmentInfoList = + new _core_media_segment_info_js__WEBPACK_IMPORTED_MODULE_4__.MediaSegmentInfoList( + "audio" + ); + this._videoSegmentInfoList = + new _core_media_segment_info_js__WEBPACK_IMPORTED_MODULE_4__.MediaSegmentInfoList( + "video" + ); + this._onInitSegment = null; + this._onMediaSegment = null; + // Workaround for chrome < 50: Always force first sample as a Random Access Point in media segment + // see https://bugs.chromium.org/p/chromium/issues/detail?id=229412 + this._forceFirstIDR = + _utils_browser_js__WEBPACK_IMPORTED_MODULE_3__.default.chrome && + (_utils_browser_js__WEBPACK_IMPORTED_MODULE_3__.default.version + .major < 50 || + (_utils_browser_js__WEBPACK_IMPORTED_MODULE_3__.default + .version.major === 50 && + _utils_browser_js__WEBPACK_IMPORTED_MODULE_3__.default + .version.build < 2661)) + ? true + : false; + // Workaround for IE11/Edge: Fill silent aac frame after keyframe-seeking + // Make audio beginDts equals with video beginDts, in order to fix seek freeze + this._fillSilentAfterSeek = + _utils_browser_js__WEBPACK_IMPORTED_MODULE_3__.default.msedge || + _utils_browser_js__WEBPACK_IMPORTED_MODULE_3__.default.msie; + // While only FireFox supports 'audio/mp4, codecs="mp3"', use 'audio/mpeg' for chrome, safari, ... + this._mp3UseMpegAudio = + !_utils_browser_js__WEBPACK_IMPORTED_MODULE_3__.default.firefox; + this._fillAudioTimestampGap = this._config.fixAudioTimestampGap; + } + MP4Remuxer.prototype.destroy = function () { + this._dtsBase = -1; + this._dtsBaseInited = false; + this._audioMeta = null; + this._videoMeta = null; + this._audioSegmentInfoList.clear(); + this._audioSegmentInfoList = null; + this._videoSegmentInfoList.clear(); + this._videoSegmentInfoList = null; + this._onInitSegment = null; + this._onMediaSegment = null; + }; + MP4Remuxer.prototype.bindDataSource = function (producer) { + producer.onDataAvailable = this.remux.bind(this); + producer.onTrackMetadata = + this._onTrackMetadataReceived.bind(this); + return this; + }; + Object.defineProperty(MP4Remuxer.prototype, "onInitSegment", { + /* prototype: function onInitSegment(type: string, initSegment: ArrayBuffer): void + InitSegment: { + type: string, + data: ArrayBuffer, + codec: string, + container: string + } + */ + get: function () { + return this._onInitSegment; + }, + set: function (callback) { + this._onInitSegment = callback; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(MP4Remuxer.prototype, "onMediaSegment", { + /* prototype: function onMediaSegment(type: string, mediaSegment: MediaSegment): void + MediaSegment: { + type: string, + data: ArrayBuffer, + sampleCount: int32 + info: MediaSegmentInfo + } + */ + get: function () { + return this._onMediaSegment; + }, + set: function (callback) { + this._onMediaSegment = callback; + }, + enumerable: false, + configurable: true, + }); + MP4Remuxer.prototype.insertDiscontinuity = function () { + this._audioNextDts = this._videoNextDts = undefined; + }; + MP4Remuxer.prototype.seek = function (originalDts) { + this._audioStashedLastSample = null; + this._videoStashedLastSample = null; + this._videoSegmentInfoList.clear(); + this._audioSegmentInfoList.clear(); + }; + MP4Remuxer.prototype.remux = function (audioTrack, videoTrack) { + if (!this._onMediaSegment) { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_5__.IllegalStateException( + "MP4Remuxer: onMediaSegment callback must be specificed!" + ); + } + if (!this._dtsBaseInited) { + this._calculateDtsBase(audioTrack, videoTrack); + } + if (videoTrack) { + this._remuxVideo(videoTrack); + } + if (audioTrack) { + this._remuxAudio(audioTrack); + } + }; + MP4Remuxer.prototype._onTrackMetadataReceived = function ( + type, + metadata + ) { + var metabox = null; + var container = "mp4"; + var codec = metadata.codec; + if (type === "audio") { + this._audioMeta = metadata; + if (metadata.codec === "mp3" && this._mp3UseMpegAudio) { + // 'audio/mpeg' for MP3 audio track + container = "mpeg"; + codec = ""; + metabox = new Uint8Array(); + } else { + // 'audio/mp4, codecs="codec"' + metabox = + _mp4_generator_js__WEBPACK_IMPORTED_MODULE_1__.default.generateInitSegment( + metadata + ); + } + } else if (type === "video") { + this._videoMeta = metadata; + metabox = + _mp4_generator_js__WEBPACK_IMPORTED_MODULE_1__.default.generateInitSegment( + metadata + ); + } else { + return; + } + // dispatch metabox (Initialization Segment) + if (!this._onInitSegment) { + throw new _utils_exception_js__WEBPACK_IMPORTED_MODULE_5__.IllegalStateException( + "MP4Remuxer: onInitSegment callback must be specified!" + ); + } + this._onInitSegment(type, { + type: type, + data: metabox.buffer, + codec: codec, + container: type + "/" + container, + mediaDuration: metadata.duration, // in timescale 1000 (milliseconds) + }); + }; + MP4Remuxer.prototype._calculateDtsBase = function ( + audioTrack, + videoTrack + ) { + if (this._dtsBaseInited) { + return; + } + if ( + audioTrack && + audioTrack.samples && + audioTrack.samples.length + ) { + this._audioDtsBase = audioTrack.samples[0].dts; + } + if ( + videoTrack && + videoTrack.samples && + videoTrack.samples.length + ) { + this._videoDtsBase = videoTrack.samples[0].dts; + } + this._dtsBase = Math.min(this._audioDtsBase, this._videoDtsBase); + this._dtsBaseInited = true; + }; + MP4Remuxer.prototype.getTimestampBase = function () { + if (!this._dtsBaseInited) { + return undefined; + } + return this._dtsBase; + }; + MP4Remuxer.prototype.flushStashedSamples = function () { + var videoSample = this._videoStashedLastSample; + var audioSample = this._audioStashedLastSample; + var videoTrack = { + type: "video", + id: 1, + sequenceNumber: 0, + samples: [], + length: 0, + }; + if (videoSample != null) { + videoTrack.samples.push(videoSample); + videoTrack.length = videoSample.length; + } + var audioTrack = { + type: "audio", + id: 2, + sequenceNumber: 0, + samples: [], + length: 0, + }; + if (audioSample != null) { + audioTrack.samples.push(audioSample); + audioTrack.length = audioSample.length; + } + this._videoStashedLastSample = null; + this._audioStashedLastSample = null; + this._remuxVideo(videoTrack, true); + this._remuxAudio(audioTrack, true); + }; + MP4Remuxer.prototype._remuxAudio = function (audioTrack, force) { + if (this._audioMeta == null) { + return; + } + var track = audioTrack; + var samples = track.samples; + var dtsCorrection = undefined; + var firstDts = -1, + lastDts = -1, + lastPts = -1; + var refSampleDuration = this._audioMeta.refSampleDuration; + var mpegRawTrack = + this._audioMeta.codec === "mp3" && this._mp3UseMpegAudio; + var firstSegmentAfterSeek = + this._dtsBaseInited && this._audioNextDts === undefined; + var insertPrefixSilentFrame = false; + if (!samples || samples.length === 0) { + return; + } + if (samples.length === 1 && !force) { + // If [sample count in current batch] === 1 && (force != true) + // Ignore and keep in demuxer's queue + return; + } // else if (force === true) do remux + var offset = 0; + var mdatbox = null; + var mdatBytes = 0; + // calculate initial mdat size + if (mpegRawTrack) { + // for raw mpeg buffer + offset = 0; + mdatBytes = track.length; + } else { + // for fmp4 mdat box + offset = 8; // size + type + mdatBytes = 8 + track.length; + } + var lastSample = null; + // Pop the lastSample and waiting for stash + if (samples.length > 1) { + lastSample = samples.pop(); + mdatBytes -= lastSample.length; + } + // Insert [stashed lastSample in the previous batch] to the front + if (this._audioStashedLastSample != null) { + var sample = this._audioStashedLastSample; + this._audioStashedLastSample = null; + samples.unshift(sample); + mdatBytes += sample.length; + } + // Stash the lastSample of current batch, waiting for next batch + if (lastSample != null) { + this._audioStashedLastSample = lastSample; + } + var firstSampleOriginalDts = samples[0].dts - this._dtsBase; + // calculate dtsCorrection + if (this._audioNextDts) { + dtsCorrection = firstSampleOriginalDts - this._audioNextDts; + } else { + // this._audioNextDts == undefined + if (this._audioSegmentInfoList.isEmpty()) { + dtsCorrection = 0; + if ( + this._fillSilentAfterSeek && + !this._videoSegmentInfoList.isEmpty() + ) { + if (this._audioMeta.originalCodec !== "mp3") { + insertPrefixSilentFrame = true; + } + } + } else { + var lastSample_1 = + this._audioSegmentInfoList.getLastSampleBefore( + firstSampleOriginalDts + ); + if (lastSample_1 != null) { + var distance = + firstSampleOriginalDts - + (lastSample_1.originalDts + lastSample_1.duration); + if (distance <= 3) { + distance = 0; + } + var expectedDts = + lastSample_1.dts + lastSample_1.duration + distance; + dtsCorrection = firstSampleOriginalDts - expectedDts; + } else { + // lastSample == null, cannot found + dtsCorrection = 0; + } + } + } + if (insertPrefixSilentFrame) { + // align audio segment beginDts to match with current video segment's beginDts + var firstSampleDts = firstSampleOriginalDts - dtsCorrection; + var videoSegment = + this._videoSegmentInfoList.getLastSegmentBefore( + firstSampleOriginalDts + ); + if ( + videoSegment != null && + videoSegment.beginDts < firstSampleDts + ) { + var silentUnit = + _aac_silent_js__WEBPACK_IMPORTED_MODULE_2__.default.getSilentFrame( + this._audioMeta.originalCodec, + this._audioMeta.channelCount + ); + if (silentUnit) { + var dts = videoSegment.beginDts; + var silentFrameDuration = + firstSampleDts - videoSegment.beginDts; + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.v( + this.TAG, + "InsertPrefixSilentAudio: dts: " + + dts + + ", duration: " + + silentFrameDuration + ); + samples.unshift({ unit: silentUnit, dts: dts, pts: dts }); + mdatBytes += silentUnit.byteLength; + } // silentUnit == null: Cannot generate, skip + } else { + insertPrefixSilentFrame = false; + } + } + var mp4Samples = []; + // Correct dts for each sample, and calculate sample duration. Then output to mp4Samples + for (var i = 0; i < samples.length; i++) { + var sample = samples[i]; + var unit = sample.unit; + var originalDts = sample.dts - this._dtsBase; + var dts = originalDts; + var needFillSilentFrames = false; + var silentFrames = null; + var sampleDuration = 0; + if (originalDts < -0.001) { + continue; //pass the first sample with the invalid dts + } + if ( + this._audioMeta.codec !== "mp3" && + refSampleDuration != null + ) { + // for AAC codec, we need to keep dts increase based on refSampleDuration + var curRefDts = originalDts; + var maxAudioFramesDrift = 3; + if (this._audioNextDts) { + curRefDts = this._audioNextDts; + } + dtsCorrection = originalDts - curRefDts; + if ( + dtsCorrection <= + -maxAudioFramesDrift * refSampleDuration + ) { + // If we're overlapping by more than maxAudioFramesDrift number of frame, drop this sample + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Dropping 1 audio frame (originalDts: " + + originalDts + + " ms ,curRefDts: " + + curRefDts + + " ms) due to dtsCorrection: " + + dtsCorrection + + " ms overlap." + ); + continue; + } else if ( + dtsCorrection >= maxAudioFramesDrift * refSampleDuration && + this._fillAudioTimestampGap && + !_utils_browser_js__WEBPACK_IMPORTED_MODULE_3__.default + .safari + ) { + // Silent frame generation, if large timestamp gap detected && config.fixAudioTimestampGap + needFillSilentFrames = true; + // We need to insert silent frames to fill timestamp gap + var frameCount = Math.floor( + dtsCorrection / refSampleDuration + ); + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Large audio timestamp gap detected, may cause AV sync to drift. " + + "Silent frames will be generated to avoid unsync.\n" + + ("originalDts: " + + originalDts + + " ms, curRefDts: " + + curRefDts + + " ms, ") + + ("dtsCorrection: " + + Math.round(dtsCorrection) + + " ms, generate: " + + frameCount + + " frames") + ); + dts = Math.floor(curRefDts); + sampleDuration = + Math.floor(curRefDts + refSampleDuration) - dts; + var silentUnit = + _aac_silent_js__WEBPACK_IMPORTED_MODULE_2__.default.getSilentFrame( + this._audioMeta.originalCodec, + this._audioMeta.channelCount + ); + if (silentUnit == null) { + _utils_logger_js__WEBPACK_IMPORTED_MODULE_0__.default.w( + this.TAG, + "Unable to generate silent frame for " + + (this._audioMeta.originalCodec + + " with " + + this._audioMeta.channelCount + + " channels, repeat last frame") + ); + // Repeat last frame + silentUnit = unit; + } + silentFrames = []; + for (var j = 0; j < frameCount; j++) { + curRefDts = curRefDts + refSampleDuration; + var intDts = Math.floor(curRefDts); // change to integer + var intDuration = + Math.floor(curRefDts + refSampleDuration) - intDts; + var frame = { + dts: intDts, + pts: intDts, + cts: 0, + unit: silentUnit, + size: silentUnit.byteLength, + duration: intDuration, + originalDts: originalDts, + flags: { + isLeading: 0, + dependsOn: 1, + isDependedOn: 0, + hasRedundancy: 0, + }, + }; + silentFrames.push(frame); + mdatBytes += frame.size; + } + this._audioNextDts = curRefDts + refSampleDuration; + } else { + dts = Math.floor(curRefDts); + sampleDuration = + Math.floor(curRefDts + refSampleDuration) - dts; + this._audioNextDts = curRefDts + refSampleDuration; + } + } else { + // keep the original dts calculate algorithm for mp3 + dts = originalDts - dtsCorrection; + if (i !== samples.length - 1) { + var nextDts = + samples[i + 1].dts - this._dtsBase - dtsCorrection; + sampleDuration = nextDts - dts; + } else { + // the last sample + if (lastSample != null) { + // use stashed sample's dts to calculate sample duration + var nextDts = + lastSample.dts - this._dtsBase - dtsCorrection; + sampleDuration = nextDts - dts; + } else if (mp4Samples.length >= 1) { + // use second last sample duration + sampleDuration = + mp4Samples[mp4Samples.length - 1].duration; + } else { + // the only one sample, use reference sample duration + sampleDuration = Math.floor(refSampleDuration); + } + } + this._audioNextDts = dts + sampleDuration; + } + if (firstDts === -1) { + firstDts = dts; + } + mp4Samples.push({ + dts: dts, + pts: dts, + cts: 0, + unit: sample.unit, + size: sample.unit.byteLength, + duration: sampleDuration, + originalDts: originalDts, + flags: { + isLeading: 0, + dependsOn: 1, + isDependedOn: 0, + hasRedundancy: 0, + }, + }); + if (needFillSilentFrames) { + // Silent frames should be inserted after wrong-duration frame + mp4Samples.push.apply(mp4Samples, silentFrames); + } + } + if (mp4Samples.length === 0) { + //no samples need to remux + track.samples = []; + track.length = 0; + return; + } + // allocate mdatbox + if (mpegRawTrack) { + // allocate for raw mpeg buffer + mdatbox = new Uint8Array(mdatBytes); + } else { + // allocate for fmp4 mdat box + mdatbox = new Uint8Array(mdatBytes); + // size field + mdatbox[0] = (mdatBytes >>> 24) & 0xff; + mdatbox[1] = (mdatBytes >>> 16) & 0xff; + mdatbox[2] = (mdatBytes >>> 8) & 0xff; + mdatbox[3] = mdatBytes & 0xff; + // type field (fourCC) + mdatbox.set( + _mp4_generator_js__WEBPACK_IMPORTED_MODULE_1__.default.types + .mdat, + 4 + ); + } + // Write samples into mdatbox + for (var i = 0; i < mp4Samples.length; i++) { + var unit = mp4Samples[i].unit; + mdatbox.set(unit, offset); + offset += unit.byteLength; + } + var latest = mp4Samples[mp4Samples.length - 1]; + lastDts = latest.dts + latest.duration; + //this._audioNextDts = lastDts; + // fill media segment info & add to info list + var info = + new _core_media_segment_info_js__WEBPACK_IMPORTED_MODULE_4__.MediaSegmentInfo(); + info.beginDts = firstDts; + info.endDts = lastDts; + info.beginPts = firstDts; + info.endPts = lastDts; + info.originalBeginDts = mp4Samples[0].originalDts; + info.originalEndDts = latest.originalDts + latest.duration; + info.firstSample = + new _core_media_segment_info_js__WEBPACK_IMPORTED_MODULE_4__.SampleInfo( + mp4Samples[0].dts, + mp4Samples[0].pts, + mp4Samples[0].duration, + mp4Samples[0].originalDts, + false + ); + info.lastSample = + new _core_media_segment_info_js__WEBPACK_IMPORTED_MODULE_4__.SampleInfo( + latest.dts, + latest.pts, + latest.duration, + latest.originalDts, + false + ); + if (!this._isLive) { + this._audioSegmentInfoList.append(info); + } + track.samples = mp4Samples; + track.sequenceNumber++; + var moofbox = null; + if (mpegRawTrack) { + // Generate empty buffer, because useless for raw mpeg + moofbox = new Uint8Array(); + } else { + // Generate moof for fmp4 segment + moofbox = + _mp4_generator_js__WEBPACK_IMPORTED_MODULE_1__.default.moof( + track, + firstDts + ); + } + track.samples = []; + track.length = 0; + var segment = { + type: "audio", + data: this._mergeBoxes(moofbox, mdatbox).buffer, + sampleCount: mp4Samples.length, + info: info, + }; + if (mpegRawTrack && firstSegmentAfterSeek) { + // For MPEG audio stream in MSE, if seeking occurred, before appending new buffer + // We need explicitly set timestampOffset to the desired point in timeline for mpeg SourceBuffer. + segment.timestampOffset = firstDts; + } + this._onMediaSegment("audio", segment); + }; + MP4Remuxer.prototype._remuxVideo = function (videoTrack, force) { + if (this._videoMeta == null) { + return; + } + var track = videoTrack; + var samples = track.samples; + var dtsCorrection = undefined; + var firstDts = -1, + lastDts = -1; + var firstPts = -1, + lastPts = -1; + if (!samples || samples.length === 0) { + return; + } + if (samples.length === 1 && !force) { + // If [sample count in current batch] === 1 && (force != true) + // Ignore and keep in demuxer's queue + return; + } // else if (force === true) do remux + var offset = 8; + var mdatbox = null; + var mdatBytes = 8 + videoTrack.length; + var lastSample = null; + // Pop the lastSample and waiting for stash + if (samples.length > 1) { + lastSample = samples.pop(); + mdatBytes -= lastSample.length; + } + // Insert [stashed lastSample in the previous batch] to the front + if (this._videoStashedLastSample != null) { + var sample = this._videoStashedLastSample; + this._videoStashedLastSample = null; + samples.unshift(sample); + mdatBytes += sample.length; + } + // Stash the lastSample of current batch, waiting for next batch + if (lastSample != null) { + this._videoStashedLastSample = lastSample; + } + var firstSampleOriginalDts = samples[0].dts - this._dtsBase; + // calculate dtsCorrection + if (this._videoNextDts) { + dtsCorrection = firstSampleOriginalDts - this._videoNextDts; + } else { + // this._videoNextDts == undefined + if (this._videoSegmentInfoList.isEmpty()) { + dtsCorrection = 0; + } else { + var lastSample_2 = + this._videoSegmentInfoList.getLastSampleBefore( + firstSampleOriginalDts + ); + if (lastSample_2 != null) { + var distance = + firstSampleOriginalDts - + (lastSample_2.originalDts + lastSample_2.duration); + if (distance <= 3) { + distance = 0; + } + var expectedDts = + lastSample_2.dts + lastSample_2.duration + distance; + dtsCorrection = firstSampleOriginalDts - expectedDts; + } else { + // lastSample == null, cannot found + dtsCorrection = 0; + } + } + } + var info = + new _core_media_segment_info_js__WEBPACK_IMPORTED_MODULE_4__.MediaSegmentInfo(); + var mp4Samples = []; + // Correct dts for each sample, and calculate sample duration. Then output to mp4Samples + for (var i = 0; i < samples.length; i++) { + var sample = samples[i]; + var originalDts = sample.dts - this._dtsBase; + var isKeyframe = sample.isKeyframe; + var dts = originalDts - dtsCorrection; + var cts = sample.cts; + var pts = dts + cts; + if (firstDts === -1) { + firstDts = dts; + firstPts = pts; + } + var sampleDuration = 0; + if (i !== samples.length - 1) { + var nextDts = + samples[i + 1].dts - this._dtsBase - dtsCorrection; + sampleDuration = nextDts - dts; + } else { + // the last sample + if (lastSample != null) { + // use stashed sample's dts to calculate sample duration + var nextDts = + lastSample.dts - this._dtsBase - dtsCorrection; + sampleDuration = nextDts - dts; + } else if (mp4Samples.length >= 1) { + // use second last sample duration + sampleDuration = mp4Samples[mp4Samples.length - 1].duration; + } else { + // the only one sample, use reference sample duration + sampleDuration = Math.floor( + this._videoMeta.refSampleDuration + ); + } + } + if (isKeyframe) { + var syncPoint = + new _core_media_segment_info_js__WEBPACK_IMPORTED_MODULE_4__.SampleInfo( + dts, + pts, + sampleDuration, + sample.dts, + true + ); + syncPoint.fileposition = sample.fileposition; + info.appendSyncPoint(syncPoint); + } + mp4Samples.push({ + dts: dts, + pts: pts, + cts: cts, + units: sample.units, + size: sample.length, + isKeyframe: isKeyframe, + duration: sampleDuration, + originalDts: originalDts, + flags: { + isLeading: 0, + dependsOn: isKeyframe ? 2 : 1, + isDependedOn: isKeyframe ? 1 : 0, + hasRedundancy: 0, + isNonSync: isKeyframe ? 0 : 1, + }, + }); + } + // allocate mdatbox + mdatbox = new Uint8Array(mdatBytes); + mdatbox[0] = (mdatBytes >>> 24) & 0xff; + mdatbox[1] = (mdatBytes >>> 16) & 0xff; + mdatbox[2] = (mdatBytes >>> 8) & 0xff; + mdatbox[3] = mdatBytes & 0xff; + mdatbox.set( + _mp4_generator_js__WEBPACK_IMPORTED_MODULE_1__.default.types + .mdat, + 4 + ); + // Write samples into mdatbox + for (var i = 0; i < mp4Samples.length; i++) { + var units = mp4Samples[i].units; + while (units.length) { + var unit = units.shift(); + var data = unit.data; + mdatbox.set(data, offset); + offset += data.byteLength; + } + } + var latest = mp4Samples[mp4Samples.length - 1]; + lastDts = latest.dts + latest.duration; + lastPts = latest.pts + latest.duration; + this._videoNextDts = lastDts; + // fill media segment info & add to info list + info.beginDts = firstDts; + info.endDts = lastDts; + info.beginPts = firstPts; + info.endPts = lastPts; + info.originalBeginDts = mp4Samples[0].originalDts; + info.originalEndDts = latest.originalDts + latest.duration; + info.firstSample = + new _core_media_segment_info_js__WEBPACK_IMPORTED_MODULE_4__.SampleInfo( + mp4Samples[0].dts, + mp4Samples[0].pts, + mp4Samples[0].duration, + mp4Samples[0].originalDts, + mp4Samples[0].isKeyframe + ); + info.lastSample = + new _core_media_segment_info_js__WEBPACK_IMPORTED_MODULE_4__.SampleInfo( + latest.dts, + latest.pts, + latest.duration, + latest.originalDts, + latest.isKeyframe + ); + if (!this._isLive) { + this._videoSegmentInfoList.append(info); + } + track.samples = mp4Samples; + track.sequenceNumber++; + // workaround for chrome < 50: force first sample as a random access point + // see https://bugs.chromium.org/p/chromium/issues/detail?id=229412 + if (this._forceFirstIDR) { + var flags = mp4Samples[0].flags; + flags.dependsOn = 2; + flags.isNonSync = 0; + } + var moofbox = + _mp4_generator_js__WEBPACK_IMPORTED_MODULE_1__.default.moof( + track, + firstDts + ); + track.samples = []; + track.length = 0; + this._onMediaSegment("video", { + type: "video", + data: this._mergeBoxes(moofbox, mdatbox).buffer, + sampleCount: mp4Samples.length, + info: info, + }); + }; + MP4Remuxer.prototype._mergeBoxes = function (moof, mdat) { + var result = new Uint8Array(moof.byteLength + mdat.byteLength); + result.set(moof, 0); + result.set(mdat, moof.byteLength); + return result; + }; + return MP4Remuxer; + })(); + /* harmony default export */ __webpack_exports__["default"] = + MP4Remuxer; + + /***/ + }, + + /***/ "./src/utils/browser.js": + /*!******************************!*\ + !*** ./src/utils/browser.js ***! + \******************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + var Browser = {}; + function detect() { + // modified from jquery-browser-plugin + var ua = self.navigator.userAgent.toLowerCase(); + 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)) || + []; + 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) || + []; + var matched = { + browser: match[5] || match[3] || match[1] || "", + version: match[2] || match[4] || "0", + majorVersion: match[4] || match[2] || "0", + platform: platform_match[0] || "", + }; + var browser = {}; + if (matched.browser) { + browser[matched.browser] = true; + var versionArray = matched.majorVersion.split("."); + browser.version = { + major: parseInt(matched.majorVersion, 10), + string: matched.version, + }; + if (versionArray.length > 1) { + browser.version.minor = parseInt(versionArray[1], 10); + } + if (versionArray.length > 2) { + browser.version.build = parseInt(versionArray[2], 10); + } + } + if (matched.platform) { + browser[matched.platform] = true; + } + if (browser.chrome || browser.opr || browser.safari) { + browser.webkit = true; + } + // MSIE. IE11 has 'rv' identifer + if (browser.rv || browser.iemobile) { + if (browser.rv) { + delete browser.rv; + } + var msie = "msie"; + matched.browser = msie; + browser[msie] = true; + } + // Microsoft Edge + if (browser.edge) { + delete browser.edge; + var msedge = "msedge"; + matched.browser = msedge; + browser[msedge] = true; + } + // Opera 15+ + if (browser.opr) { + var opera = "opera"; + matched.browser = opera; + browser[opera] = true; + } + // Stock android browsers are marked as Safari + if (browser.safari && browser.android) { + var android = "android"; + matched.browser = android; + browser[android] = true; + } + browser.name = matched.browser; + browser.platform = matched.platform; + for (var key in Browser) { + if (Browser.hasOwnProperty(key)) { + delete Browser[key]; + } + } + Object.assign(Browser, browser); + } + detect(); + /* harmony default export */ __webpack_exports__["default"] = Browser; + + /***/ + }, + + /***/ "./src/utils/exception.js": + /*!********************************!*\ + !*** ./src/utils/exception.js ***! + \********************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ RuntimeException: function () { + return /* binding */ RuntimeException; + }, + /* harmony export */ IllegalStateException: function () { + return /* binding */ IllegalStateException; + }, + /* harmony export */ InvalidArgumentException: function () { + return /* binding */ InvalidArgumentException; + }, + /* harmony export */ NotImplementedException: function () { + return /* binding */ NotImplementedException; + }, + /* harmony export */ + }); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + var __extends = + (undefined && undefined.__extends) || + (function () { + var extendStatics = function (d, b) { + extendStatics = + Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && + function (d, b) { + d.__proto__ = b; + }) || + function (d, b) { + for (var p in b) + if (Object.prototype.hasOwnProperty.call(b, p)) + d[p] = b[p]; + }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError( + "Class extends value " + + String(b) + + " is not a constructor or null" + ); + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = + b === null + ? Object.create(b) + : ((__.prototype = b.prototype), new __()); + }; + })(); + var RuntimeException = /** @class */ (function () { + function RuntimeException(message) { + this._message = message; + } + Object.defineProperty(RuntimeException.prototype, "name", { + get: function () { + return "RuntimeException"; + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(RuntimeException.prototype, "message", { + get: function () { + return this._message; + }, + enumerable: false, + configurable: true, + }); + RuntimeException.prototype.toString = function () { + return this.name + ": " + this.message; + }; + return RuntimeException; + })(); + + var IllegalStateException = /** @class */ (function (_super) { + __extends(IllegalStateException, _super); + function IllegalStateException(message) { + return _super.call(this, message) || this; + } + Object.defineProperty(IllegalStateException.prototype, "name", { + get: function () { + return "IllegalStateException"; + }, + enumerable: false, + configurable: true, + }); + return IllegalStateException; + })(RuntimeException); + + var InvalidArgumentException = /** @class */ (function (_super) { + __extends(InvalidArgumentException, _super); + function InvalidArgumentException(message) { + return _super.call(this, message) || this; + } + Object.defineProperty(InvalidArgumentException.prototype, "name", { + get: function () { + return "InvalidArgumentException"; + }, + enumerable: false, + configurable: true, + }); + return InvalidArgumentException; + })(RuntimeException); + + var NotImplementedException = /** @class */ (function (_super) { + __extends(NotImplementedException, _super); + function NotImplementedException(message) { + return _super.call(this, message) || this; + } + Object.defineProperty(NotImplementedException.prototype, "name", { + get: function () { + return "NotImplementedException"; + }, + enumerable: false, + configurable: true, + }); + return NotImplementedException; + })(RuntimeException); + + /***/ + }, + + /***/ "./src/utils/logger.js": + /*!*****************************!*\ + !*** ./src/utils/logger.js ***! + \*****************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony import */ var events__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__( + /*! events */ "./node_modules/events/events.js" + ); + /* harmony import */ var events__WEBPACK_IMPORTED_MODULE_0___default = + /*#__PURE__*/ __webpack_require__.n( + events__WEBPACK_IMPORTED_MODULE_0__ + ); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + var Log = /** @class */ (function () { + function Log() {} + Log.e = function (tag, msg) { + if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG; + var str = "[" + tag + "] > " + msg; + if (Log.ENABLE_CALLBACK) { + Log.emitter.emit("log", "error", str); + } + if (!Log.ENABLE_ERROR) { + return; + } + if (console.error) { + console.error(str); + } else if (console.warn) { + console.warn(str); + } else { + console.log(str); + } + }; + Log.i = function (tag, msg) { + if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG; + var str = "[" + tag + "] > " + msg; + if (Log.ENABLE_CALLBACK) { + Log.emitter.emit("log", "info", str); + } + if (!Log.ENABLE_INFO) { + return; + } + if (console.info) { + console.info(str); + } else { + console.log(str); + } + }; + Log.w = function (tag, msg) { + if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG; + var str = "[" + tag + "] > " + msg; + if (Log.ENABLE_CALLBACK) { + Log.emitter.emit("log", "warn", str); + } + if (!Log.ENABLE_WARN) { + return; + } + if (console.warn) { + console.warn(str); + } else { + console.log(str); + } + }; + Log.d = function (tag, msg) { + if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG; + var str = "[" + tag + "] > " + msg; + if (Log.ENABLE_CALLBACK) { + Log.emitter.emit("log", "debug", str); + } + if (!Log.ENABLE_DEBUG) { + return; + } + if (console.debug) { + console.debug(str); + } else { + console.log(str); + } + }; + Log.v = function (tag, msg) { + if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG; + var str = "[" + tag + "] > " + msg; + if (Log.ENABLE_CALLBACK) { + Log.emitter.emit("log", "verbose", str); + } + if (!Log.ENABLE_VERBOSE) { + return; + } + console.log(str); + }; + return Log; + })(); + Log.GLOBAL_TAG = "flv.js"; + Log.FORCE_GLOBAL_TAG = false; + Log.ENABLE_ERROR = true; + Log.ENABLE_INFO = true; + Log.ENABLE_WARN = true; + Log.ENABLE_DEBUG = true; + Log.ENABLE_VERBOSE = true; + Log.ENABLE_CALLBACK = false; + Log.emitter = new (events__WEBPACK_IMPORTED_MODULE_0___default())(); + /* harmony default export */ __webpack_exports__["default"] = Log; + + /***/ + }, + + /***/ "./src/utils/logging-control.js": + /*!**************************************!*\ + !*** ./src/utils/logging-control.js ***! + \**************************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* harmony import */ var events__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__( + /*! events */ "./node_modules/events/events.js" + ); + /* harmony import */ var events__WEBPACK_IMPORTED_MODULE_0___default = + /*#__PURE__*/ __webpack_require__.n( + events__WEBPACK_IMPORTED_MODULE_0__ + ); + /* harmony import */ var _logger_js__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__(/*! ./logger.js */ "./src/utils/logger.js"); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + var LoggingControl = /** @class */ (function () { + function LoggingControl() {} + Object.defineProperty(LoggingControl, "forceGlobalTag", { + get: function () { + return _logger_js__WEBPACK_IMPORTED_MODULE_1__.default + .FORCE_GLOBAL_TAG; + }, + set: function (enable) { + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.FORCE_GLOBAL_TAG = + enable; + LoggingControl._notifyChange(); + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(LoggingControl, "globalTag", { + get: function () { + return _logger_js__WEBPACK_IMPORTED_MODULE_1__.default + .GLOBAL_TAG; + }, + set: function (tag) { + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.GLOBAL_TAG = + tag; + LoggingControl._notifyChange(); + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(LoggingControl, "enableAll", { + get: function () { + return ( + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default + .ENABLE_VERBOSE && + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default + .ENABLE_DEBUG && + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_INFO && + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_WARN && + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_ERROR + ); + }, + set: function (enable) { + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_VERBOSE = + enable; + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_DEBUG = + enable; + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_INFO = + enable; + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_WARN = + enable; + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_ERROR = + enable; + LoggingControl._notifyChange(); + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(LoggingControl, "enableDebug", { + get: function () { + return _logger_js__WEBPACK_IMPORTED_MODULE_1__.default + .ENABLE_DEBUG; + }, + set: function (enable) { + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_DEBUG = + enable; + LoggingControl._notifyChange(); + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(LoggingControl, "enableVerbose", { + get: function () { + return _logger_js__WEBPACK_IMPORTED_MODULE_1__.default + .ENABLE_VERBOSE; + }, + set: function (enable) { + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_VERBOSE = + enable; + LoggingControl._notifyChange(); + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(LoggingControl, "enableInfo", { + get: function () { + return _logger_js__WEBPACK_IMPORTED_MODULE_1__.default + .ENABLE_INFO; + }, + set: function (enable) { + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_INFO = + enable; + LoggingControl._notifyChange(); + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(LoggingControl, "enableWarn", { + get: function () { + return _logger_js__WEBPACK_IMPORTED_MODULE_1__.default + .ENABLE_WARN; + }, + set: function (enable) { + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_WARN = + enable; + LoggingControl._notifyChange(); + }, + enumerable: false, + configurable: true, + }); + Object.defineProperty(LoggingControl, "enableError", { + get: function () { + return _logger_js__WEBPACK_IMPORTED_MODULE_1__.default + .ENABLE_ERROR; + }, + set: function (enable) { + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_ERROR = + enable; + LoggingControl._notifyChange(); + }, + enumerable: false, + configurable: true, + }); + LoggingControl.getConfig = function () { + return { + globalTag: + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.GLOBAL_TAG, + forceGlobalTag: + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default + .FORCE_GLOBAL_TAG, + enableVerbose: + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default + .ENABLE_VERBOSE, + enableDebug: + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_DEBUG, + enableInfo: + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_INFO, + enableWarn: + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_WARN, + enableError: + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_ERROR, + enableCallback: + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default + .ENABLE_CALLBACK, + }; + }; + LoggingControl.applyConfig = function (config) { + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.GLOBAL_TAG = + config.globalTag; + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.FORCE_GLOBAL_TAG = + config.forceGlobalTag; + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_VERBOSE = + config.enableVerbose; + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_DEBUG = + config.enableDebug; + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_INFO = + config.enableInfo; + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_WARN = + config.enableWarn; + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_ERROR = + config.enableError; + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_CALLBACK = + config.enableCallback; + }; + LoggingControl._notifyChange = function () { + var emitter = LoggingControl.emitter; + if (emitter.listenerCount("change") > 0) { + var config = LoggingControl.getConfig(); + emitter.emit("change", config); + } + }; + LoggingControl.registerListener = function (listener) { + LoggingControl.emitter.addListener("change", listener); + }; + LoggingControl.removeListener = function (listener) { + LoggingControl.emitter.removeListener("change", listener); + }; + LoggingControl.addLogListener = function (listener) { + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.emitter.addListener( + "log", + listener + ); + if ( + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.emitter.listenerCount( + "log" + ) > 0 + ) { + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_CALLBACK = true; + LoggingControl._notifyChange(); + } + }; + LoggingControl.removeLogListener = function (listener) { + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.emitter.removeListener( + "log", + listener + ); + if ( + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.emitter.listenerCount( + "log" + ) === 0 + ) { + _logger_js__WEBPACK_IMPORTED_MODULE_1__.default.ENABLE_CALLBACK = false; + LoggingControl._notifyChange(); + } + }; + return LoggingControl; + })(); + LoggingControl.emitter = + new (events__WEBPACK_IMPORTED_MODULE_0___default())(); + /* harmony default export */ __webpack_exports__["default"] = + LoggingControl; + + /***/ + }, + + /***/ "./src/utils/polyfill.js": + /*!*******************************!*\ + !*** ./src/utils/polyfill.js ***! + \*******************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + var Polyfill = /** @class */ (function () { + function Polyfill() {} + Polyfill.install = function () { + // ES6 Object.setPrototypeOf + Object.setPrototypeOf = + Object.setPrototypeOf || + function (obj, proto) { + obj.__proto__ = proto; + return obj; + }; + // ES6 Object.assign + Object.assign = + Object.assign || + function (target) { + if (target === undefined || target === null) { + throw new TypeError( + "Cannot convert undefined or null to object" + ); + } + var output = Object(target); + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + if (source !== undefined && source !== null) { + for (var key in source) { + if (source.hasOwnProperty(key)) { + output[key] = source[key]; + } + } + } + } + return output; + }; + // String.prototype.startsWith() + if (!String.prototype.startsWith) { + Object.defineProperty(String.prototype, "startsWith", { + value: function (search, rawPos) { + var pos = rawPos > 0 ? rawPos | 0 : 0; + return this.substring(pos, pos + search.length) === search; + }, + }); + } + // ES6 Promise (missing support in IE11) + if (typeof self.Promise !== "function") { + __webpack_require__( + /*! es6-promise */ "./node_modules/es6-promise/dist/es6-promise.js" + ).polyfill(); + } + }; + return Polyfill; + })(); + Polyfill.install(); + /* harmony default export */ __webpack_exports__["default"] = + Polyfill; + + /***/ + }, + + /***/ "./src/utils/typedarray-equality.js": + /*!******************************************!*\ + !*** ./src/utils/typedarray-equality.js ***! + \******************************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* + * Copyright (C) 2022 magicxqq. All Rights Reserved. + * + * @author magicxqq + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + function isAligned16(a /*: Uint8Array*/) { + return a.byteOffset % 2 === 0 && a.byteLength % 2 === 0; + } + function isAligned32(a /*: Uint8Array*/) { + return a.byteOffset % 4 === 0 && a.byteLength % 4 === 0; + } + function compareArray( + a /*: Uint8Array | Uint16Array | Uint32Array*/, + b /*: Uint8Array | Uint16Array | Uint32Array*/ + ) { + for (var i = 0; i < a.length; i++) { + if (a[i] !== b[i]) { + return false; + } + } + return true; + } + function equal8(a /*: Uint8Array*/, b /*: Uint8Array*/) { + return compareArray(a, b); + } + function equal16(a /*: Uint8Array*/, b /*: Uint8Array*/) { + var a16 = new Uint16Array(a.buffer, a.byteOffset, a.byteLength / 2); + var b16 = new Uint16Array(b.buffer, b.byteOffset, b.byteLength / 2); + return compareArray(a16, b16); + } + function equal32(a /*: Uint8Array*/, b /*: Uint8Array*/) { + var a32 = new Uint32Array(a.buffer, a.byteOffset, a.byteLength / 4); + var b32 = new Uint32Array(b.buffer, b.byteOffset, b.byteLength / 4); + return compareArray(a32, b32); + } + function buffersAreEqual(a /*: Uint8Array*/, b /*: */) { + if (a.byteLength !== b.byteLength) { + return false; + } + if (isAligned32(a) && isAligned32(b)) { + return equal32(a, b); + } + if (isAligned16(a) && isAligned16(b)) { + return equal16(a, b); + } + return equal8(a, b); + } + /* harmony default export */ __webpack_exports__["default"] = + buffersAreEqual; + + /***/ + }, + + /***/ "./src/utils/utf8-conv.js": + /*!********************************!*\ + !*** ./src/utils/utf8-conv.js ***! + \********************************/ + /***/ function ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) { + "use strict"; + __webpack_require__.r(__webpack_exports__); + /* + * Copyright (C) 2016 Bilibili. All Rights Reserved. + * + * This file is derived from C++ project libWinTF8 (https://github.com/m13253/libWinTF8) + * @author zheng qian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + function checkContinuation(uint8array, start, checkLength) { + var array = uint8array; + if (start + checkLength < array.length) { + while (checkLength--) { + if ((array[++start] & 0xc0) !== 0x80) return false; + } + return true; + } else { + return false; + } + } + function decodeUTF8(uint8array) { + var out = []; + var input = uint8array; + var i = 0; + var length = uint8array.length; + while (i < length) { + if (input[i] < 0x80) { + out.push(String.fromCharCode(input[i])); + ++i; + continue; + } else if (input[i] < 0xc0) { + // fallthrough + } else if (input[i] < 0xe0) { + if (checkContinuation(input, i, 1)) { + var ucs4 = ((input[i] & 0x1f) << 6) | (input[i + 1] & 0x3f); + if (ucs4 >= 0x80) { + out.push(String.fromCharCode(ucs4 & 0xffff)); + i += 2; + continue; + } + } + } else if (input[i] < 0xf0) { + if (checkContinuation(input, i, 2)) { + var ucs4 = + ((input[i] & 0xf) << 12) | + ((input[i + 1] & 0x3f) << 6) | + (input[i + 2] & 0x3f); + if (ucs4 >= 0x800 && (ucs4 & 0xf800) !== 0xd800) { + out.push(String.fromCharCode(ucs4 & 0xffff)); + i += 3; + continue; + } + } + } else if (input[i] < 0xf8) { + if (checkContinuation(input, i, 3)) { + var ucs4 = + ((input[i] & 0x7) << 18) | + ((input[i + 1] & 0x3f) << 12) | + ((input[i + 2] & 0x3f) << 6) | + (input[i + 3] & 0x3f); + if (ucs4 > 0x10000 && ucs4 < 0x110000) { + ucs4 -= 0x10000; + out.push(String.fromCharCode((ucs4 >>> 10) | 0xd800)); + out.push(String.fromCharCode((ucs4 & 0x3ff) | 0xdc00)); + i += 4; + continue; + } + } + } + out.push(String.fromCharCode(0xfffd)); + ++i; + } + return out.join(""); + } + /* harmony default export */ __webpack_exports__["default"] = + decodeUTF8; + + /***/ + }, + + /******/ + }; + /************************************************************************/ + /******/ // The module cache + /******/ var __webpack_module_cache__ = {}; + /******/ + /******/ // The require function + /******/ function __webpack_require__(moduleId) { + /******/ // Check if module is in cache + /******/ var cachedModule = __webpack_module_cache__[moduleId]; + /******/ if (cachedModule !== undefined) { + /******/ return cachedModule.exports; + /******/ + } + /******/ // Create a new module (and put it into the cache) + /******/ var module = (__webpack_module_cache__[moduleId] = { + /******/ // no module.id needed + /******/ // no module.loaded needed + /******/ exports: {}, + /******/ + }); + /******/ + /******/ // Execute the module function + /******/ __webpack_modules__[moduleId].call( + module.exports, + module, + module.exports, + __webpack_require__ + ); + /******/ + /******/ // Return the exports of the module + /******/ return module.exports; + /******/ + } + /******/ + /******/ // expose the modules object (__webpack_modules__) + /******/ __webpack_require__.m = __webpack_modules__; + /******/ + /************************************************************************/ + /******/ /* webpack/runtime/compat get default export */ /******/ !(function () { + /******/ // getDefaultExport function for compatibility with non-harmony modules + /******/ __webpack_require__.n = function (module) { + /******/ var getter = + module && module.__esModule + ? /******/ function () { + return module["default"]; + } + : /******/ function () { + return module; + }; + /******/ __webpack_require__.d(getter, { a: getter }); + /******/ return getter; + /******/ + }; + /******/ + })(); + /******/ + /******/ /* webpack/runtime/define property getters */ /******/ !(function () { + /******/ // define getter functions for harmony exports + /******/ __webpack_require__.d = function (exports, definition) { + /******/ for (var key in definition) { + /******/ if ( + __webpack_require__.o(definition, key) && + !__webpack_require__.o(exports, key) + ) { + /******/ Object.defineProperty(exports, key, { + enumerable: true, + get: definition[key], + }); + /******/ + } + /******/ + } + /******/ + }; + /******/ + })(); + /******/ + /******/ /* webpack/runtime/global */ /******/ !(function () { + /******/ __webpack_require__.g = (function () { + /******/ if (typeof globalThis === "object") return globalThis; + /******/ try { + /******/ return this || new Function("return this")(); + /******/ + } catch (e) { + /******/ if (typeof window === "object") return window; + /******/ + } + /******/ + })(); + /******/ + })(); + /******/ + /******/ /* webpack/runtime/hasOwnProperty shorthand */ /******/ !(function () { + /******/ __webpack_require__.o = function (obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); + }; + /******/ + })(); + /******/ + /******/ /* webpack/runtime/make namespace object */ /******/ !(function () { + /******/ // define __esModule on exports + /******/ __webpack_require__.r = function (exports) { + /******/ if (typeof Symbol !== "undefined" && Symbol.toStringTag) { + /******/ Object.defineProperty(exports, Symbol.toStringTag, { + value: "Module", + }); + /******/ + } + /******/ Object.defineProperty(exports, "__esModule", { value: true }); + /******/ + }; + /******/ + })(); + /******/ + /************************************************************************/ + /******/ + /******/ // module factories are used so entry inlining is disabled + /******/ // startup + /******/ // Load entry module and return exports + /******/ var __webpack_exports__ = __webpack_require__("./src/index.js"); + /******/ + /******/ return __webpack_exports__; + /******/ + })(); +}); + +// export default flvjs; +//# sourceMappingURL=flv.js.map diff --git a/src/views/components/VideoPlayer.vue b/src/views/components/VideoPlayer.vue new file mode 100644 index 0000000..bd15c81 --- /dev/null +++ b/src/views/components/VideoPlayer.vue @@ -0,0 +1,78 @@ + + + diff --git a/src/views/reservoir/safeOperation/components/ProjectDetail.vue b/src/views/reservoir/safeOperation/components/ProjectDetail.vue index a678484..cdbd96a 100644 --- a/src/views/reservoir/safeOperation/components/ProjectDetail.vue +++ b/src/views/reservoir/safeOperation/components/ProjectDetail.vue @@ -1,6 +1,6 @@