12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/virtual_audio_output_stream.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/logging.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/virtual_audio_input_stream.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace media { 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)VirtualAudioOutputStream::VirtualAudioOutputStream( 13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const AudioParameters& params, VirtualAudioInputStream* target, 14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const AfterCloseCallback& after_close_cb) 15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : params_(params), target_input_stream_(target), 16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch after_close_cb_(after_close_cb), callback_(NULL), volume_(1.0f) { 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(params_.IsValid()); 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(target); 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // VAOS can be constructed on any thread, but will DCHECK that all 21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // AudioOutputStream methods are called from the same thread. 22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch thread_checker_.DetachFromThread(); 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)VirtualAudioOutputStream::~VirtualAudioOutputStream() { 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!callback_); 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool VirtualAudioOutputStream::Open() { 30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VirtualAudioOutputStream::Start(AudioSourceCallback* callback) { 35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!callback_); 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_ = callback; 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) target_input_stream_->AddOutputStream(this, params_); 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VirtualAudioOutputStream::Stop() { 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (callback_) { 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) target_input_stream_->RemoveOutputStream(this, params_); 45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch callback_ = NULL; 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VirtualAudioOutputStream::Close() { 50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Stop(); 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If a non-null AfterCloseCallback was provided to the constructor, invoke it 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // here. The callback is moved to a stack-local first since |this| could be 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // destroyed during Run(). 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!after_close_cb_.is_null()) { 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const AfterCloseCallback cb = after_close_cb_; 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) after_close_cb_.Reset(); 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cb.Run(this); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VirtualAudioOutputStream::SetVolume(double volume) { 65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) volume_ = volume; 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VirtualAudioOutputStream::GetVolume(double* volume) { 70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *volume = volume_; 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)double VirtualAudioOutputStream::ProvideInput(AudioBus* audio_bus, 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta buffer_delay) { 76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Note: This method may be invoked on any one thread, depending on the 77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // platform. 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(callback_); 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int frames = callback_->OnMoreData(audio_bus, AudioBuffersState()); 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (frames < audio_bus->frames()) 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_bus->ZeroFramesPartial(frames, audio_bus->frames() - frames); 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return frames > 0 ? volume_ : 0; 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace media 88