// Copyright (c) 2012 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 "media/audio/audio_output_controller.h"

#include <stdint.h>

#include <algorithm>
#include <limits>

#include "base/bind.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/task_runner_util.h"
#include "base/threading/platform_thread.h"
#include "base/trace_event/trace_event.h"
#include "media/base/audio_timestamp_helper.h"

using base::TimeDelta;

namespace media {
namespace {

// Time in seconds between two successive measurements of audio power levels.
constexpr int kPowerMonitorLogIntervalSeconds = 15;

// Used to log the result of rendering startup.
// Elements in this enum should not be deleted or rearranged; the only
// permitted operation is to add new elements before
// STREAM_CREATION_RESULT_MAX and update STREAM_CREATION_RESULT_MAX.
enum StreamCreationResult {
  STREAM_CREATION_OK = 0,
  STREAM_CREATION_CREATE_FAILED = 1,
  STREAM_CREATION_OPEN_FAILED = 2,
  STREAM_CREATION_RESULT_MAX = STREAM_CREATION_OPEN_FAILED,
};

void LogStreamCreationResult(bool for_device_change,
                             StreamCreationResult result) {
  if (for_device_change) {
    UMA_HISTOGRAM_ENUMERATION(
        "Media.AudioOutputController.ProxyStreamCreationResultForDeviceChange",
        result, STREAM_CREATION_RESULT_MAX + 1);
  } else {
    UMA_HISTOGRAM_ENUMERATION(
        "Media.AudioOutputController.ProxyStreamCreationResult", result,
        STREAM_CREATION_RESULT_MAX + 1);
  }
}

}  // namespace

AudioOutputController::ErrorStatisticsTracker::ErrorStatisticsTracker()
    : on_more_io_data_called_(0) {
  // WedgeCheck() will look to see if |on_more_io_data_called_| is true after
  // the timeout expires and log this as a UMA stat. If the stream is
  // paused/closed before the timer fires, nothing is logged.
  wedge_timer_.Start(FROM_HERE, TimeDelta::FromSeconds(5), this,
                     &ErrorStatisticsTracker::WedgeCheck);
}

AudioOutputController::ErrorStatisticsTracker::~ErrorStatisticsTracker() {
  UMA_HISTOGRAM_BOOLEAN("Media.AudioOutputController.CallbackError",
                        error_during_callback_);
}

void AudioOutputController::ErrorStatisticsTracker::RegisterError() {
  error_during_callback_ = true;
}

void AudioOutputController::ErrorStatisticsTracker::OnMoreDataCalled() {
  // Indicate that we haven't wedged (at least not indefinitely, WedgeCheck()
  // may have already fired if OnMoreData() took an abnormal amount of time).
  // Since this thread is the only writer of |on_more_io_data_called_| once the
  // thread starts, it's safe to compare and then increment.
  if (on_more_io_data_called_.IsZero())
    on_more_io_data_called_.Increment();
}

void AudioOutputController::ErrorStatisticsTracker::WedgeCheck() {
  UMA_HISTOGRAM_BOOLEAN("Media.AudioOutputControllerPlaybackStartupSuccess",
                        on_more_io_data_called_.IsOne());
}

AudioOutputController::AudioOutputController(
    AudioManager* audio_manager,
    EventHandler* handler,
    const AudioParameters& params,
    const std::string& output_device_id,
    SyncReader* sync_reader)
    : audio_manager_(audio_manager),
      params_(params),
      handler_(handler),
      output_device_id_(output_device_id),
      stream_(NULL),
      diverting_to_stream_(NULL),
      should_duplicate_(0),
      volume_(1.0),
      state_(kEmpty),
      sync_reader_(sync_reader),
      message_loop_(audio_manager->GetTaskRunner()),
      power_monitor_(
          params.sample_rate(),
          TimeDelta::FromMilliseconds(kPowerMeasurementTimeConstantMillis)),
      weak_factory_for_errors_(this) {
  DCHECK(audio_manager);
  DCHECK(handler_);
  DCHECK(sync_reader_);
  DCHECK(message_loop_.get());
  weak_this_for_errors_ = weak_factory_for_errors_.GetWeakPtr();
}

AudioOutputController::~AudioOutputController() {
  CHECK_EQ(kClosed, state_);
  CHECK_EQ(nullptr, stream_);
  CHECK(duplication_targets_.empty());
}

// static
scoped_refptr<AudioOutputController> AudioOutputController::Create(
    AudioManager* audio_manager,
    EventHandler* event_handler,
    const AudioParameters& params,
    const std::string& output_device_id,
    SyncReader* sync_reader) {
  CHECK(audio_manager);
  CHECK_EQ(AudioManager::Get(), audio_manager);
  DCHECK(sync_reader);
  DCHECK(params.IsValid());

  scoped_refptr<AudioOutputController> controller(new AudioOutputController(
      audio_manager, event_handler, params, output_device_id, sync_reader));
  controller->message_loop_->PostTask(
      FROM_HERE,
      base::BindOnce(&AudioOutputController::DoCreate, controller, false));
  return controller;
}

void AudioOutputController::Play() {
  CHECK_EQ(AudioManager::Get(), audio_manager_);
  message_loop_->PostTask(FROM_HERE,
                          base::BindOnce(&AudioOutputController::DoPlay, this));
}

void AudioOutputController::Pause() {
  CHECK_EQ(AudioManager::Get(), audio_manager_);
  message_loop_->PostTask(
      FROM_HERE, base::BindOnce(&AudioOutputController::DoPause, this));
}

void AudioOutputController::Close(base::OnceClosure closed_task) {
  CHECK_EQ(AudioManager::Get(), audio_manager_);
  DCHECK(!closed_task.is_null());
  message_loop_->PostTaskAndReply(
      FROM_HERE, base::BindOnce(&AudioOutputController::DoClose, this),
      std::move(closed_task));
}

void AudioOutputController::SetVolume(double volume) {
  CHECK_EQ(AudioManager::Get(), audio_manager_);
  message_loop_->PostTask(
      FROM_HERE,
      base::BindOnce(&AudioOutputController::DoSetVolume, this, volume));
}

void AudioOutputController::DoCreate(bool is_for_device_change) {
  DCHECK(message_loop_->BelongsToCurrentThread());
  SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.CreateTime");
  TRACE_EVENT0("audio", "AudioOutputController::DoCreate");
  handler_->OnLog(is_for_device_change ? "AOC::DoCreate (for device change)"
                                       : "AOC::DoCreate");

  // Close() can be called before DoCreate() is executed.
  if (state_ == kClosed)
    return;

  DoStopCloseAndClearStream();  // Calls RemoveOutputDeviceChangeListener().
  DCHECK_EQ(kEmpty, state_);

  stream_ = diverting_to_stream_ ?
      diverting_to_stream_ :
      audio_manager_->MakeAudioOutputStreamProxy(params_, output_device_id_);
  if (!stream_) {
    state_ = kError;
    LogStreamCreationResult(is_for_device_change,
                            STREAM_CREATION_CREATE_FAILED);
    handler_->OnControllerError();
    return;
  }

  if (!stream_->Open()) {
    DoStopCloseAndClearStream();
    LogStreamCreationResult(is_for_device_change, STREAM_CREATION_OPEN_FAILED);
    state_ = kError;
    handler_->OnControllerError();
    return;
  }

  LogStreamCreationResult(is_for_device_change, STREAM_CREATION_OK);

  // Everything started okay, so re-register for state change callbacks if
  // stream_ was created via AudioManager.
  if (stream_ != diverting_to_stream_)
    audio_manager_->AddOutputDeviceChangeListener(this);

  // We have successfully opened the stream. Set the initial volume.
  stream_->SetVolume(volume_);

  // Finally set the state to kCreated.
  state_ = kCreated;

  // And then report we have been created if we haven't done so already.
  if (!is_for_device_change)
    handler_->OnControllerCreated();
}

void AudioOutputController::DoPlay() {
  DCHECK(message_loop_->BelongsToCurrentThread());
  SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PlayTime");
  TRACE_EVENT0("audio", "AudioOutputController::DoPlay");
  handler_->OnLog("AOC::DoPlay");

  // We can start from created or paused state.
  if (state_ != kCreated && state_ != kPaused)
    return;

  // Ask for first packet.
  sync_reader_->RequestMoreData(base::TimeDelta(), base::TimeTicks(), 0);

  state_ = kPlaying;

  if (will_monitor_audio_levels()) {
    last_audio_level_log_time_ = base::TimeTicks::Now();
  }

  stats_tracker_.emplace();

  stream_->Start(this);

  handler_->OnControllerPlaying();
}

void AudioOutputController::StopStream() {
  DCHECK(message_loop_->BelongsToCurrentThread());

  if (state_ == kPlaying) {
    stream_->Stop();
    stats_tracker_.reset();

    if (will_monitor_audio_levels()) {
      LogAudioPowerLevel("StopStream");
    }

    // A stopped stream is silent, and power_montior_.Scan() is no longer being
    // called; so we must reset the power monitor.
    power_monitor_.Reset();

    state_ = kPaused;
  }
}

void AudioOutputController::DoPause() {
  DCHECK(message_loop_->BelongsToCurrentThread());
  SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PauseTime");
  TRACE_EVENT0("audio", "AudioOutputController::DoPause");
  handler_->OnLog("AOC::DoPause");

  StopStream();

  if (state_ != kPaused)
    return;

  // Let the renderer know we've stopped.  Necessary to let PPAPI clients know
  // audio has been shutdown.  TODO(dalecurtis): This stinks.  PPAPI should have
  // a better way to know when it should exit PPB_Audio_Shared::Run().
  sync_reader_->RequestMoreData(base::TimeDelta::Max(), base::TimeTicks(), 0);

  handler_->OnControllerPaused();
}

void AudioOutputController::DoClose() {
  DCHECK(message_loop_->BelongsToCurrentThread());
  SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.CloseTime");
  TRACE_EVENT0("audio", "AudioOutputController::DoClose");
  handler_->OnLog("AOC::DoClose");

  if (state_ != kClosed) {
    DoStopCloseAndClearStream();
    sync_reader_->Close();
    state_ = kClosed;
  }
}

void AudioOutputController::DoSetVolume(double volume) {
  DCHECK(message_loop_->BelongsToCurrentThread());

  // Saves the volume to a member first. We may not be able to set the volume
  // right away but when the stream is created we'll set the volume.
  volume_ = volume;

  switch (state_) {
    case kCreated:
    case kPlaying:
    case kPaused:
      stream_->SetVolume(volume_);
      break;
    default:
      return;
  }
}

void AudioOutputController::DoReportError() {
  DCHECK(message_loop_->BelongsToCurrentThread());
  TRACE_EVENT0("audio", "AudioOutputController::DoReportError");
  DLOG(ERROR) << "AudioOutputController::DoReportError";
  if (state_ != kClosed) {
    if (stats_tracker_)
      stats_tracker_->RegisterError();
    handler_->OnControllerError();
  }
}

int AudioOutputController::OnMoreData(base::TimeDelta delay,
                                      base::TimeTicks delay_timestamp,
                                      int prior_frames_skipped,
                                      AudioBus* dest) {
  TRACE_EVENT0("audio", "AudioOutputController::OnMoreData");

  stats_tracker_->OnMoreDataCalled();

  sync_reader_->Read(dest);

  const int frames =
      dest->is_bitstream_format() ? dest->GetBitstreamFrames() : dest->frames();
  delay += AudioTimestampHelper::FramesToTime(frames, params_.sample_rate());

  sync_reader_->RequestMoreData(delay, delay_timestamp, prior_frames_skipped);

  if (should_duplicate_.IsOne()) {
    const base::TimeTicks reference_time = delay_timestamp + delay;
    std::unique_ptr<AudioBus> copy(AudioBus::Create(params_));
    dest->CopyTo(copy.get());
    message_loop_->PostTask(
        FROM_HERE,
        base::BindOnce(
            &AudioOutputController::BroadcastDataToDuplicationTargets, this,
            std::move(copy), reference_time));
  }

  if (will_monitor_audio_levels()) {
    power_monitor_.Scan(*dest, frames);

    const auto now = base::TimeTicks::Now();
    if ((now - last_audio_level_log_time_).InSeconds() >
        kPowerMonitorLogIntervalSeconds) {
      LogAudioPowerLevel("OnMoreData");
      last_audio_level_log_time_ = now;
    }
  }

  return frames;
}

void AudioOutputController::BroadcastDataToDuplicationTargets(
    std::unique_ptr<AudioBus> audio_bus,
    base::TimeTicks reference_time) {
  DCHECK(message_loop_->BelongsToCurrentThread());
  if (state_ != kPlaying || duplication_targets_.empty())
    return;

  // Note: Do not need to acquire lock since this is running on the same thread
  // as where the set is modified.
  for (auto target = std::next(duplication_targets_.begin(), 1);
       target != duplication_targets_.end(); ++target) {
    std::unique_ptr<AudioBus> copy(AudioBus::Create(params_));
    audio_bus->CopyTo(copy.get());
    (*target)->OnData(std::move(copy), reference_time);
  }

  (*duplication_targets_.begin())->OnData(std::move(audio_bus), reference_time);
}

void AudioOutputController::LogAudioPowerLevel(const std::string& call_name) {
  std::pair<float, bool> power_and_clip =
      power_monitor_.ReadCurrentPowerAndClip();
  handler_->OnLog(base::StringPrintf("AOC::%s: average audio level=%.2f dBFS",
                                     call_name.c_str(), power_and_clip.first));
}

void AudioOutputController::OnError() {
  // Handle error on the audio controller thread.  We defer errors for one
  // second in case they are the result of a device change; delay chosen to
  // exceed duration of device changes which take a few hundred milliseconds.
  message_loop_->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(&AudioOutputController::DoReportError,
                     weak_this_for_errors_),
      base::TimeDelta::FromSeconds(1));
}

