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

#include "base/bind.h"
#include "base/stringprintf.h"
#include "base/sys_byteorder.h"
#include "base/threading/platform_thread.h"

namespace media {

NullAudioSink::NullAudioSink()
    : initialized_(false),
      playing_(false),
      callback_(NULL),
      thread_("NullAudioThread"),
      hash_audio_for_testing_(false) {
}

void NullAudioSink::Initialize(const AudioParameters& params,
                               RenderCallback* callback) {
  DCHECK(!initialized_);
  params_ = params;

  audio_bus_ = AudioBus::Create(params_);

  if (hash_audio_for_testing_) {
    md5_channel_contexts_.reset(new base::MD5Context[params_.channels()]);
    for (int i = 0; i < params_.channels(); i++)
      base::MD5Init(&md5_channel_contexts_[i]);
  }

  callback_ = callback;
  initialized_ = true;
}

void NullAudioSink::Start() {
  if (!thread_.Start())
    return;

  thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
      &NullAudioSink::FillBufferTask, this));
}

void NullAudioSink::Stop() {
  SetPlaying(false);
  thread_.Stop();
}

void NullAudioSink::Play() {
  SetPlaying(true);
}

void NullAudioSink::Pause(bool /* flush */) {
  SetPlaying(false);
}

bool NullAudioSink::SetVolume(double volume) {
  // Audio is always muted.
  return volume == 0.0;
}

void NullAudioSink::SetPlaying(bool is_playing) {
  base::AutoLock auto_lock(lock_);
  playing_ = is_playing;
}

NullAudioSink::~NullAudioSink() {
  DCHECK(!thread_.IsRunning());
}

void NullAudioSink::FillBufferTask() {
  base::AutoLock auto_lock(lock_);

  base::TimeDelta delay;
  // Only consume buffers when actually playing.
  if (playing_)  {
    int frames_received = callback_->Render(audio_bus_.get(), 0);
    int frames_per_millisecond =
        params_.sample_rate() / base::Time::kMillisecondsPerSecond;

    if (hash_audio_for_testing_ && frames_received > 0) {
      DCHECK_EQ(sizeof(float), sizeof(uint32));
      int channels = audio_bus_->channels();
      for (int channel_idx = 0; channel_idx < channels; ++channel_idx) {
        float* channel = audio_bus_->channel(channel_idx);
        for (int frame_idx = 0; frame_idx < frames_received; frame_idx++) {
          // Convert float to uint32 w/o conversion loss.
          uint32 frame = base::ByteSwapToLE32(
              bit_cast<uint32>(channel[frame_idx]));
          base::MD5Update(
              &md5_channel_contexts_[channel_idx], base::StringPiece(
                  reinterpret_cast<char*>(&frame), sizeof(frame)));
        }
      }
    }

    // Calculate our sleep duration.
    delay = base::TimeDelta::FromMilliseconds(
        frames_received / frames_per_millisecond);
  } else {
    // If paused, sleep for 10 milliseconds before polling again.
    delay = base::TimeDelta::FromMilliseconds(10);
  }

  // Sleep for at least one millisecond so we don't spin the CPU.
  MessageLoop::current()->PostDelayedTask(
      FROM_HERE,
      base::Bind(&NullAudioSink::FillBufferTask, this),
      std::max(delay, base::TimeDelta::FromMilliseconds(1)));
}

void NullAudioSink::StartAudioHashForTesting() {
  DCHECK(!initialized_);
  hash_audio_for_testing_ = true;
}

std::string NullAudioSink::GetAudioHashForTesting() {
  DCHECK(hash_audio_for_testing_);

  // If initialize failed or was never called, ensure we return an empty hash.
  int channels = 1;
  if (!initialized_) {
    md5_channel_contexts_.reset(new base::MD5Context[1]);
    base::MD5Init(&md5_channel_contexts_[0]);
  } else {
    channels = audio_bus_->channels();
  }

  // Hash all channels into the first channel.
  base::MD5Digest digest;
  for (int i = 1; i < channels; i++) {
    base::MD5Final(&digest, &md5_channel_contexts_[i]);
    base::MD5Update(&md5_channel_contexts_[0], base::StringPiece(
        reinterpret_cast<char*>(&digest), sizeof(base::MD5Digest)));
  }

  base::MD5Final(&digest, &md5_channel_contexts_[0]);
  return base::MD5DigestToBase16(digest);
}

}  // namespace media
