/* | |
* Copyright 2011 castLabs, Berlin | |
* | |
* Licensed under the Apache License, Version 2.0 (the License); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an AS IS BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
package com.googlecode.mp4parser.boxes.mp4.objectdescriptors; | |
import com.coremedia.iso.Hex; | |
import com.coremedia.iso.IsoTypeWriter; | |
import java.io.IOException; | |
import java.nio.ByteBuffer; | |
import java.util.Arrays; | |
import java.util.HashMap; | |
import java.util.Map; | |
// | |
//GetAudioObjectType() | |
//{ | |
//audioObjectType; 5 uimsbf | |
//if (audioObjectType == 31) { | |
//audioObjectType = 32 + audioObjectTypeExt; 6 uimsbf | |
//} | |
//return audioObjectType; | |
//} | |
//AudioSpecificConfig () | |
//{ | |
//audioObjectType = GetAudioObjectType(); | |
//samplingFrequencyIndex; 4 bslbf | |
//if ( samplingFrequencyIndex == 0xf ) { | |
//samplingFrequency; 24 uimsbf | |
//} | |
//channelConfiguration; 4 bslbf | |
//sbrPresentFlag = -1; | |
//psPresentFlag = -1; | |
//if ( audioObjectType == 5 || | |
//audioObjectType == 29 ) { | |
//extensionAudioObjectType = 5; | |
//sbrPresentFlag = 1; | |
//if ( audioObjectType == 29 ) { | |
//psPresentFlag = 1; | |
//} | |
//extensionSamplingFrequencyIndex; 4 uimsbf | |
//if ( extensionSamplingFrequencyIndex == 0xf ) | |
//extensionSamplingFrequency; 24 uimsbf | |
//audioObjectType = GetAudioObjectType(); | |
//if ( audioObjectType == 22 ) | |
//extensionChannelConfiguration; 4 uimsbf | |
//} | |
//else { | |
//extensionAudioObjectType = 0; | |
//} | |
//switch (audioObjectType) { | |
//case 1: | |
//case 2: | |
//case 3: | |
//case 4: | |
//case 6: | |
//case 7: | |
//case 17: | |
//case 19: | |
//case 20: | |
//case 21: | |
//case 22: | |
//case 23: | |
//GASpecificConfig(); | |
//break: | |
//case 8: | |
//CelpSpecificConfig(); | |
//break; | |
//case 9: | |
//HvxcSpecificConfig(); | |
//break: | |
//case 12: | |
//TTSSpecificConfig(); | |
//break; | |
//case 13: | |
//case 14: | |
//case 15: | |
//case 16: | |
//StructuredAudioSpecificConfig(); | |
//break; | |
//case 24: | |
//ErrorResilientCelpSpecificConfig(); | |
//break; | |
//case 25: | |
//ErrorResilientHvxcSpecificConfig(); | |
//break; | |
//case 26: | |
//case 27: | |
//ParametricSpecificConfig(); | |
//break; | |
// case 28: | |
//SSCSpecificConfig(); | |
//break; | |
//case 30: | |
//sacPayloadEmbedding; 1 uimsbf | |
//SpatialSpecificConfig(); | |
//break; | |
//case 32: | |
//case 33: | |
//case 34: | |
//MPEG_1_2_SpecificConfig(); | |
//break; | |
//case 35: | |
//DSTSpecificConfig(); | |
//break; | |
//case 36: | |
//fillBits; 5 bslbf | |
//ALSSpecificConfig(); | |
//break; | |
//case 37: | |
//case 38: | |
//SLSSpecificConfig(); | |
//break; | |
//case 39: | |
//ELDSpecificConfig(channelConfiguration); | |
//break: | |
//case 40: | |
//case 41: | |
//SymbolicMusicSpecificConfig(); | |
//break; | |
//default: | |
///* reserved */ | |
//} | |
//switch (audioObjectType) { | |
//case 17: | |
//case 19: | |
//case 20: | |
//case 21: | |
//case 22: | |
//case 23: | |
//case 24: | |
//case 25: | |
//case 26: | |
//case 27: | |
//case 39: | |
//epConfig; 2 bslbf | |
//if ( epConfig == 2 || epConfig == 3 ) { | |
//ErrorProtectionSpecificConfig(); | |
//} | |
//if ( epConfig == 3 ) { | |
//directMapping; 1 bslbf | |
//if ( ! directMapping ) { | |
///* tbd */ | |
//} | |
//} | |
//} | |
//if ( extensionAudioObjectType != 5 && bits_to_decode() >= 16 ) { | |
//syncExtensionType; 11 bslbf | |
//if (syncExtensionType == 0x2b7) { | |
// extensionAudioObjectType = GetAudioObjectType(); | |
//if ( extensionAudioObjectType == 5 ) { | |
//sbrPresentFlag; 1 uimsbf | |
//if (sbrPresentFlag == 1) { | |
//extensionSamplingFrequencyIndex; 4 uimsbf | |
//if ( extensionSamplingFrequencyIndex == 0xf ) { | |
//extensionSamplingFrequency; 24 uimsbf | |
//} | |
//if ( bits_to_decode() >= 12 ) { | |
//syncExtensionType; 11 bslbf | |
//if (syncExtesionType == 0x548) { | |
//psPresentFlag; 1 uimsbf | |
//} | |
//} | |
//} | |
//} | |
//if ( extensionAudioObjectType == 22 ) { | |
//sbrPresentFlag; 1 uimsbf | |
//if (sbrPresentFlag == 1) { | |
//extensionSamplingFrequencyIndex; 4 uimsbf | |
//if ( extensionSamplingFrequencyIndex == 0xf ) { | |
//extensionSamplingFrequency; 24 uimsbf | |
//} | |
//} | |
//extensionChannelConfiguration; 4 uimsbf | |
//} | |
//} | |
//} | |
//} | |
// } | |
// | |
// TFCodingType | |
//0x0 AAC scaleable | |
//0x1 BSAC | |
//0x2 TwinVQ | |
//0x3 AAC non scaleable (i.e. multichannel) | |
// | |
// class TFSpecificConfig( uint(4) samplingFrequencyIndex, uint(4) channelConfiguration ) { | |
//uint(2) TFCodingType; | |
//uint(1) frameLength; | |
//uint(1) dependsOnCoreCoder; | |
//if (dependsOnCoreCoder == 1){ | |
//uint(14)coreCoderDelay | |
//} | |
//if (TFCodingType==BSAC) { | |
//uint(11) lslayer_length | |
//} | |
//uint (1) extensionFlag; | |
//if (channelConfiguration == 0 ){ | |
//program_config_element(); | |
//} | |
//if (extensionFlag==1){ | |
//<to be defined in mpeg4 phase 2> | |
//} | |
//} | |
// | |
//program_config_element() | |
//{ | |
//element_instance_tag 4 uimsbf | |
//profile 2 uimsbf | |
//sampling_frequency_index 4 uimsbf | |
//num_front_channel_elements 4 uimsbf | |
//num_side_channel_elements 4 uimsbf | |
//num_back_channel_elements 4 uimsbf | |
// num_lfe_channel_elements 2 uimsbf | |
//num_assoc_data_elements 3 uimsbf | |
//num_valid_cc_elements 4 uimsbf | |
//mono_mixdown_present 1 uimsbf | |
//if ( mono_mixdown_present == 1 ) | |
//mono_mixdown_element_number 4 uimsbf | |
//stereo_mixdown_present 1 uimsbf | |
//if ( stereo_mixdown_present == 1 ) | |
//stereo_mixdown_element_number 4 uimsbf | |
//matrix_mixdown_idx_present 1 uimsbf | |
//if ( matrix_mixdown_idx_present == 1 ) { | |
//matrix_mixdown_idx 2 uimsbf | |
//pseudo_surround_enable 1 uimsbf | |
//} | |
//for ( i = 0; i < num_front_channel_elements; i++) { | |
//front_element_is_cpe[i]; 1 bslbf | |
//front_element_tag_select[i]; 4 uimsbf | |
//} | |
//for ( i = 0; i < num_side_channel_elements; i++) { | |
//side_element_is_cpe[i]; 1 bslbf | |
//side_element_tag_select[i]; 4 uimsbf | |
//} | |
//for ( i = 0; i < num_back_channel_elements; i++) { | |
//back_element_is_cpe[i]; 1 bslbf | |
//back_element_tag_select[i]; 4 uimsbf | |
//} | |
//for ( i = 0; i < num_lfe_channel_elements; i++) | |
//lfe_element_tag_select[i]; 4 uimsbf | |
//for ( i = 0; i < num_assoc_data_elements; i++) | |
//assoc_data_element_tag_select[i]; 4 uimsbf | |
//for ( i = 0; i < num_valid_cc_elements; i++) { | |
//cc_element_is_ind_sw[i]; 1 uimsbf | |
//valid_cc_element_tag_select[i]; 4 uimsbf | |
//} | |
//byte_alignment() | |
//comment_field_bytes 8 uimsbf | |
//for ( i = 0; i < comment_field_bytes; i++) | |
//comment_field_data[i]; 8 uimsbf | |
//} | |
@Descriptor(tags = 0x5, objectTypeIndication = 0x40) | |
public class AudioSpecificConfig extends BaseDescriptor { | |
byte[] configBytes; | |
public static Map<Integer, Integer> samplingFrequencyIndexMap = new HashMap<Integer, Integer>(); | |
public static Map<Integer, String> audioObjectTypeMap = new HashMap<Integer, String>(); | |
int audioObjectType; | |
int samplingFrequencyIndex; | |
int samplingFrequency; | |
int channelConfiguration; | |
int extensionAudioObjectType; | |
int sbrPresentFlag; | |
int psPresentFlag; | |
int extensionSamplingFrequencyIndex; | |
int extensionSamplingFrequency; | |
int extensionChannelConfiguration; | |
int sacPayloadEmbedding; | |
int fillBits; | |
int epConfig; | |
int directMapping; | |
int syncExtensionType; | |
//GASpecificConfig | |
int frameLengthFlag; | |
int dependsOnCoreCoder; | |
int coreCoderDelay; | |
int extensionFlag; | |
int layerNr; | |
int numOfSubFrame; | |
int layer_length; | |
int aacSectionDataResilienceFlag; | |
int aacScalefactorDataResilienceFlag; | |
int aacSpectralDataResilienceFlag; | |
int extensionFlag3; | |
boolean gaSpecificConfig; | |
//ParametricSpecificConfig | |
int isBaseLayer; | |
int paraMode; | |
int paraExtensionFlag; | |
int hvxcVarMode; | |
int hvxcRateMode; | |
int erHvxcExtensionFlag; | |
int var_ScalableFlag; | |
int hilnQuantMode; | |
int hilnMaxNumLine; | |
int hilnSampleRateCode; | |
int hilnFrameLength; | |
int hilnContMode; | |
int hilnEnhaLayer; | |
int hilnEnhaQuantMode; | |
boolean parametricSpecificConfig; | |
@Override | |
public void parseDetail(ByteBuffer bb) throws IOException { | |
ByteBuffer configBytes = bb.slice(); | |
configBytes.limit(sizeOfInstance); | |
bb.position(bb.position() + sizeOfInstance); | |
//copy original bytes to internal array for constructing codec config strings (todo until writing of the config is supported) | |
this.configBytes = new byte[sizeOfInstance]; | |
configBytes.get(this.configBytes); | |
configBytes.rewind(); | |
BitReaderBuffer bitReaderBuffer = new BitReaderBuffer(configBytes); | |
audioObjectType = getAudioObjectType(bitReaderBuffer); | |
samplingFrequencyIndex = bitReaderBuffer.readBits(4); | |
if (samplingFrequencyIndex == 0xf) { | |
samplingFrequency = bitReaderBuffer.readBits(24); | |
} | |
channelConfiguration = bitReaderBuffer.readBits(4); | |
if (audioObjectType == 5 || | |
audioObjectType == 29) { | |
extensionAudioObjectType = 5; | |
sbrPresentFlag = 1; | |
if (audioObjectType == 29) { | |
psPresentFlag = 1; | |
} | |
extensionSamplingFrequencyIndex = bitReaderBuffer.readBits(4); | |
if (extensionSamplingFrequencyIndex == 0xf) | |
extensionSamplingFrequency = bitReaderBuffer.readBits(24); | |
audioObjectType = getAudioObjectType(bitReaderBuffer); | |
if (audioObjectType == 22) | |
extensionChannelConfiguration = bitReaderBuffer.readBits(4); | |
} else { | |
extensionAudioObjectType = 0; | |
} | |
switch (audioObjectType) { | |
case 1: | |
case 2: | |
case 3: | |
case 4: | |
case 6: | |
case 7: | |
case 17: | |
case 19: | |
case 20: | |
case 21: | |
case 22: | |
case 23: | |
parseGaSpecificConfig(samplingFrequencyIndex, channelConfiguration, audioObjectType, bitReaderBuffer); | |
//GASpecificConfig(); | |
break; | |
case 8: | |
throw new UnsupportedOperationException("can't parse CelpSpecificConfig yet"); | |
//CelpSpecificConfig(); | |
//break; | |
case 9: | |
throw new UnsupportedOperationException("can't parse HvxcSpecificConfig yet"); | |
//HvxcSpecificConfig(); | |
//break; | |
case 12: | |
throw new UnsupportedOperationException("can't parse TTSSpecificConfig yet"); | |
//TTSSpecificConfig(); | |
//break; | |
case 13: | |
case 14: | |
case 15: | |
case 16: | |
throw new UnsupportedOperationException("can't parse StructuredAudioSpecificConfig yet"); | |
//StructuredAudioSpecificConfig(); | |
//break; | |
case 24: | |
throw new UnsupportedOperationException("can't parse ErrorResilientCelpSpecificConfig yet"); | |
//ErrorResilientCelpSpecificConfig(); | |
//break; | |
case 25: | |
throw new UnsupportedOperationException("can't parse ErrorResilientHvxcSpecificConfig yet"); | |
//ErrorResilientHvxcSpecificConfig(); | |
//break; | |
case 26: | |
case 27: | |
parseParametricSpecificConfig(samplingFrequencyIndex, channelConfiguration, audioObjectType, bitReaderBuffer); | |
//ParametricSpecificConfig(); | |
break; | |
case 28: | |
throw new UnsupportedOperationException("can't parse SSCSpecificConfig yet"); | |
//SSCSpecificConfig(); | |
//break; | |
case 30: | |
sacPayloadEmbedding = bitReaderBuffer.readBits(1); | |
throw new UnsupportedOperationException("can't parse SpatialSpecificConfig yet"); | |
//SpatialSpecificConfig(); | |
//break; | |
case 32: | |
case 33: | |
case 34: | |
throw new UnsupportedOperationException("can't parse MPEG_1_2_SpecificConfig yet"); | |
//MPEG_1_2_SpecificConfig(); | |
//break; | |
case 35: | |
throw new UnsupportedOperationException("can't parse DSTSpecificConfig yet"); | |
//DSTSpecificConfig(); | |
//break; | |
case 36: | |
fillBits = bitReaderBuffer.readBits(5); | |
throw new UnsupportedOperationException("can't parse ALSSpecificConfig yet"); | |
//ALSSpecificConfig(); | |
//break; | |
case 37: | |
case 38: | |
throw new UnsupportedOperationException("can't parse SLSSpecificConfig yet"); | |
//SLSSpecificConfig(); | |
//break; | |
case 39: | |
throw new UnsupportedOperationException("can't parse ELDSpecificConfig yet"); | |
//ELDSpecificConfig(channelConfiguration); | |
//break; | |
case 40: | |
case 41: | |
throw new UnsupportedOperationException("can't parse SymbolicMusicSpecificConfig yet"); | |
//SymbolicMusicSpecificConfig(); | |
//break; | |
default: | |
/* reserved */ | |
} | |
switch (audioObjectType) { | |
case 17: | |
case 19: | |
case 20: | |
case 21: | |
case 22: | |
case 23: | |
case 24: | |
case 25: | |
case 26: | |
case 27: | |
case 39: | |
epConfig = bitReaderBuffer.readBits(2); | |
if (epConfig == 2 || epConfig == 3) { | |
throw new UnsupportedOperationException("can't parse ErrorProtectionSpecificConfig yet"); | |
//ErrorProtectionSpecificConfig(); | |
} | |
if (epConfig == 3) { | |
directMapping = bitReaderBuffer.readBits(1); | |
if (directMapping == 0) { | |
/* tbd */ | |
throw new RuntimeException("not implemented"); | |
} | |
} | |
} | |
if (extensionAudioObjectType != 5 && bitReaderBuffer.remainingBits() >= 16) { | |
syncExtensionType = bitReaderBuffer.readBits(11); | |
if (syncExtensionType == 0x2b7) { | |
extensionAudioObjectType = getAudioObjectType(bitReaderBuffer); | |
if (extensionAudioObjectType == 5) { | |
sbrPresentFlag = bitReaderBuffer.readBits(1); | |
if (sbrPresentFlag == 1) { | |
extensionSamplingFrequencyIndex = bitReaderBuffer.readBits(4); | |
if (extensionSamplingFrequencyIndex == 0xf) { | |
extensionSamplingFrequency = bitReaderBuffer.readBits(24); | |
} | |
if (bitReaderBuffer.remainingBits() >= 12) { | |
syncExtensionType = bitReaderBuffer.readBits(11); //10101001000 | |
if (syncExtensionType == 0x548) { | |
psPresentFlag = bitReaderBuffer.readBits(1); | |
} | |
} | |
} | |
} | |
if (extensionAudioObjectType == 22) { | |
sbrPresentFlag = bitReaderBuffer.readBits(1); | |
if (sbrPresentFlag == 1) { | |
extensionSamplingFrequencyIndex = bitReaderBuffer.readBits(4); | |
if (extensionSamplingFrequencyIndex == 0xf) { | |
extensionSamplingFrequency = bitReaderBuffer.readBits(24); | |
} | |
} | |
extensionChannelConfiguration = bitReaderBuffer.readBits(4); | |
} | |
} | |
} | |
} | |
private int gaSpecificConfigSize() { | |
return 0; | |
} | |
public int serializedSize() { | |
int out = 4; | |
if (audioObjectType == 2) { | |
out += gaSpecificConfigSize(); | |
} else { | |
throw new UnsupportedOperationException("can't serialize that yet"); | |
} | |
return out; | |
} | |
public ByteBuffer serialize() { | |
ByteBuffer out = ByteBuffer.allocate(serializedSize()); | |
IsoTypeWriter.writeUInt8(out, 5); | |
IsoTypeWriter.writeUInt8(out, serializedSize() - 2); | |
BitWriterBuffer bwb = new BitWriterBuffer(out); | |
bwb.writeBits(audioObjectType, 5); | |
bwb.writeBits(samplingFrequencyIndex, 4); | |
if (samplingFrequencyIndex == 0xf) { | |
throw new UnsupportedOperationException("can't serialize that yet"); | |
} | |
bwb.writeBits(channelConfiguration, 4); | |
// Don't support any extensions, unusual GASpecificConfig other than the default or anything... | |
return out; | |
} | |
private int getAudioObjectType(BitReaderBuffer in) throws IOException { | |
int audioObjectType = in.readBits(5); | |
if (audioObjectType == 31) { | |
audioObjectType = 32 + in.readBits(6); | |
} | |
return audioObjectType; | |
} | |
private void parseGaSpecificConfig(int samplingFrequencyIndex, int channelConfiguration, int audioObjectType, BitReaderBuffer in) throws IOException { | |
// GASpecificConfig (samplingFrequencyIndex, | |
// channelConfiguration, | |
// audioObjectType) | |
// { | |
frameLengthFlag = in.readBits(1); | |
dependsOnCoreCoder = in.readBits(1); | |
if (dependsOnCoreCoder == 1) { | |
coreCoderDelay = in.readBits(14); | |
} | |
extensionFlag = in.readBits(1); | |
if (channelConfiguration == 0) { | |
throw new UnsupportedOperationException("can't parse program_config_element yet"); | |
//program_config_element (); | |
} | |
if ((audioObjectType == 6) || (audioObjectType == 20)) { | |
layerNr = in.readBits(3); | |
} | |
if (extensionFlag == 1) { | |
if (audioObjectType == 22) { | |
numOfSubFrame = in.readBits(5); | |
layer_length = in.readBits(11); | |
} | |
if (audioObjectType == 17 || audioObjectType == 19 || | |
audioObjectType == 20 || audioObjectType == 23) { | |
aacSectionDataResilienceFlag = in.readBits(1); | |
aacScalefactorDataResilienceFlag = in.readBits(1); | |
aacSpectralDataResilienceFlag = in.readBits(1); | |
} | |
extensionFlag3 = in.readBits(1); | |
if (extensionFlag3 == 1) { | |
/* tbd in version 3 */ | |
} | |
} | |
// } | |
gaSpecificConfig = true; | |
} | |
private void parseParametricSpecificConfig(int samplingFrequencyIndex, int channelConfiguration, int audioObjectType, BitReaderBuffer in) throws IOException { | |
/* | |
ParametricSpecificConfig() { | |
isBaseLayer; 1 uimsbf | |
if (isBaseLayer) { | |
PARAconfig(); | |
} else { | |
HILNenexConfig(); | |
} | |
} | |
*/ | |
isBaseLayer = in.readBits(1); | |
if (isBaseLayer == 1) { | |
parseParaConfig(samplingFrequencyIndex, channelConfiguration, audioObjectType, in); | |
} else { | |
parseHilnEnexConfig(samplingFrequencyIndex, channelConfiguration, audioObjectType, in); | |
} | |
} | |
private void parseParaConfig(int samplingFrequencyIndex, int channelConfiguration, int audioObjectType, BitReaderBuffer in) throws IOException { | |
/* | |
PARAconfig() | |
{ | |
PARAmode; 2 uimsbf | |
if (PARAmode != 1) { | |
ErHVXCconfig(); | |
} | |
if (PARAmode != 0) { | |
HILNconfig(); | |
} | |
PARAextensionFlag; 1 uimsbf | |
if (PARAextensionFlag) { | |
// to be defined in MPEG-4 Phase 3 | |
} | |
} | |
*/ | |
paraMode = in.readBits(2); | |
if (paraMode != 1) { | |
parseErHvxcConfig(samplingFrequencyIndex, channelConfiguration, audioObjectType, in); | |
} | |
if (paraMode != 0) { | |
parseHilnConfig(samplingFrequencyIndex, channelConfiguration, audioObjectType, in); | |
} | |
paraExtensionFlag = in.readBits(1); | |
parametricSpecificConfig = true; | |
} | |
private void parseErHvxcConfig(int samplingFrequencyIndex, int channelConfiguration, int audioObjectType, BitReaderBuffer in) throws IOException { | |
/* | |
ErHVXCconfig() | |
{ | |
HVXCvarMode; 1 uimsbf | |
HVXCrateMode; 2 uimsbf | |
extensionFlag; 1 uimsbf | |
if (extensionFlag) { | |
var_ScalableFlag; 1 uimsbf | |
} | |
} | |
*/ | |
hvxcVarMode = in.readBits(1); | |
hvxcRateMode = in.readBits(2); | |
erHvxcExtensionFlag = in.readBits(1); | |
if (erHvxcExtensionFlag == 1) { | |
var_ScalableFlag = in.readBits(1); | |
} | |
} | |
private void parseHilnConfig(int samplingFrequencyIndex, int channelConfiguration, int audioObjectType, BitReaderBuffer in) throws IOException { | |
/* | |
HILNconfig() | |
{ | |
HILNquantMode; 1 uimsbf | |
HILNmaxNumLine; 8 uimsbf | |
HILNsampleRateCode; 4 uimsbf | |
HILNframeLength; 12 uimsbf | |
HILNcontMode; 2 uimsbf | |
} | |
*/ | |
hilnQuantMode = in.readBits(1); | |
hilnMaxNumLine = in.readBits(8); | |
hilnSampleRateCode = in.readBits(4); | |
hilnFrameLength = in.readBits(12); | |
hilnContMode = in.readBits(2); | |
} | |
private void parseHilnEnexConfig(int samplingFrequencyIndex, int channelConfiguration, int audioObjectType, BitReaderBuffer in) throws IOException { | |
/* | |
HILNenexConfig() | |
{ | |
HILNenhaLayer; 1 uimsbf | |
if (HILNenhaLayer) { | |
HILNenhaQuantMode; 2 uimsbf | |
} | |
} | |
*/ | |
hilnEnhaLayer = in.readBits(1); | |
if (hilnEnhaLayer == 1) { | |
hilnEnhaQuantMode = in.readBits(2); | |
} | |
} | |
public byte[] getConfigBytes() { | |
return configBytes; | |
} | |
public int getAudioObjectType() { | |
return audioObjectType; | |
} | |
public int getExtensionAudioObjectType() { | |
return extensionAudioObjectType; | |
} | |
public int getSbrPresentFlag() { | |
return sbrPresentFlag; | |
} | |
public int getPsPresentFlag() { | |
return psPresentFlag; | |
} | |
public void setAudioObjectType(int audioObjectType) { | |
this.audioObjectType = audioObjectType; | |
} | |
public void setSamplingFrequencyIndex(int samplingFrequencyIndex) { | |
this.samplingFrequencyIndex = samplingFrequencyIndex; | |
} | |
public void setSamplingFrequency(int samplingFrequency) { | |
this.samplingFrequency = samplingFrequency; | |
} | |
public void setChannelConfiguration(int channelConfiguration) { | |
this.channelConfiguration = channelConfiguration; | |
} | |
@Override | |
public String toString() { | |
final StringBuilder sb = new StringBuilder(); | |
sb.append("AudioSpecificConfig"); | |
sb.append("{configBytes=").append(Hex.encodeHex(configBytes)); | |
sb.append(", audioObjectType=").append(audioObjectType).append(" (").append(audioObjectTypeMap.get(audioObjectType)).append(")"); | |
sb.append(", samplingFrequencyIndex=").append(samplingFrequencyIndex).append(" (").append(samplingFrequencyIndexMap.get(samplingFrequencyIndex)).append(")"); | |
sb.append(", samplingFrequency=").append(samplingFrequency); | |
sb.append(", channelConfiguration=").append(channelConfiguration); | |
if (extensionAudioObjectType > 0) { | |
sb.append(", extensionAudioObjectType=").append(extensionAudioObjectType).append(" (").append(audioObjectTypeMap.get(extensionAudioObjectType)).append(")"); | |
sb.append(", sbrPresentFlag=").append(sbrPresentFlag); | |
sb.append(", psPresentFlag=").append(psPresentFlag); | |
sb.append(", extensionSamplingFrequencyIndex=").append(extensionSamplingFrequencyIndex).append(" (").append(samplingFrequencyIndexMap.get(extensionSamplingFrequencyIndex)).append(")"); | |
sb.append(", extensionSamplingFrequency=").append(extensionSamplingFrequency); | |
sb.append(", extensionChannelConfiguration=").append(extensionChannelConfiguration); | |
} | |
// sb.append(", sacPayloadEmbedding=").append(sacPayloadEmbedding); | |
// sb.append(", fillBits=").append(fillBits); | |
// sb.append(", epConfig=").append(epConfig); | |
// sb.append(", directMapping=").append(directMapping); | |
sb.append(", syncExtensionType=").append(syncExtensionType); | |
if (gaSpecificConfig) { | |
sb.append(", frameLengthFlag=").append(frameLengthFlag); | |
sb.append(", dependsOnCoreCoder=").append(dependsOnCoreCoder); | |
sb.append(", coreCoderDelay=").append(coreCoderDelay); | |
sb.append(", extensionFlag=").append(extensionFlag); | |
sb.append(", layerNr=").append(layerNr); | |
sb.append(", numOfSubFrame=").append(numOfSubFrame); | |
sb.append(", layer_length=").append(layer_length); | |
sb.append(", aacSectionDataResilienceFlag=").append(aacSectionDataResilienceFlag); | |
sb.append(", aacScalefactorDataResilienceFlag=").append(aacScalefactorDataResilienceFlag); | |
sb.append(", aacSpectralDataResilienceFlag=").append(aacSpectralDataResilienceFlag); | |
sb.append(", extensionFlag3=").append(extensionFlag3); | |
} | |
if (parametricSpecificConfig) { | |
sb.append(", isBaseLayer=").append(isBaseLayer); | |
sb.append(", paraMode=").append(paraMode); | |
sb.append(", paraExtensionFlag=").append(paraExtensionFlag); | |
sb.append(", hvxcVarMode=").append(hvxcVarMode); | |
sb.append(", hvxcRateMode=").append(hvxcRateMode); | |
sb.append(", erHvxcExtensionFlag=").append(erHvxcExtensionFlag); | |
sb.append(", var_ScalableFlag=").append(var_ScalableFlag); | |
sb.append(", hilnQuantMode=").append(hilnQuantMode); | |
sb.append(", hilnMaxNumLine=").append(hilnMaxNumLine); | |
sb.append(", hilnSampleRateCode=").append(hilnSampleRateCode); | |
sb.append(", hilnFrameLength=").append(hilnFrameLength); | |
sb.append(", hilnContMode=").append(hilnContMode); | |
sb.append(", hilnEnhaLayer=").append(hilnEnhaLayer); | |
sb.append(", hilnEnhaQuantMode=").append(hilnEnhaQuantMode); | |
} | |
sb.append('}'); | |
return sb.toString(); | |
} | |
static { | |
// sampling_frequency_index sampling frequeny | |
//0x0 96000 | |
//0x1 88200 | |
//0x2 64000 | |
//0x3 48000 | |
//0x4 44100 | |
//0x5 32000 | |
//0x6 24000 | |
//0x7 22050 | |
//0x8 16000 | |
//0x9 12000 | |
//0xa 11025 | |
//0xb 8000 | |
//0xc reserved | |
//0xd reserved | |
//0xe reserved | |
//0xf reserved | |
samplingFrequencyIndexMap.put(0x0, 96000); | |
samplingFrequencyIndexMap.put(0x1, 88200); | |
samplingFrequencyIndexMap.put(0x2, 64000); | |
samplingFrequencyIndexMap.put(0x3, 48000); | |
samplingFrequencyIndexMap.put(0x4, 44100); | |
samplingFrequencyIndexMap.put(0x5, 32000); | |
samplingFrequencyIndexMap.put(0x6, 24000); | |
samplingFrequencyIndexMap.put(0x7, 22050); | |
samplingFrequencyIndexMap.put(0x8, 16000); | |
samplingFrequencyIndexMap.put(0x9, 12000); | |
samplingFrequencyIndexMap.put(0xa, 11025); | |
samplingFrequencyIndexMap.put(0xb, 8000); | |
/* audioObjectType IDs | |
0 Null | |
1 AAC main X X | |
2 AAC LC X X X X X X X | |
3 AAC SSR X X | |
4 AAC LTP X X X X | |
5 SBR X X | |
6 AAC Scalable X X X X | |
7 TwinVQ X X X | |
8 CELP X X X X X X | |
9 HVXC X X X X X | |
10 (reserved) | |
11 (reserved) | |
12 TTSI X X X X X X | |
13 Main synthetic X X | |
14 Wavetable synthesis X* X* | |
15 General MIDI X* X* | |
16 Algorithmic Synthesis and Audio FX X* X* | |
17 ER AAC LC X X X | |
18 (reserved) | |
19 ER AAC LTP X X | |
20 ER AAC Scalable X X X | |
21 ER TwinVQ X X | |
22 ER BSAC X X | |
23 ER AAC LD X X X X | |
24 ER CELP X X X | |
25 ER HVXC X X | |
26 ER HILN X | |
27 ER Parametric X | |
28 SSC | |
29 PS X | |
30 MPEG Surround | |
31 (escape) | |
32 Layer-1 | |
33 Layer-2 | |
34 Layer-3 | |
35 DST | |
36 ALS | |
37 SLS | |
38 SLS non-core | |
39 ER AAC ELD | |
40 SMR Simple | |
41 SMR Main | |
*/ | |
audioObjectTypeMap.put(1, "AAC main"); | |
audioObjectTypeMap.put(2, "AAC LC"); | |
audioObjectTypeMap.put(3, "AAC SSR"); | |
audioObjectTypeMap.put(4, "AAC LTP"); | |
audioObjectTypeMap.put(5, "SBR"); | |
audioObjectTypeMap.put(6, "AAC Scalable"); | |
audioObjectTypeMap.put(7, "TwinVQ"); | |
audioObjectTypeMap.put(8, "CELP"); | |
audioObjectTypeMap.put(9, "HVXC"); | |
audioObjectTypeMap.put(10, "(reserved)"); | |
audioObjectTypeMap.put(11, "(reserved)"); | |
audioObjectTypeMap.put(12, "TTSI"); | |
audioObjectTypeMap.put(13, "Main synthetic"); | |
audioObjectTypeMap.put(14, "Wavetable synthesis"); | |
audioObjectTypeMap.put(15, "General MIDI"); | |
audioObjectTypeMap.put(16, "Algorithmic Synthesis and Audio FX"); | |
audioObjectTypeMap.put(17, "ER AAC LC"); | |
audioObjectTypeMap.put(18, "(reserved)"); | |
audioObjectTypeMap.put(19, "ER AAC LTP"); | |
audioObjectTypeMap.put(20, "ER AAC Scalable"); | |
audioObjectTypeMap.put(21, "ER TwinVQ"); | |
audioObjectTypeMap.put(22, "ER BSAC"); | |
audioObjectTypeMap.put(23, "ER AAC LD"); | |
audioObjectTypeMap.put(24, "ER CELP"); | |
audioObjectTypeMap.put(25, "ER HVXC"); | |
audioObjectTypeMap.put(26, "ER HILN"); | |
audioObjectTypeMap.put(27, "ER Parametric"); | |
audioObjectTypeMap.put(28, "SSC"); | |
audioObjectTypeMap.put(29, "PS"); | |
audioObjectTypeMap.put(30, "MPEG Surround"); | |
audioObjectTypeMap.put(31, "(escape)"); | |
audioObjectTypeMap.put(32, "Layer-1"); | |
audioObjectTypeMap.put(33, "Layer-2"); | |
audioObjectTypeMap.put(34, "Layer-3"); | |
audioObjectTypeMap.put(35, "DST"); | |
audioObjectTypeMap.put(36, "ALS"); | |
audioObjectTypeMap.put(37, "SLS"); | |
audioObjectTypeMap.put(38, "SLS non-core"); | |
audioObjectTypeMap.put(39, "ER AAC ELD"); | |
audioObjectTypeMap.put(40, "SMR Simple"); | |
audioObjectTypeMap.put(41, "SMR Main"); | |
/* profileLevelIds | |
0x00 Reserved for ISO use - | |
0x01 Main Audio Profile L1 | |
0x02 Main Audio Profile L2 | |
0x03 Main Audio Profile L3 | |
0x04 Main Audio Profile L4 | |
0x05 Scalable Audio Profile L1 | |
0x06 Scalable Audio Profile L2 | |
0x07 Scalable Audio Profile L3 | |
0x08 Scalable Audio Profile L4 | |
0x09 Speech Audio Profile L1 | |
0x0A Speech Audio Profile L2 | |
0x0B Synthetic Audio Profile L1 | |
0x0C Synthetic Audio Profile L2 | |
0x0D Synthetic Audio Profile L3 | |
0x0E High Quality Audio Profile L1 | |
0x0F High Quality Audio Profile L2 | |
0x10 High Quality Audio Profile L3 | |
0x11 High Quality Audio Profile L4 | |
0x12 High Quality Audio Profile L5 | |
0x13 High Quality Audio Profile L6 | |
0x14 High Quality Audio Profile L7 | |
0x15 High Quality Audio Profile L8 | |
0x16 Low Delay Audio Profile L1 | |
0x17 Low Delay Audio Profile L2 | |
0x18 Low Delay Audio Profile L3 | |
0x19 Low Delay Audio Profile L4 | |
0x1A Low Delay Audio Profile L5 | |
0x1B Low Delay Audio Profile L6 | |
0x1C Low Delay Audio Profile L7 | |
0x1D Low Delay Audio Profile L8 | |
0x1E Natural Audio Profile L1 | |
0x1F Natural Audio Profile L2 | |
0x20 Natural Audio Profile L3 | |
0x21 Natural Audio Profile L4 | |
0x22 Mobile Audio Internetworking Profile L1 | |
0x23 Mobile Audio Internetworking Profile L2 | |
0x24 Mobile Audio Internetworking Profile L3 | |
0x25 Mobile Audio Internetworking Profile L4 | |
0x26 Mobile Audio Internetworking Profile L5 | |
0x27 Mobile Audio Internetworking Profile L6 | |
0x28 AAC Profile L1 | |
0x29 AAC Profile L2 | |
0x2A AAC Profile L4 | |
0x2B AAC Profile L5 | |
0x2C High Efficiency AAC Profile L2 | |
0x2D High Efficiency AAC Profile L3 | |
0x2E High Efficiency AAC Profile L4 | |
0x2F High Efficiency AAC Profile L5 | |
0x30 High Efficiency AAC v2 Profile L2 | |
0x31 High Efficiency AAC v2 Profile L3 | |
0x32 High Efficiency AAC v2 Profile L4 | |
0x33 High Efficiency AAC v2 Profile L5 | |
0x34 Low Delay AAC Profile L1 | |
0x35 Baseline MPEG Surround Profile (see ISO/IEC | |
23003-1) | |
L1 | |
0x36 Baseline MPEG Surround Profile (see ISO/IEC | |
23003-1) | |
L2 | |
0x37 Baseline MPEG Surround Profile (see ISO/IEC | |
23003-1) | |
L3 | |
0x38 Baseline MPEG Surround Profile (see ISO/IEC | |
23003-1) | |
L4 | |
0c39 Baseline MPEG Surround Profile (see ISO/IEC | |
23003-1) | |
L5 | |
0x3A Baseline MPEG Surround Profile (see ISO/IEC | |
23003-1) | |
L6 | |
0x3B - 0x7F reserved for ISO use - | |
0x80 - 0xFD user private - | |
0xFE no audio profile specified - | |
0xFF no audio capability required - | |
*/ | |
} | |
public int getSamplingFrequency() { | |
return samplingFrequencyIndex == 0xf ? samplingFrequency : samplingFrequencyIndexMap.get(samplingFrequencyIndex); | |
} | |
public int getChannelConfiguration() { | |
return channelConfiguration; | |
} | |
@Override | |
public boolean equals(Object o) { | |
if (this == o) { | |
return true; | |
} | |
if (o == null || getClass() != o.getClass()) { | |
return false; | |
} | |
AudioSpecificConfig that = (AudioSpecificConfig) o; | |
if (aacScalefactorDataResilienceFlag != that.aacScalefactorDataResilienceFlag) { | |
return false; | |
} | |
if (aacSectionDataResilienceFlag != that.aacSectionDataResilienceFlag) { | |
return false; | |
} | |
if (aacSpectralDataResilienceFlag != that.aacSpectralDataResilienceFlag) { | |
return false; | |
} | |
if (audioObjectType != that.audioObjectType) { | |
return false; | |
} | |
if (channelConfiguration != that.channelConfiguration) { | |
return false; | |
} | |
if (coreCoderDelay != that.coreCoderDelay) { | |
return false; | |
} | |
if (dependsOnCoreCoder != that.dependsOnCoreCoder) { | |
return false; | |
} | |
if (directMapping != that.directMapping) { | |
return false; | |
} | |
if (epConfig != that.epConfig) { | |
return false; | |
} | |
if (erHvxcExtensionFlag != that.erHvxcExtensionFlag) { | |
return false; | |
} | |
if (extensionAudioObjectType != that.extensionAudioObjectType) { | |
return false; | |
} | |
if (extensionChannelConfiguration != that.extensionChannelConfiguration) { | |
return false; | |
} | |
if (extensionFlag != that.extensionFlag) { | |
return false; | |
} | |
if (extensionFlag3 != that.extensionFlag3) { | |
return false; | |
} | |
if (extensionSamplingFrequency != that.extensionSamplingFrequency) { | |
return false; | |
} | |
if (extensionSamplingFrequencyIndex != that.extensionSamplingFrequencyIndex) { | |
return false; | |
} | |
if (fillBits != that.fillBits) { | |
return false; | |
} | |
if (frameLengthFlag != that.frameLengthFlag) { | |
return false; | |
} | |
if (gaSpecificConfig != that.gaSpecificConfig) { | |
return false; | |
} | |
if (hilnContMode != that.hilnContMode) { | |
return false; | |
} | |
if (hilnEnhaLayer != that.hilnEnhaLayer) { | |
return false; | |
} | |
if (hilnEnhaQuantMode != that.hilnEnhaQuantMode) { | |
return false; | |
} | |
if (hilnFrameLength != that.hilnFrameLength) { | |
return false; | |
} | |
if (hilnMaxNumLine != that.hilnMaxNumLine) { | |
return false; | |
} | |
if (hilnQuantMode != that.hilnQuantMode) { | |
return false; | |
} | |
if (hilnSampleRateCode != that.hilnSampleRateCode) { | |
return false; | |
} | |
if (hvxcRateMode != that.hvxcRateMode) { | |
return false; | |
} | |
if (hvxcVarMode != that.hvxcVarMode) { | |
return false; | |
} | |
if (isBaseLayer != that.isBaseLayer) { | |
return false; | |
} | |
if (layerNr != that.layerNr) { | |
return false; | |
} | |
if (layer_length != that.layer_length) { | |
return false; | |
} | |
if (numOfSubFrame != that.numOfSubFrame) { | |
return false; | |
} | |
if (paraExtensionFlag != that.paraExtensionFlag) { | |
return false; | |
} | |
if (paraMode != that.paraMode) { | |
return false; | |
} | |
if (parametricSpecificConfig != that.parametricSpecificConfig) { | |
return false; | |
} | |
if (psPresentFlag != that.psPresentFlag) { | |
return false; | |
} | |
if (sacPayloadEmbedding != that.sacPayloadEmbedding) { | |
return false; | |
} | |
if (samplingFrequency != that.samplingFrequency) { | |
return false; | |
} | |
if (samplingFrequencyIndex != that.samplingFrequencyIndex) { | |
return false; | |
} | |
if (sbrPresentFlag != that.sbrPresentFlag) { | |
return false; | |
} | |
if (syncExtensionType != that.syncExtensionType) { | |
return false; | |
} | |
if (var_ScalableFlag != that.var_ScalableFlag) { | |
return false; | |
} | |
if (!Arrays.equals(configBytes, that.configBytes)) { | |
return false; | |
} | |
return true; | |
} | |
@Override | |
public int hashCode() { | |
int result = configBytes != null ? Arrays.hashCode(configBytes) : 0; | |
result = 31 * result + audioObjectType; | |
result = 31 * result + samplingFrequencyIndex; | |
result = 31 * result + samplingFrequency; | |
result = 31 * result + channelConfiguration; | |
result = 31 * result + extensionAudioObjectType; | |
result = 31 * result + sbrPresentFlag; | |
result = 31 * result + psPresentFlag; | |
result = 31 * result + extensionSamplingFrequencyIndex; | |
result = 31 * result + extensionSamplingFrequency; | |
result = 31 * result + extensionChannelConfiguration; | |
result = 31 * result + sacPayloadEmbedding; | |
result = 31 * result + fillBits; | |
result = 31 * result + epConfig; | |
result = 31 * result + directMapping; | |
result = 31 * result + syncExtensionType; | |
result = 31 * result + frameLengthFlag; | |
result = 31 * result + dependsOnCoreCoder; | |
result = 31 * result + coreCoderDelay; | |
result = 31 * result + extensionFlag; | |
result = 31 * result + layerNr; | |
result = 31 * result + numOfSubFrame; | |
result = 31 * result + layer_length; | |
result = 31 * result + aacSectionDataResilienceFlag; | |
result = 31 * result + aacScalefactorDataResilienceFlag; | |
result = 31 * result + aacSpectralDataResilienceFlag; | |
result = 31 * result + extensionFlag3; | |
result = 31 * result + (gaSpecificConfig ? 1 : 0); | |
result = 31 * result + isBaseLayer; | |
result = 31 * result + paraMode; | |
result = 31 * result + paraExtensionFlag; | |
result = 31 * result + hvxcVarMode; | |
result = 31 * result + hvxcRateMode; | |
result = 31 * result + erHvxcExtensionFlag; | |
result = 31 * result + var_ScalableFlag; | |
result = 31 * result + hilnQuantMode; | |
result = 31 * result + hilnMaxNumLine; | |
result = 31 * result + hilnSampleRateCode; | |
result = 31 * result + hilnFrameLength; | |
result = 31 * result + hilnContMode; | |
result = 31 * result + hilnEnhaLayer; | |
result = 31 * result + hilnEnhaQuantMode; | |
result = 31 * result + (parametricSpecificConfig ? 1 : 0); | |
return result; | |
} | |
} |