void AudioOutputController::DoStopCloseAndClearStream() {
  DCHECK(message_loop_->BelongsToCurrentThread());

  // Allow calling unconditionally and bail if we don't have a stream_ to close.
  if (stream_) {
    // Ensure no errors will be delivered while we cycle streams and any that
    // occurred immediately prior to the device change are dropped.
    weak_factory_for_errors_.InvalidateWeakPtrs();

    // De-register from state change callbacks if stream_ was created via
    // AudioManager.
    if (stream_ != diverting_to_stream_)
      audio_manager_->RemoveOutputDeviceChangeListener(this);

    StopStream();
    stream_->Close();
    stats_tracker_.reset();

    if (stream_ == diverting_to_stream_)
      diverting_to_stream_ = NULL;
    stream_ = NULL;

    // Since the stream is stopped, we can now update |weak_this_for_errors_|.
    weak_this_for_errors_ = weak_factory_for_errors_.GetWeakPtr();
  }

  state_ = kEmpty;
}

void AudioOutputController::OnDeviceChange() {
  DCHECK(message_loop_->BelongsToCurrentThread());
  SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.DeviceChangeTime");
  TRACE_EVENT0("audio", "AudioOutputController::OnDeviceChange");

  auto state_to_string = [](State state) {
    switch (state) {
      case AudioOutputController::kEmpty:
        return "empty";
      case AudioOutputController::kCreated:
        return "created";
      case AudioOutputController::kPlaying:
        return "playing";
      case AudioOutputController::kPaused:
        return "paused";
      case AudioOutputController::kClosed:
        return "closed";
      case AudioOutputController::kError:
        return "error";
    }
    return "unknown";
  };

  handler_->OnLog(base::StringPrintf("AOC::OnDeviceChange while in state: %s",
                                     state_to_string(state_)));

  // TODO(dalecurtis): Notify the renderer side that a device change has
  // occurred.  Currently querying the hardware information here will lead to
  // crashes on OSX.  See http://crbug.com/158170.

  // Recreate the stream (DoCreate() will first shut down an existing stream).
  // Exit if we ran into an error.
  const State original_state = state_;
  DoCreate(true);
  if (!stream_ || state_ == kError)
    return;

  // Get us back to the original state or an equivalent state.
  switch (original_state) {
    case kPlaying:
      DoPlay();
      return;
    case kCreated:
    case kPaused:
      // From the outside these two states are equivalent.
      return;
    default:
      NOTREACHED() << "Invalid original state.";
  }
}

