* Parses the input arrays as a DecoderSpecificInfo, as used in MP4
* containers.
* @return a DecoderConfig
*/
static DecoderConfig parseMP4DecoderSpecificInfo(byte[] data) throws AACException {
final BitStream in = new BitStream(data);
final DecoderConfig config = new DecoderConfig();
try {
config.profile = readProfile(in);
int sf = in.readBits(4);
if(sf==0xF) config.sampleFrequency = SampleFrequency.forFrequency(in.readBits(24));
else config.sampleFrequency = SampleFrequency.forInt(sf);
config.channelConfiguration = ChannelConfiguration.forInt(in.readBits(4));
switch(config.profile) {
case AAC_SBR:
config.extProfile = config.profile;
config.sbrPresent = true;
sf = in.readBits(4);
//TODO: 24 bits already read; read again?
//if(sf==0xF) config.sampleFrequency = SampleFrequency.forFrequency(in.readBits(24));
//if sample frequencies are the same: downsample SBR
config.downSampledSBR = config.sampleFrequency.getIndex()==sf;
config.sampleFrequency = SampleFrequency.forInt(sf);
config.profile = readProfile(in);
break;
case AAC_MAIN:
case AAC_LC:
case AAC_SSR:
case AAC_LTP:
case ER_AAC_LC:
case ER_AAC_LTP:
case ER_AAC_LD:
//ga-specific info:
config.frameLengthFlag = in.readBool();
if(config.frameLengthFlag) throw new AACException("config uses 960-sample frames, not yet supported"); //TODO: are 960-frames working yet?
config.dependsOnCoreCoder = in.readBool();
if(config.dependsOnCoreCoder) config.coreCoderDelay = in.readBits(14);
else config.coreCoderDelay = 0;
config.extensionFlag = in.readBool();
if(config.extensionFlag) {
if(config.profile.isErrorResilientProfile()) {
config.sectionDataResilience = in.readBool();
config.scalefactorResilience = in.readBool();
config.spectralDataResilience = in.readBool();
}
//extensionFlag3
in.skipBit();
}
if(config.channelConfiguration==ChannelConfiguration.CHANNEL_CONFIG_NONE) {
//TODO: is this working correct? -> ISO 14496-3 part 1: 1.A.4.3
in.skipBits(3); //PCE
PCE pce = new PCE();
pce.decode(in);
config.profile = pce.getProfile();
config.sampleFrequency = pce.getSampleFrequency();
config.channelConfiguration = ChannelConfiguration.forInt(pce.getChannelCount());
}
if(in.getBitsLeft()>10) readSyncExtension(in, config);
break;
default:
throw new AACException("profile not supported: "+config.profile.getIndex());
}
return config;
}
finally {
in.destroy();
}
}