// Copyright 2018 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 "cobalt/media_capture/encoders/flac_audio_encoder.h"

#include <memory>
#include <string>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/strings/string_util.h"

namespace {

// See https://tools.ietf.org/html/rfc2586 for MIME type
const char kFlacMimeType[] = "audio/flac";

// This is a guesstimated value. This number should be > 1.
const double kEstimatedFlacCompressionRatio = 1.30;

}  // namespace

namespace cobalt {
namespace media_capture {
namespace encoders {

bool FlacAudioEncoder::IsFlacMIMEType(const base::StringPiece& mime_type) {
  base::StringPiece mime_type_container = mime_type;
  size_t pos = mime_type.find_first_of(';');
  if (pos != base::StringPiece::npos) {
    mime_type_container = base::StringPiece(mime_type.begin(), pos);
  }
  const base::StringPiece flac_mime_type(kFlacMimeType);
  auto match_iterator =
      std::search(mime_type_container.begin(), mime_type_container.end(),
                  flac_mime_type.begin(), flac_mime_type.end(),
                  base::CaseInsensitiveCompareASCII<char>());
  return match_iterator == mime_type_container.begin();
}

FlacAudioEncoder::FlacAudioEncoder() : thread_("flac_encoding_thread") {
  thread_.Start();
}

FlacAudioEncoder::~FlacAudioEncoder() {
  thread_.task_runner()->PostBlockingTask(
      FROM_HERE,
      base::Bind(&FlacAudioEncoder::DestroyEncoder, base::Unretained(this)));
}

void FlacAudioEncoder::Encode(const ShellAudioBus& audio_bus,
                              base::TimeTicks reference_time) {
  std::unique_ptr<ShellAudioBus> audio_bus_copy(
      new ShellAudioBus(audio_bus.channels(), audio_bus.frames(),
                        audio_bus.sample_type(), audio_bus.storage_type()));
  audio_bus_copy->Assign(audio_bus);

  // base::Unretained usage is safe here, since we're posting to a thread that
  // we own.
  thread_.task_runner()->PostTask(
      FROM_HERE, base::Bind(&FlacAudioEncoder::DoEncode, base::Unretained(this),
                            base::Passed(&audio_bus_copy), reference_time));
}

void FlacAudioEncoder::Finish(base::TimeTicks reference_time) {
  thread_.task_runner()->PostBlockingTask(
      FROM_HERE, base::Bind(&FlacAudioEncoder::DoFinish, base::Unretained(this),
                            reference_time));
}

std::string FlacAudioEncoder::GetMimeType() const {
  return flac_encoder_->GetMimeType();
}

int64 FlacAudioEncoder::GetEstimatedOutputBitsPerSecond(
    const media_stream::AudioParameters& params) const {
  DCHECK_EQ(params.bits_per_sample(), 16);
  DCHECK_EQ(params.channel_count(), 1);
  return static_cast<int64>(params.GetBitsPerSecond() /
                            kEstimatedFlacCompressionRatio);
}

void FlacAudioEncoder::OnSetFormat(
    const media_stream::AudioParameters& params) {
  // base::Unretained usage is safe here, since we're posting to a thread that
  // we own.
  thread_.task_runner()->PostTask(FROM_HERE,
                                  base::Bind(&FlacAudioEncoder::CreateEncoder,
                                             base::Unretained(this), params));
}

void FlacAudioEncoder::CreateEncoder(
    const media_stream::AudioParameters& params) {
  flac_encoder_.reset(new speech::AudioEncoderFlac(params.sample_rate()));
}

void FlacAudioEncoder::DestroyEncoder() { flac_encoder_.reset(); }

void FlacAudioEncoder::DoEncode(std::unique_ptr<ShellAudioBus> audio_bus,
                                base::TimeTicks reference_time) {
  DCHECK(flac_encoder_);
  flac_encoder_->Encode(audio_bus.get());
  auto data = flac_encoder_->GetAndClearAvailableEncodedData();
  if (data.empty()) {
    return;
  }
  PushDataToAllListeners(reinterpret_cast<uint8*>(&data[0]), data.size(),
                         reference_time);
}

void FlacAudioEncoder::DoFinish(base::TimeTicks reference_time) {
  if (!flac_encoder_) {
    return;
  }
  flac_encoder_->Finish();
  auto data = flac_encoder_->GetAndClearAvailableEncodedData();
  if (data.empty()) {
    PushDataToAllListeners(nullptr, 0, reference_time);
    return;
  }
  PushDataToAllListeners(reinterpret_cast<uint8*>(&data[0]), data.size(),
                         reference_time);
}

}  // namespace encoders
}  // namespace media_capture
}  // namespace cobalt