const AudioParameters& AudioOutputController::GetAudioParameters() {
  return params_;
}

void AudioOutputController::StartDiverting(AudioOutputStream* to_stream) {
  message_loop_->PostTask(
      FROM_HERE, base::BindOnce(&AudioOutputController::DoStartDiverting, this,
                                to_stream));
}

void AudioOutputController::StopDiverting() {
  message_loop_->PostTask(
      FROM_HERE, base::BindOnce(&AudioOutputController::DoStopDiverting, this));
}

void AudioOutputController::StartDuplicating(AudioPushSink* sink) {
  message_loop_->PostTask(
      FROM_HERE,
      base::BindOnce(&AudioOutputController::DoStartDuplicating, this, sink));
}

void AudioOutputController::StopDuplicating(AudioPushSink* sink) {
  message_loop_->PostTask(
      FROM_HERE,
      base::BindOnce(&AudioOutputController::DoStopDuplicating, this, sink));
}

void AudioOutputController::DoStartDiverting(AudioOutputStream* to_stream) {
  DCHECK(message_loop_->BelongsToCurrentThread());

  if (state_ == kClosed)
    return;

  DCHECK(!diverting_to_stream_);
  diverting_to_stream_ = to_stream;
  // Note: OnDeviceChange() will engage the "re-create" process, which will
  // detect and use the alternate AudioOutputStream rather than create a new one
  // via AudioManager.
  OnDeviceChange();
}

