aac
Version:
An AAC decoder for Aurora.js
84 lines (64 loc) • 2.63 kB
JavaScript
var AV = require('av');
var tables = require('./tables');
var ADTSDemuxer = AV.Demuxer.extend(function() {
AV.Demuxer.register(this);
this.probe = function(stream) {
var offset = stream.offset;
// attempt to find ADTS syncword
while (stream.available(2)) {
if ((stream.readUInt16() & 0xfff6) === 0xfff0) {
stream.seek(offset);
return true;
}
}
stream.seek(offset);
return false;
};
this.prototype.init = function() {
this.bitstream = new AV.Bitstream(this.stream);
};
// Reads an ADTS header
// See http://wiki.multimedia.cx/index.php?title=ADTS
this.readHeader = function(stream) {
if (stream.read(12) !== 0xfff)
throw new Error('Invalid ADTS header.');
var ret = {};
stream.advance(3); // mpeg version and layer
var protectionAbsent = !!stream.read(1);
ret.profile = stream.read(2) + 1;
ret.samplingIndex = stream.read(4);
stream.advance(1); // private
ret.chanConfig = stream.read(3);
stream.advance(4); // original/copy, home, copywrite, and copywrite start
ret.frameLength = stream.read(13);
stream.advance(11); // fullness
ret.numFrames = stream.read(2) + 1;
if (!protectionAbsent)
stream.advance(16);
return ret;
};
this.prototype.readChunk = function() {
if (!this.sentHeader) {
var offset = this.stream.offset;
var header = ADTSDemuxer.readHeader(this.bitstream);
this.emit('format', {
formatID: 'aac ',
sampleRate: tables.SAMPLE_RATES[header.samplingIndex],
channelsPerFrame: header.chanConfig,
bitsPerChannel: 16
});
// generate a magic cookie from the ADTS header
var cookie = new Uint8Array(2);
cookie[0] = (header.profile << 3) | ((header.samplingIndex >> 1) & 7);
cookie[1] = ((header.samplingIndex & 1) << 7) | (header.chanConfig << 3);
this.emit('cookie', new AV.Buffer(cookie));
this.stream.seek(offset);
this.sentHeader = true;
}
while (this.stream.available(1)) {
var buffer = this.stream.readSingleBuffer(this.stream.remainingBytes());
this.emit('data', buffer);
}
};
});
module.exports = ADTSDemuxer;