mirror of
https://github.com/DanielnetoDotCom/YouPHPTube
synced 2025-10-03 09:49:28 +02:00
This commit is contained in:
parent
37e90e3dfe
commit
214f5d9fc3
4949 changed files with 1393320 additions and 29 deletions
105
node_modules/mux.js/cjs/mp4/emsg.js
generated
vendored
Normal file
105
node_modules/mux.js/cjs/mp4/emsg.js
generated
vendored
Normal file
|
@ -0,0 +1,105 @@
|
|||
"use strict";
|
||||
|
||||
var uint8ToCString = require('../utils/string.js').uint8ToCString;
|
||||
|
||||
var getUint64 = require('../utils/numbers.js').getUint64;
|
||||
/**
|
||||
* Based on: ISO/IEC 23009 Section: 5.10.3.3
|
||||
* References:
|
||||
* https://dashif-documents.azurewebsites.net/Events/master/event.html#emsg-format
|
||||
* https://aomediacodec.github.io/id3-emsg/
|
||||
*
|
||||
* Takes emsg box data as a uint8 array and returns a emsg box object
|
||||
* @param {UInt8Array} boxData data from emsg box
|
||||
* @returns A parsed emsg box object
|
||||
*/
|
||||
|
||||
|
||||
var parseEmsgBox = function parseEmsgBox(boxData) {
|
||||
// version + flags
|
||||
var offset = 4;
|
||||
var version = boxData[0];
|
||||
var scheme_id_uri, value, timescale, presentation_time, presentation_time_delta, event_duration, id, message_data;
|
||||
|
||||
if (version === 0) {
|
||||
scheme_id_uri = uint8ToCString(boxData.subarray(offset));
|
||||
offset += scheme_id_uri.length;
|
||||
value = uint8ToCString(boxData.subarray(offset));
|
||||
offset += value.length;
|
||||
var dv = new DataView(boxData.buffer);
|
||||
timescale = dv.getUint32(offset);
|
||||
offset += 4;
|
||||
presentation_time_delta = dv.getUint32(offset);
|
||||
offset += 4;
|
||||
event_duration = dv.getUint32(offset);
|
||||
offset += 4;
|
||||
id = dv.getUint32(offset);
|
||||
offset += 4;
|
||||
} else if (version === 1) {
|
||||
var dv = new DataView(boxData.buffer);
|
||||
timescale = dv.getUint32(offset);
|
||||
offset += 4;
|
||||
presentation_time = getUint64(boxData.subarray(offset));
|
||||
offset += 8;
|
||||
event_duration = dv.getUint32(offset);
|
||||
offset += 4;
|
||||
id = dv.getUint32(offset);
|
||||
offset += 4;
|
||||
scheme_id_uri = uint8ToCString(boxData.subarray(offset));
|
||||
offset += scheme_id_uri.length;
|
||||
value = uint8ToCString(boxData.subarray(offset));
|
||||
offset += value.length;
|
||||
}
|
||||
|
||||
message_data = new Uint8Array(boxData.subarray(offset, boxData.byteLength));
|
||||
var emsgBox = {
|
||||
scheme_id_uri: scheme_id_uri,
|
||||
value: value,
|
||||
// if timescale is undefined or 0 set to 1
|
||||
timescale: timescale ? timescale : 1,
|
||||
presentation_time: presentation_time,
|
||||
presentation_time_delta: presentation_time_delta,
|
||||
event_duration: event_duration,
|
||||
id: id,
|
||||
message_data: message_data
|
||||
};
|
||||
return isValidEmsgBox(version, emsgBox) ? emsgBox : undefined;
|
||||
};
|
||||
/**
|
||||
* Scales a presentation time or time delta with an offset with a provided timescale
|
||||
* @param {number} presentationTime
|
||||
* @param {number} timescale
|
||||
* @param {number} timeDelta
|
||||
* @param {number} offset
|
||||
* @returns the scaled time as a number
|
||||
*/
|
||||
|
||||
|
||||
var scaleTime = function scaleTime(presentationTime, timescale, timeDelta, offset) {
|
||||
return presentationTime || presentationTime === 0 ? presentationTime / timescale : offset + timeDelta / timescale;
|
||||
};
|
||||
/**
|
||||
* Checks the emsg box data for validity based on the version
|
||||
* @param {number} version of the emsg box to validate
|
||||
* @param {Object} emsg the emsg data to validate
|
||||
* @returns if the box is valid as a boolean
|
||||
*/
|
||||
|
||||
|
||||
var isValidEmsgBox = function isValidEmsgBox(version, emsg) {
|
||||
var hasScheme = emsg.scheme_id_uri !== '\0';
|
||||
var isValidV0Box = version === 0 && isDefined(emsg.presentation_time_delta) && hasScheme;
|
||||
var isValidV1Box = version === 1 && isDefined(emsg.presentation_time) && hasScheme; // Only valid versions of emsg are 0 and 1
|
||||
|
||||
return !(version > 1) && isValidV0Box || isValidV1Box;
|
||||
}; // Utility function to check if an object is defined
|
||||
|
||||
|
||||
var isDefined = function isDefined(data) {
|
||||
return data !== undefined || data !== null;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
parseEmsgBox: parseEmsgBox,
|
||||
scaleTime: scaleTime
|
||||
};
|
243
node_modules/mux.js/cjs/tools/parse-id3.js
generated
vendored
Normal file
243
node_modules/mux.js/cjs/tools/parse-id3.js
generated
vendored
Normal file
|
@ -0,0 +1,243 @@
|
|||
/**
|
||||
* mux.js
|
||||
*
|
||||
* Copyright (c) Brightcove
|
||||
* Licensed Apache-2.0 https://github.com/videojs/mux.js/blob/master/LICENSE
|
||||
*
|
||||
* Tools for parsing ID3 frame data
|
||||
* @see http://id3.org/id3v2.3.0
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var typedArrayIndexOf = require('../utils/typed-array').typedArrayIndexOf,
|
||||
// Frames that allow different types of text encoding contain a text
|
||||
// encoding description byte [ID3v2.4.0 section 4.]
|
||||
textEncodingDescriptionByte = {
|
||||
Iso88591: 0x00,
|
||||
// ISO-8859-1, terminated with \0.
|
||||
Utf16: 0x01,
|
||||
// UTF-16 encoded Unicode BOM, terminated with \0\0
|
||||
Utf16be: 0x02,
|
||||
// UTF-16BE encoded Unicode, without BOM, terminated with \0\0
|
||||
Utf8: 0x03 // UTF-8 encoded Unicode, terminated with \0
|
||||
|
||||
},
|
||||
// return a percent-encoded representation of the specified byte range
|
||||
// @see http://en.wikipedia.org/wiki/Percent-encoding
|
||||
percentEncode = function percentEncode(bytes, start, end) {
|
||||
var i,
|
||||
result = '';
|
||||
|
||||
for (i = start; i < end; i++) {
|
||||
result += '%' + ('00' + bytes[i].toString(16)).slice(-2);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
// return the string representation of the specified byte range,
|
||||
// interpreted as UTf-8.
|
||||
parseUtf8 = function parseUtf8(bytes, start, end) {
|
||||
return decodeURIComponent(percentEncode(bytes, start, end));
|
||||
},
|
||||
// return the string representation of the specified byte range,
|
||||
// interpreted as ISO-8859-1.
|
||||
parseIso88591 = function parseIso88591(bytes, start, end) {
|
||||
return unescape(percentEncode(bytes, start, end)); // jshint ignore:line
|
||||
},
|
||||
parseSyncSafeInteger = function parseSyncSafeInteger(data) {
|
||||
return data[0] << 21 | data[1] << 14 | data[2] << 7 | data[3];
|
||||
},
|
||||
frameParsers = {
|
||||
'APIC': function APIC(frame) {
|
||||
var i = 1,
|
||||
mimeTypeEndIndex,
|
||||
descriptionEndIndex,
|
||||
LINK_MIME_TYPE = '-->';
|
||||
|
||||
if (frame.data[0] !== textEncodingDescriptionByte.Utf8) {
|
||||
// ignore frames with unrecognized character encodings
|
||||
return;
|
||||
} // parsing fields [ID3v2.4.0 section 4.14.]
|
||||
|
||||
|
||||
mimeTypeEndIndex = typedArrayIndexOf(frame.data, 0, i);
|
||||
|
||||
if (mimeTypeEndIndex < 0) {
|
||||
// malformed frame
|
||||
return;
|
||||
} // parsing Mime type field (terminated with \0)
|
||||
|
||||
|
||||
frame.mimeType = parseIso88591(frame.data, i, mimeTypeEndIndex);
|
||||
i = mimeTypeEndIndex + 1; // parsing 1-byte Picture Type field
|
||||
|
||||
frame.pictureType = frame.data[i];
|
||||
i++;
|
||||
descriptionEndIndex = typedArrayIndexOf(frame.data, 0, i);
|
||||
|
||||
if (descriptionEndIndex < 0) {
|
||||
// malformed frame
|
||||
return;
|
||||
} // parsing Description field (terminated with \0)
|
||||
|
||||
|
||||
frame.description = parseUtf8(frame.data, i, descriptionEndIndex);
|
||||
i = descriptionEndIndex + 1;
|
||||
|
||||
if (frame.mimeType === LINK_MIME_TYPE) {
|
||||
// parsing Picture Data field as URL (always represented as ISO-8859-1 [ID3v2.4.0 section 4.])
|
||||
frame.url = parseIso88591(frame.data, i, frame.data.length);
|
||||
} else {
|
||||
// parsing Picture Data field as binary data
|
||||
frame.pictureData = frame.data.subarray(i, frame.data.length);
|
||||
}
|
||||
},
|
||||
'T*': function T(frame) {
|
||||
if (frame.data[0] !== textEncodingDescriptionByte.Utf8) {
|
||||
// ignore frames with unrecognized character encodings
|
||||
return;
|
||||
} // parse text field, do not include null terminator in the frame value
|
||||
// frames that allow different types of encoding contain terminated text [ID3v2.4.0 section 4.]
|
||||
|
||||
|
||||
frame.value = parseUtf8(frame.data, 1, frame.data.length).replace(/\0*$/, ''); // text information frames supports multiple strings, stored as a terminator separated list [ID3v2.4.0 section 4.2.]
|
||||
|
||||
frame.values = frame.value.split('\0');
|
||||
},
|
||||
'TXXX': function TXXX(frame) {
|
||||
var descriptionEndIndex;
|
||||
|
||||
if (frame.data[0] !== textEncodingDescriptionByte.Utf8) {
|
||||
// ignore frames with unrecognized character encodings
|
||||
return;
|
||||
}
|
||||
|
||||
descriptionEndIndex = typedArrayIndexOf(frame.data, 0, 1);
|
||||
|
||||
if (descriptionEndIndex === -1) {
|
||||
return;
|
||||
} // parse the text fields
|
||||
|
||||
|
||||
frame.description = parseUtf8(frame.data, 1, descriptionEndIndex); // do not include the null terminator in the tag value
|
||||
// frames that allow different types of encoding contain terminated text
|
||||
// [ID3v2.4.0 section 4.]
|
||||
|
||||
frame.value = parseUtf8(frame.data, descriptionEndIndex + 1, frame.data.length).replace(/\0*$/, '');
|
||||
frame.data = frame.value;
|
||||
},
|
||||
'W*': function W(frame) {
|
||||
// parse URL field; URL fields are always represented as ISO-8859-1 [ID3v2.4.0 section 4.]
|
||||
// if the value is followed by a string termination all the following information should be ignored [ID3v2.4.0 section 4.3]
|
||||
frame.url = parseIso88591(frame.data, 0, frame.data.length).replace(/\0.*$/, '');
|
||||
},
|
||||
'WXXX': function WXXX(frame) {
|
||||
var descriptionEndIndex;
|
||||
|
||||
if (frame.data[0] !== textEncodingDescriptionByte.Utf8) {
|
||||
// ignore frames with unrecognized character encodings
|
||||
return;
|
||||
}
|
||||
|
||||
descriptionEndIndex = typedArrayIndexOf(frame.data, 0, 1);
|
||||
|
||||
if (descriptionEndIndex === -1) {
|
||||
return;
|
||||
} // parse the description and URL fields
|
||||
|
||||
|
||||
frame.description = parseUtf8(frame.data, 1, descriptionEndIndex); // URL fields are always represented as ISO-8859-1 [ID3v2.4.0 section 4.]
|
||||
// if the value is followed by a string termination all the following information
|
||||
// should be ignored [ID3v2.4.0 section 4.3]
|
||||
|
||||
frame.url = parseIso88591(frame.data, descriptionEndIndex + 1, frame.data.length).replace(/\0.*$/, '');
|
||||
},
|
||||
'PRIV': function PRIV(frame) {
|
||||
var i;
|
||||
|
||||
for (i = 0; i < frame.data.length; i++) {
|
||||
if (frame.data[i] === 0) {
|
||||
// parse the description and URL fields
|
||||
frame.owner = parseIso88591(frame.data, 0, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
frame.privateData = frame.data.subarray(i + 1);
|
||||
frame.data = frame.privateData;
|
||||
}
|
||||
};
|
||||
|
||||
var parseId3Frames = function parseId3Frames(data) {
|
||||
var frameSize,
|
||||
frameHeader,
|
||||
frameStart = 10,
|
||||
tagSize = 0,
|
||||
frames = []; // If we don't have enough data for a header, 10 bytes,
|
||||
// or 'ID3' in the first 3 bytes this is not a valid ID3 tag.
|
||||
|
||||
if (data.length < 10 || data[0] !== 'I'.charCodeAt(0) || data[1] !== 'D'.charCodeAt(0) || data[2] !== '3'.charCodeAt(0)) {
|
||||
return;
|
||||
} // the frame size is transmitted as a 28-bit integer in the
|
||||
// last four bytes of the ID3 header.
|
||||
// The most significant bit of each byte is dropped and the
|
||||
// results concatenated to recover the actual value.
|
||||
|
||||
|
||||
tagSize = parseSyncSafeInteger(data.subarray(6, 10)); // ID3 reports the tag size excluding the header but it's more
|
||||
// convenient for our comparisons to include it
|
||||
|
||||
tagSize += 10; // check bit 6 of byte 5 for the extended header flag.
|
||||
|
||||
var hasExtendedHeader = data[5] & 0x40;
|
||||
|
||||
if (hasExtendedHeader) {
|
||||
// advance the frame start past the extended header
|
||||
frameStart += 4; // header size field
|
||||
|
||||
frameStart += parseSyncSafeInteger(data.subarray(10, 14));
|
||||
tagSize -= parseSyncSafeInteger(data.subarray(16, 20)); // clip any padding off the end
|
||||
} // parse one or more ID3 frames
|
||||
// http://id3.org/id3v2.3.0#ID3v2_frame_overview
|
||||
|
||||
|
||||
do {
|
||||
// determine the number of bytes in this frame
|
||||
frameSize = parseSyncSafeInteger(data.subarray(frameStart + 4, frameStart + 8));
|
||||
|
||||
if (frameSize < 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
frameHeader = String.fromCharCode(data[frameStart], data[frameStart + 1], data[frameStart + 2], data[frameStart + 3]);
|
||||
var frame = {
|
||||
id: frameHeader,
|
||||
data: data.subarray(frameStart + 10, frameStart + frameSize + 10)
|
||||
};
|
||||
frame.key = frame.id; // parse frame values
|
||||
|
||||
if (frameParsers[frame.id]) {
|
||||
// use frame specific parser
|
||||
frameParsers[frame.id](frame);
|
||||
} else if (frame.id[0] === 'T') {
|
||||
// use text frame generic parser
|
||||
frameParsers['T*'](frame);
|
||||
} else if (frame.id[0] === 'W') {
|
||||
// use URL link frame generic parser
|
||||
frameParsers['W*'](frame);
|
||||
}
|
||||
|
||||
frames.push(frame);
|
||||
frameStart += 10; // advance past the frame header
|
||||
|
||||
frameStart += frameSize; // advance past the frame body
|
||||
} while (frameStart < tagSize);
|
||||
|
||||
return frames;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
parseId3Frames: parseId3Frames,
|
||||
parseSyncSafeInteger: parseSyncSafeInteger,
|
||||
frameParsers: frameParsers
|
||||
};
|
26
node_modules/mux.js/cjs/utils/string.js
generated
vendored
Normal file
26
node_modules/mux.js/cjs/utils/string.js
generated
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
"use strict";
|
||||
|
||||
/**
|
||||
* Returns the first string in the data array ending with a null char '\0'
|
||||
* @param {UInt8} data
|
||||
* @returns the string with the null char
|
||||
*/
|
||||
var uint8ToCString = function uint8ToCString(data) {
|
||||
var index = 0;
|
||||
var curChar = String.fromCharCode(data[index]);
|
||||
var retString = '';
|
||||
|
||||
while (curChar !== '\0') {
|
||||
retString += curChar;
|
||||
index++;
|
||||
curChar = String.fromCharCode(data[index]);
|
||||
} // Add nullChar
|
||||
|
||||
|
||||
retString += curChar;
|
||||
return retString;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
uint8ToCString: uint8ToCString
|
||||
};
|
23
node_modules/mux.js/cjs/utils/typed-array.js
generated
vendored
Normal file
23
node_modules/mux.js/cjs/utils/typed-array.js
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
"use strict";
|
||||
|
||||
// IE11 doesn't support indexOf for TypedArrays.
|
||||
// Once IE11 support is dropped, this function should be removed.
|
||||
var typedArrayIndexOf = function typedArrayIndexOf(typedArray, element, fromIndex) {
|
||||
if (!typedArray) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
var currentIndex = fromIndex;
|
||||
|
||||
for (; currentIndex < typedArray.length; currentIndex++) {
|
||||
if (typedArray[currentIndex] === element) {
|
||||
return currentIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
typedArrayIndexOf: typedArrayIndexOf
|
||||
};
|
103
node_modules/mux.js/es/mp4/emsg.js
generated
vendored
Normal file
103
node_modules/mux.js/es/mp4/emsg.js
generated
vendored
Normal file
|
@ -0,0 +1,103 @@
|
|||
var uint8ToCString = require('../utils/string.js').uint8ToCString;
|
||||
|
||||
var getUint64 = require('../utils/numbers.js').getUint64;
|
||||
/**
|
||||
* Based on: ISO/IEC 23009 Section: 5.10.3.3
|
||||
* References:
|
||||
* https://dashif-documents.azurewebsites.net/Events/master/event.html#emsg-format
|
||||
* https://aomediacodec.github.io/id3-emsg/
|
||||
*
|
||||
* Takes emsg box data as a uint8 array and returns a emsg box object
|
||||
* @param {UInt8Array} boxData data from emsg box
|
||||
* @returns A parsed emsg box object
|
||||
*/
|
||||
|
||||
|
||||
var parseEmsgBox = function parseEmsgBox(boxData) {
|
||||
// version + flags
|
||||
var offset = 4;
|
||||
var version = boxData[0];
|
||||
var scheme_id_uri, value, timescale, presentation_time, presentation_time_delta, event_duration, id, message_data;
|
||||
|
||||
if (version === 0) {
|
||||
scheme_id_uri = uint8ToCString(boxData.subarray(offset));
|
||||
offset += scheme_id_uri.length;
|
||||
value = uint8ToCString(boxData.subarray(offset));
|
||||
offset += value.length;
|
||||
var dv = new DataView(boxData.buffer);
|
||||
timescale = dv.getUint32(offset);
|
||||
offset += 4;
|
||||
presentation_time_delta = dv.getUint32(offset);
|
||||
offset += 4;
|
||||
event_duration = dv.getUint32(offset);
|
||||
offset += 4;
|
||||
id = dv.getUint32(offset);
|
||||
offset += 4;
|
||||
} else if (version === 1) {
|
||||
var dv = new DataView(boxData.buffer);
|
||||
timescale = dv.getUint32(offset);
|
||||
offset += 4;
|
||||
presentation_time = getUint64(boxData.subarray(offset));
|
||||
offset += 8;
|
||||
event_duration = dv.getUint32(offset);
|
||||
offset += 4;
|
||||
id = dv.getUint32(offset);
|
||||
offset += 4;
|
||||
scheme_id_uri = uint8ToCString(boxData.subarray(offset));
|
||||
offset += scheme_id_uri.length;
|
||||
value = uint8ToCString(boxData.subarray(offset));
|
||||
offset += value.length;
|
||||
}
|
||||
|
||||
message_data = new Uint8Array(boxData.subarray(offset, boxData.byteLength));
|
||||
var emsgBox = {
|
||||
scheme_id_uri: scheme_id_uri,
|
||||
value: value,
|
||||
// if timescale is undefined or 0 set to 1
|
||||
timescale: timescale ? timescale : 1,
|
||||
presentation_time: presentation_time,
|
||||
presentation_time_delta: presentation_time_delta,
|
||||
event_duration: event_duration,
|
||||
id: id,
|
||||
message_data: message_data
|
||||
};
|
||||
return isValidEmsgBox(version, emsgBox) ? emsgBox : undefined;
|
||||
};
|
||||
/**
|
||||
* Scales a presentation time or time delta with an offset with a provided timescale
|
||||
* @param {number} presentationTime
|
||||
* @param {number} timescale
|
||||
* @param {number} timeDelta
|
||||
* @param {number} offset
|
||||
* @returns the scaled time as a number
|
||||
*/
|
||||
|
||||
|
||||
var scaleTime = function scaleTime(presentationTime, timescale, timeDelta, offset) {
|
||||
return presentationTime || presentationTime === 0 ? presentationTime / timescale : offset + timeDelta / timescale;
|
||||
};
|
||||
/**
|
||||
* Checks the emsg box data for validity based on the version
|
||||
* @param {number} version of the emsg box to validate
|
||||
* @param {Object} emsg the emsg data to validate
|
||||
* @returns if the box is valid as a boolean
|
||||
*/
|
||||
|
||||
|
||||
var isValidEmsgBox = function isValidEmsgBox(version, emsg) {
|
||||
var hasScheme = emsg.scheme_id_uri !== '\0';
|
||||
var isValidV0Box = version === 0 && isDefined(emsg.presentation_time_delta) && hasScheme;
|
||||
var isValidV1Box = version === 1 && isDefined(emsg.presentation_time) && hasScheme; // Only valid versions of emsg are 0 and 1
|
||||
|
||||
return !(version > 1) && isValidV0Box || isValidV1Box;
|
||||
}; // Utility function to check if an object is defined
|
||||
|
||||
|
||||
var isDefined = function isDefined(data) {
|
||||
return data !== undefined || data !== null;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
parseEmsgBox: parseEmsgBox,
|
||||
scaleTime: scaleTime
|
||||
};
|
243
node_modules/mux.js/es/tools/parse-id3.js
generated
vendored
Normal file
243
node_modules/mux.js/es/tools/parse-id3.js
generated
vendored
Normal file
|
@ -0,0 +1,243 @@
|
|||
/**
|
||||
* mux.js
|
||||
*
|
||||
* Copyright (c) Brightcove
|
||||
* Licensed Apache-2.0 https://github.com/videojs/mux.js/blob/master/LICENSE
|
||||
*
|
||||
* Tools for parsing ID3 frame data
|
||||
* @see http://id3.org/id3v2.3.0
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var typedArrayIndexOf = require('../utils/typed-array').typedArrayIndexOf,
|
||||
// Frames that allow different types of text encoding contain a text
|
||||
// encoding description byte [ID3v2.4.0 section 4.]
|
||||
textEncodingDescriptionByte = {
|
||||
Iso88591: 0x00,
|
||||
// ISO-8859-1, terminated with \0.
|
||||
Utf16: 0x01,
|
||||
// UTF-16 encoded Unicode BOM, terminated with \0\0
|
||||
Utf16be: 0x02,
|
||||
// UTF-16BE encoded Unicode, without BOM, terminated with \0\0
|
||||
Utf8: 0x03 // UTF-8 encoded Unicode, terminated with \0
|
||||
|
||||
},
|
||||
// return a percent-encoded representation of the specified byte range
|
||||
// @see http://en.wikipedia.org/wiki/Percent-encoding
|
||||
percentEncode = function percentEncode(bytes, start, end) {
|
||||
var i,
|
||||
result = '';
|
||||
|
||||
for (i = start; i < end; i++) {
|
||||
result += '%' + ('00' + bytes[i].toString(16)).slice(-2);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
// return the string representation of the specified byte range,
|
||||
// interpreted as UTf-8.
|
||||
parseUtf8 = function parseUtf8(bytes, start, end) {
|
||||
return decodeURIComponent(percentEncode(bytes, start, end));
|
||||
},
|
||||
// return the string representation of the specified byte range,
|
||||
// interpreted as ISO-8859-1.
|
||||
parseIso88591 = function parseIso88591(bytes, start, end) {
|
||||
return unescape(percentEncode(bytes, start, end)); // jshint ignore:line
|
||||
},
|
||||
parseSyncSafeInteger = function parseSyncSafeInteger(data) {
|
||||
return data[0] << 21 | data[1] << 14 | data[2] << 7 | data[3];
|
||||
},
|
||||
frameParsers = {
|
||||
'APIC': function APIC(frame) {
|
||||
var i = 1,
|
||||
mimeTypeEndIndex,
|
||||
descriptionEndIndex,
|
||||
LINK_MIME_TYPE = '-->';
|
||||
|
||||
if (frame.data[0] !== textEncodingDescriptionByte.Utf8) {
|
||||
// ignore frames with unrecognized character encodings
|
||||
return;
|
||||
} // parsing fields [ID3v2.4.0 section 4.14.]
|
||||
|
||||
|
||||
mimeTypeEndIndex = typedArrayIndexOf(frame.data, 0, i);
|
||||
|
||||
if (mimeTypeEndIndex < 0) {
|
||||
// malformed frame
|
||||
return;
|
||||
} // parsing Mime type field (terminated with \0)
|
||||
|
||||
|
||||
frame.mimeType = parseIso88591(frame.data, i, mimeTypeEndIndex);
|
||||
i = mimeTypeEndIndex + 1; // parsing 1-byte Picture Type field
|
||||
|
||||
frame.pictureType = frame.data[i];
|
||||
i++;
|
||||
descriptionEndIndex = typedArrayIndexOf(frame.data, 0, i);
|
||||
|
||||
if (descriptionEndIndex < 0) {
|
||||
// malformed frame
|
||||
return;
|
||||
} // parsing Description field (terminated with \0)
|
||||
|
||||
|
||||
frame.description = parseUtf8(frame.data, i, descriptionEndIndex);
|
||||
i = descriptionEndIndex + 1;
|
||||
|
||||
if (frame.mimeType === LINK_MIME_TYPE) {
|
||||
// parsing Picture Data field as URL (always represented as ISO-8859-1 [ID3v2.4.0 section 4.])
|
||||
frame.url = parseIso88591(frame.data, i, frame.data.length);
|
||||
} else {
|
||||
// parsing Picture Data field as binary data
|
||||
frame.pictureData = frame.data.subarray(i, frame.data.length);
|
||||
}
|
||||
},
|
||||
'T*': function T(frame) {
|
||||
if (frame.data[0] !== textEncodingDescriptionByte.Utf8) {
|
||||
// ignore frames with unrecognized character encodings
|
||||
return;
|
||||
} // parse text field, do not include null terminator in the frame value
|
||||
// frames that allow different types of encoding contain terminated text [ID3v2.4.0 section 4.]
|
||||
|
||||
|
||||
frame.value = parseUtf8(frame.data, 1, frame.data.length).replace(/\0*$/, ''); // text information frames supports multiple strings, stored as a terminator separated list [ID3v2.4.0 section 4.2.]
|
||||
|
||||
frame.values = frame.value.split('\0');
|
||||
},
|
||||
'TXXX': function TXXX(frame) {
|
||||
var descriptionEndIndex;
|
||||
|
||||
if (frame.data[0] !== textEncodingDescriptionByte.Utf8) {
|
||||
// ignore frames with unrecognized character encodings
|
||||
return;
|
||||
}
|
||||
|
||||
descriptionEndIndex = typedArrayIndexOf(frame.data, 0, 1);
|
||||
|
||||
if (descriptionEndIndex === -1) {
|
||||
return;
|
||||
} // parse the text fields
|
||||
|
||||
|
||||
frame.description = parseUtf8(frame.data, 1, descriptionEndIndex); // do not include the null terminator in the tag value
|
||||
// frames that allow different types of encoding contain terminated text
|
||||
// [ID3v2.4.0 section 4.]
|
||||
|
||||
frame.value = parseUtf8(frame.data, descriptionEndIndex + 1, frame.data.length).replace(/\0*$/, '');
|
||||
frame.data = frame.value;
|
||||
},
|
||||
'W*': function W(frame) {
|
||||
// parse URL field; URL fields are always represented as ISO-8859-1 [ID3v2.4.0 section 4.]
|
||||
// if the value is followed by a string termination all the following information should be ignored [ID3v2.4.0 section 4.3]
|
||||
frame.url = parseIso88591(frame.data, 0, frame.data.length).replace(/\0.*$/, '');
|
||||
},
|
||||
'WXXX': function WXXX(frame) {
|
||||
var descriptionEndIndex;
|
||||
|
||||
if (frame.data[0] !== textEncodingDescriptionByte.Utf8) {
|
||||
// ignore frames with unrecognized character encodings
|
||||
return;
|
||||
}
|
||||
|
||||
descriptionEndIndex = typedArrayIndexOf(frame.data, 0, 1);
|
||||
|
||||
if (descriptionEndIndex === -1) {
|
||||
return;
|
||||
} // parse the description and URL fields
|
||||
|
||||
|
||||
frame.description = parseUtf8(frame.data, 1, descriptionEndIndex); // URL fields are always represented as ISO-8859-1 [ID3v2.4.0 section 4.]
|
||||
// if the value is followed by a string termination all the following information
|
||||
// should be ignored [ID3v2.4.0 section 4.3]
|
||||
|
||||
frame.url = parseIso88591(frame.data, descriptionEndIndex + 1, frame.data.length).replace(/\0.*$/, '');
|
||||
},
|
||||
'PRIV': function PRIV(frame) {
|
||||
var i;
|
||||
|
||||
for (i = 0; i < frame.data.length; i++) {
|
||||
if (frame.data[i] === 0) {
|
||||
// parse the description and URL fields
|
||||
frame.owner = parseIso88591(frame.data, 0, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
frame.privateData = frame.data.subarray(i + 1);
|
||||
frame.data = frame.privateData;
|
||||
}
|
||||
};
|
||||
|
||||
var parseId3Frames = function parseId3Frames(data) {
|
||||
var frameSize,
|
||||
frameHeader,
|
||||
frameStart = 10,
|
||||
tagSize = 0,
|
||||
frames = []; // If we don't have enough data for a header, 10 bytes,
|
||||
// or 'ID3' in the first 3 bytes this is not a valid ID3 tag.
|
||||
|
||||
if (data.length < 10 || data[0] !== 'I'.charCodeAt(0) || data[1] !== 'D'.charCodeAt(0) || data[2] !== '3'.charCodeAt(0)) {
|
||||
return;
|
||||
} // the frame size is transmitted as a 28-bit integer in the
|
||||
// last four bytes of the ID3 header.
|
||||
// The most significant bit of each byte is dropped and the
|
||||
// results concatenated to recover the actual value.
|
||||
|
||||
|
||||
tagSize = parseSyncSafeInteger(data.subarray(6, 10)); // ID3 reports the tag size excluding the header but it's more
|
||||
// convenient for our comparisons to include it
|
||||
|
||||
tagSize += 10; // check bit 6 of byte 5 for the extended header flag.
|
||||
|
||||
var hasExtendedHeader = data[5] & 0x40;
|
||||
|
||||
if (hasExtendedHeader) {
|
||||
// advance the frame start past the extended header
|
||||
frameStart += 4; // header size field
|
||||
|
||||
frameStart += parseSyncSafeInteger(data.subarray(10, 14));
|
||||
tagSize -= parseSyncSafeInteger(data.subarray(16, 20)); // clip any padding off the end
|
||||
} // parse one or more ID3 frames
|
||||
// http://id3.org/id3v2.3.0#ID3v2_frame_overview
|
||||
|
||||
|
||||
do {
|
||||
// determine the number of bytes in this frame
|
||||
frameSize = parseSyncSafeInteger(data.subarray(frameStart + 4, frameStart + 8));
|
||||
|
||||
if (frameSize < 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
frameHeader = String.fromCharCode(data[frameStart], data[frameStart + 1], data[frameStart + 2], data[frameStart + 3]);
|
||||
var frame = {
|
||||
id: frameHeader,
|
||||
data: data.subarray(frameStart + 10, frameStart + frameSize + 10)
|
||||
};
|
||||
frame.key = frame.id; // parse frame values
|
||||
|
||||
if (frameParsers[frame.id]) {
|
||||
// use frame specific parser
|
||||
frameParsers[frame.id](frame);
|
||||
} else if (frame.id[0] === 'T') {
|
||||
// use text frame generic parser
|
||||
frameParsers['T*'](frame);
|
||||
} else if (frame.id[0] === 'W') {
|
||||
// use URL link frame generic parser
|
||||
frameParsers['W*'](frame);
|
||||
}
|
||||
|
||||
frames.push(frame);
|
||||
frameStart += 10; // advance past the frame header
|
||||
|
||||
frameStart += frameSize; // advance past the frame body
|
||||
} while (frameStart < tagSize);
|
||||
|
||||
return frames;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
parseId3Frames: parseId3Frames,
|
||||
parseSyncSafeInteger: parseSyncSafeInteger,
|
||||
frameParsers: frameParsers
|
||||
};
|
24
node_modules/mux.js/es/utils/string.js
generated
vendored
Normal file
24
node_modules/mux.js/es/utils/string.js
generated
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* Returns the first string in the data array ending with a null char '\0'
|
||||
* @param {UInt8} data
|
||||
* @returns the string with the null char
|
||||
*/
|
||||
var uint8ToCString = function uint8ToCString(data) {
|
||||
var index = 0;
|
||||
var curChar = String.fromCharCode(data[index]);
|
||||
var retString = '';
|
||||
|
||||
while (curChar !== '\0') {
|
||||
retString += curChar;
|
||||
index++;
|
||||
curChar = String.fromCharCode(data[index]);
|
||||
} // Add nullChar
|
||||
|
||||
|
||||
retString += curChar;
|
||||
return retString;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
uint8ToCString: uint8ToCString
|
||||
};
|
21
node_modules/mux.js/es/utils/typed-array.js
generated
vendored
Normal file
21
node_modules/mux.js/es/utils/typed-array.js
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
// IE11 doesn't support indexOf for TypedArrays.
|
||||
// Once IE11 support is dropped, this function should be removed.
|
||||
var typedArrayIndexOf = function typedArrayIndexOf(typedArray, element, fromIndex) {
|
||||
if (!typedArray) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
var currentIndex = fromIndex;
|
||||
|
||||
for (; currentIndex < typedArray.length; currentIndex++) {
|
||||
if (typedArray[currentIndex] === element) {
|
||||
return currentIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
typedArrayIndexOf: typedArrayIndexOf
|
||||
};
|
105
node_modules/mux.js/lib/mp4/emsg.js
generated
vendored
Normal file
105
node_modules/mux.js/lib/mp4/emsg.js
generated
vendored
Normal file
|
@ -0,0 +1,105 @@
|
|||
var uint8ToCString = require('../utils/string.js').uint8ToCString;
|
||||
var getUint64 = require('../utils/numbers.js').getUint64;
|
||||
|
||||
/**
|
||||
* Based on: ISO/IEC 23009 Section: 5.10.3.3
|
||||
* References:
|
||||
* https://dashif-documents.azurewebsites.net/Events/master/event.html#emsg-format
|
||||
* https://aomediacodec.github.io/id3-emsg/
|
||||
*
|
||||
* Takes emsg box data as a uint8 array and returns a emsg box object
|
||||
* @param {UInt8Array} boxData data from emsg box
|
||||
* @returns A parsed emsg box object
|
||||
*/
|
||||
var parseEmsgBox = function(boxData) {
|
||||
// version + flags
|
||||
var offset = 4;
|
||||
var version = boxData[0];
|
||||
var scheme_id_uri,
|
||||
value,
|
||||
timescale,
|
||||
presentation_time,
|
||||
presentation_time_delta,
|
||||
event_duration,
|
||||
id,
|
||||
message_data;
|
||||
if (version === 0) {
|
||||
scheme_id_uri = uint8ToCString(boxData.subarray(offset));
|
||||
offset += scheme_id_uri.length;
|
||||
value = uint8ToCString(boxData.subarray(offset));
|
||||
offset += value.length;
|
||||
var dv = new DataView(boxData.buffer);
|
||||
timescale = dv.getUint32(offset);
|
||||
offset += 4;
|
||||
presentation_time_delta = dv.getUint32(offset);
|
||||
offset += 4;
|
||||
event_duration = dv.getUint32(offset);
|
||||
offset += 4;
|
||||
id = dv.getUint32(offset);
|
||||
offset += 4;
|
||||
} else if (version === 1) {
|
||||
var dv = new DataView(boxData.buffer);
|
||||
timescale = dv.getUint32(offset);
|
||||
offset += 4;
|
||||
presentation_time = getUint64(boxData.subarray(offset));
|
||||
offset += 8;
|
||||
event_duration = dv.getUint32(offset);
|
||||
offset += 4;
|
||||
id = dv.getUint32(offset);
|
||||
offset += 4;
|
||||
scheme_id_uri = uint8ToCString(boxData.subarray(offset));
|
||||
offset += scheme_id_uri.length;
|
||||
value = uint8ToCString(boxData.subarray(offset));
|
||||
offset += value.length;
|
||||
}
|
||||
|
||||
message_data = new Uint8Array(boxData.subarray(offset, boxData.byteLength));
|
||||
var emsgBox = {
|
||||
scheme_id_uri,
|
||||
value,
|
||||
// if timescale is undefined or 0 set to 1
|
||||
timescale: timescale ? timescale : 1,
|
||||
presentation_time,
|
||||
presentation_time_delta,
|
||||
event_duration,
|
||||
id,
|
||||
message_data };
|
||||
|
||||
return isValidEmsgBox(version, emsgBox) ? emsgBox : undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Scales a presentation time or time delta with an offset with a provided timescale
|
||||
* @param {number} presentationTime
|
||||
* @param {number} timescale
|
||||
* @param {number} timeDelta
|
||||
* @param {number} offset
|
||||
* @returns the scaled time as a number
|
||||
*/
|
||||
var scaleTime = function(presentationTime, timescale, timeDelta, offset) {
|
||||
return presentationTime || presentationTime === 0 ? presentationTime / timescale : offset + timeDelta / timescale;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks the emsg box data for validity based on the version
|
||||
* @param {number} version of the emsg box to validate
|
||||
* @param {Object} emsg the emsg data to validate
|
||||
* @returns if the box is valid as a boolean
|
||||
*/
|
||||
var isValidEmsgBox = function(version, emsg) {
|
||||
var hasScheme = emsg.scheme_id_uri !== '\0'
|
||||
var isValidV0Box = version === 0 && isDefined(emsg.presentation_time_delta) && hasScheme;
|
||||
var isValidV1Box = version === 1 && isDefined(emsg.presentation_time) && hasScheme;
|
||||
// Only valid versions of emsg are 0 and 1
|
||||
return !(version > 1) && isValidV0Box || isValidV1Box;
|
||||
};
|
||||
|
||||
// Utility function to check if an object is defined
|
||||
var isDefined = function(data) {
|
||||
return data !== undefined || data !== null;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
parseEmsgBox: parseEmsgBox,
|
||||
scaleTime: scaleTime
|
||||
};
|
252
node_modules/mux.js/lib/tools/parse-id3.js
generated
vendored
Normal file
252
node_modules/mux.js/lib/tools/parse-id3.js
generated
vendored
Normal file
|
@ -0,0 +1,252 @@
|
|||
/**
|
||||
* mux.js
|
||||
*
|
||||
* Copyright (c) Brightcove
|
||||
* Licensed Apache-2.0 https://github.com/videojs/mux.js/blob/master/LICENSE
|
||||
*
|
||||
* Tools for parsing ID3 frame data
|
||||
* @see http://id3.org/id3v2.3.0
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var
|
||||
typedArrayIndexOf = require('../utils/typed-array').typedArrayIndexOf,
|
||||
// Frames that allow different types of text encoding contain a text
|
||||
// encoding description byte [ID3v2.4.0 section 4.]
|
||||
textEncodingDescriptionByte = {
|
||||
Iso88591: 0x00, // ISO-8859-1, terminated with \0.
|
||||
Utf16: 0x01, // UTF-16 encoded Unicode BOM, terminated with \0\0
|
||||
Utf16be: 0x02, // UTF-16BE encoded Unicode, without BOM, terminated with \0\0
|
||||
Utf8: 0x03 // UTF-8 encoded Unicode, terminated with \0
|
||||
},
|
||||
// return a percent-encoded representation of the specified byte range
|
||||
// @see http://en.wikipedia.org/wiki/Percent-encoding
|
||||
percentEncode = function(bytes, start, end) {
|
||||
var i, result = '';
|
||||
for (i = start; i < end; i++) {
|
||||
result += '%' + ('00' + bytes[i].toString(16)).slice(-2);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
// return the string representation of the specified byte range,
|
||||
// interpreted as UTf-8.
|
||||
parseUtf8 = function(bytes, start, end) {
|
||||
return decodeURIComponent(percentEncode(bytes, start, end));
|
||||
},
|
||||
// return the string representation of the specified byte range,
|
||||
// interpreted as ISO-8859-1.
|
||||
parseIso88591 = function(bytes, start, end) {
|
||||
return unescape(percentEncode(bytes, start, end)); // jshint ignore:line
|
||||
},
|
||||
parseSyncSafeInteger = function(data) {
|
||||
return (data[0] << 21) |
|
||||
(data[1] << 14) |
|
||||
(data[2] << 7) |
|
||||
(data[3]);
|
||||
},
|
||||
frameParsers = {
|
||||
'APIC': function(frame) {
|
||||
var
|
||||
i = 1,
|
||||
mimeTypeEndIndex,
|
||||
descriptionEndIndex,
|
||||
LINK_MIME_TYPE = '-->';
|
||||
|
||||
if (frame.data[0] !== textEncodingDescriptionByte.Utf8) {
|
||||
// ignore frames with unrecognized character encodings
|
||||
return;
|
||||
}
|
||||
|
||||
// parsing fields [ID3v2.4.0 section 4.14.]
|
||||
mimeTypeEndIndex = typedArrayIndexOf(frame.data, 0, i);
|
||||
if (mimeTypeEndIndex < 0) {
|
||||
// malformed frame
|
||||
return;
|
||||
}
|
||||
|
||||
// parsing Mime type field (terminated with \0)
|
||||
frame.mimeType = parseIso88591(frame.data, i, mimeTypeEndIndex);
|
||||
i = mimeTypeEndIndex + 1;
|
||||
|
||||
// parsing 1-byte Picture Type field
|
||||
frame.pictureType = frame.data[i];
|
||||
i++
|
||||
|
||||
descriptionEndIndex = typedArrayIndexOf(frame.data, 0, i);
|
||||
if (descriptionEndIndex < 0) {
|
||||
// malformed frame
|
||||
return;
|
||||
}
|
||||
|
||||
// parsing Description field (terminated with \0)
|
||||
frame.description = parseUtf8(frame.data, i, descriptionEndIndex);
|
||||
i = descriptionEndIndex + 1;
|
||||
|
||||
if (frame.mimeType === LINK_MIME_TYPE) {
|
||||
// parsing Picture Data field as URL (always represented as ISO-8859-1 [ID3v2.4.0 section 4.])
|
||||
frame.url = parseIso88591(frame.data, i, frame.data.length)
|
||||
} else {
|
||||
// parsing Picture Data field as binary data
|
||||
frame.pictureData = frame.data.subarray(i, frame.data.length);
|
||||
}
|
||||
},
|
||||
'T*': function(frame) {
|
||||
if (frame.data[0] !== textEncodingDescriptionByte.Utf8) {
|
||||
// ignore frames with unrecognized character encodings
|
||||
return;
|
||||
}
|
||||
|
||||
// parse text field, do not include null terminator in the frame value
|
||||
// frames that allow different types of encoding contain terminated text [ID3v2.4.0 section 4.]
|
||||
frame.value = parseUtf8(frame.data, 1, frame.data.length).replace(/\0*$/, '');
|
||||
// text information frames supports multiple strings, stored as a terminator separated list [ID3v2.4.0 section 4.2.]
|
||||
frame.values = frame.value.split('\0');
|
||||
},
|
||||
'TXXX': function(frame) {
|
||||
var descriptionEndIndex;
|
||||
|
||||
if (frame.data[0] !== textEncodingDescriptionByte.Utf8) {
|
||||
// ignore frames with unrecognized character encodings
|
||||
return;
|
||||
}
|
||||
|
||||
descriptionEndIndex = typedArrayIndexOf(frame.data, 0, 1);
|
||||
|
||||
if (descriptionEndIndex === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// parse the text fields
|
||||
frame.description = parseUtf8(frame.data, 1, descriptionEndIndex);
|
||||
// do not include the null terminator in the tag value
|
||||
// frames that allow different types of encoding contain terminated text
|
||||
// [ID3v2.4.0 section 4.]
|
||||
frame.value = parseUtf8(
|
||||
frame.data,
|
||||
descriptionEndIndex + 1,
|
||||
frame.data.length
|
||||
).replace(/\0*$/, '');
|
||||
frame.data = frame.value;
|
||||
},
|
||||
'W*': function(frame) {
|
||||
// parse URL field; URL fields are always represented as ISO-8859-1 [ID3v2.4.0 section 4.]
|
||||
// if the value is followed by a string termination all the following information should be ignored [ID3v2.4.0 section 4.3]
|
||||
frame.url = parseIso88591(frame.data, 0, frame.data.length).replace(/\0.*$/, '');
|
||||
},
|
||||
'WXXX': function(frame) {
|
||||
var descriptionEndIndex;
|
||||
|
||||
if (frame.data[0] !== textEncodingDescriptionByte.Utf8) {
|
||||
// ignore frames with unrecognized character encodings
|
||||
return;
|
||||
}
|
||||
|
||||
descriptionEndIndex = typedArrayIndexOf(frame.data, 0, 1);
|
||||
|
||||
if (descriptionEndIndex === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// parse the description and URL fields
|
||||
frame.description = parseUtf8(frame.data, 1, descriptionEndIndex);
|
||||
// URL fields are always represented as ISO-8859-1 [ID3v2.4.0 section 4.]
|
||||
// if the value is followed by a string termination all the following information
|
||||
// should be ignored [ID3v2.4.0 section 4.3]
|
||||
frame.url = parseIso88591(
|
||||
frame.data,
|
||||
descriptionEndIndex + 1,
|
||||
frame.data.length
|
||||
).replace(/\0.*$/, '');
|
||||
},
|
||||
'PRIV': function(frame) {
|
||||
var i;
|
||||
|
||||
for (i = 0; i < frame.data.length; i++) {
|
||||
if (frame.data[i] === 0) {
|
||||
// parse the description and URL fields
|
||||
frame.owner = parseIso88591(frame.data, 0, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
frame.privateData = frame.data.subarray(i + 1);
|
||||
frame.data = frame.privateData;
|
||||
}
|
||||
};
|
||||
|
||||
var parseId3Frames = function(data) {
|
||||
var frameSize, frameHeader,
|
||||
frameStart = 10,
|
||||
tagSize = 0,
|
||||
frames = [];
|
||||
|
||||
// If we don't have enough data for a header, 10 bytes,
|
||||
// or 'ID3' in the first 3 bytes this is not a valid ID3 tag.
|
||||
if (data.length < 10 ||
|
||||
data[0] !== 'I'.charCodeAt(0) ||
|
||||
data[1] !== 'D'.charCodeAt(0) ||
|
||||
data[2] !== '3'.charCodeAt(0)) {
|
||||
return;
|
||||
}
|
||||
// the frame size is transmitted as a 28-bit integer in the
|
||||
// last four bytes of the ID3 header.
|
||||
// The most significant bit of each byte is dropped and the
|
||||
// results concatenated to recover the actual value.
|
||||
tagSize = parseSyncSafeInteger(data.subarray(6, 10));
|
||||
|
||||
// ID3 reports the tag size excluding the header but it's more
|
||||
// convenient for our comparisons to include it
|
||||
tagSize += 10;
|
||||
// check bit 6 of byte 5 for the extended header flag.
|
||||
var hasExtendedHeader = data[5] & 0x40;
|
||||
if (hasExtendedHeader) {
|
||||
// advance the frame start past the extended header
|
||||
frameStart += 4; // header size field
|
||||
frameStart += parseSyncSafeInteger(data.subarray(10, 14));
|
||||
tagSize -= parseSyncSafeInteger(data.subarray(16, 20)); // clip any padding off the end
|
||||
}
|
||||
|
||||
// parse one or more ID3 frames
|
||||
// http://id3.org/id3v2.3.0#ID3v2_frame_overview
|
||||
do {
|
||||
// determine the number of bytes in this frame
|
||||
frameSize = parseSyncSafeInteger(data.subarray(frameStart + 4, frameStart + 8));
|
||||
if (frameSize < 1) {
|
||||
break;
|
||||
}
|
||||
frameHeader = String.fromCharCode(data[frameStart],
|
||||
data[frameStart + 1],
|
||||
data[frameStart + 2],
|
||||
data[frameStart + 3]);
|
||||
|
||||
var frame = {
|
||||
id: frameHeader,
|
||||
data: data.subarray(frameStart + 10, frameStart + frameSize + 10)
|
||||
};
|
||||
frame.key = frame.id;
|
||||
|
||||
// parse frame values
|
||||
if (frameParsers[frame.id]) {
|
||||
// use frame specific parser
|
||||
frameParsers[frame.id](frame);
|
||||
} else if (frame.id[0] === 'T') {
|
||||
// use text frame generic parser
|
||||
frameParsers['T*'](frame);
|
||||
} else if (frame.id[0] === 'W') {
|
||||
// use URL link frame generic parser
|
||||
frameParsers['W*'](frame);
|
||||
}
|
||||
|
||||
frames.push(frame);
|
||||
|
||||
frameStart += 10; // advance past the frame header
|
||||
frameStart += frameSize; // advance past the frame body
|
||||
} while (frameStart < tagSize);
|
||||
|
||||
return frames;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
parseId3Frames: parseId3Frames,
|
||||
parseSyncSafeInteger: parseSyncSafeInteger,
|
||||
frameParsers: frameParsers,
|
||||
};
|
20
node_modules/mux.js/lib/utils/string.js
generated
vendored
Normal file
20
node_modules/mux.js/lib/utils/string.js
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* Returns the first string in the data array ending with a null char '\0'
|
||||
* @param {UInt8} data
|
||||
* @returns the string with the null char
|
||||
*/
|
||||
var uint8ToCString = function(data) {
|
||||
var index = 0;
|
||||
var curChar = String.fromCharCode(data[index]);
|
||||
var retString = '';
|
||||
while (curChar !== '\0') {
|
||||
retString += curChar;
|
||||
index++;
|
||||
curChar = String.fromCharCode(data[index]);
|
||||
}
|
||||
// Add nullChar
|
||||
retString += curChar;
|
||||
return retString;
|
||||
};
|
||||
|
||||
module.exports = { uint8ToCString };
|
19
node_modules/mux.js/lib/utils/typed-array.js
generated
vendored
Normal file
19
node_modules/mux.js/lib/utils/typed-array.js
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
// IE11 doesn't support indexOf for TypedArrays.
|
||||
// Once IE11 support is dropped, this function should be removed.
|
||||
var typedArrayIndexOf = (typedArray, element, fromIndex) => {
|
||||
if (!typedArray) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
var currentIndex = fromIndex;
|
||||
|
||||
for (; currentIndex < typedArray.length; currentIndex++) {
|
||||
if (typedArray[currentIndex] === element) {
|
||||
return currentIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
|
||||
module.exports = { typedArrayIndexOf };
|
49
node_modules/mux.js/test/mp4-emsg.test.js
generated
vendored
Normal file
49
node_modules/mux.js/test/mp4-emsg.test.js
generated
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
'use strict';
|
||||
|
||||
var QUnit = require('qunit'),
|
||||
emsg = require('../lib/mp4/emsg'),
|
||||
generateEmsgBoxData = require('./utils/mp4-helpers').generateEmsgBoxData,
|
||||
messageData = new Uint8Array([0x64, 0x61, 0x74, 0x61]); // data;
|
||||
|
||||
QUnit.module('EMSG Parsing');
|
||||
|
||||
QUnit.test('Can parse a v0 emsg box', function(assert) {
|
||||
var boxData = generateEmsgBoxData(0, messageData);
|
||||
var parsedBox = emsg.parseEmsgBox(boxData);
|
||||
|
||||
assert.equal(parsedBox.scheme_id_uri, 'urn:foo:bar:2023\0', 'v0 box has expected scheme_id_uri');
|
||||
assert.equal(parsedBox.value, 'foo.bar.value\0', 'v0 box has expected value');
|
||||
assert.equal(parsedBox.timescale, 100, 'v0 box has expected timescale');
|
||||
assert.equal(parsedBox.presentation_time, undefined, 'v0 box has expected presentation_time');
|
||||
assert.equal(parsedBox.presentation_time_delta, 1000, 'v0 box has expected presentation_time_delta');
|
||||
assert.equal(parsedBox.event_duration, 0, 'v0 box has expected event_duration');
|
||||
assert.equal(parsedBox.id, 1, 'v0 box has expected id');
|
||||
assert.deepEqual(parsedBox.message_data, messageData, 'v0 box has expected data');
|
||||
|
||||
});
|
||||
|
||||
QUnit.test('Can parse a v1 emsg box', function(assert) {
|
||||
var boxData = generateEmsgBoxData(1, messageData);
|
||||
var parsedBox = emsg.parseEmsgBox(boxData);
|
||||
|
||||
assert.equal(parsedBox.scheme_id_uri, 'urn:foo:bar:2023\0', 'v1 box has expected scheme_id_uri');
|
||||
assert.equal(parsedBox.value, 'foo.bar.value\0', 'v1 box has expected value');
|
||||
assert.equal(parsedBox.timescale, 100, 'v1 box has expected timescale');
|
||||
assert.equal(parsedBox.presentation_time, 10000, 'v1 box has expected presentation_time');
|
||||
assert.equal(parsedBox.presentation_time_delta, undefined, 'v1 box has expected presentation_time_delta');
|
||||
assert.equal(parsedBox.event_duration, 1, 'v1 box has expected event_duration');
|
||||
assert.equal(parsedBox.id, 2, 'v1 box has expected id');
|
||||
assert.deepEqual(parsedBox.message_data, messageData, 'v1 box has expected data');
|
||||
});
|
||||
|
||||
QUnit.test('Will return undefined if the emsg version is invalid', function(assert) {
|
||||
var badBoxData = generateEmsgBoxData(2, messageData);
|
||||
var parsedBox = emsg.parseEmsgBox(badBoxData);
|
||||
assert.equal(parsedBox, undefined, 'parsed box is undefined');
|
||||
});
|
||||
|
||||
QUnit.test('Will return undefined if the emsg data is malformed', function(assert) {
|
||||
var badBoxData = generateEmsgBoxData(3, messageData);
|
||||
var parsedBox = emsg.parseEmsgBox(badBoxData);
|
||||
assert.equal(parsedBox, undefined, 'malformed box is undefined');
|
||||
});
|
32
node_modules/mux.js/test/utils.string.test.js
generated
vendored
Normal file
32
node_modules/mux.js/test/utils.string.test.js
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
'use strict';
|
||||
|
||||
var
|
||||
QUnit = require('qunit'),
|
||||
string = require('../lib/utils/string');
|
||||
|
||||
QUnit.module('String Utils');
|
||||
|
||||
QUnit.test('Converts a uint8 array into a C string from start of array until first null char', function(assert) {
|
||||
var uint8String = new Uint8Array([0x66, 0x6F, 0x6F, 0x2E, 0x62, 0x61, 0x72, 0x2E, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x00,
|
||||
0x76, 0x61, 0x6C, 0x75, 0x65, 0x2E, 0x62, 0x61, 0x72, 0x00]); // foo.bar.value\0value.bar\0
|
||||
var firstString = string.uint8ToCString(uint8String);
|
||||
assert.equal(firstString, 'foo.bar.value\0', 'converts uint8 data to a c string');
|
||||
assert.equal(firstString.length, 14, 'string has the correct length');
|
||||
var secondString = string.uint8ToCString(uint8String.subarray(14));
|
||||
assert.equal(secondString, 'value.bar\0', 'converts uint8 data to a c string');
|
||||
assert.equal(secondString.length, 10, 'string has the correct length');
|
||||
});
|
||||
|
||||
QUnit.test('Converts a uint8 array with no null char into a C string', function(assert) {
|
||||
var uint8String = new Uint8Array([0x66, 0x6F, 0x6F, 0x2E, 0x62, 0x61, 0x72]); // foo.bar
|
||||
var firstString = string.uint8ToCString(uint8String);
|
||||
assert.equal(firstString, 'foo.bar\0', 'converts uint8 data to a c string');
|
||||
assert.equal(firstString.length, 8, 'string has the correct length');
|
||||
});
|
||||
|
||||
QUnit.test('Returns a null char from a uint8 array starting with a null char', function(assert) {
|
||||
var uint8String = new Uint8Array([0x00, 0x66, 0x6F, 0x6F, 0x2E, 0x62, 0x61, 0x72]); // \0foo.bar
|
||||
var firstString = string.uint8ToCString(uint8String);
|
||||
assert.equal(firstString, '\0', 'converts uint8 data to a c string');
|
||||
assert.equal(firstString.length, 1, 'string has the correct length');
|
||||
});
|
28
node_modules/mux.js/test/utils.typed-array.test.js
generated
vendored
Normal file
28
node_modules/mux.js/test/utils.typed-array.test.js
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var
|
||||
QUnit = require('qunit'),
|
||||
typedArrayIndexOf = require('../lib/utils/typed-array').typedArrayIndexOf;
|
||||
|
||||
QUnit.module('typedArrayIndexOf');
|
||||
|
||||
QUnit.test('returns -1 when no typed array', function(assert) {
|
||||
assert.equal(typedArrayIndexOf(null, 5, 0), -1, 'returned -1');
|
||||
});
|
||||
|
||||
QUnit.test('returns -1 when element not found', function(assert) {
|
||||
assert.equal(typedArrayIndexOf(new Uint8Array([2, 3]), 5, 0), -1, 'returned -1');
|
||||
});
|
||||
|
||||
QUnit.test('returns -1 when element not found starting from index', function(assert) {
|
||||
assert.equal(typedArrayIndexOf(new Uint8Array([3, 5, 6, 7]), 5, 2), -1, 'returned -1');
|
||||
});
|
||||
|
||||
QUnit.test('returns index when element found', function(assert) {
|
||||
assert.equal(typedArrayIndexOf(new Uint8Array([2, 3, 5]), 5, 0), 2, 'returned 2');
|
||||
});
|
||||
|
||||
QUnit.test('returns index when element found starting from index', function(assert) {
|
||||
assert.equal(typedArrayIndexOf(new Uint8Array([2, 3, 5]), 5, 2), 2, 'returned 2');
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue