/* * aac.c: Frontend Status Monitor plugin for the Video Disk Recorder * * See the README file for copyright information and how to reach the author. * */ #include "tools.h" #include "aac.h" #define IS_HEAAC_AUDIO(buf) (((buf)[0] == 0xFF) && (((buf)[1] & 0xF6) == 0xF0)) int cFemonAAC::sampleRateS[16] = { 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, -1, -1, -1, -1 }; cFemonAAC::cFemonAAC(cFemonAudioIf *audioHandlerP) : audioHandlerM(audioHandlerP) { } cFemonAAC::~cFemonAAC() { } bool cFemonAAC::processAudio(const uint8_t *bufP, int lenP) { cFemonBitStream bs(bufP, lenP * 8); if (!audioHandlerM) return false; /* ADTS Fixed Header: * syncword 12b always: '111111111111' * id 1b 0: MPEG-4, 1: MPEG-2 * layer 2b always: '00' * protection_absent 1b * profile 2b 0: Main profile AAC MAIN 1: Low Complexity profile (LC) AAC LC 2: Scalable Sample Rate profile (SSR) AAC SSR 3: (reserved) AAC LTP * sampling_frequency_index 4b * private_bit 1b * channel_configuration 3b * original/copy 1b * home 1b * emphasis 2b only if ID == 0 (ie MPEG-4) */ // skip PES header if (!PesLongEnough(lenP)) return false; bs.SkipBits(8 * PesPayloadOffset(bufP)); // HE-AAC audio detection if (bs.GetBits(12) != 0xFFF) // syncword return false; bs.SkipBit(); // id // layer must be 0 if (bs.GetBits(2)) // layer return false; bs.SkipBit(); // protection_absent bs.SkipBits(2); // profile int sampling_frequency_index = bs.GetBits(4); // sampling_frequency_index bs.SkipBit(); // private pid int channel_configuration = bs.GetBits(3); // channel_configuration audioHandlerM->SetAudioCodec(AUDIO_CODEC_HEAAC); audioHandlerM->SetAudioBitrate(AUDIO_BITRATE_RESERVED); switch (channel_configuration) { case 0: audioHandlerM->SetAudioChannel(AUDIO_CHANNEL_MODE_STEREO); break; case 1: audioHandlerM->SetAudioChannel(AUDIO_CHANNEL_MODE_JOINT_STEREO); break; case 2: audioHandlerM->SetAudioChannel(AUDIO_CHANNEL_MODE_DUAL); break; case 3: audioHandlerM->SetAudioChannel(AUDIO_CHANNEL_MODE_SINGLE); break; default: audioHandlerM->SetAudioChannel(AUDIO_CHANNEL_MODE_INVALID); break; } switch (sampling_frequency_index) { case 0xC ... 0xF: audioHandlerM->SetAudioSamplingFrequency(AUDIO_SAMPLING_FREQUENCY_RESERVED); break; default: audioHandlerM->SetAudioSamplingFrequency(sampleRateS[sampling_frequency_index]); break; } return true; }