// 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/win/audio_unified_win.h"

#include <Functiondiscoverykeys_devpkey.h>

#include "base/debug/trace_event.h"
#ifndef NDEBUG
#include "base/file_util.h"
#include "base/path_service.h"
#endif
#include "base/time/time.h"
#include "base/win/scoped_com_initializer.h"
#include "media/audio/win/audio_manager_win.h"
#include "media/audio/win/avrt_wrapper_win.h"
#include "media/audio/win/core_audio_util_win.h"

using base::win::ScopedComPtr;
using base::win::ScopedCOMInitializer;
using base::win::ScopedCoMem;

// Smoothing factor in exponential smoothing filter where 0 < alpha < 1.
// Larger values of alpha reduce the level of smoothing.
// See http://en.wikipedia.org/wiki/Exponential_smoothing for details.
static const double kAlpha = 0.1;

// Compute a rate compensation which always attracts us back to a specified
// target level over a period of |kCorrectionTimeSeconds|.
static const double kCorrectionTimeSeconds = 0.1;

#ifndef NDEBUG
// Max number of columns in the output text file |kUnifiedAudioDebugFileName|.
// See LogElementNames enumerator for details on what each column represents.
static const size_t kMaxNumSampleTypes = 4;

static const size_t kMaxNumParams = 2;

// Max number of rows in the output file |kUnifiedAudioDebugFileName|.
// Each row corresponds to one set of sample values for (approximately) the
// same time instant (stored in the first column).
static const size_t kMaxFileSamples = 10000;

// Name of output debug file used for off-line analysis of measurements which
// can be utilized for performance tuning of this class.
static const char kUnifiedAudioDebugFileName[] = "unified_win_debug.txt";

// Name of output debug file used for off-line analysis of measurements.
// This file will contain a list of audio parameters.
static const char kUnifiedAudioParamsFileName[] = "unified_win_params.txt";
#endif

// Use the acquired IAudioClock interface to derive a time stamp of the audio
// sample which is currently playing through the speakers.
static double SpeakerStreamPosInMilliseconds(IAudioClock* clock) {
  UINT64 device_frequency = 0, position = 0;
  if (FAILED(clock->GetFrequency(&device_frequency)) ||
      FAILED(clock->GetPosition(&position, NULL))) {
    return 0.0;
  }
  return base::Time::kMillisecondsPerSecond *
      (static_cast<double>(position) / device_frequency);
}

// Get a time stamp in milliseconds given number of audio frames in |num_frames|
// using the current sample rate |fs| as scale factor.
// Example: |num_frames| = 960 and |fs| = 48000 => 20 [ms].
static double CurrentStreamPosInMilliseconds(UINT64 num_frames, DWORD fs) {
  return base::Time::kMillisecondsPerSecond *
      (static_cast<double>(num_frames) / fs);
}

// Convert a timestamp in milliseconds to byte units given the audio format
// in |format|.
// Example: |ts_milliseconds| equals 10, sample rate is 48000 and frame size
// is 4 bytes per audio frame => 480 * 4 = 1920 [bytes].
static int MillisecondsToBytes(double ts_milliseconds,
                               const WAVEFORMATPCMEX& format) {
  double seconds = ts_milliseconds / base::Time::kMillisecondsPerSecond;
  return static_cast<int>(seconds * format.Format.nSamplesPerSec *
      format.Format.nBlockAlign + 0.5);
}

// Convert frame count to milliseconds given the audio format in |format|.
static double FrameCountToMilliseconds(int num_frames,
                                       const WAVEFORMATPCMEX& format) {
  return (base::Time::kMillisecondsPerSecond * num_frames) /
      static_cast<double>(format.Format.nSamplesPerSec);
}

