// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "starboard/shared/win32/win32_audio_decoder.h"

#include <algorithm>

#include "starboard/shared/win32/atomic_queue.h"
#include "starboard/shared/win32/error_utils.h"
#include "starboard/shared/win32/media_foundation_utils.h"
#include "starboard/shared/win32/win32_decoder_impl.h"

namespace starboard {
namespace shared {
namespace win32 {

namespace {
using Microsoft::WRL::ComPtr;
using ::starboard::shared::win32::CheckResult;

const int kStreamId = 0;

std::vector<ComPtr<IMFMediaType>> Filter(
    GUID subtype_guid, const std::vector<ComPtr<IMFMediaType>>& input) {
  std::vector<ComPtr<IMFMediaType>> output;
  for (size_t i = 0; i < input.size(); ++i) {
    ComPtr<IMFMediaType> curr = input[i];
    GUID guid_value;
    HRESULT hr = curr->GetGUID(MF_MT_SUBTYPE, &guid_value);
    CheckResult(hr);
    if (subtype_guid == guid_value) {
      output.push_back(curr);
    }
  }

  return output;
}

std::vector<ComPtr<IMFMediaType>> GetAvailableTypes(IMFTransform* decoder) {
  std::vector<ComPtr<IMFMediaType>> output;
  for (DWORD i = 0; ; ++i) {
    ComPtr<IMFMediaType> curr_type;
    HRESULT input_hr_success = decoder->GetInputAvailableType(
        kStreamId,
        i,
        curr_type.GetAddressOf());
    if (!SUCCEEDED(input_hr_success)) {
      break;
    }
    output.push_back(curr_type);
  }

  return output;
}

class WinAudioFormat {
 public:
  explicit WinAudioFormat(const SbMediaAudioHeader& audio_header) {
    WAVEFORMATEX* wave_format = WaveFormatTexPtr();
    wave_format->nAvgBytesPerSec = audio_header.average_bytes_per_second;
    wave_format->nBlockAlign = audio_header.block_alignment;
    wave_format->nChannels = audio_header.number_of_channels;
    wave_format->nSamplesPerSec = audio_header.samples_per_second;
    wave_format->wBitsPerSample = audio_header.bits_per_sample;
    wave_format->wFormatTag = audio_header.format_tag;

    // TODO: Investigate this more.
    wave_format->cbSize = kAudioExtraFormatBytes;
    std::uint8_t* audio_specific_config = AudioSpecificConfigPtr();

    // These are hard-coded audio specif audio configuration.
    // Use |SbMediaAudioHeader::audio_specific_config| instead.
    SB_DCHECK(kAudioExtraFormatBytes == 2);
    // TODO: What do these values do?
    audio_specific_config[0] = 0x12;
    audio_specific_config[1] = 0x10;
  }
  WAVEFORMATEX* WaveFormatTexPtr() {
    return reinterpret_cast<WAVEFORMATEX*>(full_structure);
  }
  uint8_t* AudioSpecificConfigPtr() {
    return full_structure + sizeof(WAVEFORMATEX);
  }

  UINT32 Size() const {
    return sizeof(full_structure);
  }

