kontainer-js
Version:
A media file format generator/parser that exposes a React-like API.
402 lines (305 loc) • 12 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = undefined;
var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _get2 = require('babel-runtime/helpers/get');
var _get3 = _interopRequireDefault(_get2);
var _inherits2 = require('babel-runtime/helpers/inherits');
var _inherits3 = _interopRequireDefault(_inherits2);
var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray');
var _slicedToArray3 = _interopRequireDefault(_slicedToArray2);
var _Element2 = require('./Element');
var _Element3 = _interopRequireDefault(_Element2);
var _Buffer = require('../../core/Buffer');
var _Buffer2 = _interopRequireDefault(_Buffer);
var _Reader = require('../../core/Reader');
var _Reader2 = _interopRequireDefault(_Reader);
var _Writer = require('../../core/Writer');
var _Writer2 = _interopRequireDefault(_Writer);
var _Util = require('../../core/Util');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function decodeFlags(flags) {
return {
keyframe: !!(flags & 0x80),
invisible: !!(flags & 0x08),
lacing: flags >> 1 & 0x03,
discardable: !!(flags & 0x01)
};
}
function encodeFlags(flags) {
var byte = 0;
if (flags.keyframe) {
byte |= 0x80;
}
if (flags.invisible) {
byte |= 0x08;
}
byte |= TypeBlock.LACING_EBML << 1;
if (flags.discardable) {
byte |= 0x01;
}
return byte;
}
function getEBMLFrameSizeCode(byteLength) {
switch (byteLength) {
case 1:
return 63;
case 2:
return 8191;
case 3:
return 1048575;
case 4:
return 134217727;
case 5:
return 17179869183;
case 6:
return 2199023255551;
case 7:
return 281474976710655;
}
}
function readEBMLFrameSize(buffer, offset, signed) {
var msb = buffer[offset];
for (var i = 1; i <= 7; i++) {
if (msb >>> 8 - i & 0x01) {
// search the most left 1 bit
buffer[offset] &= 0xFF >>> i; // drop left i bits
var readBytesNum = void 0,
frameSize = void 0;
if (signed) {
var _Reader$readNumber = _Reader2.default.readNumber(buffer, offset, i, true);
var _Reader$readNumber2 = (0, _slicedToArray3.default)(_Reader$readNumber, 2);
readBytesNum = _Reader$readNumber2[0];
frameSize = _Reader$readNumber2[1];
frameSize -= getEBMLFrameSizeCode(i);
} else {
var _Reader$readNumber3 = _Reader2.default.readNumber(buffer, offset, i, false);
var _Reader$readNumber4 = (0, _slicedToArray3.default)(_Reader$readNumber3, 2);
readBytesNum = _Reader$readNumber4[0];
frameSize = _Reader$readNumber4[1];
}
buffer[offset] = msb; // restore
return [readBytesNum, frameSize];
}
}
(0, _Util.throwException)('Invalid EBML frame size');
}
function writeEBMLFrameSize(size, buffer, offset, sizeLen, signed) {
if (signed) {
size += getEBMLFrameSizeCode(sizeLen);
}
var writtenBytesNum = _Writer2.default.writeNumber(size, buffer, offset, sizeLen);
if (buffer) {
buffer[offset] &= 0xFF >>> sizeLen; // drop left sizeLen bits
buffer[offset] |= 0x01 << 8 - sizeLen; // set the most left bit to 1
}
return writtenBytesNum;
}
function getNecessaryBytesNumForEBMLFrameSize(value) {
var bytesNum = 0;
if (value >= -63 && value <= 63) {
bytesNum = 1;
} else if (value >= -8191 && value <= 8191) {
bytesNum = 2;
} else if (value >= -1048575 && value <= 1048575) {
bytesNum = 3;
} else if (value >= -134217727 && value <= 134217727) {
bytesNum = 4;
} else if (value >= -17179869183 && value <= 17179869183) {
bytesNum = 5;
} else if (value >= -2199023255551 && value <= 2199023255551) {
bytesNum = 6;
} else if (value >= -281474976710655 && value <= 281474976710655) {
bytesNum = 7;
} else {
(0, _Util.throwException)('Matroska.TypeBlock.serialize(' + value + '): largesize(>=2^53) is not supported.');
}
return bytesNum;
}
function readFrameSizeList(buffer, offset, length, lacing, numberOfFramesInLace) {
var base = offset;
if (lacing === TypeBlock.LACING_NONE) {
return [0, []];
} else if (lacing === TypeBlock.LACING_FIXED_SIZE) {
return [0, new Array(numberOfFramesInLace).fill(Math.floor(length / numberOfFramesInLace))];
}
var frameSizeList = [];
var tempSize = 0;
for (var i = 0; i < numberOfFramesInLace; i++) {
if (i !== 0 && i === numberOfFramesInLace - 1) {
break;
}
if (lacing === TypeBlock.LACING_XIPH) {
var byte = buffer[base++];
tempSize += byte;
if (byte !== 255) {
frameSizeList.push(tempSize);
tempSize = 0;
}
} else if (lacing === TypeBlock.LACING_EBML) {
var _readEBMLFrameSize = readEBMLFrameSize(buffer, base, i > 0);
var _readEBMLFrameSize2 = (0, _slicedToArray3.default)(_readEBMLFrameSize, 2);
var readBytesNum = _readEBMLFrameSize2[0];
var frameSize = _readEBMLFrameSize2[1];
if (i === 0) {
frameSizeList.push(frameSize);
} else {
frameSizeList.push(frameSizeList[i - 1] + frameSize);
}
base += readBytesNum;
}
}
var theLastFrameSize = offset + length - base - frameSizeList.reduce(function (a, b) {
return a + b;
}, 0);
if (theLastFrameSize > 0) {
frameSizeList.push(theLastFrameSize);
}
return [base - offset, frameSizeList];
}
var TypeBlock = function (_Element) {
(0, _inherits3.default)(TypeBlock, _Element);
function TypeBlock() {
var _Object$getPrototypeO;
(0, _classCallCheck3.default)(this, TypeBlock);
for (var _len = arguments.length, params = Array(_len), _key = 0; _key < _len; _key++) {
params[_key] = arguments[_key];
}
return (0, _possibleConstructorReturn3.default)(this, (_Object$getPrototypeO = (0, _getPrototypeOf2.default)(TypeBlock)).call.apply(_Object$getPrototypeO, [this].concat(params)));
}
(0, _createClass3.default)(TypeBlock, [{
key: 'serialize',
value: function serialize(buffer) {
var offset = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];
var props = this.props;
var trackNumber = props.trackNumber;
var timecode = props.timecode;
var flags = props.flags;
var frames = props.frames;
var trackNumberLength = _Element3.default.getNecessaryBytesNumForSize(trackNumber);
var frameSizeList = [];
var frameSizeLengthList = [];
var frameLength = 0;
for (var i = 0; i < frames.length; i++) {
var len = frames[i].length;
if (i === 0) {
frameSizeList.push(len);
frameSizeLengthList.push(getNecessaryBytesNumForEBMLFrameSize(len));
} else if (i < frames.length - 1) {
var diff = len - frames[i - 1].length;
frameSizeList.push(diff);
frameSizeLengthList.push(getNecessaryBytesNumForEBMLFrameSize(diff));
}
frameLength += len;
}
var totalSize = trackNumberLength + 2 // timecode
+ 1 // flags
+ 1 // numberOfFramesInLaceMinusOne
+ frameSizeLengthList.reduce(function (a, b) {
return a + b;
}, 0) + frameLength;
var base = offset;
(0, _get3.default)((0, _getPrototypeOf2.default)(TypeBlock.prototype), 'setElementSize', this).call(this, totalSize);
base += (0, _get3.default)((0, _getPrototypeOf2.default)(TypeBlock.prototype), 'serialize', this).call(this, buffer, base);
base += _Element3.default.writeElementSize(trackNumber, buffer, base, trackNumberLength);
base += _Writer2.default.writeNumber(timecode, buffer, base, 2);
base += _Writer2.default.writeNumber(encodeFlags(flags), buffer, base, 1);
base += _Writer2.default.writeNumber(frames.length - 1, buffer, base, 1);
for (var _i = 0; _i < frames.length; _i++) {
if (_i === 0 || _i < frames.length - 1) {
base += writeEBMLFrameSize(frameSizeList[_i], buffer, base, frameSizeLengthList[_i], _i > 0);
}
}
if (buffer) {
var tempBase = base;
for (var _i2 = 0; _i2 < frames.length; _i2++) {
var frame = frames[_i2];
_Buffer2.default.wrap(buffer).copyFrom(frame, 0, frame.length, tempBase);
tempBase += frame.length;
}
}
base += frameLength;
return this.size;
}
}], [{
key: 'parse',
value: function parse(buffer) {
var offset = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];
var base = offset,
readBytesNum = void 0,
props = void 0,
trackNumber = void 0,
timecode = void 0,
flags = void 0,
numberOfFramesInLaceMinusOne = void 0,
frameSizeList = void 0;
var _Element$parse = _Element3.default.parse(buffer, base);
var _Element$parse2 = (0, _slicedToArray3.default)(_Element$parse, 2);
readBytesNum = _Element$parse2[0];
props = _Element$parse2[1];
base += readBytesNum;
_Reader2.default.ASSERT(buffer, base, props.size);
var endOfElement = base + props.size;
var _Element$readElementS = _Element3.default.readElementSize(buffer, base);
var _Element$readElementS2 = (0, _slicedToArray3.default)(_Element$readElementS, 2);
readBytesNum = _Element$readElementS2[0];
trackNumber = _Element$readElementS2[1];
base += readBytesNum;
var _Reader$readNumber5 = _Reader2.default.readNumber(buffer, base, 2, true);
var _Reader$readNumber6 = (0, _slicedToArray3.default)(_Reader$readNumber5, 2);
readBytesNum = _Reader$readNumber6[0];
timecode = _Reader$readNumber6[1];
base += readBytesNum;
flags = buffer[base++];
var _decodeFlags = decodeFlags(flags);
var keyframe = _decodeFlags.keyframe;
var invisible = _decodeFlags.invisible;
var lacing = _decodeFlags.lacing;
var discardable = _decodeFlags.discardable;
if (lacing === TypeBlock.LACING_NONE) {
frameSizeList = [];
var frameSize = endOfElement - base;
if (frameSize > 0) {
frameSizeList.push(frameSize);
}
} else {
var _Reader$readNumber7 = _Reader2.default.readNumber(buffer, base, 1);
var _Reader$readNumber8 = (0, _slicedToArray3.default)(_Reader$readNumber7, 2);
readBytesNum = _Reader$readNumber8[0];
numberOfFramesInLaceMinusOne = _Reader$readNumber8[1];
base += readBytesNum;
var _readFrameSizeList = readFrameSizeList(buffer, base, endOfElement - base, lacing, numberOfFramesInLaceMinusOne + 1);
var _readFrameSizeList2 = (0, _slicedToArray3.default)(_readFrameSizeList, 2);
readBytesNum = _readFrameSizeList2[0];
frameSizeList = _readFrameSizeList2[1];
base += readBytesNum;
}
var frames = [];
frameSizeList.forEach(function (frameSize) {
var buf = _Buffer2.default.wrap(buffer).copy(base, frameSize);
base += frameSize;
frames.push(buf.getView());
});
props.trackNumber = trackNumber;
props.timecode = timecode;
props.flags = { keyframe: keyframe, invisible: invisible, discardable: discardable };
props.frames = frames;
return [base - offset, props];
}
}]);
return TypeBlock;
}(_Element3.default);
exports.default = TypeBlock;
TypeBlock.LACING_NONE = 0;
TypeBlock.LACING_XIPH = 1;
TypeBlock.LACING_EBML = 3;
TypeBlock.LACING_FIXED_SIZE = 2;