namespace media {

WASAPIUnifiedStream::WASAPIUnifiedStream(AudioManagerWin* manager,
                                         const AudioParameters& params,
                                         const std::string& input_device_id)
    : creating_thread_id_(base::PlatformThread::CurrentId()),
      manager_(manager),
      params_(params),
      input_channels_(params.input_channels()),
      output_channels_(params.channels()),
      input_device_id_(input_device_id),
      share_mode_(CoreAudioUtil::GetShareMode()),
      opened_(false),
      volume_(1.0),
      output_buffer_size_frames_(0),
      input_buffer_size_frames_(0),
      endpoint_render_buffer_size_frames_(0),
      endpoint_capture_buffer_size_frames_(0),
      num_written_frames_(0),
      total_delay_ms_(0.0),
      total_delay_bytes_(0),
      source_(NULL),
      input_callback_received_(false),
      io_sample_rate_ratio_(1),
      target_fifo_frames_(0),
      average_delta_(0),
      fifo_rate_compensation_(1),
      update_output_delay_(false),
      capture_delay_ms_(0) {
  TRACE_EVENT0("audio", "WASAPIUnifiedStream::WASAPIUnifiedStream");
  VLOG(1) << "WASAPIUnifiedStream::WASAPIUnifiedStream()";
  DCHECK(manager_);

  VLOG(1) << "Input channels : " << input_channels_;
  VLOG(1) << "Output channels: " << output_channels_;
  VLOG(1) << "Sample rate    : " << params_.sample_rate();
  VLOG(1) << "Buffer size    : " << params.frames_per_buffer();

#ifndef NDEBUG
  input_time_stamps_.reset(new int64[kMaxFileSamples]);
  num_frames_in_fifo_.reset(new int[kMaxFileSamples]);
  resampler_margin_.reset(new int[kMaxFileSamples]);
  fifo_rate_comps_.reset(new double[kMaxFileSamples]);
  num_elements_.reset(new int[kMaxNumSampleTypes]);
  std::fill(num_elements_.get(), num_elements_.get() + kMaxNumSampleTypes, 0);
  input_params_.reset(new int[kMaxNumParams]);
  output_params_.reset(new int[kMaxNumParams]);
#endif

  DVLOG_IF(1, share_mode_ == AUDCLNT_SHAREMODE_EXCLUSIVE)
      << "Core Audio (WASAPI) EXCLUSIVE MODE is enabled.";

  // Load the Avrt DLL if not already loaded. Required to support MMCSS.
  bool avrt_init = avrt::Initialize();
  DCHECK(avrt_init) << "Failed to load the avrt.dll";

  // All events are auto-reset events and non-signaled initially.

  // Create the event which the audio engine will signal each time a buffer
  // has been recorded.
  capture_event_.Set(CreateEvent(NULL, FALSE, FALSE, NULL));

  // Create the event which will be set in Stop() when straeming shall stop.
  stop_streaming_event_.Set(CreateEvent(NULL, FALSE, FALSE, NULL));
}

WASAPIUnifiedStream::~WASAPIUnifiedStream() {
  VLOG(1) << "WASAPIUnifiedStream::~WASAPIUnifiedStream()";
#ifndef NDEBUG
  base::FilePath data_file_name;
  PathService::Get(base::DIR_EXE, &data_file_name);
  data_file_name = data_file_name.AppendASCII(kUnifiedAudioDebugFileName);
  data_file_ = base::OpenFile(data_file_name, "wt");
  DVLOG(1) << ">> Output file " << data_file_name.value() << " is created.";

  size_t n = 0;
  size_t elements_to_write = *std::min_element(
      num_elements_.get(), num_elements_.get() + kMaxNumSampleTypes);
  while (n < elements_to_write) {
    fprintf(data_file_, "%I64d %d %d %10.9f\n",
        input_time_stamps_[n],
        num_frames_in_fifo_[n],
        resampler_margin_[n],
        fifo_rate_comps_[n]);
    ++n;
  }
  base::CloseFile(data_file_);

  base::FilePath param_file_name;
  PathService::Get(base::DIR_EXE, &param_file_name);
  param_file_name = param_file_name.AppendASCII(kUnifiedAudioParamsFileName);
  param_file_ = base::OpenFile(param_file_name, "wt");
  DVLOG(1) << ">> Output file " << param_file_name.value() << " is created.";
  fprintf(param_file_, "%d %d\n", input_params_[0], input_params_[1]);
  fprintf(param_file_, "%d %d\n", output_params_[0], output_params_[1]);
  base::CloseFile(param_file_);
#endif
}

bool WASAPIUnifiedStream::Open() {
  TRACE_EVENT0("audio", "WASAPIUnifiedStream::Open");
  DVLOG(1) << "WASAPIUnifiedStream::Open()";
  DCHECK_EQ(GetCurrentThreadId(), creating_thread_id_);
  if (opened_)
    return true;

  AudioParameters hw_output_params;
  HRESULT hr = CoreAudioUtil::GetPreferredAudioParameters(
      eRender, eConsole, &hw_output_params);
  if (FAILED(hr)) {
    LOG(ERROR) << "Failed to get preferred output audio parameters.";
    return false;
  }

  AudioParameters hw_input_params;
  if (input_device_id_ == AudioManagerBase::kDefaultDeviceId) {
    // Query native parameters for the default capture device.
    hr = CoreAudioUtil::GetPreferredAudioParameters(
        eCapture, eConsole, &hw_input_params);
  } else {
    // Query native parameters for the capture device given by
    // |input_device_id_|.
    hr = CoreAudioUtil::GetPreferredAudioParameters(
        input_device_id_, &hw_input_params);
  }
  if (FAILED(hr)) {
    LOG(ERROR) << "Failed to get preferred input audio parameters.";
    return false;
  }

  // It is currently only possible to open up the output audio device using
  // the native number of channels.
  if (output_channels_ != hw_output_params.channels()) {
    LOG(ERROR) << "Audio device does not support requested output channels.";
    return false;
  }

  // It is currently only possible to open up the input audio device using
  // the native number of channels. If the client asks for a higher channel
  // count, we will do channel upmixing in this class. The most typical
  // example is that the client provides stereo but the hardware can only be
  // opened in mono mode. We will do mono to stereo conversion in this case.
  if (input_channels_ < hw_input_params.channels()) {
    LOG(ERROR) << "Audio device does not support requested input channels.";
    return false;
  } else if (input_channels_ > hw_input_params.channels()) {
    ChannelLayout input_layout =
        GuessChannelLayout(hw_input_params.channels());
    ChannelLayout output_layout = GuessChannelLayout(input_channels_);
    channel_mixer_.reset(new ChannelMixer(input_layout, output_layout));
    DVLOG(1) << "Remixing input channel layout from " << input_layout
             << " to " << output_layout << "; from "
             << hw_input_params.channels() << " channels to "
             << input_channels_;
  }

  if (hw_output_params.sample_rate() != params_.sample_rate()) {
    LOG(ERROR) << "Requested sample-rate: " << params_.sample_rate()
               << " must match the hardware sample-rate: "
               << hw_output_params.sample_rate();
    return false;
  }

  if (hw_output_params.frames_per_buffer() != params_.frames_per_buffer()) {
    LOG(ERROR) << "Requested buffer size: " << params_.frames_per_buffer()
               << " must match the hardware buffer size: "
               << hw_output_params.frames_per_buffer();
    return false;
  }

  // Set up WAVEFORMATPCMEX structures for input and output given the specified
  // audio parameters.
  SetIOFormats(hw_input_params, params_);

  // Create the input and output busses.
  input_bus_ = AudioBus::Create(
      hw_input_params.channels(), input_buffer_size_frames_);
  output_bus_ = AudioBus::Create(params_);

  // One extra bus is needed for the input channel mixing case.
  if (channel_mixer_) {
    DCHECK_LT(hw_input_params.channels(), input_channels_);
    // The size of the |channel_bus_| must be the same as the size of the
    // output bus to ensure that the channel manager can deal with both
    // resampled and non-resampled data as input.
    channel_bus_ = AudioBus::Create(
        input_channels_, params_.frames_per_buffer());
  }

  // Check if FIFO and resampling is required to match the input rate to the
  // output rate. If so, a special thread loop, optimized for this case, will
  // be used. This mode is also called varispeed mode.
  // Note that we can also use this mode when input and output rates are the
  // same but native buffer sizes differ (can happen if two different audio
  // devices are used). For this case, the resampler uses a target ratio of
  // 1.0 but SetRatio is called to compensate for clock-drift. The FIFO is
  // required to compensate for the difference in buffer sizes.
  // TODO(henrika): we could perhaps improve the performance for the second
  // case here by only using the FIFO and avoid resampling. Not sure how much
  // that would give and we risk not compensation for clock drift.
  if (hw_input_params.sample_rate() != params_.sample_rate() ||
      hw_input_params.frames_per_buffer() != params_.frames_per_buffer()) {
    DoVarispeedInitialization(hw_input_params, params_);
  }

  // Render side (event driven only in varispeed mode):

  ScopedComPtr<IAudioClient> audio_output_client =
      CoreAudioUtil::CreateDefaultClient(eRender, eConsole);
  if (!audio_output_client)
    return false;

  if (!CoreAudioUtil::IsFormatSupported(audio_output_client,
                                        share_mode_,
                                        &output_format_)) {
    return false;
  }

  if (share_mode_ == AUDCLNT_SHAREMODE_SHARED) {
    // The |render_event_| will be NULL unless varispeed mode is utilized.
    hr = CoreAudioUtil::SharedModeInitialize(
        audio_output_client, &output_format_, render_event_.Get(),
        &endpoint_render_buffer_size_frames_);
  } else {
    // TODO(henrika): add support for AUDCLNT_SHAREMODE_EXCLUSIVE.
  }
  if (FAILED(hr))
    return false;

  ScopedComPtr<IAudioRenderClient> audio_render_client =
      CoreAudioUtil::CreateRenderClient(audio_output_client);
  if (!audio_render_client)
    return false;

  // Capture side (always event driven but format depends on varispeed or not):

  ScopedComPtr<IAudioClient> audio_input_client;
  if (input_device_id_ == AudioManagerBase::kDefaultDeviceId) {
    audio_input_client = CoreAudioUtil::CreateDefaultClient(eCapture, eConsole);
  } else {
    ScopedComPtr<IMMDevice> audio_input_device(
      CoreAudioUtil::CreateDevice(input_device_id_));
    audio_input_client = CoreAudioUtil::CreateClient(audio_input_device);
  }
  if (!audio_input_client)
    return false;

  if (!CoreAudioUtil::IsFormatSupported(audio_input_client,
                                        share_mode_,
                                        &input_format_)) {
    return false;
  }

  if (share_mode_ == AUDCLNT_SHAREMODE_SHARED) {
    // Include valid event handle for event-driven initialization.
    // The input side is always event driven independent of if varispeed is
    // used or not.
    hr = CoreAudioUtil::SharedModeInitialize(
        audio_input_client, &input_format_, capture_event_.Get(),
        &endpoint_capture_buffer_size_frames_);
  } else {
    // TODO(henrika): add support for AUDCLNT_SHAREMODE_EXCLUSIVE.
  }
  if (FAILED(hr))
    return false;

  ScopedComPtr<IAudioCaptureClient> audio_capture_client =
      CoreAudioUtil::CreateCaptureClient(audio_input_client);
  if (!audio_capture_client)
    return false;

  // Varispeed mode requires additional preparations.
  if (VarispeedMode())
    ResetVarispeed();

  // Store all valid COM interfaces.
  audio_output_client_ = audio_output_client;
  audio_render_client_ = audio_render_client;
  audio_input_client_ = audio_input_client;
  audio_capture_client_ = audio_capture_client;

  opened_ = true;
  return SUCCEEDED(hr);
}

void WASAPIUnifiedStream::Start(AudioSourceCallback* callback) {
  TRACE_EVENT0("audio", "WASAPIUnifiedStream::Start");
  DVLOG(1) << "WASAPIUnifiedStream::Start()";
  DCHECK_EQ(GetCurrentThreadId(), creating_thread_id_);
  CHECK(callback);
  CHECK(opened_);

  if (audio_io_thread_) {
    CHECK_EQ(callback, source_);
    return;
  }

  source_ = callback;

  if (VarispeedMode()) {
    ResetVarispeed();
    fifo_rate_compensation_ = 1.0;
    average_delta_ = 0.0;
    input_callback_received_ = false;
    update_output_delay_ = false;
  }

  // Create and start the thread that will listen for capture events.
  // We will also listen on render events on the same thread if varispeed
  // mode is utilized.
  audio_io_thread_.reset(
      new base::DelegateSimpleThread(this, "wasapi_io_thread"));
  audio_io_thread_->Start();
  if (!audio_io_thread_->HasBeenStarted()) {
    DLOG(ERROR) << "Failed to start WASAPI IO thread.";
    return;
  }

  // Start input streaming data between the endpoint buffer and the audio
  // engine.
  HRESULT hr = audio_input_client_->Start();
  if (FAILED(hr)) {
    StopAndJoinThread(hr);
    return;
  }

  // Ensure that the endpoint buffer is prepared with silence.
  if (share_mode_ == AUDCLNT_SHAREMODE_SHARED) {
    if (!CoreAudioUtil::FillRenderEndpointBufferWithSilence(
             audio_output_client_, audio_render_client_)) {
      DLOG(WARNING) << "Failed to prepare endpoint buffers with silence.";
      return;
    }
  }
  num_written_frames_ = endpoint_render_buffer_size_frames_;

  // Start output streaming data between the endpoint buffer and the audio
  // engine.
  hr = audio_output_client_->Start();
  if (FAILED(hr)) {
    StopAndJoinThread(hr);
    return;
  }
}

void WASAPIUnifiedStream::Stop() {
  TRACE_EVENT0("audio", "WASAPIUnifiedStream::Stop");
  DVLOG(1) << "WASAPIUnifiedStream::Stop()";
  DCHECK_EQ(GetCurrentThreadId(), creating_thread_id_);
  if (!audio_io_thread_)
    return;

  // Stop input audio streaming.
  HRESULT hr = audio_input_client_->Stop();
  if (FAILED(hr)) {
    DLOG_IF(ERROR, hr != AUDCLNT_E_NOT_INITIALIZED)
      << "Failed to stop input streaming: " << std::hex << hr;
  }

  // Stop output audio streaming.
  hr = audio_output_client_->Stop();
  if (FAILED(hr)) {
    DLOG_IF(ERROR, hr != AUDCLNT_E_NOT_INITIALIZED)
        << "Failed to stop output streaming: " << std::hex << hr;
  }

  // Wait until the thread completes and perform cleanup.
  SetEvent(stop_streaming_event_.Get());
  audio_io_thread_->Join();
  audio_io_thread_.reset();

  // Ensure that we don't quit the main thread loop immediately next
  // time Start() is called.
  ResetEvent(stop_streaming_event_.Get());

  // Clear source callback, it'll be set again on the next Start() call.
  source_ = NULL;

  // Flush all pending data and reset the audio clock stream position to 0.
  hr = audio_output_client_->Reset();
  if (FAILED(hr)) {
    DLOG_IF(ERROR, hr != AUDCLNT_E_NOT_INITIALIZED)
        << "Failed to reset output streaming: " << std::hex << hr;
  }

  audio_input_client_->Reset();
  if (FAILED(hr)) {
    DLOG_IF(ERROR, hr != AUDCLNT_E_NOT_INITIALIZED)
        << "Failed to reset input streaming: " << std::hex << hr;
  }

  // Extra safety check to ensure that the buffers are cleared.
  // If the buffers are not cleared correctly, the next call to Start()
  // would fail with AUDCLNT_E_BUFFER_ERROR at IAudioRenderClient::GetBuffer().
  // TODO(henrika): this check is is only needed for shared-mode streams.
  UINT32 num_queued_frames = 0;
  audio_output_client_->GetCurrentPadding(&num_queued_frames);
  DCHECK_EQ(0u, num_queued_frames);
}

void WASAPIUnifiedStream::Close() {
  TRACE_EVENT0("audio", "WASAPIUnifiedStream::Close");
  DVLOG(1) << "WASAPIUnifiedStream::Close()";
  DCHECK_EQ(GetCurrentThreadId(), creating_thread_id_);

  // It is valid to call Close() before calling open or Start().
  // It is also valid to call Close() after Start() has been called.
  Stop();

  // Inform the audio manager that we have been closed. This will cause our
  // destruction.
  manager_->ReleaseOutputStream(this);
}

void WASAPIUnifiedStream::SetVolume(double volume) {
  DVLOG(1) << "SetVolume(volume=" << volume << ")";
  if (volume < 0 || volume > 1)
    return;
  volume_ = volume;
}

void WASAPIUnifiedStream::GetVolume(double* volume) {
  DVLOG(1) << "GetVolume()";
  *volume = static_cast<double>(volume_);
}


void WASAPIUnifiedStream::ProvideInput(int frame_delay, AudioBus* audio_bus) {
  // TODO(henrika): utilize frame_delay?
  // A non-zero framed delay means multiple callbacks were necessary to
  // fulfill the requested number of frames.
  if (frame_delay > 0)
    DVLOG(3) << "frame_delay: " << frame_delay;

#ifndef NDEBUG
  resampler_margin_[num_elements_[RESAMPLER_MARGIN]] =
    fifo_->frames() - audio_bus->frames();
  num_elements_[RESAMPLER_MARGIN]++;
#endif

  if (fifo_->frames() < audio_bus->frames()) {
    DVLOG(ERROR) << "Not enough data in the FIFO ("
                 << fifo_->frames() << " < " << audio_bus->frames() << ")";
    audio_bus->Zero();
    return;
  }

  fifo_->Consume(audio_bus, 0, audio_bus->frames());
}

void WASAPIUnifiedStream::SetIOFormats(const AudioParameters& input_params,
                                       const AudioParameters& output_params) {
  for (int n = 0; n < 2; ++n) {
    const AudioParameters& params = (n == 0) ? input_params : output_params;
    WAVEFORMATPCMEX* xformat = (n == 0) ? &input_format_ : &output_format_;
    WAVEFORMATEX* format = &xformat->Format;

    // Begin with the WAVEFORMATEX structure that specifies the basic format.
    format->wFormatTag = WAVE_FORMAT_EXTENSIBLE;
    format->nChannels =  params.channels();
    format->nSamplesPerSec = params.sample_rate();
    format->wBitsPerSample = params.bits_per_sample();
    format->nBlockAlign = (format->wBitsPerSample / 8) * format->nChannels;
    format->nAvgBytesPerSec = format->nSamplesPerSec * format->nBlockAlign;
    format->cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);

    // Add the parts which are unique to WAVE_FORMAT_EXTENSIBLE.
    // Note that we always open up using the native channel layout.
    (*xformat).Samples.wValidBitsPerSample = format->wBitsPerSample;
    (*xformat).dwChannelMask =
        CoreAudioUtil::GetChannelConfig(
            std::string(), n == 0 ? eCapture : eRender);
    (*xformat).SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
  }

