diff options
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/chrome.gyp | 12 | ||||
-rw-r--r-- | chrome/renderer/audio_message_filter.cc | 109 | ||||
-rw-r--r-- | chrome/renderer/audio_message_filter.h | 84 | ||||
-rw-r--r-- | chrome/renderer/media/audio_renderer_impl.cc | 151 | ||||
-rw-r--r-- | chrome/renderer/media/audio_renderer_impl.h | 134 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 105 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 40 | ||||
-rw-r--r-- | chrome/renderer/renderer.vcproj | 8 | ||||
-rw-r--r-- | chrome/renderer/webmediaplayer_delegate_impl.cc | 16 | ||||
-rw-r--r-- | chrome/renderer/webmediaplayer_delegate_impl.h | 4 |
10 files changed, 390 insertions, 273 deletions
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 1ccb9d8..8b869f9 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -1220,6 +1220,8 @@ 'browser/views/options/content_page_view.h', 'browser/views/options/cookies_view.cc', 'browser/views/options/cookies_view.h', + 'browser/views/options/exceptions_page_view.cc', + 'browser/views/options/exceptions_page_view.h', 'browser/views/options/fonts_languages_window_view.cc', 'browser/views/options/fonts_languages_window_view.h', 'browser/views/options/fonts_page_view.cc', @@ -1235,12 +1237,12 @@ 'browser/views/options/options_page_view.cc', 'browser/views/options/options_page_view.h', 'browser/views/options/options_window_view.cc', + 'browser/views/options/passwords_exceptions_window_view.cc', + 'browser/views/options/passwords_exceptions_window_view.h', + 'browser/views/options/passwords_page_view.cc', + 'browser/views/options/passwords_page_view.h', 'browser/views/page_info_window.cc', 'browser/views/page_info_window.h', - 'browser/views/password_manager_exceptions_view.cc', - 'browser/views/password_manager_exceptions_view.h', - 'browser/views/password_manager_view.cc', - 'browser/views/password_manager_view.h', 'browser/views/repost_form_warning_view.cc', 'browser/views/repost_form_warning_view.h', 'browser/views/restart_message_box.cc', @@ -1459,6 +1461,8 @@ 'renderer/net/render_dns_queue.h', 'renderer/about_handler.cc', 'renderer/about_handler.h', + 'renderer/audio_message_filter.cc', + 'renderer/audio_message_filter.h', 'renderer/debug_message_handler.cc', 'renderer/debug_message_handler.h', 'renderer/devtools_agent.cc', diff --git a/chrome/renderer/audio_message_filter.cc b/chrome/renderer/audio_message_filter.cc new file mode 100644 index 0000000..6e22bbd --- /dev/null +++ b/chrome/renderer/audio_message_filter.cc @@ -0,0 +1,109 @@ +// Copyright (c) 2009 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 "base/message_loop.h" +#include "chrome/common/render_messages.h" +#include "chrome/renderer/audio_message_filter.h" + +AudioMessageFilter::AudioMessageFilter(int32 route_id) + : channel_(NULL), + route_id_(route_id), + message_loop_(NULL) { +} + +AudioMessageFilter::~AudioMessageFilter() { +} + +// Called on the IPC thread. +bool AudioMessageFilter::Send(IPC::Message* message) { + if (!channel_) { + delete message; + return false; + } + message->set_routing_id(route_id_); + return channel_->Send(message); +} + +bool AudioMessageFilter::OnMessageReceived(const IPC::Message& message) { + if (message.routing_id() != route_id_) + return false; + + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(AudioMessageFilter, message) + IPC_MESSAGE_HANDLER(ViewMsg_RequestAudioPacket, OnRequestPacket) + IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamCreated, OnStreamCreated) + IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamStateChanged, + OnStreamStateChanged) + IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamVolume, OnStreamVolume) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void AudioMessageFilter::OnFilterAdded(IPC::Channel* channel) { + // Captures the message loop for IPC. + message_loop_ = MessageLoop::current(); + channel_ = channel; +} + +void AudioMessageFilter::OnFilterRemoved() { + channel_ = NULL; +} + +void AudioMessageFilter::OnChannelClosing() { + channel_ = NULL; +} + +void AudioMessageFilter::OnRequestPacket(int stream_id) { + Delegate* delegate = delegates_.Lookup(stream_id); + if (!delegate) { + DLOG(WARNING) << "Got audio packet request for a non-existent or removed" + " audio renderer."; + return; + } + delegate->OnRequestPacket(); +} + +void AudioMessageFilter::OnStreamCreated(int stream_id, + base::SharedMemoryHandle handle, + int length) { + Delegate* delegate = delegates_.Lookup(stream_id); + if (!delegate) { + DLOG(WARNING) << "Got audio stream event for a non-existent or removed" + " audio renderer."; + return; + } + delegate->OnCreated(handle, length); +} + +void AudioMessageFilter::OnStreamStateChanged(int stream_id, + AudioOutputStream::State state, + int info) { + Delegate* delegate = delegates_.Lookup(stream_id); + if (!delegate) { + DLOG(WARNING) << "Got audio stream event for a non-existent or removed" + " audio renderer."; + return; + } + delegate->OnStateChanged(state, info); +} + +void AudioMessageFilter::OnStreamVolume(int stream_id, + double left, double right) { + Delegate* delegate = delegates_.Lookup(stream_id); + if (!delegate) { + DLOG(WARNING) << "Got audio stream event for a non-existent or removed" + " audio renderer."; + return; + } + delegate->OnVolume(left, right); +} + +int32 AudioMessageFilter::AddDelegate(Delegate* delegate) { + return delegates_.Add(delegate); +} + +void AudioMessageFilter::RemoveDelegate(int32 id) { + delegates_.Remove(id); +} diff --git a/chrome/renderer/audio_message_filter.h b/chrome/renderer/audio_message_filter.h new file mode 100644 index 0000000..8514c1e --- /dev/null +++ b/chrome/renderer/audio_message_filter.h @@ -0,0 +1,84 @@ +// Copyright (c) 2009 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. +// +// MessageFilter that handles audio messages and delegates them to audio +// renderers. Created on render thread, AudioMessageFilter is operated on +// IO thread (main thread of render process), it intercepts audio messages +// and process them on IO thread since these messages are time critical. + +#ifndef CHROME_RENDERER_AUDIO_MESSAGE_FILTER_H_ +#define CHROME_RENDERER_AUDIO_MESSAGE_FILTER_H_ + +#include "base/id_map.h" +#include "base/shared_memory.h" +#include "chrome/common/ipc_channel_proxy.h" +#include "media/audio/audio_output.h" + +class AudioMessageFilter : public IPC::ChannelProxy::MessageFilter { + public: + class Delegate { + public: + // Called when an audio packet is requested from the browser process. + virtual void OnRequestPacket() = 0; + + // Called when state of an audio stream has changed in the browser process. + virtual void OnStateChanged(AudioOutputStream::State state, int info) = 0; + + // Called when an audio stream has been created in the browser process. + virtual void OnCreated(base::SharedMemoryHandle handle, size_t length) = 0; + + // Called when notification of stream volume is received from the browser + // process. + virtual void OnVolume(double left, double right) = 0; + }; + + AudioMessageFilter(int32 route_id); + ~AudioMessageFilter(); + + // Add a delegate to the map and return id of the entry. + int32 AddDelegate(Delegate* delegate); + + // Remove a delegate referenced by |id| from the map. + void RemoveDelegate(int32 id); + + // Sends an IPC message using |channel_|. + bool Send(IPC::Message* message); + + MessageLoop* message_loop() { return message_loop_; } + + private: + // IPC::ChannelProxy::MessageFilter override. Called on IO thread. + virtual bool OnMessageReceived(const IPC::Message& message); + virtual void OnFilterAdded(IPC::Channel* channel); + virtual void OnFilterRemoved(); + virtual void OnChannelClosing(); + + // Received when browser process wants more audio packet. + void OnRequestPacket(int stream_id); + + // Received when browser process has created an audio output stream. + void OnStreamCreated(int stream_id, base::SharedMemoryHandle handle, + int length); + + // Received when internal state of browser process' audio output device has + // changed. + void OnStreamStateChanged(int stream_id, AudioOutputStream::State state, + int info); + + // Notification of volume property of an audio output stream. + void OnStreamVolume(int stream_id, double left, double right); + + // A map of stream ids to delegates. + IDMap<Delegate> delegates_; + + IPC::Channel* channel_; + + int32 route_id_; + + MessageLoop* message_loop_; + + DISALLOW_COPY_AND_ASSIGN(AudioMessageFilter); +}; + +#endif // CHROME_RENDERER_AUDIO_MESSAGE_FITLER_H_ diff --git a/chrome/renderer/media/audio_renderer_impl.cc b/chrome/renderer/media/audio_renderer_impl.cc index a0b6ae3..4f0627c 100644 --- a/chrome/renderer/media/audio_renderer_impl.cc +++ b/chrome/renderer/media/audio_renderer_impl.cc @@ -2,32 +2,42 @@ // source code is governed by a BSD-style license that can be found in the // LICENSE file. +#include "chrome/common/render_messages.h" +#include "chrome/renderer/audio_message_filter.h" #include "chrome/renderer/media/audio_renderer_impl.h" #include "chrome/renderer/render_view.h" #include "chrome/renderer/render_thread.h" -#include "chrome/renderer/webmediaplayer_delegate_impl.h" #include "media/base/filter_host.h" -// We'll try to fill 4096 samples per buffer, which is roughly ~92ms of audio +// We'll try to fill 8192 samples per buffer, which is roughly ~194ms of audio // data for a 44.1kHz audio source. -static const size_t kSamplesPerBuffer = 4096; +static const size_t kSamplesPerBuffer = 8192; -AudioRendererImpl::AudioRendererImpl(WebMediaPlayerDelegateImpl* delegate) +AudioRendererImpl::AudioRendererImpl(AudioMessageFilter* filter) : AudioRendererBase(kDefaultMaxQueueSize), - delegate_(delegate), + filter_(filter), stream_id_(0), shared_memory_(NULL), shared_memory_size_(0), - packet_requested_(false), - render_loop_(RenderThread::current()->message_loop()), - resource_release_event_(true, false) { - // TODO(hclam): do we need to move this method call to render thread? - delegate_->SetAudioRenderer(this); + io_loop_(filter->message_loop()), + stopped_(false), + packet_request_event_(true, false) { + DCHECK(io_loop_); } AudioRendererImpl::~AudioRendererImpl() { } +bool AudioRendererImpl::HasStopped() { + AutoLock auto_lock(lock_); + return stopped_; +} + +void AudioRendererImpl::SignalStop() { + AutoLock auto_lock(lock_); + stopped_ = true; +} + bool AudioRendererImpl::IsMediaFormatSupported( const media::MediaFormat& media_format) { int channels; @@ -47,32 +57,37 @@ bool AudioRendererImpl::OnInitialize(const media::MediaFormat& media_format) { // Create the audio output stream in browser process. size_t packet_size = kSamplesPerBuffer * channels * sample_bits / 8; - render_loop_->PostTask(FROM_HERE, - NewRunnableMethod(this, &AudioRendererImpl::OnCreateAudioStream, + io_loop_->PostTask(FROM_HERE, + NewRunnableMethod(this, &AudioRendererImpl::OnCreateStream, AudioManager::AUDIO_PCM_LINEAR, channels, sample_rate, sample_bits, packet_size)); return true; } void AudioRendererImpl::OnStop() { - delegate_->SetAudioRenderer(NULL); - if (!resource_release_event_.IsSignaled()) { - render_loop_->PostTask(FROM_HERE, - NewRunnableMethod(this, - &AudioRendererImpl::ReleaseResources, false)); - resource_release_event_.Wait(); - } + if (HasStopped()) + return; + + SignalStop(); + io_loop_->PostTask(FROM_HERE, + NewRunnableMethod(this, &AudioRendererImpl::OnDestroy)); } void AudioRendererImpl::OnReadComplete(media::Buffer* buffer_in) { + if (HasStopped()) + return; + // Use the base class to queue the buffer. AudioRendererBase::OnReadComplete(buffer_in); // Post a task to render thread to notify a packet reception. - render_loop_->PostTask(FROM_HERE, - NewRunnableMethod(this, &AudioRendererImpl::OnNotifyAudioPacketReady)); + io_loop_->PostTask(FROM_HERE, + NewRunnableMethod(this, &AudioRendererImpl::OnNotifyPacketReady)); } void AudioRendererImpl::SetPlaybackRate(float rate) { + if (HasStopped()) + return; + // TODO(hclam): handle playback rates not equal to 1.0. if (rate == 1.0f) { // TODO(hclam): what should I do here? OnCreated has fired StartAudioStream @@ -83,30 +98,45 @@ void AudioRendererImpl::SetPlaybackRate(float rate) { } void AudioRendererImpl::SetVolume(float volume) { + if (HasStopped()) + return; + // TODO(hclam): change this to multichannel if possible. - render_loop_->PostTask(FROM_HERE, + io_loop_->PostTask(FROM_HERE, NewRunnableMethod( - this, &AudioRendererImpl::OnSetAudioVolume, volume, volume)); + this, &AudioRendererImpl::OnSetVolume, volume, volume)); } void AudioRendererImpl::OnCreated(base::SharedMemoryHandle handle, size_t length) { + DCHECK(MessageLoop::current() == io_loop_); + + if (HasStopped()) + return; + shared_memory_.reset(new base::SharedMemory(handle, false)); shared_memory_->Map(length); shared_memory_size_ = length; - // TODO(hclam): is there any better place to do this? - OnStartAudioStream(); + + filter_->Send(new ViewHostMsg_StartAudioStream(0, stream_id_)); } void AudioRendererImpl::OnRequestPacket() { - packet_requested_ = true; - // Post a task to render thread and try to grab a packet for sending back. - render_loop_->PostTask(FROM_HERE, - NewRunnableMethod(this, &AudioRendererImpl::OnNotifyAudioPacketReady)); + DCHECK(MessageLoop::current() == io_loop_); + + packet_request_event_.Signal(); + + // Try to fill in the fulfil the packet request. + OnNotifyPacketReady(); } void AudioRendererImpl::OnStateChanged(AudioOutputStream::State state, int info) { + DCHECK(MessageLoop::current() == io_loop_); + + if (HasStopped()) + return; + switch (state) { case AudioOutputStream::STATE_ERROR: host_->Error(media::PIPELINE_ERROR_AUDIO_HARDWARE); @@ -122,46 +152,67 @@ void AudioRendererImpl::OnStateChanged(AudioOutputStream::State state, } void AudioRendererImpl::OnVolume(double left, double right) { + if (HasStopped()) + return; + // TODO(hclam): decide whether we need to report the current volume to // pipeline. } -void AudioRendererImpl::ReleaseResources(bool is_render_thread_dying) { - if (!is_render_thread_dying) - OnCloseAudioStream(); - resource_release_event_.Signal(); -} - -void AudioRendererImpl::OnCreateAudioStream( +void AudioRendererImpl::OnCreateStream( AudioManager::Format format, int channels, int sample_rate, int bits_per_sample, size_t packet_size) { - stream_id_ = delegate_->view()->CreateAudioStream( - this, format, channels, sample_rate, bits_per_sample, packet_size); -} + DCHECK(MessageLoop::current() == io_loop_); + + if (HasStopped()) + return; -void AudioRendererImpl::OnStartAudioStream() { - delegate_->view()->StartAudioStream(stream_id_); + // Make sure we don't call create more than once. + DCHECK_EQ(0, stream_id_); + stream_id_ = filter_->AddDelegate(this); + + ViewHostMsg_Audio_CreateStream params; + params.format = format; + params.channels = channels; + params.sample_rate = sample_rate; + params.bits_per_sample = bits_per_sample; + params.packet_size = packet_size; + + filter_->Send(new ViewHostMsg_CreateAudioStream(0, stream_id_, params)); } -void AudioRendererImpl::OnCloseAudioStream() { - // Unregister ourself from RenderView, we will not be called anymore. - delegate_->view()->CloseAudioStream(stream_id_); +void AudioRendererImpl::OnDestroy() { + DCHECK(MessageLoop::current() == io_loop_); + + filter_->RemoveDelegate(stream_id_); + filter_->Send(new ViewHostMsg_CloseAudioStream(0, stream_id_)); } -void AudioRendererImpl::OnSetAudioVolume(double left, double right) { - delegate_->view()->SetAudioVolume(stream_id_, left, right); +void AudioRendererImpl::OnSetVolume(double left, double right) { + DCHECK(MessageLoop::current() == io_loop_); + + if (HasStopped()) + return; + + filter_->Send(new ViewHostMsg_SetAudioVolume(0, stream_id_, left, right)); } -void AudioRendererImpl::OnNotifyAudioPacketReady() { - if (packet_requested_) { +void AudioRendererImpl::OnNotifyPacketReady() { + DCHECK(MessageLoop::current() == io_loop_); + + if (HasStopped()) + return; + + if (packet_request_event_.IsSignaled()) { DCHECK(shared_memory_.get()); // Fill into the shared memory. size_t filled = FillBuffer(static_cast<uint8*>(shared_memory_->memory()), shared_memory_size_); if (filled > 0) { - packet_requested_ = false; + packet_request_event_.Reset(); // Then tell browser process we are done filling into the buffer. - delegate_->view()->NotifyAudioPacketReady(stream_id_, filled); + filter_->Send( + new ViewHostMsg_NotifyAudioPacketReady(0, stream_id_, filled)); } } } diff --git a/chrome/renderer/media/audio_renderer_impl.h b/chrome/renderer/media/audio_renderer_impl.h index 6945f8a..3628e44 100644 --- a/chrome/renderer/media/audio_renderer_impl.h +++ b/chrome/renderer/media/audio_renderer_impl.h @@ -7,27 +7,27 @@ // // Relationship of classes. // -// AudioRendererHost AudioRendererImpl -// ^ ^ -// | | -// v IPC v -// ResourceMessageFilter <---------> RenderView +// AudioRendererHost AudioRendererImpl +// ^ ^ +// | | +// v IPC v +// ResourceMessageFilter <---------> AudioMessageFilter // // Implementation of interface with audio device is in AudioRendererHost and // it provides services and entry points in ResourceMessageFilter, allowing -// usage of IPC calls to interact with audio device. RenderView acts as a portal -// for IPC calls and does no more than delegation. +// usage of IPC calls to interact with audio device. AudioMessageFilter acts +// as a portal for IPC calls and does no more than delegation. // // Transportation of audio buffer is done by using shared memory, after -// OnCreateAudioStream is executed, OnCreated would be called along with a +// OnCreateStream is executed, OnCreated would be called along with a // SharedMemoryHandle upon successful creation of audio output stream in the // browser process. The same piece of shared memory would be used during the // lifetime of this unit. // // This class lives inside three threads during it's lifetime, namely: -// 1. Render thread -// The thread within which this class is constructed and destroyed, -// interfacing with RenderView should only happen here. +// 1. IO thread. +// The thread within which this class receives all the IPC messages and +// IPC communications can only happen in this thread. // 2. Pipeline thread // Initialization of filter and proper stopping of filters happens here. // Properties of this filter is also set in this thread. @@ -39,32 +39,33 @@ // Render thread // +-- CreateFactory() // | Helper method for construction this class. -// |-- IsMetidFormatSupported() -// | Helper method to identify media formats accepted by this class for -// | construction. -// |-- OnCreateAudioStream() -// | Calls RenderView::CreateAudioStream(). -// |-- OnStartAudioStream() -// | Calls RenderView::StartAudioStream(). -// |-- OnCloseAudioStream() -// | Calls RenderView::CloseAudioStream(). -// |-- OnSetAudioVolume() -// | Calls RenderView::SetAudioVolume(). -// |-- OnNotifyAudioPacketReady -// | Calls RenderView::NotifyAudioPacketReady(). +// \-- IsMediaFormatSupported() +// Helper method to identify media formats accepted by this class for +// construction. +// +// IO thread (Main thread in render process) +// +-- OnCreateStream() +// | Sends an IPC message to browser to create audio output stream and +// | register this object with AudioMessageFilter. +// |-- OnSetVolume() +// | Sends an IPC message to browser to set volume. +// |-- OnNotifyPacketReady +// | Try to fill the shared memory with decoded audio packet and sends IPC +// | messages to browser if packet is ready. // |-- OnRequestPacket() -// | Called from RenderView when an audio packet requested is received -// | from browser process. +// | Called from AudioMessageFilter when an audio packet requested is +// | received from browser process. // |-- OnStateChanged() -// | Called from RenderView upon state change of the audio output stream -// | in the browser process. Error of the output stream is reported here. +// | Called from AudioMessageFilter upon state change of the audio output +// | stream in the browser process. Error of the stream is reported here. // |-- OnCreated() -// | Called from RenderView upon successful creation of audio output stream -// | in the browser process, called along with a SharedMemoryHandle. +// | Called from AudioMessageFilter upon successful creation of audio output +// | stream in the browser process, called along with a SharedMemoryHandle. // |-- OnVolume() -// | Called from RenderView about the volume of the audio output stream. -// \-- ReleaseResource() -// Release resources that live inside render thread. +// | Called from AudioMessageFilter about the volume of the audio output +// | stream. +// \-- OnDestroy() +// Release resources that live inside io thread. // // Pipeline thread // +-- AudioRendererImpl() @@ -90,38 +91,35 @@ #ifndef CHROME_RENDERER_MEDIA_AUDIO_RENDERER_IMPL_H_ #define CHROME_RENDERER_MEDIA_AUDIO_RENDERER_IMPL_H_ +#include "base/lock.h" #include "base/shared_memory.h" #include "base/waitable_event.h" +#include "chrome/renderer/audio_message_filter.h" #include "media/audio/audio_output.h" #include "media/base/factory.h" #include "media/base/filters.h" #include "media/filters/audio_renderer_base.h" -class WebMediaPlayerDelegateImpl; +class AudioMessageFilter; -class AudioRendererImpl : public media::AudioRendererBase { +class AudioRendererImpl : public media::AudioRendererBase, + public AudioMessageFilter::Delegate { public: // Methods called on render thread ------------------------------------------ // Methods called during construction. - static media::FilterFactory* CreateFactory( - WebMediaPlayerDelegateImpl* delegate) { + static media::FilterFactory* CreateFactory(AudioMessageFilter* filter) { return new media::FilterFactoryImpl1<AudioRendererImpl, - WebMediaPlayerDelegateImpl*>(delegate); + AudioMessageFilter*>(filter); } static bool IsMediaFormatSupported(const media::MediaFormat& format); - // Methods call from RenderView when audio related IPC messages are received - // from browser process. + // Methods called on IO thread ---------------------------------------------- + // AudioMessageFilter::Delegate methods, called by AudioMessageFilter. void OnRequestPacket(); void OnStateChanged(AudioOutputStream::State state, int info); void OnCreated(base::SharedMemoryHandle handle, size_t length); void OnVolume(double left, double right); - // Release resources that lives in renderer thread, i.e. audio output streams. - // |render_thread_is_dying| tells us if render thread is being destroyed, - // if true it's not safe to access any object that lives inside render thread. - void ReleaseResources(bool render_thread_is_dying); - // Methods called on pipeline thread ---------------------------------------- // media::MediaFilter implementation. virtual void SetPlaybackRate(float rate); @@ -140,25 +138,26 @@ class AudioRendererImpl : public media::AudioRendererBase { private: friend class media::FilterFactoryImpl1<AudioRendererImpl, - WebMediaPlayerDelegateImpl*>; + AudioMessageFilter*>; - explicit AudioRendererImpl(WebMediaPlayerDelegateImpl* delegate); + explicit AudioRendererImpl(AudioMessageFilter* filter); virtual ~AudioRendererImpl(); - // Methods call on render thread -------------------------------------------- - // The following methods are tasks posted on the render thread that needs to - // be executed on that thread. They interact with WebMediaPlayerDelegateImpl - // and the containing RenderView, because method calls to RenderView must be - // executed on render thread. - void OnCreateAudioStream(AudioManager::Format format, int channels, - int sample_rate, int bits_per_sample, - size_t packet_size); - void OnStartAudioStream(); - void OnCloseAudioStream(); - void OnSetAudioVolume(double left, double right); - void OnNotifyAudioPacketReady(); - - WebMediaPlayerDelegateImpl* delegate_; + bool HasStopped(); + void SignalStop(); + + // Methods call on IO thread ------------------------------------------------ + // The following methods are tasks posted on the IO thread that needs to + // be executed on that thread. They interact with AudioMessageFilter and + // sends IPC messages on that thread. + void OnCreateStream(AudioManager::Format format, int channels, + int sample_rate, int bits_per_sample, + size_t packet_size); + void OnSetVolume(double left, double right); + void OnNotifyPacketReady(); + void OnDestroy(); + + scoped_refptr<AudioMessageFilter> filter_; // ID of the stream created in the browser process. int32 stream_id_; @@ -167,15 +166,12 @@ class AudioRendererImpl : public media::AudioRendererBase { scoped_ptr<base::SharedMemory> shared_memory_; size_t shared_memory_size_; - // Flag that tells whether we have any unfulfilled packet request. - bool packet_requested_; - - // Message loop for the render thread, it's the message loop where this class - // is constructed. - MessageLoop* render_loop_; + // Message loop for the io thread. + MessageLoop* io_loop_; - // Event for releasing resources that live in render thread. - base::WaitableEvent resource_release_event_; + Lock lock_; + bool stopped_; + base::WaitableEvent packet_request_event_; DISALLOW_COPY_AND_ASSIGN(AudioRendererImpl); }; diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 967e2a1..f5ca189 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -28,6 +28,7 @@ #include "chrome/common/thumbnail_score.h" #include "chrome/common/url_constants.h" #include "chrome/renderer/about_handler.h" +#include "chrome/renderer/audio_message_filter.h" #include "chrome/renderer/debug_message_handler.h" #include "chrome/renderer/devtools_agent.h" #include "chrome/renderer/devtools_agent_filter.h" @@ -219,6 +220,7 @@ RenderView::~RenderView() { render_thread_->RemoveFilter(debug_message_handler_); if (devtools_agent_filter_.get()) render_thread_->RemoveFilter(devtools_agent_filter_); + render_thread_->RemoveFilter(audio_message_filter_); #ifdef CHROME_PERSONALIZATION Personalization::CleanupRendererPersonalization(personalization_); @@ -355,6 +357,9 @@ void RenderView::Init(gfx::NativeViewId parent_hwnd, render_thread_->AddFilter(debug_message_handler_); if (dev_tools_enabled) render_thread_->AddFilter(devtools_agent_filter_); + + audio_message_filter_ = new AudioMessageFilter(routing_id_); + render_thread_->AddFilter(audio_message_filter_); } void RenderView::OnMessageReceived(const IPC::Message& message) { @@ -445,11 +450,6 @@ void RenderView::OnMessageReceived(const IPC::Message& message) { OnReceivedAutofillSuggestions) IPC_MESSAGE_HANDLER(ViewMsg_PopupNotificationVisiblityChanged, OnPopupNotificationVisiblityChanged) - IPC_MESSAGE_HANDLER(ViewMsg_RequestAudioPacket, OnRequestAudioPacket) - IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamCreated, OnAudioStreamCreated) - IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamStateChanged, - OnAudioStreamStateChanged) - IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamVolume, OnAudioStreamVolume) IPC_MESSAGE_HANDLER(ViewMsg_MoveOrResizeStarted, OnMoveOrResizeStarted) IPC_MESSAGE_HANDLER(ViewMsg_ExtensionResponse, OnExtensionResponse) IPC_MESSAGE_HANDLER(ViewMsg_ClearFocusedNode, OnClearFocusedNode) @@ -2937,106 +2937,11 @@ MessageLoop* RenderView::GetMessageLoopForIO() { return NULL; } -void RenderView::OnRequestAudioPacket(int stream_id) { - AudioRendererImpl* audio_renderer = audio_renderers_.Lookup(stream_id); - if (!audio_renderer) { - // It is possible that AudioRendererImpl is un-registered but we still - // receives packet requests here, because of closing a stream is not a - // synchronous operation with the browser process. - return; - } - audio_renderer->OnRequestPacket(); -} - -void RenderView::OnAudioStreamCreated( - int stream_id, base::SharedMemoryHandle handle, int length) { - AudioRendererImpl* audio_renderer = audio_renderers_.Lookup(stream_id); - if (!audio_renderer) { - return; - } - audio_renderer->OnCreated(handle, length); -} - -void RenderView::OnAudioStreamStateChanged( - int stream_id, AudioOutputStream::State state, int info) { - AudioRendererImpl* audio_renderer = audio_renderers_.Lookup(stream_id); - if (!audio_renderer) { - return; - } - audio_renderer->OnStateChanged(state, info); -} - -void RenderView::OnAudioStreamVolume(int stream_id, double left, double right) { - AudioRendererImpl* audio_renderer = audio_renderers_.Lookup(stream_id); - if (!audio_renderer) { - return; - } - audio_renderer->OnVolume(left, right); -} - void RenderView::OnMoveOrResizeStarted() { if (webview()) webview()->HideAutofillPopup(); } -int32 RenderView::CreateAudioStream(AudioRendererImpl* audio_renderer, - AudioManager::Format format, int channels, - int sample_rate, int bits_per_sample, - size_t packet_size) { - DCHECK(RenderThread::current()->message_loop() == MessageLoop::current()); - // Loop through the map and make sure there's no renderer already in the map. - for (IDMap<AudioRendererImpl>::const_iterator iter = audio_renderers_.begin(); - iter != audio_renderers_.end(); ++iter) { - DCHECK(iter->second != audio_renderer); - } - - // Add to map and send the IPC to browser process. - int32 stream_id = audio_renderers_.Add(audio_renderer); - ViewHostMsg_Audio_CreateStream params; - params.format = format; - params.channels = channels; - params.sample_rate = sample_rate; - params.bits_per_sample = bits_per_sample; - params.packet_size = packet_size; - Send(new ViewHostMsg_CreateAudioStream(routing_id_, stream_id, params)); - return stream_id; -} - -void RenderView::StartAudioStream(int stream_id) { - DCHECK(RenderThread::current()->message_loop() == MessageLoop::current()); - DCHECK(audio_renderers_.Lookup(stream_id) != NULL); - Send(new ViewHostMsg_StartAudioStream(routing_id_, stream_id)); -} - -void RenderView::CloseAudioStream(int stream_id) { - DCHECK(RenderThread::current()->message_loop() == MessageLoop::current()); - if (audio_renderers_.Lookup(stream_id) != NULL) { - // Remove the entry from the map and send a close message to browser - // process, we won't be getting anything back from browser even if there's - // an error. - audio_renderers_.Remove(stream_id); - Send(new ViewHostMsg_CloseAudioStream(routing_id_, stream_id)); - } -} - -void RenderView::NotifyAudioPacketReady(int stream_id, size_t size) { - DCHECK(RenderThread::current()->message_loop() == MessageLoop::current()); - DCHECK(audio_renderers_.Lookup(stream_id) != NULL); - Send(new ViewHostMsg_NotifyAudioPacketReady(routing_id_, stream_id, size)); -} - -void RenderView::GetAudioVolume(int stream_id) { - DCHECK(RenderThread::current()->message_loop() == MessageLoop::current()); - DCHECK(audio_renderers_.Lookup(stream_id) != NULL); - Send(new ViewHostMsg_GetAudioVolume(routing_id_, stream_id)); -} - -void RenderView::SetAudioVolume(int stream_id, double left, double right) { - DCHECK(RenderThread::current()->message_loop() == MessageLoop::current()); - DCHECK(audio_renderers_.Lookup(stream_id) != NULL); - Send(new ViewHostMsg_SetAudioVolume(routing_id_, stream_id, left, right)); -} - void RenderView::OnResize(const gfx::Size& new_size, const gfx::Rect& resizer_rect) { if (webview()) diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index d0264f3..f6bd01b 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -26,7 +26,6 @@ #include "chrome/renderer/external_host_bindings.h" #include "chrome/renderer/external_js_object.h" #include "chrome/renderer/render_widget.h" -#include "media/audio/audio_output.h" #include "testing/gtest/include/gtest/gtest_prod.h" #include "third_party/WebKit/WebKit/chromium/public/WebConsoleMessage.h" #include "webkit/glue/dom_serializer_delegate.h" @@ -44,7 +43,7 @@ #pragma warning(disable: 4250) #endif -class AudioRendererImpl; +class AudioMessageFilter; class DictionaryValue; class DebugMessageHandler; class DevToolsAgent; @@ -372,18 +371,7 @@ class RenderView : public RenderWidget, // the renderer, which processes all IPC, to any I/O should be non-blocking. MessageLoop* GetMessageLoopForIO(); - // Register the audio renderer and try to create an audio output stream in the - // browser process. Always return a stream id. Audio renderer will then - // receive state change notification messages. - int32 CreateAudioStream(AudioRendererImpl* renderer, - AudioManager::Format format, int channels, - int sample_rate, int bits_per_sample, - size_t packet_size); - void StartAudioStream(int stream_id); - void CloseAudioStream(int stream_id); - void NotifyAudioPacketReady(int stream_id, size_t size); - void GetAudioVolume(int stream_id); - void SetAudioVolume(int stream_id, double left, double right); + AudioMessageFilter* audio_message_filter() { return audio_message_filter_; } void OnClearFocusedNode(); @@ -591,21 +579,6 @@ class RenderView : public RenderWidget, // grouping, and should form our own grouping. void OnDisassociateFromPopupCount(); - // Received when browser process wants more audio packet. - void OnRequestAudioPacket(int stream_id); - - // Received when browser process has created an audio output stream for us. - void OnAudioStreamCreated(int stream_id, base::SharedMemoryHandle handle, - int length); - - // Received when internal state of browser process' audio output device has - // changed. - void OnAudioStreamStateChanged(int stream_id, AudioOutputStream::State state, - int info); - - // Notification of volume property of an audio output stream. - void OnAudioStreamVolume(int stream_id, double left, double right); - // Sends the selection text to the browser. void OnRequestSelectionText(); @@ -833,12 +806,15 @@ class RenderView : public RenderWidget, // change but is overridden by tests. int delay_seconds_for_form_state_sync_; - // A set of audio renderers registered to use IPC for audio output. - IDMap<AudioRendererImpl> audio_renderers_; - // Maps pending callback IDs to their frames. IDMap<WebFrame> pending_extension_callbacks_; + scoped_refptr<AudioMessageFilter> audio_message_filter_; + + // The currently selected text. This is currently only updated on Linux, where + // it's for the selection clipboard. + std::string selection_text_; + DISALLOW_COPY_AND_ASSIGN(RenderView); }; diff --git a/chrome/renderer/renderer.vcproj b/chrome/renderer/renderer.vcproj index 56f9e82..5a388fd 100644 --- a/chrome/renderer/renderer.vcproj +++ b/chrome/renderer/renderer.vcproj @@ -222,6 +222,14 @@ > </File> <File + RelativePath=".\audio_message_filter.cc" + > + </File> + <File + RelativePath=".\audio_message_filter.h" + > + </File> + <File RelativePath=".\debug_message_handler.cc" > </File> diff --git a/chrome/renderer/webmediaplayer_delegate_impl.cc b/chrome/renderer/webmediaplayer_delegate_impl.cc index 5a0f1c2..d605a99 100644 --- a/chrome/renderer/webmediaplayer_delegate_impl.cc +++ b/chrome/renderer/webmediaplayer_delegate_impl.cc @@ -57,7 +57,6 @@ WebMediaPlayerDelegateImpl::WebMediaPlayerDelegateImpl(RenderView* view) ready_state_(webkit_glue::WebMediaPlayer::HAVE_NOTHING), main_loop_(NULL), filter_factory_(new media::FilterFactoryCollection()), - audio_renderer_(NULL), video_renderer_(NULL), data_source_(NULL), web_media_player_(NULL), @@ -70,7 +69,8 @@ WebMediaPlayerDelegateImpl::WebMediaPlayerDelegateImpl(RenderView* view) filter_factory_->AddFactory(media::FFmpegAudioDecoder::CreateFactory()); filter_factory_->AddFactory(media::FFmpegVideoDecoder::CreateFactory()); #endif - filter_factory_->AddFactory(AudioRendererImpl::CreateFactory(this)); + filter_factory_->AddFactory(AudioRendererImpl::CreateFactory( + view_->audio_message_filter())); filter_factory_->AddFactory(VideoRendererImpl::CreateFactory(this)); filter_factory_->AddFactory(DataSourceImpl::CreateFactory(this)); } @@ -315,15 +315,8 @@ void WebMediaPlayerDelegateImpl::DidInitializePipeline(bool successful) { &webkit_glue::WebMediaPlayer::NotifyReadyStateChange); } -void WebMediaPlayerDelegateImpl::SetAudioRenderer( - AudioRendererImpl* audio_renderer) { - DCHECK(!audio_renderer_); - audio_renderer_ = audio_renderer; -} - void WebMediaPlayerDelegateImpl::SetVideoRenderer( VideoRendererImpl* video_renderer) { - DCHECK(!video_renderer_); video_renderer_ = video_renderer; } @@ -373,11 +366,6 @@ void WebMediaPlayerDelegateImpl::StopPipeline(bool render_thread_is_dying) { // Instruct the renderers and data source to release all Renderer related // resources during destruction of render thread, because they won't have any // chance to release these resources on render thread by posting tasks on it. - if (audio_renderer_) { - audio_renderer_->ReleaseResources(render_thread_is_dying); - audio_renderer_ = NULL; - } - if (data_source_) { data_source_->ReleaseResources(render_thread_is_dying); data_source_ = NULL; diff --git a/chrome/renderer/webmediaplayer_delegate_impl.h b/chrome/renderer/webmediaplayer_delegate_impl.h index fc976bf..b104ee6 100644 --- a/chrome/renderer/webmediaplayer_delegate_impl.h +++ b/chrome/renderer/webmediaplayer_delegate_impl.h @@ -188,10 +188,6 @@ class WebMediaPlayerDelegateImpl : public webkit_glue::WebMediaPlayerDelegate, // the same lifetime as the pipeline. media::PipelineImpl pipeline_; - // Holds a pointer to the audio renderer so we can tell it to stop during - // render thread destruction. - scoped_refptr<AudioRendererImpl> audio_renderer_; - // We have the interface to VideoRenderer to delegate paint messages to it // from WebKit. scoped_refptr<VideoRendererImpl> video_renderer_; |