1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "media/base/audio_renderer_mixer_input.h" 6 7#include "base/bind.h" 8#include "base/logging.h" 9#include "media/base/audio_renderer_mixer.h" 10 11namespace media { 12 13AudioRendererMixerInput::AudioRendererMixerInput( 14 const GetMixerCB& get_mixer_cb, const RemoveMixerCB& remove_mixer_cb) 15 : playing_(false), 16 initialized_(false), 17 volume_(1.0f), 18 get_mixer_cb_(get_mixer_cb), 19 remove_mixer_cb_(remove_mixer_cb), 20 mixer_(NULL), 21 callback_(NULL), 22 error_cb_(base::Bind( 23 &AudioRendererMixerInput::OnRenderError, base::Unretained(this))) { 24} 25 26AudioRendererMixerInput::~AudioRendererMixerInput() { 27 DCHECK(!playing_); 28 DCHECK(!mixer_); 29} 30 31void AudioRendererMixerInput::Initialize( 32 const AudioParameters& params, 33 AudioRendererSink::RenderCallback* callback) { 34 DCHECK(callback); 35 DCHECK(!initialized_); 36 37 params_ = params; 38 callback_ = callback; 39 initialized_ = true; 40} 41 42void AudioRendererMixerInput::Start() { 43 DCHECK(initialized_); 44 DCHECK(!playing_); 45 DCHECK(!mixer_); 46 mixer_ = get_mixer_cb_.Run(params_); 47 48 // Note: OnRenderError() may be called immediately after this call returns. 49 mixer_->AddErrorCallback(error_cb_); 50} 51 52void AudioRendererMixerInput::Stop() { 53 // Stop() may be called at any time, if Pause() hasn't been called we need to 54 // remove our mixer input before shutdown. 55 if (playing_) { 56 mixer_->RemoveMixerInput(this); 57 playing_ = false; 58 } 59 60 if (mixer_) { 61 // TODO(dalecurtis): This is required so that |callback_| isn't called after 62 // Stop() by an error event since it may outlive this ref-counted object. We 63 // should instead have sane ownership semantics: http://crbug.com/151051 64 mixer_->RemoveErrorCallback(error_cb_); 65 remove_mixer_cb_.Run(params_); 66 mixer_ = NULL; 67 } 68} 69 70void AudioRendererMixerInput::Play() { 71 DCHECK(initialized_); 72 DCHECK(mixer_); 73 74 if (playing_) 75 return; 76 77 mixer_->AddMixerInput(this); 78 playing_ = true; 79} 80 81void AudioRendererMixerInput::Pause() { 82 DCHECK(initialized_); 83 DCHECK(mixer_); 84 85 if (!playing_) 86 return; 87 88 mixer_->RemoveMixerInput(this); 89 playing_ = false; 90} 91 92bool AudioRendererMixerInput::SetVolume(double volume) { 93 volume_ = volume; 94 return true; 95} 96 97double AudioRendererMixerInput::ProvideInput(AudioBus* audio_bus, 98 base::TimeDelta buffer_delay) { 99 int frames_filled = callback_->Render( 100 audio_bus, static_cast<int>(buffer_delay.InMillisecondsF() + 0.5)); 101 102 // AudioConverter expects unfilled frames to be zeroed. 103 if (frames_filled < audio_bus->frames()) { 104 audio_bus->ZeroFramesPartial( 105 frames_filled, audio_bus->frames() - frames_filled); 106 } 107 108 return frames_filled > 0 ? volume_ : 0; 109} 110 111void AudioRendererMixerInput::OnRenderError() { 112 callback_->OnRenderError(); 113} 114 115} // namespace media 116