  input_buffer_size_frames_ = input_params.frames_per_buffer();
  output_buffer_size_frames_ = output_params.frames_per_buffer();
  VLOG(1) << "#audio frames per input buffer : " << input_buffer_size_frames_;
  VLOG(1) << "#audio frames per output buffer: " << output_buffer_size_frames_;

#ifndef NDEBUG
  input_params_[0] = input_format_.Format.nSamplesPerSec;
  input_params_[1] = input_buffer_size_frames_;
  output_params_[0] = output_format_.Format.nSamplesPerSec;
  output_params_[1] = output_buffer_size_frames_;
#endif
}

void WASAPIUnifiedStream::DoVarispeedInitialization(
    const AudioParameters& input_params, const AudioParameters& output_params) {
  DVLOG(1) << "WASAPIUnifiedStream::DoVarispeedInitialization()";

  // A FIFO is required in this mode for input to output buffering.
  // Note that it will add some latency.
  fifo_.reset(new AudioFifo(input_params.channels(), kFifoSize));
  VLOG(1) << "Using FIFO of size " << fifo_->max_frames()
          << " (#channels=" << input_params.channels() << ")";

  // Create the multi channel resampler using the initial sample rate ratio.
  // We will call MultiChannelResampler::SetRatio() during runtime to
  // allow arbitrary combinations of input and output devices running off
  // different clocks and using different drivers, with potentially
  // differing sample-rates. Note that the requested block size is given by
  // the native input buffer size |input_buffer_size_frames_|.
  io_sample_rate_ratio_ = input_params.sample_rate() /
      static_cast<double>(output_params.sample_rate());
  DVLOG(2) << "io_sample_rate_ratio: " << io_sample_rate_ratio_;
  resampler_.reset(new MultiChannelResampler(
      input_params.channels(), io_sample_rate_ratio_, input_buffer_size_frames_,
      base::Bind(&WASAPIUnifiedStream::ProvideInput, base::Unretained(this))));
  VLOG(1) << "Resampling from " << input_params.sample_rate() << " to "
          << output_params.sample_rate();

  // The optimal number of frames we'd like to keep in the FIFO at all times.
  // The actual size will vary but the goal is to ensure that the average size
  // is given by this value.
  target_fifo_frames_ = kTargetFifoSafetyFactor * input_buffer_size_frames_;
  VLOG(1) << "Target FIFO size: " <<  target_fifo_frames_;

  // Create the event which the audio engine will signal each time it
  // wants an audio buffer to render.
  render_event_.Set(CreateEvent(NULL, FALSE, FALSE, NULL));

  // Allocate memory for temporary audio bus used to store resampled input
  // audio.
  resampled_bus_ = AudioBus::Create(
      input_params.channels(), output_buffer_size_frames_);

  // Buffer initial silence corresponding to target I/O buffering.
  ResetVarispeed();
}

