mp4box
Version:
JavaScript version of GPAC's MP4Box tool
166 lines (146 loc) • 4.54 kB
JavaScript
/*
* Copyright (c) 2012-2013. Telecom ParisTech/TSI/MM/GPAC Cyril Concolato
* License: BSD-3-Clause (see LICENSE file)
*/
var MPEG4DescriptorParser = function () {
var ES_DescrTag = 0x03;
var DecoderConfigDescrTag = 0x04;
var DecSpecificInfoTag = 0x05;
var SLConfigDescrTag = 0x06;
var descTagToName = [];
descTagToName[ES_DescrTag] = "ES_Descriptor";
descTagToName[DecoderConfigDescrTag] = "DecoderConfigDescriptor";
descTagToName[DecSpecificInfoTag] = "DecoderSpecificInfo";
descTagToName[SLConfigDescrTag] = "SLConfigDescriptor";
this.getDescriptorName = function(tag) {
return descTagToName[tag];
}
var that = this;
var classes = {};
this.parseOneDescriptor = function (stream) {
var hdrSize = 0;
var size = 0;
var tag;
var desc;
var byteRead;
tag = stream.readUint8();
hdrSize++;
byteRead = stream.readUint8();
hdrSize++;
while (byteRead & 0x80) {
size = (size << 7) + (byteRead & 0x7F);
byteRead = stream.readUint8();
hdrSize++;
}
size = (size << 7) + (byteRead & 0x7F);
Log.debug("MPEG4DescriptorParser", "Found "+(descTagToName[tag] || "Descriptor "+tag)+", size "+size+" at position "+stream.getPosition());
if (descTagToName[tag]) {
desc = new classes[descTagToName[tag]](size);
} else {
desc = new classes.Descriptor(size);
}
desc.parse(stream);
return desc;
}
classes.Descriptor = function(_tag, _size) {
this.tag = _tag;
this.size = _size;
this.descs = [];
}
classes.Descriptor.prototype.parse = function (stream) {
this.data = stream.readUint8Array(this.size);
}
classes.Descriptor.prototype.findDescriptor = function (tag) {
for (var i = 0; i < this.descs.length; i++) {
if (this.descs[i].tag == tag) {
return this.descs[i];
}
}
return null;
}
classes.Descriptor.prototype.parseRemainingDescriptors = function (stream) {
var start = stream.position;
while (stream.position < start+this.size) {
var desc = that.parseOneDescriptor(stream);
this.descs.push(desc);
}
}
classes.ES_Descriptor = function (size) {
classes.Descriptor.call(this, ES_DescrTag, size);
}
classes.ES_Descriptor.prototype = new classes.Descriptor();
classes.ES_Descriptor.prototype.parse = function(stream) {
this.ES_ID = stream.readUint16();
this.flags = stream.readUint8();
this.size -= 3;
if (this.flags & 0x80) {
this.dependsOn_ES_ID = stream.readUint16();
this.size -= 2;
} else {
this.dependsOn_ES_ID = 0;
}
if (this.flags & 0x40) {
var l = stream.readUint8();
this.URL = stream.readString(l);
this.size -= l+1;
} else {
this.URL = "";
}
if (this.flags & 0x20) {
this.OCR_ES_ID = stream.readUint16();
this.size -= 2;
} else {
this.OCR_ES_ID = 0;
}
this.parseRemainingDescriptors(stream);
}
classes.ES_Descriptor.prototype.getOTI = function(stream) {
var dcd = this.findDescriptor(DecoderConfigDescrTag);
if (dcd) {
return dcd.oti;
} else {
return 0;
}
}
classes.ES_Descriptor.prototype.getAudioConfig = function(stream) {
var dcd = this.findDescriptor(DecoderConfigDescrTag);
if (!dcd) return null;
var dsi = dcd.findDescriptor(DecSpecificInfoTag);
if (dsi && dsi.data) {
var audioObjectType = (dsi.data[0]& 0xF8) >> 3;
if (audioObjectType === 31 && dsi.data.length >= 2) {
audioObjectType = 32 + ((dsi.data[0] & 0x7) << 3) + ((dsi.data[1] & 0xE0) >> 5);
}
return audioObjectType;
} else {
return null;
}
}
classes.DecoderConfigDescriptor = function (size) {
classes.Descriptor.call(this, DecoderConfigDescrTag, size);
}
classes.DecoderConfigDescriptor.prototype = new classes.Descriptor();
classes.DecoderConfigDescriptor.prototype.parse = function(stream) {
this.oti = stream.readUint8();
this.streamType = stream.readUint8();
this.upStream = ((this.streamType >> 1) & 1) !== 0;
this.streamType = this.streamType >>> 2;
this.bufferSize = stream.readUint24();
this.maxBitrate = stream.readUint32();
this.avgBitrate = stream.readUint32();
this.size -= 13;
this.parseRemainingDescriptors(stream);
}
classes.DecoderSpecificInfo = function (size) {
classes.Descriptor.call(this, DecSpecificInfoTag, size);
}
classes.DecoderSpecificInfo.prototype = new classes.Descriptor();
classes.SLConfigDescriptor = function (size) {
classes.Descriptor.call(this, SLConfigDescrTag, size);
}
classes.SLConfigDescriptor.prototype = new classes.Descriptor();
return this;
}
if (typeof exports !== 'undefined') {
exports.MPEG4DescriptorParser = MPEG4DescriptorParser;
}