// 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_("FlacEncodingThd") {
  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