void WASAPIUnifiedStream::ResetVarispeed() {
  DCHECK(VarispeedMode());

  // Buffer initial silence corresponding to target I/O buffering.
  fifo_->Clear();
  scoped_ptr<AudioBus> silence =
      AudioBus::Create(input_format_.Format.nChannels,
                       target_fifo_frames_);
  silence->Zero();
  fifo_->Push(silence.get());
  resampler_->Flush();
}

void WASAPIUnifiedStream::Run() {
  ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA);

  // Increase the thread priority.
  audio_io_thread_->SetThreadPriority(base::kThreadPriority_RealtimeAudio);

  // Enable MMCSS to ensure that this thread receives prioritized access to
  // CPU resources.
  // TODO(henrika): investigate if it is possible to include these additional
  // settings in SetThreadPriority() as well.
  DWORD task_index = 0;
  HANDLE mm_task = avrt::AvSetMmThreadCharacteristics(L"Pro Audio",
                                                      &task_index);
  bool mmcss_is_ok =
      (mm_task && avrt::AvSetMmThreadPriority(mm_task, AVRT_PRIORITY_CRITICAL));
  if (!mmcss_is_ok) {
    // Failed to enable MMCSS on this thread. It is not fatal but can lead
    // to reduced QoS at high load.
    DWORD err = GetLastError();
    LOG(WARNING) << "Failed to enable MMCSS (error code=" << err << ").";
  }

  // The IAudioClock interface enables us to monitor a stream's data
  // rate and the current position in the stream. Allocate it before we
  // start spinning.
  ScopedComPtr<IAudioClock> audio_output_clock;
  HRESULT hr = audio_output_client_->GetService(
      __uuidof(IAudioClock), audio_output_clock.ReceiveVoid());
  LOG_IF(WARNING, FAILED(hr)) << "Failed to create IAudioClock: "
                              << std::hex << hr;

  bool streaming = true;
  bool error = false;

  HANDLE wait_array[3];
  size_t num_handles = 0;
  wait_array[num_handles++] = stop_streaming_event_;
  wait_array[num_handles++] = capture_event_;
  if (render_event_) {
    // One extra event handle is needed in varispeed mode.
    wait_array[num_handles++] = render_event_;
  }

  // Keep streaming audio until stop event is signaled.
  // Capture events are always used but render events are only active in
  // varispeed mode.
  while (streaming && !error) {
    // Wait for a close-down event, or a new capture event.
    DWORD wait_result = WaitForMultipleObjects(num_handles,
                                               wait_array,
                                               FALSE,
                                               INFINITE);
    switch (wait_result) {
      case WAIT_OBJECT_0 + 0:
        // |stop_streaming_event_| has been set.
        streaming = false;
        break;
      case WAIT_OBJECT_0 + 1:
        // |capture_event_| has been set
        if (VarispeedMode()) {
          ProcessInputAudio();
        } else {
          ProcessInputAudio();
          ProcessOutputAudio(audio_output_clock);
        }
        break;
      case WAIT_OBJECT_0 + 2:
        DCHECK(VarispeedMode());
        // |render_event_| has been set
        ProcessOutputAudio(audio_output_clock);
        break;
      default:
        error = true;
        break;
    }
  }

  if (streaming && error) {
    // Stop audio streaming since something has gone wrong in our main thread
    // loop. Note that, we are still in a "started" state, hence a Stop() call
    // is required to join the thread properly.
    audio_input_client_->Stop();
    audio_output_client_->Stop();
    PLOG(ERROR) << "WASAPI streaming failed.";
  }

  // Disable MMCSS.
  if (mm_task && !avrt::AvRevertMmThreadCharacteristics(mm_task)) {
    PLOG(WARNING) << "Failed to disable MMCSS";
  }
}

