Created
May 30, 2018 13:31
-
-
Save peaBerberian/42ba705713a5f72a50c8b7f4af6f101c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Find the right box in an isobmff file from its hexa-encoded name. | |
| * @param {Uint8Array} buf - the isobmff | |
| * @param {Number} boxName - the 'name' of the box (e.g. 'sidx' or 'moov'), | |
| * hexa encoded | |
| * @returns {Number} - offset where the corresponding box is (starting with its | |
| * size), -1 if not found. | |
| */ | |
| function findBox(buf, boxName) { | |
| const length = buf.length; | |
| let i = 0; | |
| while (i + 8 < length) { | |
| const size = be4toi(buf, i); | |
| if (size < 0) { | |
| throw new Error("The computed size is out of range."); | |
| } | |
| const name = be4toi(buf, i + 4); | |
| if (name === boxName) { | |
| if (i + size > length) { | |
| throw new Error("box out of range"); | |
| } | |
| return i; | |
| } | |
| i += size; | |
| } | |
| return -1; | |
| } | |
| /** | |
| * Translate groups of 2 big-endian bytes to Integer (from 0 up to 65535). | |
| * @param {TypedArray} bytes | |
| * @param {Number} off - The offset (from the start of the given array) | |
| * @returns {Number} | |
| */ | |
| function be2toi(bytes, off) { | |
| return ( | |
| (bytes[0+off] << 8) + | |
| (bytes[1+off]) | |
| ); | |
| } | |
| /** | |
| * Translate groups of 3 big-endian bytes to Integer. | |
| * @param {TypedArray} bytes | |
| * @param {Number} off - The offset (from the start of the given array) | |
| * @returns {Number} | |
| */ | |
| function be3toi(bytes, off) { | |
| return ( | |
| (bytes[0+off] * 0x0010000) + | |
| (bytes[1+off] * 0x0000100) + | |
| (bytes[2+off]) | |
| ); | |
| } | |
| /** | |
| * Translate groups of 4 big-endian bytes to Integer. | |
| * @param {TypedArray} bytes | |
| * @param {Number} off - The offset (from the start of the given array) | |
| * @returns {Number} | |
| */ | |
| function be4toi(bytes, off) { | |
| return ( | |
| (bytes[0+off] * 0x1000000) + | |
| (bytes[1+off] * 0x0010000) + | |
| (bytes[2+off] * 0x0000100) + | |
| (bytes[3+off]) | |
| ); | |
| } | |
| /** | |
| * Translate groups of 8 big-endian bytes to Integer. | |
| * @param {TypedArray} bytes | |
| * @param {Number} off - The offset (from the start of the given array) | |
| * @returns {Number} | |
| */ | |
| function be8toi(bytes, off) { | |
| return ( | |
| ( | |
| (bytes[0+off] * 0x1000000) + | |
| (bytes[1+off] * 0x0010000) + | |
| (bytes[2+off] * 0x0000100) + | |
| (bytes[3+off]) | |
| ) * 0x100000000 + | |
| (bytes[4+off] * 0x1000000) + | |
| (bytes[5+off] * 0x0010000) + | |
| (bytes[6+off] * 0x0000100) + | |
| (bytes[7+off]) | |
| ); | |
| } | |
| /** | |
| * Returns segment ranges from sidx box. | |
| * | |
| * The returned value is an array of byte ranges, each under the form: | |
| * ```js | |
| * [start_byte, end_byte] | |
| * ``` | |
| * | |
| * @param {Uint8Array} buf - Whole ISOBMFF file. | |
| * @param {number} baseOffset - Offset where the sidx box starts (more | |
| * specifically its size starts) in `buf`. | |
| * @returns {Array.<Array.<number>>} | |
| */ | |
| function getSegmentRangesFromSidx(buf, baseOffset) { | |
| let offset = baseOffset; | |
| // length of the box, in bytes | |
| const size = be4toi(buf, offset); | |
| offset = offset + | |
| 4 + // length (already parsed) | |
| 4; // name of the box (== "sidx") | |
| // version of the sidx box | |
| const version = buf[offset]; | |
| if (version > 1) { // only `0` or `1` are known | |
| throw new Error("Unsupported sidx version", version); | |
| } | |
| offset = offset + | |
| 1 + // version (already parsed) | |
| 3 + // skip flags | |
| 4 + // skip reference_id | |
| 4 + // skip timescale | |
| (version === 0 ? 4 : 8); // skip earliest_presentation_time | |
| const firstSegmentOffset = baseOffset + size + | |
| (version === 0 ? be4toi(buf, offset) : be8toi(buf, offset)); | |
| offset = offset + | |
| (version === 0 ? 4 : 8) + // first_offset (already parsed) | |
| 2; // reserved bytes we do not care about | |
| const nbOfSegments = be2toi(buf, offset); | |
| offset += 2; // reference_count (already parsed -> nbOfSegments) | |
| let currentSegmentOffset = firstSegmentOffset; | |
| const ranges = []; | |
| let i = nbOfSegments; | |
| while(i--) { | |
| const first4Bytes = be4toi(buf, offset); | |
| offset += 12; | |
| const referenceType = first4Bytes >> 31 & 0x01; | |
| if (referenceType) { | |
| throw new Error("The sidx contains a reference to another sidx."); | |
| } | |
| const referenceSize = first4Bytes & 0x7FFFFFFF; | |
| ranges.push([currentSegmentOffset, currentSegmentOffset + referenceSize - 1]); | |
| currentSegmentOffset += referenceSize; | |
| } | |
| return ranges; | |
| } | |
| /** | |
| * Try to find and return segment ranges from a ISOBMFF buffer. | |
| * @see getSegmentRangesFromSidx for return type | |
| * @param {Uint8Array} buf - Whole ISOBMFF file. | |
| * @returns {Array.<Array.<number>>} | |
| */ | |
| function getSegmentRanges(buf) { | |
| const sidxOffset = findBox(buf, 0x73696478 /* "sidx" */); | |
| if (sidxOffset < 0) { | |
| // sidx not found | |
| return []; | |
| } | |
| return getSegmentRangesFromSidx(buf, sidxOffset); | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Exemple avec un segment d'init (en Uint8Array):