// Copyright 2018 The Cobalt Authors. 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/starboard/player/video_dmp_writer.h"

#include <map>
#include <sstream>
#include <string>

#include "starboard/common/log.h"
#include "starboard/common/mutex.h"
#include "starboard/common/string.h"
#include "starboard/once.h"
#include "starboard/shared/starboard/application.h"

namespace starboard {
namespace shared {
namespace starboard {
namespace player {
namespace video_dmp {

namespace {

using std::placeholders::_1;
using std::placeholders::_2;

class PlayerToWriterMap {
 public:
  PlayerToWriterMap()
      : dump_video_data_(Application::Get()->GetCommandLine()->HasSwitch(
            "dump_video_data")) {}
  bool dump_video_data() const { return dump_video_data_; }
  void Register(SbPlayer player) {
    ScopedLock scoped_lock(mutex_);
    SB_DCHECK(map_.find(player) == map_.end());
    map_[player] = new VideoDmpWriter;
  }
  void Unregister(SbPlayer player) {
    ScopedLock scoped_lock(mutex_);
    auto iter = map_.find(player);
    SB_DCHECK(iter != map_.end());
    delete iter->second;
    map_.erase(iter);
  }
  VideoDmpWriter* Get(SbPlayer player) {
    ScopedLock scoped_lock(mutex_);
    auto iter = map_.find(player);
    SB_DCHECK(iter != map_.end());
    return iter->second;
  }

 private:
  Mutex mutex_;
  bool dump_video_data_;
  std::map<SbPlayer, VideoDmpWriter*> map_;
};

SB_ONCE_INITIALIZE_FUNCTION(PlayerToWriterMap, GetOrCreatePlayerToWriterMap);

}  // namespace

VideoDmpWriter::VideoDmpWriter() : file_(kSbFileInvalid) {
  int index = 0;
  std::string file_name;
  while (!SbFileIsValid(file_)) {
    std::stringstream ss;
    ss << "video_" << index << ".dmp";
    file_name = ss.str();

    bool created = false;
    file_ = SbFileOpen(file_name.c_str(), kSbFileCreateOnly | kSbFileWrite,
                       &created, NULL);
    ++index;
  }
  SB_LOG(INFO) << "Dump video content to " << file_name;

  write_cb_ = std::bind(&VideoDmpWriter::WriteToFile, this, _1, _2);

  Write(write_cb_, kByteOrderMark);
  Write(write_cb_, kSupportWriterVersion);
}

VideoDmpWriter::~VideoDmpWriter() {
  SbFileClose(file_);
}

// static
void VideoDmpWriter::OnPlayerCreate(
    SbPlayer player,
    SbMediaAudioCodec audio_codec,
    SbMediaVideoCodec video_codec,
    SbDrmSystem drm_system,
    const SbMediaAudioSampleInfo* audio_sample_info) {
  // TODO: Allow dump of drm initialization data
  SB_UNREFERENCED_PARAMETER(drm_system);

  PlayerToWriterMap* map = GetOrCreatePlayerToWriterMap();
  if (!map->dump_video_data()) {
    return;
  }
  map->Register(player);
  VideoDmpWriter* dmp_writer = map->Get(player);
#if SB_API_VERSION < 11
  dmp_writer->audio_codec_ = audio_codec;
  dmp_writer->video_codec_ = video_codec;
#endif  // SB_API_VERSION < 11
  dmp_writer->DumpConfigs(video_codec, audio_codec, audio_sample_info);
}

// static
void VideoDmpWriter::OnPlayerWriteSample(
    SbPlayer player,
    const scoped_refptr<InputBuffer>& input_buffer) {
  PlayerToWriterMap* map = GetOrCreatePlayerToWriterMap();
  if (!map->dump_video_data()) {
    return;
  }
  map->Get(player)->DumpAccessUnit(input_buffer);
}

// static
void VideoDmpWriter::OnPlayerDestroy(SbPlayer player) {
  PlayerToWriterMap* map = GetOrCreatePlayerToWriterMap();
  if (!map->dump_video_data()) {
    return;
  }
  map->Unregister(player);
}

void VideoDmpWriter::DumpConfigs(
    SbMediaVideoCodec video_codec,
    SbMediaAudioCodec audio_codec,
    const SbMediaAudioSampleInfo* audio_sample_info) {
  Write(write_cb_, kRecordTypeAudioConfig);
  Write(write_cb_, audio_codec);
  if (audio_codec != kSbMediaAudioCodecNone) {
    SB_DCHECK(audio_sample_info);
    Write(write_cb_, audio_codec, *audio_sample_info);
  }

  Write(write_cb_, kRecordTypeVideoConfig);
  Write(write_cb_, video_codec);
}

void VideoDmpWriter::DumpAccessUnit(
    const scoped_refptr<InputBuffer>& input_buffer) {
  const SbMediaType& sample_type = input_buffer->sample_type();
  const void* sample_buffer = static_cast<const void*>(input_buffer->data());
  const int& sample_buffer_size = input_buffer->size();
  const SbTime& sample_timestamp = input_buffer->timestamp();
  const SbDrmSampleInfo* drm_sample_info = input_buffer->drm_info();

  if (sample_type == kSbMediaTypeAudio) {
    Write(write_cb_, kRecordTypeAudioAccessUnit);
  } else {
    SB_DCHECK(sample_type == kSbMediaTypeVideo);
    Write(write_cb_, kRecordTypeVideoAccessUnit);
  }

  Write(write_cb_, sample_timestamp);

  if (drm_sample_info && drm_sample_info->identifier_size == 16 &&
      (drm_sample_info->initialization_vector_size == 8 ||
       drm_sample_info->initialization_vector_size == 16)) {
    Write(write_cb_, true);
    Write(write_cb_, *drm_sample_info);
  } else {
    Write(write_cb_, false);
  }
  Write(write_cb_, static_cast<uint32_t>(sample_buffer_size));
  Write(write_cb_, sample_buffer, static_cast<size_t>(sample_buffer_size));

  if (sample_type == kSbMediaTypeAudio) {
    const SbMediaAudioSampleInfo& audio_sample_info =
        input_buffer->audio_sample_info();
#if SB_API_VERSION >= 11
    Write(write_cb_, audio_sample_info.codec, audio_sample_info);
#else   // SB_API_VERSION >= 11
    Write(write_cb_, audio_codec_, audio_sample_info);
#endif  // SB_API_VERSION >= 11
  } else {
    SB_DCHECK(sample_type == kSbMediaTypeVideo);
    const SbMediaVideoSampleInfo& video_sample_info =
        input_buffer->video_sample_info();
#if SB_API_VERSION >= 11
    Write(write_cb_, video_sample_info.codec, video_sample_info);
#else   // SB_API_VERSION >= 11
    Write(write_cb_, video_codec_, video_sample_info);
#endif  // SB_API_VERSION >= 11
  }
}

int VideoDmpWriter::WriteToFile(const void* buffer, int size) {
  return SbFileWrite(file_, static_cast<const char*>(buffer), size);
}

}  // namespace video_dmp
}  // namespace player
}  // namespace starboard
}  // namespace shared
}  // namespace starboard
