/*
 * latm.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 "latm.h"

int cFemonLATM::bitrateS[3][16] =
{
  {0,  32,  48,  56,  64,  80,  96, 112, 128, 144, 160, 176, 192, 224, 256, -1}, // MPEG-2 Layer I
  {0,   8,  16,  24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160, -1}, // MPEG-2 Layer II/III
  {0,   8,  16,  24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160, -1}  // MPEG-2 Layer II/III
};

int cFemonLATM::sampleRateS[4] =
{
  22050, 24000, 16000, -1
};

cFemonLATM::cFemonLATM(cFemonAudioIf *audioHandlerP)
: audioHandlerM(audioHandlerP)
{
}

cFemonLATM::~cFemonLATM()
{
}

bool cFemonLATM::processAudio(const uint8_t *bufP, int lenP)
{
  cFemonBitStream bs(bufP, lenP * 8);

  if (!audioHandlerM)
     return false;

  // skip PES header
  if (!PesLongEnough(lenP))
      return false;
  bs.SkipBits(8 * PesPayloadOffset(bufP));

  // MPEG audio detection
  if (bs.GetBits(12) != 0x56E)              // syncword
     return false;

  audioHandlerM->SetAudioCodec(AUDIO_CODEC_LATM);

  if (bs.GetBit() == 0)                     // id: MPEG-1=1, extension to lower sampling frequencies=0
     return true;                           // @todo: lower sampling frequencies support
  int layer = 3 - bs.GetBits(2);            // layer: I=11, II=10, III=01
  bs.SkipBit();                             // protection bit
  int bit_rate_index = bs.GetBits(4);       // bitrate index
  int sampling_frequency = bs.GetBits(2);   // sampling frequency
  bs.SkipBit();                             // padding bit
  bs.SkipBit();                             // private pid
  int mode = bs.GetBits(2);                 // mode

  switch (mode) {
    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;
  }

  if (layer == 3) {
      audioHandlerM->SetAudioBitrate(AUDIO_BITRATE_FREE);
  }
  else {
     switch (bit_rate_index) {
       case 0:
            audioHandlerM->SetAudioBitrate(AUDIO_BITRATE_FREE);
            break;

       case 0xF:
            audioHandlerM->SetAudioBitrate(AUDIO_BITRATE_RESERVED);
            break;

       default:
            audioHandlerM->SetAudioBitrate(1000 * bitrateS[layer][bit_rate_index]);
            break;
     }
  }

  switch (sampling_frequency) {
    case 3:
         audioHandlerM->SetAudioSamplingFrequency(AUDIO_SAMPLING_FREQUENCY_RESERVED);
         break;

    default:
         audioHandlerM->SetAudioSamplingFrequency(sampleRateS[sampling_frequency]);
         break;
  }

  return true;
}
