net.sourceforge.jaad.aac.DecoderConfig Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jcodec Show documentation
Show all versions of jcodec Show documentation
Pure Java implementation of video/audio codecs and formats
package net.sourceforge.jaad.aac;
import static net.sourceforge.jaad.aac.Profile.*;
import net.sourceforge.jaad.aac.syntax.BitStream;
import net.sourceforge.jaad.aac.syntax.SyntaxConstants;
import net.sourceforge.jaad.aac.syntax.IBitStream;
import net.sourceforge.jaad.aac.syntax.PCE;
/**
* This class is part of JAAD ( jaadec.sourceforge.net ) that is distributed
* under the Public Domain license. Code changes provided by the JCodec project
* are distributed under FreeBSD license.
*
* DecoderConfig that must be passed to the
* Decoder
constructor. Typically it is created via one of the
* static parsing methods.
*
* @author in-somnia
*/
public class DecoderConfig implements SyntaxConstants {
private Profile profile, extProfile;
private SampleFrequency sampleFrequency;
private ChannelConfiguration channelConfiguration;
private boolean frameLengthFlag;
private boolean dependsOnCoreCoder;
private int coreCoderDelay;
private boolean extensionFlag;
//extension: SBR
private boolean sbrPresent, downSampledSBR, sbrEnabled;
//extension: error resilience
private boolean sectionDataResilience, scalefactorResilience, spectralDataResilience;
private DecoderConfig() {
profile = Profile.AAC_MAIN;
extProfile = Profile.UNKNOWN;
sampleFrequency = SampleFrequency.SAMPLE_FREQUENCY_NONE;
channelConfiguration = ChannelConfiguration.CHANNEL_CONFIG_UNSUPPORTED;
frameLengthFlag = false;
sbrPresent = false;
downSampledSBR = false;
sbrEnabled = true;
sectionDataResilience = false;
scalefactorResilience = false;
spectralDataResilience = false;
}
/* ========== gets/sets ========== */
public ChannelConfiguration getChannelConfiguration() {
return channelConfiguration;
}
public void setChannelConfiguration(ChannelConfiguration channelConfiguration) {
this.channelConfiguration = channelConfiguration;
}
public int getCoreCoderDelay() {
return coreCoderDelay;
}
public void setCoreCoderDelay(int coreCoderDelay) {
this.coreCoderDelay = coreCoderDelay;
}
public boolean isDependsOnCoreCoder() {
return dependsOnCoreCoder;
}
public void setDependsOnCoreCoder(boolean dependsOnCoreCoder) {
this.dependsOnCoreCoder = dependsOnCoreCoder;
}
public Profile getExtObjectType() {
return extProfile;
}
public void setExtObjectType(Profile extObjectType) {
this.extProfile = extObjectType;
}
public int getFrameLength() {
return frameLengthFlag ? WINDOW_SMALL_LEN_LONG : WINDOW_LEN_LONG;
}
public boolean isSmallFrameUsed() {
return frameLengthFlag;
}
public void setSmallFrameUsed(boolean shortFrame) {
this.frameLengthFlag = shortFrame;
}
public Profile getProfile() {
return profile;
}
public void setProfile(Profile profile) {
this.profile = profile;
}
public SampleFrequency getSampleFrequency() {
return sampleFrequency;
}
public void setSampleFrequency(SampleFrequency sampleFrequency) {
this.sampleFrequency = sampleFrequency;
}
//=========== SBR =============
public boolean isSBRPresent() {
return sbrPresent;
}
public boolean isSBRDownSampled() {
return downSampledSBR;
}
public boolean isSBREnabled() {
return sbrEnabled;
}
public void setSBREnabled(boolean enabled) {
sbrEnabled = enabled;
}
//=========== ER =============
public boolean isScalefactorResilienceUsed() {
return scalefactorResilience;
}
public boolean isSectionDataResilienceUsed() {
return sectionDataResilience;
}
public boolean isSpectralDataResilienceUsed() {
return spectralDataResilience;
}
/* ======== static builder ========= */
/**
* Parses the input arrays as a DecoderSpecificInfo, as used in MP4
* containers.
*
* @return a DecoderConfig
*/
public static DecoderConfig parseMP4DecoderSpecificInfo(byte[] data) throws AACException {
final IBitStream _in = BitStream.createBitStream(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));
Profile cp = config.profile;
if (AAC_SBR == cp) {
config.extProfile = cp;
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);
} else if (AAC_MAIN == cp || AAC_LC == cp || AAC_SSR == cp || AAC_LTP == cp || ER_AAC_LC == cp || ER_AAC_LTP == cp || ER_AAC_LD == cp ) {
//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(cp.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);
} else {
throw new AACException("profile not supported: "+cp.getIndex());
}
return config;
}
finally {
_in.destroy();
}
}
private static Profile readProfile(IBitStream _in) throws AACException {
int i = _in.readBits(5);
if(i==31) i = 32+_in.readBits(6);
return Profile.forInt(i);
}
private static void readSyncExtension(IBitStream _in, DecoderConfig config) throws AACException {
final int type = _in.readBits(11);
switch(type) {
case 0x2B7:
final Profile profile = Profile.forInt(_in.readBits(5));
if(profile.equals(Profile.AAC_SBR)) {
config.sbrPresent = _in.readBool();
if(config.sbrPresent) {
config.profile = profile;
int tmp = _in.readBits(4);
if(tmp==config.sampleFrequency.getIndex()) config.downSampledSBR = true;
if(tmp==15) {
throw new AACException("sample rate specified explicitly, not supported yet!");
//tmp = _in.readBits(24);
}
}
}
break;
}
}
}