rx-player
Version:
Canal+ HTML5 Video Player
255 lines (254 loc) • 9.36 kB
JavaScript
;
/**
* Copyright 2015 CANAL+ Group
*
* 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 __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getBox = getBox;
exports.getBoxContent = getBoxContent;
exports.getBoxesContent = getBoxesContent;
exports.getBoxOffsets = getBoxOffsets;
exports.getChildBox = getChildBox;
exports.getNextBoxOffsets = getNextBoxOffsets;
exports.getUuidContent = getUuidContent;
var log_1 = require("../../../log");
var assert_1 = require("../../../utils/assert");
var byte_parsing_1 = require("../../../utils/byte_parsing");
/**
* From a given buffer representing ISOBMFF data, browses inner boxes in
* `childNames`, each element being a child box of the one before it.
* Returns `null` if one of the child (or if the parent) is not found.
* @param {Uint8Array} buf
* @param {number[]} childNames
* @returns {Uint8Array|null}
*/
function getChildBox(buf, childNames) {
var e_1, _a;
var currBox = buf;
try {
for (var childNames_1 = __values(childNames), childNames_1_1 = childNames_1.next(); !childNames_1_1.done; childNames_1_1 = childNames_1.next()) {
var childName = childNames_1_1.value;
var box = getBoxContent(currBox, childName);
if (box === null) {
return null;
}
currBox = box;
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (childNames_1_1 && !childNames_1_1.done && (_a = childNames_1.return)) _a.call(childNames_1);
}
finally { if (e_1) throw e_1.error; }
}
return currBox;
}
/**
* Returns the content of a box based on its name.
* `null` if not found.
* @param {Uint8Array} buf - the isobmff data
* @param {Number} boxName - the 4-letter 'name' of the box as a 4 byte integer
* generated from encoding the corresponding ASCII in big endian.
* @returns {UInt8Array|null}
*/
function getBoxContent(buf, boxName) {
var offsets = getBoxOffsets(buf, boxName);
return offsets !== null ? buf.subarray(offsets[1], offsets[2]) : null;
}
/**
* Reads the whole ISOBMFF and returns the content of all boxes with the given
* name, in order.
* @param {Uint8Array} buf - the isobmff data
* @param {Number} boxName - the 4-letter 'name' of the box as a 4 byte integer
* generated from encoding the corresponding ASCII in big endian.
* @returns {Array.<Uint8Array>}
*/
function getBoxesContent(buf, boxName) {
var ret = [];
var currentBuf = buf;
while (true) {
var offsets = getBoxOffsets(currentBuf, boxName);
if (offsets === null) {
return ret;
}
// Guard against a (very highly improbable) infinite loop
(0, assert_1.default)(offsets[2] !== 0 && currentBuf.length !== 0);
ret.push(currentBuf.subarray(offsets[1], offsets[2]));
currentBuf = currentBuf.subarray(offsets[2]);
}
}
/**
* Returns an ISOBMFF box - size and name included - based on its name.
* `null` if not found.
* @param {Uint8Array} buf - the isobmff data
* @param {Number} boxName - the 4-letter 'name' of the box as a 4 byte integer
* generated from encoding the corresponding ASCII in big endian.
* @returns {UInt8Array|null}
*/
function getBox(buf, boxName) {
var offsets = getBoxOffsets(buf, boxName);
return offsets !== null ? buf.subarray(offsets[0], offsets[2]) : null;
}
/**
* Returns byte offsets for the start of the box, the start of its content and
* the end of the box (not inclusive).
*
* `null` if not found.
*
* If found, the tuple returned has three elements, all numbers:
* 1. The starting byte corresponding to the start of the box (from its size)
* 2. The beginning of the box content - meaning the first byte after the
* size and the name of the box.
* 3. The first byte after the end of the box, might be equal to `buf`'s
* length if we're considering the last box.
* @param {Uint8Array} buf - the isobmff data
* @param {Number} boxName - the 4-letter 'name' of the box as a 4 byte integer
* generated from encoding the corresponding ASCII in big endian.
* @returns {Array.<number>|null}
*/
function getBoxOffsets(buf, boxName) {
var len = buf.length;
var boxBaseOffset = 0;
var name;
var lastBoxSize = 0;
var lastOffset;
while (boxBaseOffset + 8 <= len) {
lastOffset = boxBaseOffset;
lastBoxSize = (0, byte_parsing_1.be4toi)(buf, lastOffset);
lastOffset += 4;
name = (0, byte_parsing_1.be4toi)(buf, lastOffset);
lastOffset += 4;
if (lastBoxSize === 0) {
lastBoxSize = len - boxBaseOffset;
}
else if (lastBoxSize === 1) {
if (lastOffset + 8 > len) {
return null;
}
lastBoxSize = (0, byte_parsing_1.be8toi)(buf, lastOffset);
lastOffset += 8;
}
if (lastBoxSize < 0) {
throw new Error("ISOBMFF: Size out of range");
}
if (name === boxName) {
if (boxName === 0x75756964 /* === "uuid" */) {
lastOffset += 16; // Skip uuid name
}
return [boxBaseOffset, lastOffset, boxBaseOffset + lastBoxSize];
}
else {
boxBaseOffset += lastBoxSize;
}
}
return null;
}
/**
* Gives the content of a specific UUID box.
* `undefined` if that box is not found.
*
* If found, the returned Uint8Array contains just the box's content: the box
* without its name and size.
* @param {Uint8Array} buf
* @param {Number} id1
* @param {Number} id2
* @param {Number} id3
* @param {Number} id4
* @returns {Uint8Array|undefined}
*/
function getUuidContent(buf, id1, id2, id3, id4) {
var len = buf.length;
var boxSize;
for (var boxBaseOffset = 0; boxBaseOffset < len; boxBaseOffset += boxSize) {
var currentOffset = boxBaseOffset;
boxSize = (0, byte_parsing_1.be4toi)(buf, currentOffset);
currentOffset += 4;
var boxName = (0, byte_parsing_1.be4toi)(buf, currentOffset);
currentOffset += 4;
if (boxSize === 0) {
boxSize = len - boxBaseOffset;
}
else if (boxSize === 1) {
if (currentOffset + 8 > len) {
return undefined;
}
boxSize = (0, byte_parsing_1.be8toi)(buf, currentOffset);
currentOffset += 8;
}
if (boxName === 0x75756964 /* === "uuid" */ &&
currentOffset + 16 <= len &&
(0, byte_parsing_1.be4toi)(buf, currentOffset) === id1 &&
(0, byte_parsing_1.be4toi)(buf, currentOffset + 4) === id2 &&
(0, byte_parsing_1.be4toi)(buf, currentOffset + 8) === id3 &&
(0, byte_parsing_1.be4toi)(buf, currentOffset + 12) === id4) {
currentOffset += 16;
return buf.subarray(currentOffset, boxBaseOffset + boxSize);
}
}
}
/**
* For the next encountered box, return byte offsets corresponding to:
* 1. the starting byte offset for the next box (should always be equal to
* `0`).
* 2. The beginning of the box content - meaning the first byte after the
* size and the name of the box.
* 3. The first byte after the end of the box, might be equal to `buf`'s
* length if we're considering the last box.
*
* `null` if no box is found.
* @param {Uint8Array} buf - the isobmff data
* @returns {Array.<number>|null}
*/
function getNextBoxOffsets(buf) {
var len = buf.length;
if (len < 8) {
log_1.default.warn("isobmff", "box inferior to 8 bytes, cannot find offsets");
return null;
}
var lastOffset = 0;
var boxSize = (0, byte_parsing_1.be4toi)(buf, lastOffset);
lastOffset += 4;
var name = (0, byte_parsing_1.be4toi)(buf, lastOffset);
lastOffset += 4;
if (boxSize === 0) {
boxSize = len;
}
else if (boxSize === 1) {
if (lastOffset + 8 > len) {
log_1.default.warn("isobmff", "box too short, cannot find offsets");
return null;
}
boxSize = (0, byte_parsing_1.be8toi)(buf, lastOffset);
lastOffset += 8;
}
if (boxSize < 0) {
throw new Error("ISOBMFF: Size out of range");
}
if (name === 0x75756964 /* === "uuid" */) {
lastOffset += 16; // Skip uuid name
}
return [0, lastOffset, boxSize];
}