2,543
社区成员
发帖
与我相关
我的任务
分享
aac_state_t::aac_state_t() : h(NULL), freq(0), channels(0) {open();}
aac_state_t::~aac_state_t() {close();}
bool aac_state_t::open()
{
close();
if(!(h = NeAACDecOpen())) return false;
NeAACDecConfigurationPtr c = NeAACDecGetCurrentConfiguration(h);
//c->outputFormat = FAAD_FMT_FLOAT;
c->outputFormat = FAAD_FMT_16BIT;
NeAACDecSetConfiguration(h, c);
return true;
}
void aac_state_t::close()
{
if(h) NeAACDecClose(h);
h = NULL;
}
bool aac_state_t::init(unsigned char *buffer, unsigned long buffer_size)
{
open();
return !NeAACDecInit(h, buffer, buffer_size, &freq, &channels);
}
bool aac_state_t::init2(unsigned char *buffer, unsigned long buffer_size)
{
open();
return !NeAACDecInit2(h, buffer, buffer_size, &freq, &channels);
}
BOOL CAACDecoder::SetParser(IBaseAudioParser *pAudioParser)
{
if(pAudioParser == NULL)
return FALSE;
AUDIOFORMAT *pAudioFormat = pAudioParser->GetAudioFormat();
if((pAudioFormat == NULL) || (pAudioFormat->wFormatTag != AUDIO_FORMAT_AAC && pAudioFormat->wFormatTag != AUDIO_FORMAT_HEAAC))
return FALSE;
m_pAudioParser = pAudioParser;
if(pAudioFormat->wFormatTag == AUDIO_FORMAT_HEAAC)
{
m_aac_type = LATM;
}
else if(pAudioFormat->nFileFormat == FILE_FORMAT_MPEG || pAudioFormat->nFileFormat == FILE_FORMAT_TS)
{
m_aac_type = ADTS;
}
else
{
m_aac_type = RAW;
m_aac_state.init2((BYTE*)(pAudioFormat + 1), pAudioFormat->cbSize);
}
return TRUE;
}
PCMFRAME *CAACDecoder::GetNextFrame()
{
if(m_pAudioParser == NULL)
return NULL;
while(AUDIOFRAME *pFrame = m_pAudioParser->GetNextFrame())
{
if(m_aac_type == LATM || m_aac_type == ADTS)
{
if(m_aac_state.freq == 0 || m_aac_state.channels == 0)
{
if(m_aac_type == LATM)
{
if(pFrame->cbSample < 4) continue;
if(pFrame->pbSample[0] != 0x56) continue;
if(pFrame->pbSample[3] & 0x80) continue;
}
else
{
if(pFrame->cbSample < 7) continue;
if(pFrame->pbSample[0] != 0xff) continue;
if((pFrame->pbSample[1] & 0xf0) != 0xf0) continue;
}
m_aac_state.init(pFrame->pbSample, pFrame->cbSample);
}
}
NeAACDecFrameInfo info;
SHORT* src = (SHORT*)NeAACDecDecode(m_aac_state.h, &info, pFrame->pbSample + pFrame->cbDataOffset, pFrame->cbSample - pFrame->cbDataOffset);
if(info.error)
{
if(m_aac_type == LATM || m_aac_type == ADTS)
{
m_aac_state.freq = 0;
m_aac_state.channels = 0;
}
else
{
AUDIOFORMAT *pAudioFormat = m_pAudioParser->GetAudioFormat();
m_aac_state.init2((BYTE*)(pAudioFormat + 1), pAudioFormat->cbSize);
}
}
if(!src || info.samples == 0) continue;
// HACK: bug in faad2 with mono sources?
if(info.channels == 2 && info.channel_position[1] == UNKNOWN_CHANNEL)
{
info.channel_position[0] = FRONT_CHANNEL_LEFT;
info.channel_position[1] = FRONT_CHANNEL_RIGHT;
}
if(m_pSample == NULL)
{
m_dwSample = 2 * info.samples;
m_pSample = new SHORT[m_dwSample];
}
else if(m_dwSample < info.samples)
{
delete[] m_pSample;
m_dwSample = 2 * info.samples;
m_pSample = new SHORT[m_dwSample];
}
std::map<int, int> chmask;
chmask[FRONT_CHANNEL_CENTER] = SPEAKER_FRONT_CENTER;
chmask[FRONT_CHANNEL_LEFT] = SPEAKER_FRONT_LEFT;
chmask[FRONT_CHANNEL_RIGHT] = SPEAKER_FRONT_RIGHT;
chmask[SIDE_CHANNEL_LEFT] = SPEAKER_SIDE_LEFT;
chmask[SIDE_CHANNEL_RIGHT] = SPEAKER_SIDE_RIGHT;
chmask[BACK_CHANNEL_LEFT] = SPEAKER_BACK_LEFT;
chmask[BACK_CHANNEL_RIGHT] = SPEAKER_BACK_RIGHT;
chmask[BACK_CHANNEL_CENTER] = SPEAKER_BACK_CENTER;
chmask[LFE_CHANNEL] = SPEAKER_LOW_FREQUENCY;
DWORD dwChannelMask = 0;
for(int i = 0; i < info.channels; i++)
{
if(info.channel_position[i] == UNKNOWN_CHANNEL) {/*ASSERT(0);*/ continue;}
dwChannelMask |= chmask[info.channel_position[i]];
}
int chmap[countof(info.channel_position)];
memset(chmap, 0, sizeof(chmap));
for(int i = 0; i < info.channels; i++)
{
unsigned int ch = 0, mask = chmask[info.channel_position[i]];
for(int j = 0; j < 32; j++)
{
if(dwChannelMask & (1 << j))
{
if((1 << j) == mask) {chmap[i] = ch; break;}
ch++;
}
}
}
if(info.channels <= 2) dwChannelMask = 0;
SHORT* dst = m_pSample;
for(int j = 0; j < info.samples; j += info.channels, dst += info.channels)
for(int i = 0; i < info.channels; i++)
dst[chmap[i]] = *src++;
m_pcmFrame.nChannels = info.channels;
m_pcmFrame.nSamplesPerSec = info.samplerate;
m_pcmFrame.cbSample = info.samples;
m_pcmFrame.pbSample = m_pSample;
return &m_pcmFrame;
}
return NULL;
}
// 文件读写缓冲区类,获得一帧aac属性和位置
bool CAudioHeaderParser::ParseLATM(AUDIOFORMAT *pAudioFormat)
{
if(!pAudioFormat) return(false);
__int64 len = GetRemaining();
for(; len >= 3 && BitRead(11, true) != 0x2b7; len--)
return(false);
if(len < 3)
return(false);
BitRead(11);
WORD aac_frame_length = BitRead(13);
BYTE use_same_stream_mux = BitRead(1);
if(!use_same_stream_mux)
{
BYTE version = BitRead(1);
if(version)
{
BYTE versionA = BitRead(1);
BYTE byte_for_value = BitRead(2);
DWORD tara_buffer_fullness = BitRead(byte_for_value * 8);
}
BYTE all_streams_same_time_framing = BitRead(1);
BYTE sub_frames = BitRead(6) + 1;
BYTE programs = BitRead(4) + 1;
BYTE layers = BitRead(3) + 1;
if(!all_streams_same_time_framing || sub_frames > 1 || programs > 1 || layers > 1)
return(false);
if(version)
{
BYTE byte_for_value = BitRead(2);
DWORD asc_len = BitRead(byte_for_value * 8);
}
BYTE object_type_index = BitRead(5);
BYTE sampling_frequency_index = BitRead(4);
if(sampling_frequency_index == 0x0f)
{
pAudioFormat->nSamplesPerSec = BitRead(24);
}
BYTE channels_configuration = BitRead(4);
if(object_type_index == 5)
{
sampling_frequency_index = BitRead(4);
if(sampling_frequency_index == 0x0f)
{
pAudioFormat->nSamplesPerSec = BitRead(24);
}
object_type_index = BitRead(5);
}
if(sampling_frequency_index > 11 && sampling_frequency_index != 15)
return(false);
static int freq[] = {96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000};
pAudioFormat->wFormatTag = AUDIO_FORMAT_HEAAC;
pAudioFormat->nChannels = channels_configuration <= 6 ? channels_configuration : 2;
if(sampling_frequency_index != 0x0f) pAudioFormat->nSamplesPerSec = freq[sampling_frequency_index];
pAudioFormat->nBlockAlign = aac_frame_length + 3;
pAudioFormat->nAvgBytesPerSec = pAudioFormat->nBlockAlign * pAudioFormat->nSamplesPerSec / 1024; // ok?;
pAudioFormat->wBitsPerSample = 0;
pAudioFormat->cbSize = 0;
nFrameSize = aac_frame_length;
nFrameDuration = 10000000i64 * 1024 / pAudioFormat->nSamplesPerSec ; // ok?
}
else
{
pAudioFormat->wFormatTag = AUDIO_FORMAT_HEAAC;
pAudioFormat->nChannels = 0;
pAudioFormat->nSamplesPerSec = 0;
pAudioFormat->nBlockAlign = aac_frame_length + 3;
pAudioFormat->nAvgBytesPerSec = 0;
pAudioFormat->wBitsPerSample = 0;
pAudioFormat->cbSize = 0;
nFrameSize = aac_frame_length;
nFrameDuration = 0;
}
return(true);
}
// 文件解析类,获取每一帧aac给解码器解码
AUDIOFRAME *CLATMAACParser::GetNextFrame()
{
if(m_pHeaderParser == NULL) //CAudioHeaderParser
return NULL;
int nRead = 0;
int nOffset = 0;
BYTE AudioFormatData[sizeof(AUDIOFORMAT) + 10];
AUDIOFORMAT *pAudioFormat = (AUDIOFORMAT *)AudioFormatData;
while(m_pHeaderParser->GetRemaining() > 0)
{
__int64 pos = m_pHeaderParser->GetPos();
if(m_pHeaderParser->ParseLATM(pAudioFormat))
{
if(m_pSample == NULL)
{
m_dwSample = 2 * pAudioFormat->nBlockAlign;
m_pSample = new BYTE[m_dwSample];
}
else if(m_dwSample < pAudioFormat->nBlockAlign)
{
delete[] m_pSample;
m_dwSample = 2 * pAudioFormat->nBlockAlign;
m_pSample = new BYTE[m_dwSample];
}
m_pHeaderParser->Seek(pos);
nRead = m_pHeaderParser->ByteRead(m_pSample, pAudioFormat->nBlockAlign);
nOffset = 0;//pAudioFormat->nBlockAlign - m_pHeaderParser->nFrameSize;
// not good
if(((nRead == pAudioFormat->nBlockAlign) && (m_pHeaderParser->GetRemaining() == 0)) || m_pHeaderParser->ParseLATM(pAudioFormat))
{
m_pHeaderParser->Seek(pos + nRead);
break;
}
else
{
nRead = 0;
nOffset = 0;
m_pHeaderParser->Seek(pos + 1);
continue;
}
}
else
{
//m_pHeaderParser->Seek(pos + 1);
m_pHeaderParser->Seek(pos);
BYTE ch = 0;
if(m_pHeaderParser->ByteRead(&ch, 1) < 1)
break;
}
}
if(nRead > 0)
{
m_audioFrame.cbSample = nRead;
m_audioFrame.cbDataOffset = nOffset;
m_audioFrame.pbSample = m_pSample;
return &m_audioFrame;
}
return NULL;
}