15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/renderer/media/renderer_webaudiodevice_impl.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/renderer/media/audio_device_factory.h" 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/renderer/render_frame_impl.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/renderer/render_view_impl.h" 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/audio/audio_output_device.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/media_switches.h" 14a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "third_party/WebKit/public/web/WebLocalFrame.h" 157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebView.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebAudioDevice; 18a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochusing blink::WebLocalFrame; 19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebVector; 20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebView; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RendererWebAudioDeviceImpl::RendererWebAudioDeviceImpl( 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const media::AudioParameters& params, 26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) WebAudioDevice::RenderCallback* callback, 27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int session_id) 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : params_(params), 29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) client_callback_(callback), 30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) session_id_(session_id) { 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(client_callback_); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RendererWebAudioDeviceImpl::~RendererWebAudioDeviceImpl() { 35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!output_device_.get()); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RendererWebAudioDeviceImpl::start() { 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (output_device_.get()) 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; // Already started. 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Assumption: This method is being invoked within a V8 call stack. CHECKs 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // will fail in the call to frameForCurrentContext() otherwise. 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Therefore, we can perform look-ups to determine which RenderView is 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // starting the audio device. The reason for all this is because the creator 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // of the WebAudio objects might not be the actual source of the audio (e.g., 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // an extension creates a object that is passed and used within a page). 51a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch WebLocalFrame* const web_frame = WebLocalFrame::frameForCurrentContext(); 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebView* const web_view = web_frame ? web_frame->view() : NULL; 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RenderFrame* const render_frame = 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) web_frame ? RenderFrame::FromWebFrame(web_frame) : NULL; 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RenderViewImpl* const render_view = 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) web_view ? RenderViewImpl::FromWebView(web_view) : NULL; 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) output_device_ = AudioDeviceFactory::NewOutputDevice( 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) render_view ? render_view->routing_id() : MSG_ROUTING_NONE, 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) render_frame ? render_frame->GetRoutingID(): MSG_ROUTING_NONE); 60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) output_device_->InitializeWithSessionId(params_, this, session_id_); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_device_->Start(); 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Note: Default behavior is to auto-play on start. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RendererWebAudioDeviceImpl::stop() { 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (output_device_.get()) { 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_device_->Stop(); 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_device_ = NULL; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double RendererWebAudioDeviceImpl::sampleRate() { 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return params_.sample_rate(); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int RendererWebAudioDeviceImpl::Render(media::AudioBus* dest, 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int audio_delay_milliseconds) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (client_callback_) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wrap the output pointers using WebVector. 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebVector<float*> web_audio_dest_data( 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<size_t>(dest->channels())); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < dest->channels(); ++i) 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) web_audio_dest_data[i] = dest->channel(i); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO(xians): Remove the following |web_audio_source_data| after 88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // changing the blink interface. 89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) WebVector<float*> web_audio_source_data(static_cast<size_t>(0)); 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client_callback_->render(web_audio_source_data, 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) web_audio_dest_data, 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest->frames()); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return dest->frames(); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RendererWebAudioDeviceImpl::OnRenderError() { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(crogers): implement error handling. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 103