// Copyright 2014 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/filters/ffmpeg_aac_bitstream_converter.h"

#include "base/logging.h"
#include "media/ffmpeg/ffmpeg_common.h"

namespace media {

namespace {

// Creates an ADTS header and stores in |hdr|
// Assumes |hdr| points to an array of length |kAdtsHeaderSize|
// Returns false if parameter values are for an unsupported configuration.
bool GenerateAdtsHeader(int codec,
                        int layer,
                        int audio_profile,
                        int sample_rate_index,
                        int private_stream,
                        int channel_configuration,
                        int originality,
                        int home,
                        int copyrighted_stream,
                        int copyright_start,
                        int frame_length,
                        int buffer_fullness,
                        int number_of_frames_minus_one,
                        uint8_t* hdr) {
  DCHECK_EQ(codec, AV_CODEC_ID_AAC);

  memset(reinterpret_cast<void *>(hdr), 0,
         FFmpegAACBitstreamConverter::kAdtsHeaderSize);
  // Ref: http://wiki.multimedia.cx/index.php?title=ADTS
  // ADTS header structure is the following
  // AAAAAAAA  AAAABCCD  EEFFFFGH  HHIJKLMM  MMMMMMMM  MMMOOOOO  OOOOOOPP
  //
  // A    Syncword 0xFFF, all bits must be 1
  // B    MPEG Version: 0 for MPEG-4, 1 for MPEG-2
  // C    Layer: always 0
  // D    Protection absent: Set to 1 if no CRC and 0 if there is CRC.
  // E    Profile: the MPEG-4 Audio Object Type minus 1.
  // F    MPEG-4 Sampling Frequency Index (15 is forbidden)
  // G    Private stream:
  // H    MPEG-4 Channel Configuration
  // I    Originality
  // J    Home
  // K    Copyrighted Stream
  // L    Copyright_ start
  // M    Frame length. This must include the ADTS header length.
  // O    Buffer fullness
  // P    Number of AAC frames in ADTS frame minus 1.
  //      For maximum compatibility always use 1 AAC frame per ADTS frame.

  // Syncword
  hdr[0] = 0xFF;
  hdr[1] = 0xF0;

  // Layer is always 0. No further action required.

  // Protection absent (no CRC) is always 1.
  hdr[1] |= 1;

  switch (audio_profile) {
    case FF_PROFILE_AAC_MAIN:
      break;
    case FF_PROFILE_AAC_HE:
    case FF_PROFILE_AAC_HE_V2:
    case FF_PROFILE_AAC_LOW:
      hdr[2] |= (1 << 6);
      break;
    case FF_PROFILE_AAC_SSR:
      hdr[2] |= (2 << 6);
      break;
    case FF_PROFILE_AAC_LTP:
      hdr[2] |= (3 << 6);
      break;
    default:
      DLOG(ERROR) << "[" << __func__ << "] "
                  << "unsupported audio profile:" << audio_profile;
      return false;
  }

  hdr[2] |= ((sample_rate_index & 0xf) << 2);

  if (private_stream)
    hdr[2] |= (1 << 1);

  switch (channel_configuration) {
    case 1:
      // front-center
      hdr[3] |= (1 << 6);
      break;
    case 2:
      // front-left, front-right
      hdr[3] |= (2 << 6);
      break;
    case 3:
      // front-center, front-left, front-right
      hdr[3] |= (3 << 6);
      break;
    case 4:
      // front-center, front-left, front-right, back-center
      hdr[2] |= 1;
      break;
    case 5:
      // front-center, front-left, front-right, back-left, back-right
      hdr[2] |= 1;
      hdr[3] |= (1 << 6);
      break;
    case 6:
      // front-center, front-left, front-right, back-left, back-right,
      // LFE-channel
      hdr[2] |= 1;
      hdr[3] |= (2 << 6);
      break;
    case 8:
      // front-center, front-left, front-right, side-left, side-right,
      // back-left, back-right, LFE-channel
      hdr[2] |= 1;
      hdr[3] |= (3 << 6);
      break;
    default:
      DLOG(ERROR) << "[" << __func__ << "] "
                  << "unsupported number of audio channels:"
                  << channel_configuration;
      return false;
  }

  if (originality)
    hdr[3] |= (1 << 5);

  if (home)
    hdr[3] |= (1 << 4);

  if (copyrighted_stream)
    hdr[3] |= (1 << 3);

  if (copyright_start)
    hdr[3] |= (1 << 2);

  // frame length
  hdr[3] |= (frame_length >> 11) & 0x03;
  hdr[4] = (frame_length >> 3) & 0xFF;
  hdr[5] |= (frame_length & 7) << 5;

  // buffer fullness
  hdr[5] |= (buffer_fullness >> 6) & 0x1F;
  hdr[6] |= (buffer_fullness & 0x3F) << 2;

  hdr[6] |= number_of_frames_minus_one & 0x3;

  return true;
}

}

FFmpegAACBitstreamConverter::FFmpegAACBitstreamConverter(
    AVCodecParameters* stream_codec_parameters)
    : stream_codec_parameters_(stream_codec_parameters),
      header_generated_(false),
      codec_(),
      audio_profile_(),
      sample_rate_index_(),
      channel_configuration_(),
      frame_length_() {
  CHECK(stream_codec_parameters_);
}

FFmpegAACBitstreamConverter::~FFmpegAACBitstreamConverter() = default;

bool FFmpegAACBitstreamConverter::ConvertPacket(AVPacket* packet) {
  if (packet == NULL || !packet->data) {
    return false;
  }

  int header_plus_packet_size =
      packet->size + kAdtsHeaderSize;
  if (!stream_codec_parameters_->extradata) {
    DLOG(ERROR) << "extradata is null";
    return false;
  }
  if (stream_codec_parameters_->extradata_size < 2) {
    DLOG(ERROR) << "extradata too small to contain MP4A header";
    return false;
  }
  int sample_rate_index =
      ((stream_codec_parameters_->extradata[0] & 0x07) << 1) |
      ((stream_codec_parameters_->extradata[1] & 0x80) >> 7);
  if (sample_rate_index > 12) {
    sample_rate_index = 4;
  }

  if (!header_generated_ || codec_ != stream_codec_parameters_->codec_id ||
      audio_profile_ != stream_codec_parameters_->profile ||
      sample_rate_index_ != sample_rate_index ||
      channel_configuration_ != stream_codec_parameters_->channels ||
      frame_length_ != header_plus_packet_size) {
    header_generated_ =
        GenerateAdtsHeader(stream_codec_parameters_->codec_id,
                           0,  // layer
                           stream_codec_parameters_->profile, sample_rate_index,
                           0,  // private stream
                           stream_codec_parameters_->channels,
                           0,  // originality
                           0,  // home
                           0,  // copyrighted_stream
                           0,  // copyright_ start
                           header_plus_packet_size,
                           0x7FF,  // buffer fullness
                           0,      // one frame per packet
                           hdr_);
    codec_ = stream_codec_parameters_->codec_id;
    audio_profile_ = stream_codec_parameters_->profile;
    sample_rate_index_ = sample_rate_index;
    channel_configuration_ = stream_codec_parameters_->channels;
    frame_length_ = header_plus_packet_size;
  }

  // Inform caller if the header generation failed.
  if (!header_generated_)
    return false;

  // Allocate new packet for the output.
  AVPacket dest_packet;
  if (av_new_packet(&dest_packet, header_plus_packet_size) != 0)
    return false;  // Memory allocation failure.

  memcpy(dest_packet.data, hdr_, kAdtsHeaderSize);
  memcpy(reinterpret_cast<void*>(dest_packet.data + kAdtsHeaderSize),
         reinterpret_cast<void*>(packet->data), packet->size);

  // This is a bit tricky: since the interface does not allow us to replace
  // the pointer of the old packet with a new one, we will initially copy the
  // metadata from old packet to new bigger packet.
  av_packet_copy_props(&dest_packet, packet);

  // Release the old packet.
  av_packet_unref(packet);

  // Finally, replace the values in the input packet.
  memcpy(packet, &dest_packet, sizeof(*packet));
  return true;
}

}  // namespace media