void AudioOutputController::DoStopDiverting() {
  DCHECK(message_loop_->BelongsToCurrentThread());

  if (state_ == kClosed)
    return;

  // Note: OnDeviceChange() will cause the existing stream (the consumer of the
  // diverted audio data) to be closed, and diverting_to_stream_ will be set
  // back to NULL.
  OnDeviceChange();
  DCHECK(!diverting_to_stream_);
}

void AudioOutputController::DoStartDuplicating(AudioPushSink* to_stream) {
  DCHECK(message_loop_->BelongsToCurrentThread());
  if (state_ == kClosed)
    return;

  if (duplication_targets_.empty())
    should_duplicate_.Increment();

  duplication_targets_.insert(to_stream);
}

void AudioOutputController::DoStopDuplicating(AudioPushSink* to_stream) {
  DCHECK(message_loop_->BelongsToCurrentThread());
  to_stream->Close();

  duplication_targets_.erase(to_stream);
  if (duplication_targets_.empty()) {
    const bool is_nonzero = should_duplicate_.Decrement();
    DCHECK(!is_nonzero);
  }
}

std::pair<float, bool> AudioOutputController::ReadCurrentPowerAndClip() {
  DCHECK(will_monitor_audio_levels());
  return power_monitor_.ReadCurrentPowerAndClip();
}

}  // namespace media