 private:
  static const UINT32 kAudioExtraFormatBytes = 2;
  uint8_t full_structure[sizeof(WAVEFORMATEX) + kAudioExtraFormatBytes];
};

class AbstractWin32AudioDecoderImpl : public AbstractWin32AudioDecoder,
                                    public MediaBufferConsumerInterface {
 public:
  AbstractWin32AudioDecoderImpl(SbMediaAudioCodec codec,
                              SbMediaAudioFrameStorageType audio_frame_fmt,
                              SbMediaAudioSampleType sample_type,
                              const SbMediaAudioHeader& audio_header)
      : codec_(codec),
        audio_frame_fmt_(audio_frame_fmt),
        sample_type_(sample_type),
        audio_header_(audio_header) {
    MediaBufferConsumerInterface* media_cb = this;
    impl_.reset(new DecoderImpl("audio", media_cb));
    EnsureAudioDecoderCreated();
  }

  static GUID ConvertToWin32AudioCodec(SbMediaAudioCodec codec) {
    switch (codec) {
      case kSbMediaAudioCodecNone: { return MFAudioFormat_PCM; }
      case kSbMediaAudioCodecAac: { return MFAudioFormat_AAC; }
      case kSbMediaAudioCodecOpus: { return MFAudioFormat_Opus; }
      case kSbMediaAudioCodecVorbis: {
        SB_NOTIMPLEMENTED();
      }
    }
    return MFAudioFormat_PCM;
  }

  virtual void Consume(ComPtr<IMFMediaBuffer> media_buffer,
                       int64_t win32_timestamp) {
    BYTE* buffer;
    DWORD length;
    HRESULT hr = media_buffer->Lock(&buffer, NULL, &length);
    CheckResult(hr);
    SB_DCHECK(length);

    const uint8_t* data = reinterpret_cast<uint8_t*>(buffer);
    const size_t data_size = static_cast<size_t>(length);

    DecodedAudioPtr data_ptr(new DecodedAudio(
        audio_header_.number_of_channels, sample_type_, audio_frame_fmt_,
        ConvertToMediaTime(win32_timestamp), data_size));

    std::copy(data, data + data_size, data_ptr->buffer());

    output_queue_.PushBack(data_ptr);
    media_buffer->Unlock();
  }

  ComPtr<IMFMediaType> Configure(IMFTransform* decoder) {
    ComPtr<IMFMediaType> input_type;
    HRESULT hr = MFCreateMediaType(&input_type);
    CheckResult(hr);

    WinAudioFormat audio_fmt(audio_header_);
    hr = MFInitMediaTypeFromWaveFormatEx(
        input_type.Get(),
        audio_fmt.WaveFormatTexPtr(),
        audio_fmt.Size());

    CheckResult(hr);

    hr = input_type->SetUINT32(MF_MT_AAC_PAYLOAD_TYPE, 0);  // raw aac
    CheckResult(hr);

    GUID subtype = ConvertToWin32AudioCodec(codec_);
    hr = input_type->SetGUID(MF_MT_SUBTYPE, subtype);
    CheckResult(hr);

    std::vector<ComPtr<IMFMediaType>> available_types =
        GetAvailableTypes(decoder);

    GUID audio_fmt_guid = ConvertToWin32AudioCodec(codec_);
    available_types = Filter(audio_fmt_guid, available_types);
    SB_DCHECK(available_types.size());
    ComPtr<IMFMediaType> selected = available_types[0];

    std::vector<GUID> attribs = {
      MF_MT_AUDIO_BLOCK_ALIGNMENT,
      MF_MT_AUDIO_SAMPLES_PER_SECOND,
      MF_MT_AUDIO_AVG_BYTES_PER_SECOND,
      MF_MT_AUDIO_NUM_CHANNELS,
    };

    for (auto it = attribs.begin(); it != attribs.end(); ++it) {
      CopyUint32Property(*it, input_type.Get(), selected.Get());
    }

    hr = decoder->SetInputType(0, selected.Get(), 0);

    CheckResult(hr);
    return selected;
  }

  void EnsureAudioDecoderCreated() SB_OVERRIDE {
    if (impl_->has_decoder()) {
      return;
    }

    ComPtr<IMFTransform> decoder =
        DecoderImpl::CreateDecoder(CLSID_MSAACDecMFT);

    ComPtr<IMFMediaType> media_type = Configure(decoder.Get());

    SB_DCHECK(decoder);

    impl_->set_decoder(decoder);
    impl_->ActivateDecryptor(media_type);

    // TODO: MFWinAudioFormat_PCM?
    ComPtr<IMFMediaType> output_type =
        FindMediaType(MFAudioFormat_Float, decoder.Get());

    SB_DCHECK(output_type);

    HRESULT hr = decoder->SetOutputType(0, output_type.Get(), 0);
    CheckResult(hr);

    decoder->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
    decoder->ProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0);
  }

  bool TryWrite(const InputBuffer& buff) SB_OVERRIDE {
    EnsureAudioDecoderCreated();
    if (!impl_->has_decoder()) {
      return false;  // TODO: Signal an error.
    }

    const void* data = buff.data();
    const int size = buff.size();
    const int64_t media_timestamp = buff.pts();

    // These parameters are used for decryption. But these are not used right
    // now and so remain empty.
    std::vector<uint8_t> key_id;
    std::vector<uint8_t> iv;
    std::vector<Subsample> subsamples;

    const std::int64_t win32_time_stamp = ConvertToWin32Time(media_timestamp);

    // Adjust the offset for 7 bytes to remove the ADTS header.
    const uint8_t* audio_start = static_cast<const uint8_t*>(data) + 7;
    const int audio_size = size - 7;

    const bool write_ok = impl_->TryWriteInputBuffer(
        audio_start, audio_size, win32_time_stamp, key_id, iv, subsamples);
    impl_->DeliverOutputOnAllTransforms();
    return write_ok;
  }

  void WriteEndOfStream() SB_OVERRIDE {
    if (impl_->has_decoder()) {
      impl_->DrainDecoder();
      impl_->DeliverOutputOnAllTransforms();
      output_queue_.PushBack(new DecodedAudio);
    } else {
      // Don't call DrainDecoder() if input data is never queued.
      // TODO: Send EOS.
    }
  }

  scoped_refptr<DecodedAudio> ProcessAndRead() SB_OVERRIDE {
    impl_->DeliverOutputOnAllTransforms();
    scoped_refptr<DecodedAudio> output = output_queue_.PopFront();
    return output;
  }

  SbMediaAudioCodec codec_;
  SbMediaAudioHeader audio_header_;
  SbMediaAudioSampleType sample_type_;
  SbMediaAudioFrameStorageType audio_frame_fmt_;
  scoped_ptr<DecoderImpl> impl_;
  AtomicQueue<DecodedAudioPtr> output_queue_;
};
}  // anonymous namespace.

scoped_ptr<AbstractWin32AudioDecoder> AbstractWin32AudioDecoder::Create(
    SbMediaAudioCodec code,
    SbMediaAudioFrameStorageType audio_frame_fmt,
    SbMediaAudioSampleType sample_type,
    const SbMediaAudioHeader& audio_header) {
  return scoped_ptr<AbstractWin32AudioDecoder>(new
    AbstractWin32AudioDecoderImpl(code, audio_frame_fmt, sample_type,
      audio_header));
}

}  // namespace win32
}  // namespace shared
}  // namespace starboard
