128 lines
4.3 KiB
C++
128 lines
4.3 KiB
C++
#include "aac.h"
|
|
|
|
#include "bitStream.h"
|
|
#include "vod_common.h"
|
|
|
|
const int AACCodec::aac_sample_rates[16] = {96000, 88200, 64000, 48000, 44100, 32000, 24000,
|
|
22050, 16000, 12000, 11025, 8000, 7350};
|
|
|
|
const int AACCodec::aac_channels[8] = {0, 1, 2, 3, 4, 5, 6, 8};
|
|
|
|
uint8_t* AACCodec::findAacFrame(uint8_t* buffer, uint8_t* end)
|
|
{
|
|
uint8_t* curBuf = buffer;
|
|
while (curBuf < end)
|
|
{
|
|
if (*curBuf < 0xf0)
|
|
curBuf += 2;
|
|
else if (*curBuf == 0xff && curBuf < end - 1 && (curBuf[1] & 0xf6) == 0xf0)
|
|
return curBuf;
|
|
else if ((*curBuf & 0xf6) == 0xf0 && curBuf > buffer && curBuf[-1] == 0xff)
|
|
return curBuf - 1;
|
|
else
|
|
curBuf++;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int AACCodec::getFrameSize(uint8_t* buffer) { return ((buffer[3] & 0x03) << 11) + (buffer[4] << 3) + (buffer[5] >> 5); }
|
|
|
|
bool AACCodec::decodeFrame(uint8_t* buffer, uint8_t* end)
|
|
{
|
|
BitStreamReader bits{};
|
|
try
|
|
{
|
|
bits.setBuffer(buffer, end);
|
|
if (bits.getBits(12) != 0xfff) // sync bytes
|
|
return false;
|
|
|
|
m_id = bits.getBit(); /* 0: MPEG-4, 1: MPEG-2*/
|
|
m_layer = bits.getBits(2); /* layer */
|
|
bits.skipBit(); /* protection_absent */
|
|
// -- 16 bit
|
|
m_profile = bits.getBits(2); /* profile_objecttype */
|
|
m_sample_rates_index = bits.getBits(4); /* sample_frequency_index */
|
|
if (!aac_sample_rates[m_sample_rates_index])
|
|
return false;
|
|
bits.skipBit(); /* private_bit */
|
|
m_channels_index = bits.getBits(3); /* channel_configuration */
|
|
if (!aac_channels[m_channels_index])
|
|
return false;
|
|
bits.skipBit(); /* original/copy */
|
|
bits.skipBit(); /* home */
|
|
|
|
/* adts_variable_header */
|
|
bits.skipBit(); /* copyright_identification_bit */
|
|
bits.skipBit(); /* copyright_identification_start */
|
|
int frameSize = bits.getBits(13); /* aac_frame_length */
|
|
bits.skipBits(11); /* adts_buffer_fullness */
|
|
m_rdb = bits.getBits(2); /* number_of_raw_data_blocks_in_frame */
|
|
|
|
m_channels = aac_channels[m_channels_index];
|
|
m_sample_rate = aac_sample_rates[m_sample_rates_index];
|
|
m_samples = (m_rdb + 1) * 1024;
|
|
m_bit_rate = frameSize * 8 * m_sample_rate / m_samples;
|
|
return true;
|
|
}
|
|
catch (BitStreamException e)
|
|
{
|
|
(void)e;
|
|
return NOT_ENOUGH_BUFFER;
|
|
}
|
|
}
|
|
|
|
void AACCodec::buildADTSHeader(uint8_t* buffer, int frameSize)
|
|
{
|
|
BitStreamWriter writer{};
|
|
writer.setBuffer(buffer, buffer + AAC_HEADER_LEN);
|
|
writer.putBits(12, 0xfff);
|
|
writer.putBit(m_id);
|
|
writer.putBits(2, m_layer);
|
|
writer.putBit(1); // protection_absent
|
|
writer.putBits(2, m_profile);
|
|
m_sample_rates_index = 0;
|
|
for (int i = 0; i < 16; i++)
|
|
if (aac_sample_rates[i] == m_sample_rate)
|
|
{
|
|
m_sample_rates_index = i;
|
|
break;
|
|
}
|
|
writer.putBits(4, m_sample_rates_index);
|
|
writer.putBit(0); /* private_bit */
|
|
m_channels_index = 0;
|
|
for (int i = 0; i < 8; i++)
|
|
if (aac_channels[i] == m_channels)
|
|
{
|
|
m_channels_index = i;
|
|
break;
|
|
}
|
|
writer.putBits(3, m_channels_index);
|
|
|
|
writer.putBit(0); /* original/copy */
|
|
writer.putBit(0); /* home */
|
|
|
|
/* adts_variable_header */
|
|
writer.putBit(0); /* copyright_identification_bit */
|
|
writer.putBit(0); /* copyright_identification_start */
|
|
|
|
writer.putBits(13, frameSize); // /* aac_frame_length */
|
|
writer.putBits(11, 2047); // /* adts_buffer_fullness */
|
|
writer.putBits(2, m_rdb); /* number_of_raw_data_blocks_in_frame */
|
|
writer.flushBits();
|
|
}
|
|
|
|
void AACCodec::readConfig(uint8_t* buff, int size)
|
|
{
|
|
BitStreamReader reader{};
|
|
reader.setBuffer(buff, buff + size);
|
|
int object_type = reader.getBits(5);
|
|
if (object_type == 31)
|
|
object_type = 32 + reader.getBits(6);
|
|
m_profile = (object_type & 0x3) - 1;
|
|
m_sample_rates_index = reader.getBits(4);
|
|
m_sample_rate = m_sample_rates_index == 0x0f ? reader.getBits(24) : aac_sample_rates[m_sample_rates_index];
|
|
m_channels_index = reader.getBits(4);
|
|
m_channels = aac_channels[m_channels_index];
|
|
// return specific_config_bitindex;
|
|
}
|