void WASAPIUnifiedStream::ProcessInputAudio() {
  TRACE_EVENT0("audio", "WASAPIUnifiedStream::ProcessInputAudio");

  BYTE* data_ptr = NULL;
  UINT32 num_captured_frames = 0;
  DWORD flags = 0;
  UINT64 device_position = 0;
  UINT64 capture_time_stamp = 0;

  const int bytes_per_sample = input_format_.Format.wBitsPerSample >> 3;

  base::TimeTicks now_tick = base::TimeTicks::HighResNow();

#ifndef NDEBUG
  if (VarispeedMode()) {
    input_time_stamps_[num_elements_[INPUT_TIME_STAMP]] =
        now_tick.ToInternalValue();
    num_elements_[INPUT_TIME_STAMP]++;
  }
#endif

  // Retrieve the amount of data in the capture endpoint buffer.
  // |endpoint_capture_time_stamp| is the value of the performance
  // counter at the time that the audio endpoint device recorded
  // the device position of the first audio frame in the data packet.
  HRESULT hr = audio_capture_client_->GetBuffer(&data_ptr,
                                                &num_captured_frames,
                                                &flags,
                                                &device_position,
                                                &capture_time_stamp);
  if (FAILED(hr)) {
    DLOG(ERROR) << "Failed to get data from the capture buffer";
    return;
  }

  if (hr == AUDCLNT_S_BUFFER_EMPTY) {
    // The return coded is a success code but a new packet is *not* available
    // and none of the output parameters in the GetBuffer() call contains valid
    // values. Best we can do is to deliver silence and avoid setting
    // |input_callback_received_| since this only seems to happen for the
    // initial event(s) on some devices.
    input_bus_->Zero();
  } else {
    // Valid data has been recorded and it is now OK to set the flag which
    // informs the render side that capturing has started.
    input_callback_received_ = true;
  }

  if (num_captured_frames != 0) {
    if (flags & AUDCLNT_BUFFERFLAGS_SILENT) {
      // Clear out the capture buffer since silence is reported.
      input_bus_->Zero();
    } else {
      // Store captured data in an audio bus after de-interleaving
      // the data to match the audio bus structure.
      input_bus_->FromInterleaved(
          data_ptr, num_captured_frames, bytes_per_sample);
    }
  }

  hr = audio_capture_client_->ReleaseBuffer(num_captured_frames);
  DLOG_IF(ERROR, FAILED(hr)) << "Failed to release capture buffer";

  // Buffer input into FIFO if varispeed mode is used. The render event
  // will drive resampling of this data to match the output side.
  if (VarispeedMode()) {
    int available_frames = fifo_->max_frames() - fifo_->frames();
    if (input_bus_->frames() <= available_frames) {
      fifo_->Push(input_bus_.get());
    }
#ifndef NDEBUG
    num_frames_in_fifo_[num_elements_[NUM_FRAMES_IN_FIFO]] =
        fifo_->frames();
    num_elements_[NUM_FRAMES_IN_FIFO]++;
#endif
  }

  // Save resource by not asking for new delay estimates each time.
  // These estimates are fairly stable and it is perfectly safe to only
  // sample at a rate of ~1Hz.
  // TODO(henrika): we might have to increase the update rate in varispeed
  // mode since the delay variations are higher in this mode.
  if ((now_tick - last_delay_sample_time_).InMilliseconds() >
      kTimeDiffInMillisecondsBetweenDelayMeasurements &&
      input_callback_received_) {
    // Calculate the estimated capture delay, i.e., the latency between
    // the recording time and the time we when we are notified about
    // the recorded data. Note that the capture time stamp is given in
    // 100-nanosecond (0.1 microseconds) units.
    base::TimeDelta diff =
      now_tick - base::TimeTicks::FromInternalValue(0.1 * capture_time_stamp);
    capture_delay_ms_ = diff.InMillisecondsF();

    last_delay_sample_time_ = now_tick;
    update_output_delay_ = true;
  }
}

