// Copyright 2015 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 <algorithm>
#include <limits>

#include "base/logging.h"
#include "mojo/services/media/common/cpp/linear_transform.h"
#include "services/media/audio/audio_output_manager.h"
#include "services/media/audio/audio_server_impl.h"
#include "services/media/audio/audio_track_impl.h"
#include "services/media/audio/audio_track_to_output_link.h"

namespace mojo {
namespace media {
namespace audio {

constexpr size_t AudioTrackImpl::PTS_FRACTIONAL_BITS;

// TODO(johngro): If there is ever a better way to do this type of static-table
// initialization using mojom generated structs, we should switch to it.
static const struct {
  LpcmSampleFormat sample_format;
  uint8_t min_samples_per_frame;
  uint8_t max_samples_per_frame;
  uint32_t min_frames_per_second;
  uint32_t max_frames_per_second;
} kSupportedLpcmTypeSets[] = {
  {
    .sample_format = LpcmSampleFormat::UNSIGNED_8,
    .min_samples_per_frame = 1,
    .max_samples_per_frame = 2,
    .min_frames_per_second = 1000,
    .max_frames_per_second = 48000,
  },
  {
    .sample_format = LpcmSampleFormat::SIGNED_16,
    .min_samples_per_frame = 1,
    .max_samples_per_frame = 2,
    .min_frames_per_second = 1000,
    .max_frames_per_second = 48000,
  },
};

AudioTrackImpl::AudioTrackImpl(InterfaceRequest<AudioTrack> iface,
                             AudioServerImpl* owner)
  : owner_(owner),
    binding_(this),
    pipe_(this, owner) {
  CHECK(nullptr != owner_);
  binding_.Bind(iface.Pass());
}

AudioTrackImpl::~AudioTrackImpl() {
}

AudioTrackImplPtr AudioTrackImpl::Create(InterfaceRequest<AudioTrack> iface,
                                       AudioServerImpl* owner) {
  AudioTrackImplPtr ret(new AudioTrackImpl(iface.Pass(), owner));
  ret->weak_this_ = ret;
  return ret;
}

void AudioTrackImpl::Describe(const DescribeCallback& cbk) {
  // Build a minimal descriptor
  //
  // TODO(johngro): one day, we need to make this description much more rich and
  // fully describe our capabilities, based on things like what outputs are
  // available, the class of hardware we are on, and what options we were
  // compiled with.
  //
  // For now, it would be nice to just be able to have a static const tree of
  // capabilities in this translational unit which we could use to construct our
  // message, but the nature of the structures generated by the C++ bindings
  // make this difficult.  For now, we just create a trivial descriptor entierly
  // by hand.
  AudioTrackDescriptorPtr desc(AudioTrackDescriptor::New());

  desc->supported_media_types =
    Array<MediaTypeSetPtr>::New(arraysize(kSupportedLpcmTypeSets));

  for (size_t i = 0; i < desc->supported_media_types.size(); ++i) {
    const MediaTypeSetPtr& mts =
      (desc->supported_media_types[i] = MediaTypeSet::New());

    mts->scheme  = MediaTypeScheme::LPCM;
    mts->details = MediaTypeSetDetails::New();

    const auto& s = kSupportedLpcmTypeSets[i];
    LpcmMediaTypeSetDetailsPtr lpcm_detail = LpcmMediaTypeSetDetails::New();

    lpcm_detail->sample_format         = s.sample_format;
    lpcm_detail->min_samples_per_frame = s.min_samples_per_frame;
    lpcm_detail->max_samples_per_frame = s.max_samples_per_frame;
    lpcm_detail->min_frames_per_second = s.min_frames_per_second;
    lpcm_detail->max_frames_per_second = s.max_frames_per_second;
    mts->details->set_lpcm(lpcm_detail.Pass());
  }

  cbk.Run(desc.Pass());
}

void AudioTrackImpl::Configure(AudioTrackConfigurationPtr configuration,
                              InterfaceRequest<MediaPipe> req,
                              const ConfigureCallback&    cbk) {
  // Are we already configured?
  if (pipe_.IsInitialized()) {
    cbk.Run(MediaResult::BAD_STATE);
    return;
  }

  // Check the requested configuration.
  if ((configuration->media_type->scheme != MediaTypeScheme::LPCM) ||
      (!configuration->media_type->details->is_lpcm())) {
    cbk.Run(MediaResult::UNSUPPORTED_CONFIG);
    return;
  }

  // Search our supported configuration sets to find one compatible with this
  // request.
  auto& cfg = configuration->media_type->details->get_lpcm();
  size_t i;
  for (i = 0; i < arraysize(kSupportedLpcmTypeSets); ++i) {
    const auto& cfg_set = kSupportedLpcmTypeSets[i];

    if ((cfg->sample_format == cfg_set.sample_format) &&
        (cfg->samples_per_frame >= cfg_set.min_samples_per_frame) &&
        (cfg->samples_per_frame <= cfg_set.max_samples_per_frame) &&
        (cfg->frames_per_second >= cfg_set.min_frames_per_second) &&
        (cfg->frames_per_second <= cfg_set.max_frames_per_second)) {
      break;
    }
  }

  if (i >= arraysize(kSupportedLpcmTypeSets)) {
    cbk.Run(MediaResult::UNSUPPORTED_CONFIG);
    return;
  }

  // Sanity check the ratio which relates audio frames to media time.
  int32_t  numerator   = static_cast<int32_t>(configuration->audio_frame_ratio);
  uint32_t denominator = static_cast<int32_t>(configuration->media_time_ratio);
  if ((numerator < 1) || (denominator < 1)) {
    cbk.Run(MediaResult::INVALID_ARGUMENT);
    return;
  }


  // Figure out the rate we need to scale by in order to produce our fixed
  // point timestamps.
  LinearTransform::Ratio frac_scale(1 << PTS_FRACTIONAL_BITS, 1);
  LinearTransform::Ratio frame_scale(LinearTransform::Ratio(numerator,
                                                            denominator));
  bool no_loss = LinearTransform::Ratio::Compose(frac_scale,
                                                 frame_scale,
                                                 &frame_to_media_ratio_);
  if (!no_loss) {
    cbk.Run(MediaResult::INVALID_ARGUMENT);
    return;
  }

  // Figure out how many bytes we need to hold the requested number of nSec of
  // audio.
  switch (cfg->sample_format) {
    case LpcmSampleFormat::UNSIGNED_8:
      bytes_per_frame_ = 1;
      break;

    case LpcmSampleFormat::SIGNED_16:
      bytes_per_frame_ = 2;
      break;

    case LpcmSampleFormat::SIGNED_24_IN_32:
      bytes_per_frame_ = 4;
      break;

    default:
      DCHECK(false);
      bytes_per_frame_ = 2;
      break;
  }
  bytes_per_frame_ *= cfg->samples_per_frame;

  // Overflow trying to convert from frames to bytes?
  uint64_t requested_frames = configuration->max_frames;
  if (requested_frames >
     (std::numeric_limits<size_t>::max() / bytes_per_frame_)) {
    cbk.Run(MediaResult::INSUFFICIENT_RESOURCES);
    return;
  }

  size_t requested_bytes = (requested_frames * bytes_per_frame_);

  // Attempt to initialize our shared buffer and bind it to our interface
  // request.
  if (pipe_.Init(req.Pass(), requested_bytes) != MOJO_RESULT_OK) {
    cbk.Run(MediaResult::INSUFFICIENT_RESOURCES);
    return;
  }

  // Stash our configuration.
  format_ = cfg.Pass();

  // Have the audio output manager initialize our set of outputs.  Note; there
  // is currently no need for a lock here.  Methods called from our user-facing
  // interfaces are seriailzed by nature of the mojo framework, and none of the
  // output manager's threads should ever need to manipulate the set.  Cleanup
  // of outputs which have gone away is currently handled in a lazy fashion when
  // the track fails to promote its weak reference during an operation involving
  // its outputs.
  //
  // TODO(johngro): someday, we will need to deal with recalculating properties
  // which depend on a track's current set of outputs (for example, the minimum
  // latency).  This will probably be done using a dirty flag in the track
  // implementations, and scheduling a job to recalculate the properties for the
  // dirty tracks and notify the users as appropriate.

  // If we cannot promote our own weak pointer, something is seriously wrong.
  AudioTrackImplPtr strong_this(weak_this_.lock());
  DCHECK(strong_this);
  DCHECK(owner_);
  owner_->GetOutputManager().SelectOutputsForTrack(strong_this);

  // Done
  cbk.Run(MediaResult::OK);
}

void AudioTrackImpl::GetRateControl(InterfaceRequest<RateControl> req,
                                   const GetRateControlCallback& cbk) {
  cbk.Run(rate_control_.Bind(req.Pass()));
}

void AudioTrackImpl::AddOutput(AudioTrackToOutputLinkPtr link) {
  // TODO(johngro): assert that we are on the main message loop thread.
  DCHECK(link);
  auto res = outputs_.emplace(link);
  DCHECK(res.second);
}

void AudioTrackImpl::RemoveOutput(AudioTrackToOutputLinkPtr link) {
  // TODO(johngro): assert that we are on the main message loop thread.
  DCHECK(link);

  auto iter = outputs_.find(link);
  if (iter != outputs_.end()) {
    outputs_.erase(iter);
  } else {
    // TODO(johngro): that's odd.  I can't think of a reason why we we should
    // not be able to find this link in our set of outputs... should we log
    // something about this?
    DCHECK(false);
  }
}

void AudioTrackImpl::OnPacketReceived(AudioPipe::AudioPacketRefPtr packet) {
  DCHECK(packet);
  for (const auto& output : outputs_) {
    DCHECK(output);
    output->PushToPendingQueue(packet);
  }
}

void AudioTrackImpl::OnFlushRequested(const MediaPipe::FlushCallback& cbk) {
  for (const auto& output : outputs_) {
    DCHECK(output);
    output->FlushPendingQueue();
  }
  cbk.Run(MediaResult::OK);
}

}  // namespace audio
}  // namespace media
}  // namespace mojo
