// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/mp4/aac.h"

#include <algorithm>

#include "base/logging.h"
#include "media/base/bit_reader.h"
#include "media/mp4/rcheck.h"

// The following conversion table is extracted from ISO 14496 Part 3 -
// Table 1.16 - Sampling Frequency Index.
static const int kFrequencyMap[] = {
  96000, 88200, 64000, 48000, 44100, 32000, 24000,
  22050, 16000, 12000, 11025, 8000, 7350
};

namespace media {

static ChannelLayout GetChannelLayout(uint8 channel_config) {
  switch (channel_config) {
    case 1:
      return CHANNEL_LAYOUT_MONO;
    case 2:
      return CHANNEL_LAYOUT_STEREO;
    case 3:
      return CHANNEL_LAYOUT_SURROUND;
    case 4:
      return CHANNEL_LAYOUT_4_0;
    case 5:
      return CHANNEL_LAYOUT_5_0;
    case 6:
      return CHANNEL_LAYOUT_5_1;
    case 8:
      return CHANNEL_LAYOUT_7_1;
    default:
      break;
  }

  return CHANNEL_LAYOUT_UNSUPPORTED;
}

namespace mp4 {

AAC::AAC()
    : profile_(0), frequency_index_(0), channel_config_(0), frequency_(0),
      extension_frequency_(0), channel_layout_(CHANNEL_LAYOUT_UNSUPPORTED) {
}

AAC::~AAC() {
}

bool AAC::Parse(const std::vector<uint8>& data) {
  if (data.empty())
    return false;
#if defined(COBALT_WIN)
  raw_data_ = data;
#endif  // COBALT_WIN
  BitReader reader(&data[0], data.size());
  uint8 extension_type = 0;
  bool ps_present = false;
  uint8 extension_frequency_index = 0xff;

  frequency_ = 0;
  extension_frequency_ = 0;

  // The following code is written according to ISO 14496 Part 3 Table 1.13 -
  // Syntax of AudioSpecificConfig.

  // Read base configuration
  RCHECK(reader.ReadBits(5, &profile_));
  RCHECK(reader.ReadBits(4, &frequency_index_));
  if (frequency_index_ == 0xf)
    RCHECK(reader.ReadBits(24, &frequency_));
  RCHECK(reader.ReadBits(4, &channel_config_));

  // Read extension configuration.
  if (profile_ == 5 || profile_ == 29) {
    ps_present = (profile_ == 29);
    extension_type = 5;
    RCHECK(reader.ReadBits(4, &extension_frequency_index));
    if (extension_frequency_index == 0xf)
      RCHECK(reader.ReadBits(24, &extension_frequency_));
    RCHECK(reader.ReadBits(5, &profile_));
  }

  RCHECK(SkipDecoderGASpecificConfig(&reader));
  RCHECK(SkipErrorSpecificConfig());

  // Read extension configuration again
  if (extension_type != 5) {
    uint16 sync_extension_type;
    uint8 sbr_present_flag;
    uint8 ps_present_flag;

    if (reader.ReadBits(11, &sync_extension_type) &&
        sync_extension_type == 0x2b7) {
      if (reader.ReadBits(5, &extension_type) && extension_type == 5) {
        RCHECK(reader.ReadBits(1, &sbr_present_flag));

        if (sbr_present_flag) {
          RCHECK(reader.ReadBits(4, &extension_frequency_index));

          if (extension_frequency_index == 0xf)
            RCHECK(reader.ReadBits(24, &extension_frequency_));

          RCHECK(reader.ReadBits(11, &sync_extension_type));

          if (sync_extension_type == 0x548) {
            RCHECK(reader.ReadBits(1, &ps_present_flag));
            ps_present = ps_present_flag != 0;
          }
        }
      }
    }
  }

  if (frequency_ == 0) {
    RCHECK(frequency_index_ < arraysize(kFrequencyMap));
    frequency_ = kFrequencyMap[frequency_index_];
  }

  if (extension_frequency_ == 0 && extension_frequency_index != 0xff) {
    RCHECK(extension_frequency_index < arraysize(kFrequencyMap));
    extension_frequency_ = kFrequencyMap[extension_frequency_index];
  }

  // When Parametric Stereo is on, mono will be played as stereo.
  if (ps_present && channel_config_ == 1)
    channel_layout_ = GetChannelLayout(2);
  else
    channel_layout_ = GetChannelLayout(channel_config_);

  return frequency_ != 0 && channel_layout_ != CHANNEL_LAYOUT_UNSUPPORTED &&
      profile_ >= 1 && profile_ <= 4 && frequency_index_ != 0xf &&
      channel_config_ <= 7;
}

int AAC::GetOutputSamplesPerSecond(bool sbr_in_mimetype) const {
  if (extension_frequency_ > 0)
    return extension_frequency_;

  if (!sbr_in_mimetype)
    return frequency_;

  // The following code is written according to ISO 14496 Part 3 Table 1.11 and
  // Table 1.22. (Table 1.11 refers to the capping to 48000, Table 1.22 refers
  // to SBR doubling the AAC sample rate.)
  // TODO(acolwell) : Extend sample rate cap to 96kHz for Level 5 content.
  DCHECK_GT(frequency_, 0);
  return std::min(2 * frequency_, 48000);
}

ChannelLayout AAC::channel_layout() const {
  return channel_layout_;
}

bool AAC::ConvertEsdsToADTS(std::vector<uint8>* buffer) const {
  size_t size = buffer->size() + kADTSHeaderSize;

  DCHECK(profile_ >= 1 && profile_ <= 4 && frequency_index_ != 0xf &&
         channel_config_ <= 7);

  // ADTS header uses 13 bits for packet size.
  if (size >= (1 << 13))
    return false;

  std::vector<uint8>& adts = *buffer;

  adts.insert(buffer->begin(), kADTSHeaderSize, 0);
  adts[0] = 0xff;
  adts[1] = 0xf1;
  adts[2] = ((profile_ - 1) << 6) + (frequency_index_ << 2) +
      (channel_config_ >> 2);
  adts[3] = ((channel_config_ & 0x3) << 6) + (size >> 11);
  adts[4] = (size & 0x7ff) >> 3;
  adts[5] = ((size & 7) << 5) + 0x1f;
  adts[6] = 0xfc;

  return true;
}

// Currently this function only support GASpecificConfig defined in
// ISO 14496 Part 3 Table 4.1 - Syntax of GASpecificConfig()
bool AAC::SkipDecoderGASpecificConfig(BitReader* bit_reader) const {
  switch (profile_) {
    case 1:
    case 2:
    case 3:
    case 4:
    case 6:
    case 7:
    case 17:
    case 19:
    case 20:
    case 21:
    case 22:
    case 23:
      return SkipGASpecificConfig(bit_reader);
    default:
      break;
  }

  return false;
}

bool AAC::SkipErrorSpecificConfig() const {
  switch (profile_) {
    case 17:
    case 19:
    case 20:
    case 21:
    case 22:
    case 23:
    case 24:
    case 25:
    case 26:
    case 27:
      return false;
    default:
      break;
  }

  return true;
}

// The following code is written according to ISO 14496 part 3 Table 4.1 -
// GASpecificConfig.
bool AAC::SkipGASpecificConfig(BitReader* bit_reader) const {
  uint8 extension_flag = 0;
  uint8 depends_on_core_coder;
  uint16 dummy;

  RCHECK(bit_reader->ReadBits(1, &dummy));  // frameLengthFlag
  RCHECK(bit_reader->ReadBits(1, &depends_on_core_coder));
  if (depends_on_core_coder == 1)
    RCHECK(bit_reader->ReadBits(14, &dummy));  // coreCoderDelay

  RCHECK(bit_reader->ReadBits(1, &extension_flag));
  RCHECK(channel_config_ != 0);

  if (profile_ == 6 || profile_ == 20)
    RCHECK(bit_reader->ReadBits(3, &dummy));  // layerNr

  if (extension_flag) {
    if (profile_ == 22) {
      RCHECK(bit_reader->ReadBits(5, &dummy));  // numOfSubFrame
      RCHECK(bit_reader->ReadBits(11, &dummy));  // layer_length
    }

    if (profile_ == 17 || profile_ == 19 || profile_ == 20 || profile_ == 23) {
      RCHECK(bit_reader->ReadBits(3, &dummy));  // resilience flags
    }

    RCHECK(bit_reader->ReadBits(1, &dummy));  // extensionFlag3
  }

  return true;
}

}  // namespace mp4

}  // namespace media