void WASAPIUnifiedStream::ProcessOutputAudio(IAudioClock* audio_output_clock) {
  TRACE_EVENT0("audio", "WASAPIUnifiedStream::ProcessOutputAudio");

  if (!input_callback_received_) {
    if (share_mode_ == AUDCLNT_SHAREMODE_SHARED) {
      if (!CoreAudioUtil::FillRenderEndpointBufferWithSilence(
              audio_output_client_, audio_render_client_))
        DLOG(WARNING) << "Failed to prepare endpoint buffers with silence.";
    }
    return;
  }

  // Rate adjusted resampling is required in varispeed mode. It means that
  // recorded audio samples will be read from the FIFO, resampled to match the
  // output sample-rate and then stored in |resampled_bus_|.
  if (VarispeedMode()) {
    // Calculate a varispeed rate scalar factor to compensate for drift between
    // input and output.  We use the actual number of frames still in the FIFO
    // compared with the ideal value of |target_fifo_frames_|.
    int delta = fifo_->frames() - target_fifo_frames_;

    // Average |delta| because it can jitter back/forth quite frequently
    // by +/- the hardware buffer-size *if* the input and output callbacks are
    // happening at almost exactly the same time.  Also, if the input and output
    // sample-rates are different then |delta| will jitter quite a bit due to
    // the rate conversion happening in the varispeed, plus the jittering of
    // the callbacks.  The average value is what's important here.
    // We use an exponential smoothing filter to reduce the variations.
    average_delta_ += kAlpha * (delta - average_delta_);

    // Compute a rate compensation which always attracts us back to the
    // |target_fifo_frames_| over a period of kCorrectionTimeSeconds.
    double correction_time_frames =
        kCorrectionTimeSeconds * output_format_.Format.nSamplesPerSec;
    fifo_rate_compensation_ =
        (correction_time_frames + average_delta_) / correction_time_frames;

#ifndef NDEBUG
    fifo_rate_comps_[num_elements_[RATE_COMPENSATION]] =
        fifo_rate_compensation_;
    num_elements_[RATE_COMPENSATION]++;
#endif

    // Adjust for FIFO drift.
    const double new_ratio = io_sample_rate_ratio_ * fifo_rate_compensation_;
    resampler_->SetRatio(new_ratio);
    // Get resampled input audio from FIFO where the size is given by the
    // output side.
    resampler_->Resample(resampled_bus_->frames(), resampled_bus_.get());
  }

  // Derive a new total delay estimate if the capture side has set the
  // |update_output_delay_| flag.
  if (update_output_delay_) {
    // Calculate the estimated render delay, i.e., the time difference
    // between the time when data is added to the endpoint buffer and
    // when the data is played out on the actual speaker.
    const double stream_pos = CurrentStreamPosInMilliseconds(
        num_written_frames_ + output_buffer_size_frames_,
        output_format_.Format.nSamplesPerSec);
    const double speaker_pos =
        SpeakerStreamPosInMilliseconds(audio_output_clock);
    const double render_delay_ms = stream_pos - speaker_pos;
    const double fifo_delay_ms = VarispeedMode() ?
      FrameCountToMilliseconds(target_fifo_frames_, input_format_) : 0;

    // Derive the total delay, i.e., the sum of the input and output
    // delays. Also convert the value into byte units. An extra FIFO delay
    // is added for varispeed usage cases.
    total_delay_ms_ = VarispeedMode() ?
      capture_delay_ms_ + render_delay_ms + fifo_delay_ms :
      capture_delay_ms_ + render_delay_ms;
    DVLOG(2) << "total_delay_ms   : " << total_delay_ms_;
    DVLOG(3) << " capture_delay_ms: " << capture_delay_ms_;
    DVLOG(3) << " render_delay_ms : " << render_delay_ms;
    DVLOG(3) << " fifo_delay_ms   : " << fifo_delay_ms;
    total_delay_bytes_ = MillisecondsToBytes(total_delay_ms_, output_format_);

    // Wait for new signal from the capture side.
    update_output_delay_ = false;
  }

  // Select source depending on if varispeed is utilized or not.
  // Also, the source might be the output of a channel mixer if channel mixing
  // is required to match the native input channels to the number of input
  // channels used by the client (given by |input_channels_| in this case).
  AudioBus* input_bus = VarispeedMode() ?
      resampled_bus_.get() : input_bus_.get();
  if (channel_mixer_) {
    DCHECK_EQ(input_bus->frames(), channel_bus_->frames());
    // Most common case is 1->2 channel upmixing.
    channel_mixer_->Transform(input_bus, channel_bus_.get());
    // Use the output from the channel mixer as new input bus.
    input_bus = channel_bus_.get();
  }

  // Prepare for rendering by calling OnMoreIOData().
  int frames_filled = source_->OnMoreIOData(
      input_bus,
      output_bus_.get(),
      AudioBuffersState(0, total_delay_bytes_));
  DCHECK_EQ(frames_filled, output_bus_->frames());

  // Keep track of number of rendered frames since we need it for
  // our delay calculations.
  num_written_frames_ += frames_filled;

  // Derive the the amount of available space in the endpoint buffer.
  // Avoid render attempt if there is no room for a captured packet.
  UINT32 num_queued_frames = 0;
  audio_output_client_->GetCurrentPadding(&num_queued_frames);
  if (endpoint_render_buffer_size_frames_ - num_queued_frames <
      output_buffer_size_frames_)
    return;

  // Grab all available space in the rendering endpoint buffer
  // into which the client can write a data packet.
  uint8* audio_data = NULL;
  HRESULT hr = audio_render_client_->GetBuffer(output_buffer_size_frames_,
                                               &audio_data);
  if (FAILED(hr)) {
    DLOG(ERROR) << "Failed to access render buffer";
    return;
  }

  const int bytes_per_sample = output_format_.Format.wBitsPerSample >> 3;

  // Convert the audio bus content to interleaved integer data using
  // |audio_data| as destination.
  output_bus_->Scale(volume_);
  output_bus_->ToInterleaved(
      output_buffer_size_frames_, bytes_per_sample, audio_data);

  // Release the buffer space acquired in the GetBuffer() call.
  audio_render_client_->ReleaseBuffer(output_buffer_size_frames_, 0);
  DLOG_IF(ERROR, FAILED(hr)) << "Failed to release render buffer";

  return;
}

void WASAPIUnifiedStream::HandleError(HRESULT err) {
  CHECK((started() && GetCurrentThreadId() == audio_io_thread_->tid()) ||
        (!started() && GetCurrentThreadId() == creating_thread_id_));
  NOTREACHED() << "Error code: " << std::hex << err;
  if (source_)
    source_->OnError(this);
}

void WASAPIUnifiedStream::StopAndJoinThread(HRESULT err) {
  CHECK(GetCurrentThreadId() == creating_thread_id_);
  DCHECK(audio_io_thread_.get());
  SetEvent(stop_streaming_event_.Get());
  audio_io_thread_->Join();
  audio_io_thread_.reset();
  HandleError(err);
}

}  // namespace media
