| Index: media/audio/null_audio_sink.cc
|
| diff --git a/media/audio/null_audio_sink.cc b/media/audio/null_audio_sink.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..e8cd4eb4fe58a7502d36d4729cdff33da54cd688
|
| --- /dev/null
|
| +++ b/media/audio/null_audio_sink.cc
|
| @@ -0,0 +1,110 @@
|
| +// 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/threading/platform_thread.h"
|
| +
|
| +namespace media {
|
| +
|
| +NullAudioSink::NullAudioSink()
|
| + : initialized_(false),
|
| + playback_rate_(0.0),
|
| + playing_(false),
|
| + callback_(NULL),
|
| + thread_("NullAudioThread") {
|
| +}
|
| +
|
| +NullAudioSink::~NullAudioSink() {
|
| + DCHECK(!thread_.IsRunning());
|
| + for (size_t i = 0; i < audio_data_.size(); ++i)
|
| + delete [] audio_data_[i];
|
| +}
|
| +
|
| +
|
| +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);
|
| +}
|
| +
|
| +void NullAudioSink::SetPlaybackRate(float rate) {
|
| + base::AutoLock auto_lock(lock_);
|
| + playback_rate_ = rate;
|
| +}
|
| +
|
| +bool NullAudioSink::SetVolume(double volume) {
|
| + // Audio is always muted.
|
| + return volume == 0.0;
|
| +}
|
| +
|
| +void NullAudioSink::GetVolume(double* volume) {
|
| + // Audio is always muted.
|
| + *volume = 0.0;
|
| +}
|
| +
|
| +void NullAudioSink::SetPlaying(bool is_playing) {
|
| + base::AutoLock auto_lock(lock_);
|
| + playing_ = is_playing;
|
| +}
|
| +
|
| +void NullAudioSink::Initialize(const AudioParameters& params,
|
| + RenderCallback* callback) {
|
| + DCHECK(!initialized_);
|
| + params_ = params;
|
| +
|
| + audio_data_.reserve(params.channels());
|
| + for (int i = 0; i < params.channels(); ++i) {
|
| + float* channel_data = new float[params.frames_per_buffer()];
|
| + audio_data_.push_back(channel_data);
|
| + }
|
| +
|
| + callback_ = callback;
|
| + initialized_ = true;
|
| +}
|
| +
|
| +void NullAudioSink::FillBufferTask() {
|
| + base::AutoLock auto_lock(lock_);
|
| +
|
| + base::TimeDelta delay;
|
| + // Only consume buffers when actually playing.
|
| + if (playing_) {
|
| + DCHECK_GT(playback_rate_, 0.0f);
|
| + int requested_frames = params_.frames_per_buffer();
|
| + int frames_received = callback_->Render(audio_data_, requested_frames, 0);
|
| + int frames_per_millisecond =
|
| + params_.sample_rate() / base::Time::kMillisecondsPerSecond;
|
| +
|
| + // Calculate our sleep duration, taking playback rate into consideration.
|
| + delay = base::TimeDelta::FromMilliseconds(
|
| + frames_received / (frames_per_millisecond * playback_rate_));
|
| + } 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)));
|
| +}
|
| +
|
| +} // namespace media
|
|
|