| Index: media/audio/audio_output_stream_sink.cc | 
| diff --git a/media/audio/audio_output_stream_sink.cc b/media/audio/audio_output_stream_sink.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..e233e994a1503ffd02aaba539c5c50bad113bcac | 
| --- /dev/null | 
| +++ b/media/audio/audio_output_stream_sink.cc | 
| @@ -0,0 +1,126 @@ | 
| +// Copyright 2014 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_stream_sink.h" | 
| + | 
| +#include "base/bind.h" | 
| +#include "base/bind_helpers.h" | 
| +#include "base/location.h" | 
| +#include "media/audio/audio_manager.h" | 
| + | 
| +namespace media { | 
| + | 
| +AudioOutputStreamSink::AudioOutputStreamSink() | 
| +    : render_callback_(NULL), | 
| +      audio_task_runner_(AudioManager::Get()->GetTaskRunner()), | 
| +      stream_(NULL), | 
| +      active_render_callback_(NULL) { | 
| +} | 
| + | 
| +AudioOutputStreamSink::~AudioOutputStreamSink() { | 
| +} | 
| + | 
| +void AudioOutputStreamSink::Initialize(const AudioParameters& params, | 
| +                                       RenderCallback* callback) { | 
| +  DCHECK(callback); | 
| +  DCHECK(!render_callback_); | 
| +  params_ = params; | 
| +  render_callback_ = callback; | 
| +} | 
| + | 
| +void AudioOutputStreamSink::Start() { | 
| +  audio_task_runner_->PostTask( | 
| +      FROM_HERE, base::Bind(&AudioOutputStreamSink::DoStart, this)); | 
| +} | 
| + | 
| +void AudioOutputStreamSink::Stop() { | 
| +  ClearCallback(); | 
| +  audio_task_runner_->PostTask( | 
| +      FROM_HERE, base::Bind(&AudioOutputStreamSink::DoStop, this)); | 
| +} | 
| + | 
| +void AudioOutputStreamSink::Pause() { | 
| +  ClearCallback(); | 
| +  audio_task_runner_->PostTask( | 
| +      FROM_HERE, base::Bind(&AudioOutputStreamSink::DoPause, this)); | 
| +} | 
| + | 
| +void AudioOutputStreamSink::Play() { | 
| +  base::AutoLock al(callback_lock_); | 
| +  active_render_callback_ = render_callback_; | 
| +  audio_task_runner_->PostTask( | 
| +      FROM_HERE, base::Bind(&AudioOutputStreamSink::DoPlay, this)); | 
| +} | 
| + | 
| +bool AudioOutputStreamSink::SetVolume(double volume) { | 
| +  audio_task_runner_->PostTask( | 
| +      FROM_HERE, base::Bind(&AudioOutputStreamSink::DoSetVolume, this, volume)); | 
| +  return true; | 
| +}; | 
| + | 
| +int AudioOutputStreamSink::OnMoreData(AudioBus* dest, | 
| +                                      uint32 total_bytes_delay) { | 
| +  // Note: Runs on the audio thread created by the OS. | 
| +  base::AutoLock al(callback_lock_); | 
| +  if (!active_render_callback_) | 
| +    return 0; | 
| + | 
| +  return active_render_callback_->Render( | 
| +      dest, total_bytes_delay * 1000.0 / params_.GetBytesPerSecond()); | 
| +} | 
| + | 
| +void AudioOutputStreamSink::OnError(AudioOutputStream* stream) { | 
| +  // Note: Runs on the audio thread created by the OS. | 
| +  base::AutoLock al(callback_lock_); | 
| +  if (active_render_callback_) | 
| +    active_render_callback_->OnRenderError(); | 
| +} | 
| + | 
| +void AudioOutputStreamSink::DoStart() { | 
| +  DCHECK(audio_task_runner_->BelongsToCurrentThread()); | 
| + | 
| +  // Create an AudioOutputStreamProxy which will handle any and all resampling | 
| +  // necessary to generate a low latency output stream. | 
| +  stream_ = | 
| +      AudioManager::Get()->MakeAudioOutputStreamProxy(params_, std::string()); | 
| +  if (!stream_ || !stream_->Open()) { | 
| +    render_callback_->OnRenderError(); | 
| +    if (stream_) | 
| +      stream_->Close(); | 
| +    stream_ = NULL; | 
| +  } | 
| +} | 
| + | 
| +void AudioOutputStreamSink::DoStop() { | 
| +  DCHECK(audio_task_runner_->BelongsToCurrentThread()); | 
| + | 
| +  if (!stream_) | 
| +    return; | 
| + | 
| +  DoPause(); | 
| +  stream_->Close(); | 
| +  stream_ = NULL; | 
| +} | 
| + | 
| +void AudioOutputStreamSink::DoPause() { | 
| +  DCHECK(audio_task_runner_->BelongsToCurrentThread()); | 
| +  stream_->Stop(); | 
| +} | 
| + | 
| +void AudioOutputStreamSink::DoPlay() { | 
| +  DCHECK(audio_task_runner_->BelongsToCurrentThread()); | 
| +  stream_->Start(this); | 
| +} | 
| + | 
| +void AudioOutputStreamSink::DoSetVolume(double volume) { | 
| +  DCHECK(audio_task_runner_->BelongsToCurrentThread()); | 
| +  stream_->SetVolume(volume); | 
| +} | 
| + | 
| +void AudioOutputStreamSink::ClearCallback() { | 
| +  base::AutoLock al(callback_lock_); | 
| +  active_render_callback_ = NULL; | 
| +} | 
| + | 
| +}  // namepace media | 
|  |