Chromium Code Reviews| Index: content/renderer/pepper_plugin_delegate_impl.cc |
| diff --git a/content/renderer/pepper_plugin_delegate_impl.cc b/content/renderer/pepper_plugin_delegate_impl.cc |
| index 94bbaf0e4cce424d697c16076a095b7b1920c4a2..0bff029fcb18f3b2fb72c84bee130c9e90f4f281 100644 |
| --- a/content/renderer/pepper_plugin_delegate_impl.cc |
| +++ b/content/renderer/pepper_plugin_delegate_impl.cc |
| @@ -35,6 +35,7 @@ |
| #include "content/renderer/gpu/gpu_channel_host.h" |
| #include "content/renderer/gpu/renderer_gl_context.h" |
| #include "content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.h" |
| +#include "content/renderer/media/audio_input_message_filter.h" |
| #include "content/renderer/media/audio_message_filter.h" |
| #include "content/renderer/media/video_capture_impl_manager.h" |
| #include "content/renderer/p2p/p2p_transport_impl.h" |
| @@ -184,7 +185,7 @@ class PlatformAudioImpl |
| // Initialize this audio context. StreamCreated() will be called when the |
| // stream is created. |
| bool Initialize(uint32_t sample_rate, uint32_t sample_count, |
| - webkit::ppapi::PluginDelegate::PlatformAudio::Client* client); |
| + webkit::ppapi::PluginDelegate::PlatformAudioCommonClient* client); |
| // PlatformAudio implementation (called on main thread). |
| virtual bool StartPlayback(); |
| @@ -216,7 +217,7 @@ class PlatformAudioImpl |
| // The client to notify when the stream is created. THIS MUST ONLY BE |
| // ACCESSED ON THE MAIN THREAD. |
| - webkit::ppapi::PluginDelegate::PlatformAudio::Client* client_; |
| + webkit::ppapi::PluginDelegate::PlatformAudioCommonClient* client_; |
| // MessageFilter used to send/receive IPC. THIS MUST ONLY BE ACCESSED ON THE |
| // I/O thread except to send messages and get the message loop. |
| @@ -233,7 +234,7 @@ class PlatformAudioImpl |
| bool PlatformAudioImpl::Initialize( |
| uint32_t sample_rate, uint32_t sample_count, |
| - webkit::ppapi::PluginDelegate::PlatformAudio::Client* client) { |
| + webkit::ppapi::PluginDelegate::PlatformAudioCommonClient* client) { |
| DCHECK(client); |
| // Make sure we don't call init more than once. |
| @@ -336,6 +337,172 @@ void PlatformAudioImpl::OnLowLatencyCreated( |
| } |
| } |
| +class PlatformAudioInputImpl |
| + : public webkit::ppapi::PluginDelegate::PlatformAudioInput, |
| + public AudioInputMessageFilter::Delegate, |
| + public base::RefCountedThreadSafe<PlatformAudioInputImpl> { |
| + public: |
| + PlatformAudioInputImpl() |
| + : client_(NULL), stream_id_(0), |
| + main_message_loop_(MessageLoop::current()) { |
| + filter_ = RenderThreadImpl::current()->audio_input_message_filter(); |
| + } |
| + |
| + virtual ~PlatformAudioInputImpl() { |
| + // Make sure we have been shut down. Warning: this will usually happen on |
| + // the I/O thread! |
| + DCHECK_EQ(0, stream_id_); |
| + DCHECK(!client_); |
| + } |
| + |
| + // Initialize this audio context. StreamCreated() will be called when the |
| + // stream is created. |
| + bool Initialize( |
| + uint32_t sample_rate, uint32_t sample_count, |
| + webkit::ppapi::PluginDelegate::PlatformAudioCommonClient* client); |
| + |
| + // PlatformAudio implementation (called on main thread). |
| + virtual bool StartCapture(); |
| + virtual bool StopCapture(); |
| + virtual void ShutDown(); |
| + |
| + private: |
| + // I/O thread backends to above functions. |
| + void InitializeOnIOThread(const AudioParameters& params); |
| + void StartCaptureOnIOThread(); |
| + void StopCaptureOnIOThread(); |
| + void ShutDownOnIOThread(); |
| + |
| + virtual void OnLowLatencyCreated(base::SharedMemoryHandle handle, |
| + base::SyncSocket::Handle socket_handle, |
| + uint32 length); |
| + |
| + virtual void OnVolume(double volume) {} |
| + |
| + virtual void OnStateChanged(AudioStreamState state) {} |
| + |
| + virtual void OnDeviceReady(int index) {} |
| + |
| + // The client to notify when the stream is created. THIS MUST ONLY BE |
| + // ACCESSED ON THE MAIN THREAD. |
| + webkit::ppapi::PluginDelegate::PlatformAudioCommonClient* client_; |
| + |
| + // MessageFilter used to send/receive IPC. THIS MUST ONLY BE ACCESSED ON THE |
| + // I/O thread except to send messages and get the message loop. |
| + scoped_refptr<AudioInputMessageFilter> filter_; |
| + |
| + // Our ID on the MessageFilter. THIS MUST ONLY BE ACCESSED ON THE I/O THREAD |
| + // or else you could race with the initialize function which sets it. |
| + int32 stream_id_; |
| + |
| + MessageLoop* main_message_loop_; |
|
jam
2011/11/16 20:49:52
nit: better to use MessageLoopProxy
viettrungluu
2011/11/16 23:51:17
Done (assuming that all I needed to do was to chan
|
| + |
| + DISALLOW_COPY_AND_ASSIGN(PlatformAudioInputImpl); |
| +}; |
| + |
| +bool PlatformAudioInputImpl::Initialize( |
| + uint32_t sample_rate, uint32_t sample_count, |
| + webkit::ppapi::PluginDelegate::PlatformAudioCommonClient* client) { |
| + DCHECK(client); |
| + // Make sure we don't call init more than once. |
| + DCHECK_EQ(0, stream_id_); |
| + |
| + client_ = client; |
| + |
| + AudioParameters params; |
| + params.format = AudioParameters::AUDIO_PCM_LINEAR; |
| + params.channels = 1; |
| + params.sample_rate = sample_rate; |
| + params.bits_per_sample = 16; |
| + params.samples_per_packet = sample_count; |
| + |
| + ChildProcess::current()->io_message_loop()->PostTask( |
| + FROM_HERE, |
| + NewRunnableMethod(this, &PlatformAudioInputImpl::InitializeOnIOThread, |
| + params)); |
| + return true; |
| +} |
| + |
| +bool PlatformAudioInputImpl::StartCapture() { |
| + ChildProcess::current()->io_message_loop()->PostTask( |
| + FROM_HERE, |
| + NewRunnableMethod(this, |
| + &PlatformAudioInputImpl::StartCaptureOnIOThread)); |
| + return true; |
| +} |
| + |
| +bool PlatformAudioInputImpl::StopCapture() { |
| + ChildProcess::current()->io_message_loop()->PostTask( |
| + FROM_HERE, |
| + NewRunnableMethod(this, |
| + &PlatformAudioInputImpl::StopCaptureOnIOThread)); |
| + return true; |
| +} |
| + |
| +void PlatformAudioInputImpl::ShutDown() { |
| + // Called on the main thread to stop all audio callbacks. We must only change |
| + // the client on the main thread, and the delegates from the I/O thread. |
| + client_ = NULL; |
| + ChildProcess::current()->io_message_loop()->PostTask( |
| + FROM_HERE, |
| + base::Bind(&PlatformAudioInputImpl::ShutDownOnIOThread, this)); |
| +} |
| + |
| +void PlatformAudioInputImpl::InitializeOnIOThread( |
| + const AudioParameters& params) { |
| + stream_id_ = filter_->AddDelegate(this); |
| + filter_->Send(new AudioInputHostMsg_CreateStream(stream_id_, params, true)); |
| +} |
| + |
| +void PlatformAudioInputImpl::StartCaptureOnIOThread() { |
| + if (stream_id_) |
| + filter_->Send(new AudioInputHostMsg_RecordStream(stream_id_)); |
| +} |
| + |
| +void PlatformAudioInputImpl::StopCaptureOnIOThread() { |
| + if (stream_id_) |
| + filter_->Send(new AudioInputHostMsg_CloseStream(stream_id_)); |
| +} |
| + |
| +void PlatformAudioInputImpl::ShutDownOnIOThread() { |
| + // Make sure we don't call shutdown more than once. |
| + if (!stream_id_) |
| + return; |
| + |
| + filter_->Send(new AudioInputHostMsg_CloseStream(stream_id_)); |
| + filter_->RemoveDelegate(stream_id_); |
| + stream_id_ = 0; |
| + |
| + Release(); // Release for the delegate, balances out the reference taken in |
| + // PepperPluginDelegateImpl::CreateAudioInput. |
| +} |
| + |
| +void PlatformAudioInputImpl::OnLowLatencyCreated( |
| + base::SharedMemoryHandle handle, |
| + base::SyncSocket::Handle socket_handle, |
| + uint32 length) { |
| + |
| +#if defined(OS_WIN) |
| + DCHECK(handle); |
| + DCHECK(socket_handle); |
| +#else |
| + DCHECK_NE(-1, handle.fd); |
| + DCHECK_NE(-1, socket_handle); |
| +#endif |
| + DCHECK(length); |
| + |
| + if (MessageLoop::current() == main_message_loop_) { |
| + // Must dereference the client only on the main thread. Shutdown may have |
| + // occurred while the request was in-flight, so we need to NULL check. |
| + if (client_) |
| + client_->StreamCreated(handle, length, socket_handle); |
| + } else { |
| + main_message_loop_->PostTask(FROM_HERE, |
| + NewRunnableMethod(this, &PlatformAudioInputImpl::OnLowLatencyCreated, |
| + handle, socket_handle, length)); |
| + } |
| +} |
| + |
| class DispatcherDelegate : public ppapi::proxy::ProxyChannel::Delegate { |
| public: |
| virtual ~DispatcherDelegate() {} |
| @@ -1087,8 +1254,9 @@ void PepperPluginDelegateImpl::SelectedFindResultChanged(int identifier, |
| webkit::ppapi::PluginDelegate::PlatformAudio* |
| PepperPluginDelegateImpl::CreateAudio( |
| - uint32_t sample_rate, uint32_t sample_count, |
| - webkit::ppapi::PluginDelegate::PlatformAudio::Client* client) { |
| + uint32_t sample_rate, |
| + uint32_t sample_count, |
| + webkit::ppapi::PluginDelegate::PlatformAudioCommonClient* client) { |
| scoped_refptr<PlatformAudioImpl> audio(new PlatformAudioImpl()); |
| if (audio->Initialize(sample_rate, sample_count, client)) { |
| // Balanced by Release invoked in PlatformAudioImpl::ShutDownOnIOThread(). |
| @@ -1098,6 +1266,21 @@ PepperPluginDelegateImpl::CreateAudio( |
| } |
| } |
| +webkit::ppapi::PluginDelegate::PlatformAudioInput* |
| +PepperPluginDelegateImpl::CreateAudioInput( |
| + uint32_t sample_rate, |
| + uint32_t sample_count, |
| + webkit::ppapi::PluginDelegate::PlatformAudioCommonClient* client) { |
| + scoped_refptr<PlatformAudioInputImpl> |
| + audio_input(new PlatformAudioInputImpl()); |
| + if (audio_input->Initialize(sample_rate, sample_count, client)) { |
| + // Balanced by Release invoked in |
| + // PlatformAudioInputImpl::ShutDownOnIOThread(). |
| + return audio_input.release(); |
| + } |
| + return NULL; |
| +} |
| + |
| // If a broker has not already been created for this plugin, creates one. |
| webkit::ppapi::PluginDelegate::PpapiBroker* |
| PepperPluginDelegateImpl::ConnectToPpapiBroker( |