diff options
40 files changed, 1966 insertions, 107 deletions
diff --git a/content/renderer/pepper_plugin_delegate_impl.cc b/content/renderer/pepper_plugin_delegate_impl.cc index 94bbaf0..e1453e5 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" @@ -170,7 +171,7 @@ class PlatformAudioImpl public: PlatformAudioImpl() : client_(NULL), stream_id_(0), - main_message_loop_(MessageLoop::current()) { + main_message_loop_proxy_(base::MessageLoopProxy::current()) { filter_ = RenderThreadImpl::current()->audio_message_filter(); } @@ -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. @@ -226,14 +227,14 @@ class PlatformAudioImpl // or else you could race with the initialize function which sets it. int32 stream_id_; - MessageLoop* main_message_loop_; + base::MessageLoopProxy* main_message_loop_proxy_; DISALLOW_COPY_AND_ASSIGN(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. @@ -324,18 +325,184 @@ void PlatformAudioImpl::OnLowLatencyCreated( #endif DCHECK(length); - if (MessageLoop::current() == main_message_loop_) { + if (base::MessageLoopProxy::current() == main_message_loop_proxy_) { // 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, + main_message_loop_proxy_->PostTask(FROM_HERE, NewRunnableMethod(this, &PlatformAudioImpl::OnLowLatencyCreated, handle, socket_handle, length)); } } +class PlatformAudioInputImpl + : public webkit::ppapi::PluginDelegate::PlatformAudioInput, + public AudioInputMessageFilter::Delegate, + public base::RefCountedThreadSafe<PlatformAudioInputImpl> { + public: + PlatformAudioInputImpl() + : client_(NULL), stream_id_(0), + main_message_loop_proxy_(base::MessageLoopProxy::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_; + + base::MessageLoopProxy* main_message_loop_proxy_; + + 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 (base::MessageLoopProxy::current() == main_message_loop_proxy_) { + // 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_proxy_->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( diff --git a/content/renderer/pepper_plugin_delegate_impl.h b/content/renderer/pepper_plugin_delegate_impl.h index d1e830d..d2b1bf1 100644 --- a/content/renderer/pepper_plugin_delegate_impl.h +++ b/content/renderer/pepper_plugin_delegate_impl.h @@ -213,7 +213,11 @@ class PepperPluginDelegateImpl virtual PlatformAudio* CreateAudio( uint32_t sample_rate, uint32_t sample_count, - PlatformAudio::Client* client) OVERRIDE; + PlatformAudioCommonClient* client) OVERRIDE; + virtual PlatformAudioInput* CreateAudioInput( + uint32_t sample_rate, + uint32_t sample_count, + PlatformAudioCommonClient* client) OVERRIDE; virtual PlatformImage2D* CreateImage2D(int width, int height) OVERRIDE; virtual PlatformContext3D* CreateContext3D() OVERRIDE; virtual PlatformVideoCapture* CreateVideoCapture( diff --git a/ppapi/api/dev/ppb_audio_input_dev.idl b/ppapi/api/dev/ppb_audio_input_dev.idl new file mode 100644 index 0000000..ba6b578 --- /dev/null +++ b/ppapi/api/dev/ppb_audio_input_dev.idl @@ -0,0 +1,94 @@ +/* Copyright (c) 2011 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. + */ + +/** + * This file defines the <code>PPB_AudioInput_Dev</code> interface, which + * provides realtime audio input capture. + */ + +label Chrome { + M17 = 0.1 +}; + +/** + * <code>PPB_AudioInput_Callback</code> defines the type of an audio callback + * function used to provide the audio buffer with data. This callback will be + * called on a separate thread to the creation thread. + */ +typedef void PPB_AudioInput_Callback([out] mem_t sample_buffer, + [in] uint32_t buffer_size_in_bytes, + [inout] mem_t user_data); + +/** + * The <code>PPB_AudioInput_Dev</code> interface contains pointers to several + * functions for handling audio input resources. + */ +[version=0.1, macro="PPB_AUDIO_INPUT_DEV_INTERFACE"] +interface PPB_AudioInput_Dev { + /** + * Create is a pointer to a function that creates an audio input resource. + * No sound will be captured until StartCapture() is called. + */ + PP_Resource Create( + [in] PP_Instance instance, + [in] PP_Resource config, + [in] PPB_AudioInput_Callback audio_input_callback, + [inout] mem_t user_data); + + /** + * IsAudioInput is a pointer to a function that determines if the given + * resource is an audio input resource. + * + * @param[in] resource A PP_Resource containing a resource. + * + * @return A PP_BOOL containing containing PP_TRUE if the given resource is + * an audio input resource, otherwise PP_FALSE. + */ + PP_Bool IsAudioInput( + [in] PP_Resource audio_input); + + /** + * GetCurrrentConfig() returns an audio config resource for the given audio + * resource. + * + * @param[in] config A <code>PP_Resource</code> corresponding to an audio + * resource. + * + * @return A <code>PP_Resource</code> containing the audio config resource if + * successful. + */ + PP_Resource GetCurrentConfig( + [in] PP_Resource audio_input); + + /** + * StartCapture() starts the capture of the audio input resource and begins + * periodically calling the callback. + * + * @param[in] config A <code>PP_Resource</code> corresponding to an audio + * input resource. + * + * @return A <code>PP_Bool</code> containing <code>PP_TRUE</code> if + * successful, otherwise <code>PP_FALSE</code>. Also returns + * <code>PP_TRUE</code> (and be a no-op) if called while callback is already + * in progress. + */ + PP_Bool StartCapture( + [in] PP_Resource audio_input); + + /** + * StopCapture is a pointer to a function that stops the capture of + * the audio input resource. + * + * @param[in] config A PP_Resource containing the audio input resource. + * + * @return A PP_BOOL containing PP_TRUE if successful, otherwise PP_FALSE. + * Also returns PP_TRUE (and is a no-op) if called while capture is already + * stopped. If a buffer is being captured, StopCapture will block until the + * call completes. + */ + PP_Bool StopCapture( + [in] PP_Resource audio_input); +}; + diff --git a/ppapi/api/trusted/ppb_audio_input_trusted_dev.idl b/ppapi/api/trusted/ppb_audio_input_trusted_dev.idl new file mode 100644 index 0000000..860c2e3 --- /dev/null +++ b/ppapi/api/trusted/ppb_audio_input_trusted_dev.idl @@ -0,0 +1,53 @@ +/* Copyright (c) 2011 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. + */ +/** + * This file defines the trusted audio input interface. + */ + +label Chrome { + M17 = 0.1 +}; + +/** + * This interface is to be used by proxy implementations. All + * functions should be called from the main thread only. The + * resource returned is an Audio input esource; most of the PPB_Audio + * interface is also usable on this resource. + */ +[version=0.1, macro="PPB_AUDIO_INPUT_TRUSTED_DEV_INTERFACE"] +interface PPB_AudioInputTrusted_Dev { + /** Returns an audio input resource. */ + PP_Resource CreateTrusted( + [in] PP_Instance instance); + + /** + * Opens a paused audio interface, used by trusted side of proxy. + * Returns PP_ERROR_WOULD_BLOCK on success, and invokes + * the |create_callback| asynchronously to complete. + * As this function should always be invoked from the main thread, + * do not use the blocking variant of PP_CompletionCallback. + */ + int32_t Open( + [in] PP_Resource audio_input, + [in] PP_Resource config, + [in] PP_CompletionCallback create_callback); + + /** + * Get the sync socket. Use once Open has completed. + * Returns PP_OK on success. + */ + int32_t GetSyncSocket( + [in] PP_Resource audio_input, + [out] handle_t sync_socket); + + /** + * Get the shared memory interface. Use once Open has completed. + * Returns PP_OK on success. + */ + int32_t GetSharedMemory( + [in] PP_Resource audio_input, + [out] handle_t shm_handle, + [out] uint32_t shm_size); +}; diff --git a/ppapi/c/dev/ppb_audio_input_dev.h b/ppapi/c/dev/ppb_audio_input_dev.h new file mode 100644 index 0000000..ed9e098 --- /dev/null +++ b/ppapi/c/dev/ppb_audio_input_dev.h @@ -0,0 +1,112 @@ +/* Copyright (c) 2011 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. + */ + +/* From dev/ppb_audio_input_dev.idl modified Mon Nov 14 17:58:16 2011. */ + +#ifndef PPAPI_C_DEV_PPB_AUDIO_INPUT_DEV_H_ +#define PPAPI_C_DEV_PPB_AUDIO_INPUT_DEV_H_ + +#include "ppapi/c/pp_bool.h" +#include "ppapi/c/pp_instance.h" +#include "ppapi/c/pp_macros.h" +#include "ppapi/c/pp_resource.h" +#include "ppapi/c/pp_stdint.h" + +#define PPB_AUDIO_INPUT_DEV_INTERFACE_0_1 "PPB_AudioInput(Dev);0.1" +#define PPB_AUDIO_INPUT_DEV_INTERFACE PPB_AUDIO_INPUT_DEV_INTERFACE_0_1 + +/** + * @file + * This file defines the <code>PPB_AudioInput_Dev</code> interface, which + * provides realtime audio input capture. + */ + + +/** + * @addtogroup Typedefs + * @{ + */ +/** + * <code>PPB_AudioInput_Callback</code> defines the type of an audio callback + * function used to provide the audio buffer with data. This callback will be + * called on a separate thread to the creation thread. + */ +typedef void (*PPB_AudioInput_Callback)(void* sample_buffer, + uint32_t buffer_size_in_bytes, + void* user_data); +/** + * @} + */ + +/** + * @addtogroup Interfaces + * @{ + */ +/** + * The <code>PPB_AudioInput_Dev</code> interface contains pointers to several + * functions for handling audio input resources. + */ +struct PPB_AudioInput_Dev { + /** + * Create is a pointer to a function that creates an audio input resource. + * No sound will be captured until StartCapture() is called. + */ + PP_Resource (*Create)(PP_Instance instance, + PP_Resource config, + PPB_AudioInput_Callback audio_input_callback, + void* user_data); + /** + * IsAudioInput is a pointer to a function that determines if the given + * resource is an audio input resource. + * + * @param[in] resource A PP_Resource containing a resource. + * + * @return A PP_BOOL containing containing PP_TRUE if the given resource is + * an audio input resource, otherwise PP_FALSE. + */ + PP_Bool (*IsAudioInput)(PP_Resource audio_input); + /** + * GetCurrrentConfig() returns an audio config resource for the given audio + * resource. + * + * @param[in] config A <code>PP_Resource</code> corresponding to an audio + * resource. + * + * @return A <code>PP_Resource</code> containing the audio config resource if + * successful. + */ + PP_Resource (*GetCurrentConfig)(PP_Resource audio_input); + /** + * StartCapture() starts the capture of the audio input resource and begins + * periodically calling the callback. + * + * @param[in] config A <code>PP_Resource</code> corresponding to an audio + * input resource. + * + * @return A <code>PP_Bool</code> containing <code>PP_TRUE</code> if + * successful, otherwise <code>PP_FALSE</code>. Also returns + * <code>PP_TRUE</code> (and be a no-op) if called while callback is already + * in progress. + */ + PP_Bool (*StartCapture)(PP_Resource audio_input); + /** + * StopCapture is a pointer to a function that stops the capture of + * the audio input resource. + * + * @param[in] config A PP_Resource containing the audio input resource. + * + * @return A PP_BOOL containing PP_TRUE if successful, otherwise PP_FALSE. + * Also returns PP_TRUE (and is a no-op) if called while capture is already + * stopped. If a buffer is being captured, StopCapture will block until the + * call completes. + */ + PP_Bool (*StopCapture)(PP_Resource audio_input); +}; +/** + * @} + */ + +#endif /* PPAPI_C_DEV_PPB_AUDIO_INPUT_DEV_H_ */ + diff --git a/ppapi/c/trusted/ppb_audio_input_trusted_dev.h b/ppapi/c/trusted/ppb_audio_input_trusted_dev.h new file mode 100644 index 0000000..bbdb44f --- /dev/null +++ b/ppapi/c/trusted/ppb_audio_input_trusted_dev.h @@ -0,0 +1,69 @@ +/* Copyright (c) 2011 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. + */ + +/* From trusted/ppb_audio_input_trusted_dev.idl modified Mon Nov 14 18:13:23 2011. */ + +#ifndef PPAPI_C_TRUSTED_PPB_AUDIO_INPUT_TRUSTED_DEV_H_ +#define PPAPI_C_TRUSTED_PPB_AUDIO_INPUT_TRUSTED_DEV_H_ + +#include "ppapi/c/pp_completion_callback.h" +#include "ppapi/c/pp_instance.h" +#include "ppapi/c/pp_macros.h" +#include "ppapi/c/pp_resource.h" +#include "ppapi/c/pp_stdint.h" + +#define PPB_AUDIO_INPUT_TRUSTED_DEV_INTERFACE_0_1 \ + "PPB_AudioInputTrusted(Dev);0.1" +#define PPB_AUDIO_INPUT_TRUSTED_DEV_INTERFACE \ + PPB_AUDIO_INPUT_TRUSTED_DEV_INTERFACE_0_1 + +/** + * @file + * This file defines the trusted audio input interface. + */ + + +/** + * @addtogroup Interfaces + * @{ + */ +/** + * This interface is to be used by proxy implementations. All + * functions should be called from the main thread only. The + * resource returned is an Audio input esource; most of the PPB_Audio + * interface is also usable on this resource. + */ +struct PPB_AudioInputTrusted_Dev { + /** Returns an audio input resource. */ + PP_Resource (*CreateTrusted)(PP_Instance instance); + /** + * Opens a paused audio interface, used by trusted side of proxy. + * Returns PP_ERROR_WOULD_BLOCK on success, and invokes + * the |create_callback| asynchronously to complete. + * As this function should always be invoked from the main thread, + * do not use the blocking variant of PP_CompletionCallback. + */ + int32_t (*Open)(PP_Resource audio_input, + PP_Resource config, + struct PP_CompletionCallback create_callback); + /** + * Get the sync socket. Use once Open has completed. + * Returns PP_OK on success. + */ + int32_t (*GetSyncSocket)(PP_Resource audio_input, int* sync_socket); + /** + * Get the shared memory interface. Use once Open has completed. + * Returns PP_OK on success. + */ + int32_t (*GetSharedMemory)(PP_Resource audio_input, + int* shm_handle, + uint32_t* shm_size); +}; +/** + * @} + */ + +#endif /* PPAPI_C_TRUSTED_PPB_AUDIO_INPUT_TRUSTED_DEV_H_ */ + diff --git a/ppapi/cpp/dev/audio_input_dev.cc b/ppapi/cpp/dev/audio_input_dev.cc new file mode 100644 index 0000000..fd81945 --- /dev/null +++ b/ppapi/cpp/dev/audio_input_dev.cc @@ -0,0 +1,44 @@ +// Copyright (c) 2011 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 "ppapi/cpp/dev/audio_input_dev.h" + +#include "ppapi/c/dev/ppb_audio_input_dev.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/cpp/instance.h" +#include "ppapi/cpp/module.h" +#include "ppapi/cpp/module_impl.h" + +namespace pp { + +namespace { + +template <> const char* interface_name<PPB_AudioInput_Dev>() { + return PPB_AUDIO_INPUT_DEV_INTERFACE; +} + +} // namespace + +AudioInput_Dev::AudioInput_Dev(Instance* instance, + const AudioConfig& config, + PPB_AudioInput_Callback callback, + void* user_data) + : config_(config) { + if (has_interface<PPB_AudioInput_Dev>()) { + PassRefFromConstructor(get_interface<PPB_AudioInput_Dev>()->Create( + instance->pp_instance(), config.pp_resource(), callback, user_data)); + } +} + +bool AudioInput_Dev::StartCapture() { + return has_interface<PPB_AudioInput_Dev>() && + get_interface<PPB_AudioInput_Dev>()->StartCapture(pp_resource()); +} + +bool AudioInput_Dev::StopCapture() { + return has_interface<PPB_AudioInput_Dev>() && + get_interface<PPB_AudioInput_Dev>()->StopCapture(pp_resource()); +} + +} // namespace pp diff --git a/ppapi/cpp/dev/audio_input_dev.h b/ppapi/cpp/dev/audio_input_dev.h new file mode 100644 index 0000000..2a51eb7 --- /dev/null +++ b/ppapi/cpp/dev/audio_input_dev.h @@ -0,0 +1,48 @@ +// Copyright (c) 2011 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. + +#ifndef PPAPI_CPP_DEV_AUDIO_INPUT_DEV_H_ +#define PPAPI_CPP_DEV_AUDIO_INPUT_DEV_H_ + +#include "ppapi/c/dev/ppb_audio_input_dev.h" +#include "ppapi/cpp/audio_config.h" +#include "ppapi/cpp/resource.h" + +namespace pp { + +class Instance; + +class AudioInput_Dev : public Resource { + public: + /// An empty constructor for an AudioInput resource. + AudioInput_Dev() {} + + AudioInput_Dev(Instance* instance, + const AudioConfig& config, + PPB_AudioInput_Callback callback, + void* user_data); + + /// Getter function for returning the internal <code>PPB_AudioConfig</code> + /// struct. + /// + /// @return A mutable reference to the PPB_AudioConfig struct. + AudioConfig& config() { return config_; } + + /// Getter function for returning the internal <code>PPB_AudioConfig</code> + /// struct. + /// + /// @return A const reference to the internal <code>PPB_AudioConfig</code> + /// struct. + const AudioConfig& config() const { return config_; } + + bool StartCapture(); + bool StopCapture(); + + private: + AudioConfig config_; +}; + +} // namespace pp + +#endif // PPAPI_CPP_DEV_AUDIO_INPUT_DEV_H_ diff --git a/ppapi/ppapi_cpp.gypi b/ppapi/ppapi_cpp.gypi index 8f8ba1d..7a34e52 100644 --- a/ppapi/ppapi_cpp.gypi +++ b/ppapi/ppapi_cpp.gypi @@ -198,6 +198,8 @@ 'cpp/var.h', # Dev interfaces. + 'cpp/dev/audio_input_dev.cc', + 'cpp/dev/audio_input_dev.h', 'cpp/dev/buffer_dev.cc', 'cpp/dev/buffer_dev.h', 'cpp/dev/context_3d_dev.cc', diff --git a/ppapi/ppapi_proxy.gypi b/ppapi/ppapi_proxy.gypi index 955a5f8..b1d3ee8 100644 --- a/ppapi/ppapi_proxy.gypi +++ b/ppapi/ppapi_proxy.gypi @@ -56,6 +56,8 @@ 'proxy/ppapi_messages.h', 'proxy/ppapi_param_traits.cc', 'proxy/ppapi_param_traits.h', + 'proxy/ppb_audio_input_proxy.cc', + 'proxy/ppb_audio_input_proxy.h', 'proxy/ppb_audio_proxy.cc', 'proxy/ppb_audio_proxy.h', 'proxy/ppb_broker_proxy.cc', diff --git a/ppapi/ppapi_shared.gypi b/ppapi/ppapi_shared.gypi index a3f4806..93d9f61 100644 --- a/ppapi/ppapi_shared.gypi +++ b/ppapi/ppapi_shared.gypi @@ -34,6 +34,8 @@ 'shared_impl/audio_config_impl.h', 'shared_impl/audio_impl.cc', 'shared_impl/audio_impl.h', + 'shared_impl/audio_input_impl.cc', + 'shared_impl/audio_input_impl.h', 'shared_impl/char_set_impl.cc', 'shared_impl/char_set_impl.h', 'shared_impl/crypto_impl.cc', @@ -97,6 +99,9 @@ 'thunk/ppb_audio_api.h', 'thunk/ppb_audio_config_api.h', 'thunk/ppb_audio_config_thunk.cc', + 'thunk/ppb_audio_input_api.h', + 'thunk/ppb_audio_input_thunk.cc', + 'thunk/ppb_audio_input_trusted_thunk.cc', 'thunk/ppb_audio_thunk.cc', 'thunk/ppb_audio_trusted_thunk.cc', 'thunk/ppb_broker_api.h', diff --git a/ppapi/proxy/interface_list.cc b/ppapi/proxy/interface_list.cc index 0d654a5..96ee6bc 100644 --- a/ppapi/proxy/interface_list.cc +++ b/ppapi/proxy/interface_list.cc @@ -5,6 +5,7 @@ #include "ppapi/proxy/interface_list.h" #include "base/memory/singleton.h" +#include "ppapi/c/dev/ppb_audio_input_dev.h" #include "ppapi/c/dev/ppb_buffer_dev.h" #include "ppapi/c/dev/ppb_char_set_dev.h" #include "ppapi/c/dev/ppb_console_dev.h" @@ -55,6 +56,7 @@ #include "ppapi/c/trusted/ppb_broker_trusted.h" #include "ppapi/c/trusted/ppb_url_loader_trusted.h" #include "ppapi/proxy/interface_proxy.h" +#include "ppapi/proxy/ppb_audio_input_proxy.h" #include "ppapi/proxy/ppb_audio_proxy.h" #include "ppapi/proxy/ppb_broker_proxy.h" #include "ppapi/proxy/ppb_buffer_proxy.h" diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h index 6a41a38..d38a397 100644 --- a/ppapi/proxy/ppapi_messages.h +++ b/ppapi/proxy/ppapi_messages.h @@ -216,6 +216,14 @@ IPC_MESSAGE_ROUTED5(PpapiMsg_PPBAudio_NotifyAudioStreamCreated, base::SharedMemoryHandle /* handle */, int32_t /* length */) +// PPB_AudioInput_Dev. +IPC_MESSAGE_ROUTED5(PpapiMsg_PPBAudioInput_NotifyAudioStreamCreated, + ppapi::HostResource /* audio_id */, + int32_t /* result_code (will be != PP_OK on failure) */, + IPC::PlatformFileForTransit /* socket_handle */, + base::SharedMemoryHandle /* handle */, + int32_t /* length */) + // PPB_Broker. IPC_MESSAGE_ROUTED3( PpapiMsg_PPBBroker_ConnectComplete, @@ -490,6 +498,16 @@ IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBAudio_StartOrStop, ppapi::HostResource /* audio_id */, bool /* play */) +// PPB_AudioInput. +IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBAudioInput_Create, + PP_Instance /* instance_id */, + int32_t /* sample_rate */, + uint32_t /* sample_frame_count */, + ppapi::HostResource /* result */) +IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBAudioInput_StartOrStop, + ppapi::HostResource /* audio_id */, + bool /* capture */) + // PPB_Broker. IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBBroker_Create, PP_Instance /* instance */, diff --git a/ppapi/proxy/ppb_audio_input_proxy.cc b/ppapi/proxy/ppb_audio_input_proxy.cc new file mode 100644 index 0000000..e3b9b05 --- /dev/null +++ b/ppapi/proxy/ppb_audio_input_proxy.cc @@ -0,0 +1,334 @@ +// Copyright (c) 2011 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 "ppapi/proxy/ppb_audio_input_proxy.h" + +#include "base/compiler_specific.h" +#include "base/threading/simple_thread.h" +#include "ppapi/c/dev/ppb_audio_input_dev.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/c/ppb_audio_config.h" +#include "ppapi/c/ppb_var.h" +#include "ppapi/c/trusted/ppb_audio_trusted.h" +#include "ppapi/proxy/enter_proxy.h" +#include "ppapi/proxy/plugin_dispatcher.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/shared_impl/api_id.h" +#include "ppapi/shared_impl/audio_input_impl.h" +#include "ppapi/shared_impl/ppapi_globals.h" +#include "ppapi/shared_impl/resource.h" +#include "ppapi/thunk/enter.h" +#include "ppapi/thunk/ppb_audio_config_api.h" +#include "ppapi/thunk/resource_creation_api.h" +#include "ppapi/thunk/thunk.h" + +using ppapi::thunk::EnterResourceNoLock; +using ppapi::thunk::PPB_AudioInput_API; +using ppapi::thunk::PPB_AudioConfig_API; + +namespace ppapi { +namespace proxy { + +class AudioInput : public Resource, public AudioInputImpl { + public: + AudioInput(const HostResource& audio_input_id, + PP_Resource config_id, + PPB_AudioInput_Callback callback, + void* user_data); + virtual ~AudioInput(); + + // Resource overrides. + virtual PPB_AudioInput_API* AsPPB_AudioInput_API() OVERRIDE; + + // PPB_AudioInput_API implementation. + virtual PP_Resource GetCurrentConfig() OVERRIDE; + virtual PP_Bool StartCapture() OVERRIDE; + virtual PP_Bool StopCapture() OVERRIDE; + + virtual int32_t OpenTrusted(PP_Resource config_id, + PP_CompletionCallback create_callback) OVERRIDE; + virtual int32_t GetSyncSocket(int* sync_socket) OVERRIDE; + virtual int32_t GetSharedMemory(int* shm_handle, uint32_t* shm_size) OVERRIDE; + + private: + // Owning reference to the current config object. This isn't actually used, + // we just dish it out as requested by the plugin. + PP_Resource config_; + + DISALLOW_COPY_AND_ASSIGN(AudioInput); +}; + +AudioInput::AudioInput(const HostResource& audio_input_id, + PP_Resource config_id, + PPB_AudioInput_Callback callback, + void* user_data) + : Resource(audio_input_id), + config_(config_id) { + SetCallback(callback, user_data); + PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(config_); +} + +AudioInput::~AudioInput() { + PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(config_); +} + +PPB_AudioInput_API* AudioInput::AsPPB_AudioInput_API() { + return this; +} + +PP_Resource AudioInput::GetCurrentConfig() { + // AddRef for the caller. + PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(config_); + return config_; +} + +PP_Bool AudioInput::StartCapture() { + if (capturing()) + return PP_TRUE; + SetStartCaptureState(); + PluginDispatcher::GetForResource(this)->Send( + new PpapiHostMsg_PPBAudioInput_StartOrStop( + API_ID_PPB_AUDIO_INPUT_DEV, host_resource(), true)); + return PP_TRUE; +} + +PP_Bool AudioInput::StopCapture() { + if (!capturing()) + return PP_TRUE; + PluginDispatcher::GetForResource(this)->Send( + new PpapiHostMsg_PPBAudioInput_StartOrStop( + API_ID_PPB_AUDIO_INPUT_DEV, host_resource(), false)); + SetStopCaptureState(); + return PP_TRUE; +} + +int32_t AudioInput::OpenTrusted(PP_Resource config_id, + PP_CompletionCallback create_callback) { + return PP_ERROR_NOTSUPPORTED; // Don't proxy the trusted interface. +} + +int32_t AudioInput::GetSyncSocket(int* sync_socket) { + return PP_ERROR_NOTSUPPORTED; // Don't proxy the trusted interface. +} + +int32_t AudioInput::GetSharedMemory(int* shm_handle, uint32_t* shm_size) { + return PP_ERROR_NOTSUPPORTED; // Don't proxy the trusted interface. +} + +namespace { + +base::PlatformFile IntToPlatformFile(int32_t handle) { + // TODO(piman/brettw): Change trusted interface to return a PP_FileHandle, + // those casts are ugly. +#if defined(OS_WIN) + return reinterpret_cast<HANDLE>(static_cast<intptr_t>(handle)); +#elif defined(OS_POSIX) + return handle; +#else + #error Not implemented. +#endif +} + +} // namespace + +PPB_AudioInput_Proxy::PPB_AudioInput_Proxy(Dispatcher* dispatcher) + : InterfaceProxy(dispatcher), + callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { +} + +PPB_AudioInput_Proxy::~PPB_AudioInput_Proxy() { +} + +// static +PP_Resource PPB_AudioInput_Proxy::CreateProxyResource( + PP_Instance instance_id, + PP_Resource config_id, + PPB_AudioInput_Callback audio_input_callback, + void* user_data) { + PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance_id); + if (!dispatcher) + return 0; + + EnterResourceNoLock<PPB_AudioConfig_API> config(config_id, true); + if (config.failed()) + return 0; + + HostResource result; + dispatcher->Send(new PpapiHostMsg_PPBAudioInput_Create( + API_ID_PPB_AUDIO_INPUT_DEV, instance_id, + config.object()->GetSampleRate(), config.object()->GetSampleFrameCount(), + &result)); + if (result.is_null()) + return 0; + + return (new AudioInput(result, config_id, audio_input_callback, + user_data))->GetReference(); +} + +bool PPB_AudioInput_Proxy::OnMessageReceived(const IPC::Message& msg) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(PPB_AudioInput_Proxy, msg) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBAudioInput_Create, OnMsgCreate) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBAudioInput_StartOrStop, + OnMsgStartOrStop) + IPC_MESSAGE_HANDLER(PpapiMsg_PPBAudioInput_NotifyAudioStreamCreated, + OnMsgNotifyAudioStreamCreated) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + // TODO(brettw) handle bad messages! + + return handled; +} + +void PPB_AudioInput_Proxy::OnMsgCreate(PP_Instance instance_id, + int32_t sample_rate, + uint32_t sample_frame_count, + HostResource* result) { + thunk::EnterFunction<thunk::ResourceCreationAPI> resource_creation( + instance_id, true); + if (resource_creation.failed()) + return; + + // Make the resource and get the API pointer to its trusted interface. + result->SetHostResource( + instance_id, + resource_creation.functions()->CreateAudioInputTrusted(instance_id)); + if (result->is_null()) + return; + + // At this point, we've set the result resource, and this is a sync request. + // Anything below this point must issue the AudioInputChannelConnected + // callback to the browser. Since that's an async message, it will be issued + // back to the plugin after the Create function returns (which is good + // because it would be weird to get a connected message with a failure code + // for a resource you haven't finished creating yet). + // + // The ...ForceCallback class will help ensure the callback is always called. + // All error cases must call SetResult on this class. + + EnterHostFromHostResourceForceCallback<PPB_AudioInput_API> enter( + *result, callback_factory_, + &PPB_AudioInput_Proxy::AudioInputChannelConnected, *result); + if (enter.failed()) + return; // When enter fails, it will internally schedule the callback. + + // Make an audio config object. + PP_Resource audio_config_res = + resource_creation.functions()->CreateAudioConfig( + instance_id, static_cast<PP_AudioSampleRate>(sample_rate), + sample_frame_count); + if (!audio_config_res) { + enter.SetResult(PP_ERROR_FAILED); + return; + } + + // Initiate opening the audio object. + enter.SetResult(enter.object()->OpenTrusted(audio_config_res, + enter.callback())); + + // Clean up the temporary audio config resource we made. + const PPB_Core* core = static_cast<const PPB_Core*>( + dispatcher()->local_get_interface()(PPB_CORE_INTERFACE)); + core->ReleaseResource(audio_config_res); +} + +void PPB_AudioInput_Proxy::OnMsgStartOrStop( + const HostResource& resource, + bool capture) { + EnterHostFromHostResource<PPB_AudioInput_API> enter(resource); + if (enter.failed()) + return; + if (capture) + enter.object()->StartCapture(); + else + enter.object()->StopCapture(); +} + +// Processed in the plugin (message from host). +void PPB_AudioInput_Proxy::OnMsgNotifyAudioStreamCreated( + const HostResource& audio_id, + int32_t result_code, + IPC::PlatformFileForTransit socket_handle, + base::SharedMemoryHandle handle, + uint32_t length) { + EnterPluginFromHostResource<PPB_AudioInput_API> enter(audio_id); + if (enter.failed() || result_code != PP_OK) { + // The caller may still have given us these handles in the failure case. + // The easiest way to clean these up is to just put them in the objects + // and then close them. This failure case is not performance critical. + base::SyncSocket temp_socket( + IPC::PlatformFileForTransitToPlatformFile(socket_handle)); + base::SharedMemory temp_mem(handle, false); + } else { + static_cast<AudioInput*>(enter.object())->SetStreamInfo( + handle, length, + IPC::PlatformFileForTransitToPlatformFile(socket_handle)); + } +} + +void PPB_AudioInput_Proxy::AudioInputChannelConnected( + int32_t result, + const HostResource& resource) { + IPC::PlatformFileForTransit socket_handle = + IPC::InvalidPlatformFileForTransit(); + base::SharedMemoryHandle shared_memory = IPC::InvalidPlatformFileForTransit(); + uint32_t shared_memory_length = 0; + + int32_t result_code = result; + if (result_code == PP_OK) { + result_code = GetAudioInputConnectedHandles(resource, &socket_handle, + &shared_memory, + &shared_memory_length); + } + + // Send all the values, even on error. This simplifies some of our cleanup + // code since the handles will be in the other process and could be + // inconvenient to clean up. Our IPC code will automatically handle this for + // us, as long as the remote side always closes the handles it receives + // (in OnMsgNotifyAudioStreamCreated), even in the failure case. + dispatcher()->Send(new PpapiMsg_PPBAudioInput_NotifyAudioStreamCreated( + API_ID_PPB_AUDIO_INPUT_DEV, resource, result_code, socket_handle, + shared_memory, shared_memory_length)); +} + +int32_t PPB_AudioInput_Proxy::GetAudioInputConnectedHandles( + const HostResource& resource, + IPC::PlatformFileForTransit* foreign_socket_handle, + base::SharedMemoryHandle* foreign_shared_memory_handle, + uint32_t* shared_memory_length) { + // Get the audio interface which will give us the handles. + EnterHostFromHostResource<PPB_AudioInput_API> enter(resource); + if (enter.failed()) + return PP_ERROR_NOINTERFACE; + + // Get the socket handle for signaling. + int32_t socket_handle; + int32_t result = enter.object()->GetSyncSocket(&socket_handle); + if (result != PP_OK) + return result; + + // socket_handle doesn't belong to us: don't close it. + *foreign_socket_handle = dispatcher()->ShareHandleWithRemote( + IntToPlatformFile(socket_handle), false); + if (*foreign_socket_handle == IPC::InvalidPlatformFileForTransit()) + return PP_ERROR_FAILED; + + // Get the shared memory for the buffer. + int shared_memory_handle; + result = enter.object()->GetSharedMemory(&shared_memory_handle, + shared_memory_length); + if (result != PP_OK) + return result; + + // shared_memory_handle doesn't belong to us: don't close it. + *foreign_shared_memory_handle = dispatcher()->ShareHandleWithRemote( + IntToPlatformFile(shared_memory_handle), false); + if (*foreign_shared_memory_handle == IPC::InvalidPlatformFileForTransit()) + return PP_ERROR_FAILED; + + return PP_OK; +} + +} // namespace proxy +} // namespace ppapi diff --git a/ppapi/proxy/ppb_audio_input_proxy.h b/ppapi/proxy/ppb_audio_input_proxy.h new file mode 100644 index 0000000..6244e55 --- /dev/null +++ b/ppapi/proxy/ppb_audio_input_proxy.h @@ -0,0 +1,86 @@ +// Copyright (c) 2011 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. + +#ifndef PPAPI_PPB_AUDIO_INPUT_PROXY_H_ +#define PPAPI_PPB_AUDIO_INPUT_PROXY_H_ + +#include <utility> + +#include "base/basictypes.h" +#include "base/shared_memory.h" +#include "base/sync_socket.h" +#include "ipc/ipc_platform_file.h" +#include "ppapi/c/dev/ppb_audio_input_dev.h" +#include "ppapi/c/ppb_audio_config.h" +#include "ppapi/cpp/completion_callback.h" +#include "ppapi/proxy/interface_proxy.h" +#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" + +struct PPB_AudioInput_Dev; + +namespace ppapi { + +class HostResource; + +namespace proxy { + +class PPB_AudioInput_Proxy : public InterfaceProxy { + public: + explicit PPB_AudioInput_Proxy(Dispatcher* dispatcher); + virtual ~PPB_AudioInput_Proxy(); + + static PP_Resource CreateProxyResource( + PP_Instance instance, + PP_Resource config_id, + PPB_AudioInput_Callback audio_input_callback, + void* user_data); + + // InterfaceProxy implementation. + virtual bool OnMessageReceived(const IPC::Message& msg); + + static const ApiID kApiID = API_ID_PPB_AUDIO_INPUT_DEV; + + private: + // Message handlers. + // Plugin->renderer message handlers. + void OnMsgCreate(PP_Instance instance_id, + int32_t sample_rate, + uint32_t sample_frame_count, + ppapi::HostResource* result); + void OnMsgStartOrStop(const ppapi::HostResource& audio_id, bool capture); + + // Renderer->plugin message handlers. + void OnMsgNotifyAudioStreamCreated(const ppapi::HostResource& audio_id, + int32_t result_code, + IPC::PlatformFileForTransit socket_handle, + base::SharedMemoryHandle handle, + uint32_t length); + + void AudioInputChannelConnected(int32_t result, + const ppapi::HostResource& resource); + + // In the renderer, this is called in response to a stream created message. + // It will retrieve the shared memory and socket handles and place them into + // the given out params. The return value is a PPAPI error code. + // + // The input arguments should be initialized to 0 or -1, depending on the + // platform's default invalid handle values. On error, some of these + // arguments may be written to, and others may be untouched, depending on + // where the error occurred. + int32_t GetAudioInputConnectedHandles( + const ppapi::HostResource& resource, + IPC::PlatformFileForTransit* foreign_socket_handle, + base::SharedMemoryHandle* foreign_shared_memory_handle, + uint32_t* shared_memory_length); + + pp::CompletionCallbackFactory<PPB_AudioInput_Proxy, + ProxyNonThreadSafeRefCount> callback_factory_; + + DISALLOW_COPY_AND_ASSIGN(PPB_AudioInput_Proxy); +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PPB_AUDIO_INPUT_PROXY_H_ diff --git a/ppapi/proxy/resource_creation_proxy.cc b/ppapi/proxy/resource_creation_proxy.cc index afdf56d..3777a2d 100644 --- a/ppapi/proxy/resource_creation_proxy.cc +++ b/ppapi/proxy/resource_creation_proxy.cc @@ -10,6 +10,7 @@ #include "ppapi/proxy/plugin_dispatcher.h" #include "ppapi/proxy/plugin_resource_tracker.h" #include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/ppb_audio_input_proxy.h" #include "ppapi/proxy/ppb_audio_proxy.h" #include "ppapi/proxy/ppb_buffer_proxy.h" #include "ppapi/proxy/ppb_broker_proxy.h" @@ -83,6 +84,22 @@ PP_Resource ResourceCreationProxy::CreateAudioTrusted(PP_Instance instance) { return 0; } +PP_Resource ResourceCreationProxy::CreateAudioInput( + PP_Instance instance, + PP_Resource config_id, + PPB_Audio_Callback audio_input_callback, + void* user_data) { + return PPB_AudioInput_Proxy::CreateProxyResource(instance, config_id, + audio_input_callback, + user_data); +} + +PP_Resource ResourceCreationProxy::CreateAudioInputTrusted( + PP_Instance instance) { + // Proxied plugins can't created trusted audio input devices. + return 0; +} + PP_Resource ResourceCreationProxy::CreateBroker(PP_Instance instance) { return PPB_Broker_Proxy::CreateProxyResource(instance); } diff --git a/ppapi/proxy/resource_creation_proxy.h b/ppapi/proxy/resource_creation_proxy.h index 20924d1..e543722 100644 --- a/ppapi/proxy/resource_creation_proxy.h +++ b/ppapi/proxy/resource_creation_proxy.h @@ -46,6 +46,12 @@ class ResourceCreationProxy : public InterfaceProxy, PP_AudioSampleRate sample_rate, uint32_t sample_frame_count) OVERRIDE; virtual PP_Resource CreateAudioTrusted(PP_Instance instance) OVERRIDE; + virtual PP_Resource CreateAudioInput( + PP_Instance instance, + PP_Resource config_id, + PPB_AudioInput_Callback audio_input_callback, + void* user_data) OVERRIDE; + virtual PP_Resource CreateAudioInputTrusted(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateBroker(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateBuffer(PP_Instance instance, uint32_t size) OVERRIDE; @@ -140,6 +146,8 @@ class ResourceCreationProxy : public InterfaceProxy, int32_t sample_rate, uint32_t sample_frame_count, HostResource* result); + void OnMsgCreateAudioInput(PP_Instance instance, + HostResource* result); void OnMsgCreateGraphics2D(PP_Instance instance, const PP_Size& size, PP_Bool is_always_opaque, diff --git a/ppapi/shared_impl/api_id.h b/ppapi/shared_impl/api_id.h index d439d3d..5da4b04 100644 --- a/ppapi/shared_impl/api_id.h +++ b/ppapi/shared_impl/api_id.h @@ -14,6 +14,7 @@ enum ApiID { API_ID_NONE = 0, API_ID_PPB_AUDIO = 1, API_ID_PPB_AUDIO_CONFIG, + API_ID_PPB_AUDIO_INPUT_DEV, API_ID_PPB_BROKER, API_ID_PPB_BUFFER, API_ID_PPB_CONTEXT_3D, diff --git a/ppapi/shared_impl/audio_input_impl.cc b/ppapi/shared_impl/audio_input_impl.cc new file mode 100644 index 0000000..659cd47 --- /dev/null +++ b/ppapi/shared_impl/audio_input_impl.cc @@ -0,0 +1,94 @@ +// Copyright (c) 2011 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 "ppapi/shared_impl/audio_input_impl.h" + +#include "base/logging.h" + +namespace ppapi { + +AudioInputImpl::AudioInputImpl() + : capturing_(false), + shared_memory_size_(0), + callback_(NULL), + user_data_(NULL) { +} + +AudioInputImpl::~AudioInputImpl() { + // Closing the socket causes the thread to exit - wait for it. + if (socket_.get()) + socket_->Close(); + if (audio_input_thread_.get()) { + audio_input_thread_->Join(); + audio_input_thread_.reset(); + } +} + +void AudioInputImpl::SetCallback(PPB_AudioInput_Callback callback, + void* user_data) { + callback_ = callback; + user_data_ = user_data; +} + +void AudioInputImpl::SetStartCaptureState() { + DCHECK(!capturing_); + DCHECK(!audio_input_thread_.get()); + + // If the socket doesn't exist, that means that the plugin has started before + // the browser has had a chance to create all the shared memory info and + // notify us. This is a common case. In this case, we just set the playing_ + // flag and the capture will automatically start when that data is available + // in SetStreamInfo. + if (socket_.get()) + StartThread(); + capturing_ = true; +} + +void AudioInputImpl::SetStopCaptureState() { + DCHECK(capturing_); + + if (audio_input_thread_.get()) { + audio_input_thread_->Join(); + audio_input_thread_.reset(); + } + capturing_ = false; +} + +void AudioInputImpl::SetStreamInfo( + base::SharedMemoryHandle shared_memory_handle, + size_t shared_memory_size, + base::SyncSocket::Handle socket_handle) { + socket_.reset(new base::SyncSocket(socket_handle)); + shared_memory_.reset(new base::SharedMemory(shared_memory_handle, false)); + shared_memory_size_ = shared_memory_size; + + if (callback_) { + shared_memory_->Map(shared_memory_size_); + + // In common case StartCapture() was called before StreamCreated(). + if (capturing_) + StartThread(); + } +} + +void AudioInputImpl::StartThread() { + DCHECK(callback_); + DCHECK(!audio_input_thread_.get()); + audio_input_thread_.reset(new base::DelegateSimpleThread( + this, "plugin_audio_input_thread")); + audio_input_thread_->Start(); +} + +void AudioInputImpl::Run() { + int pending_data; + void* buffer = shared_memory_->memory(); + + while (sizeof(pending_data) == socket_->Receive(&pending_data, + sizeof(pending_data)) && + pending_data >= 0) { + callback_(buffer, shared_memory_size_, user_data_); + } +} + +} // namespace ppapi diff --git a/ppapi/shared_impl/audio_input_impl.h b/ppapi/shared_impl/audio_input_impl.h new file mode 100644 index 0000000..e7604c3 --- /dev/null +++ b/ppapi/shared_impl/audio_input_impl.h @@ -0,0 +1,88 @@ +// Copyright (c) 2011 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. + +#ifndef PPAPI_SHARED_IMPL_AUDIO_INPUT_IMPL_H_ +#define PPAPI_SHARED_IMPL_AUDIO_INPUT_IMPL_H_ + +#include "base/memory/scoped_ptr.h" +#include "base/shared_memory.h" +#include "base/sync_socket.h" +#include "base/threading/simple_thread.h" +#include "ppapi/c/dev/ppb_audio_input_dev.h" +#include "ppapi/shared_impl/resource.h" +#include "ppapi/thunk/ppb_audio_input_api.h" + +namespace ppapi { + +// Implements the logic to map shared memory and run the audio thread signaled +// from the sync socket. Both the proxy and the renderer implementation use +// this code. +class PPAPI_SHARED_EXPORT AudioInputImpl + : public thunk::PPB_AudioInput_API, + public base::DelegateSimpleThread::Delegate { + public: + AudioInputImpl(); + virtual ~AudioInputImpl(); + + bool capturing() const { return capturing_; } + + // Sets the callback information that the background thread will use. This + // is optional. Without a callback, the thread will not be run. This + // non-callback mode is used in the renderer with the proxy, since the proxy + // handles the callback entirely within the plugin process. + void SetCallback(PPB_AudioInput_Callback callback, void* user_data); + + // Configures the current state to be playing or not. The caller is + // responsible for ensuring the new state is the opposite of the current one. + // + // This is the implementation for PPB_AudioInput.Start/StopCapture, except + // that it does not actually notify the audio system to stop capture, it just + // configures our object to stop generating callbacks. The actual stop + // playback request will be done in the derived classes and will be different + // from the proxy and the renderer. + void SetStartCaptureState(); + void SetStopCaptureState(); + + // Sets the shared memory and socket handles. This will automatically start + // playback if we're currently set to play. + void SetStreamInfo(base::SharedMemoryHandle shared_memory_handle, + size_t shared_memory_size, + base::SyncSocket::Handle socket_handle); + + private: + // Starts execution of the audio input thread. + void StartThread(); + + // DelegateSimpleThread::Delegate implementation. + // Run on the audio input thread. + virtual void Run(); + + // True if capturing the stream. + bool capturing_; + + // Socket used to notify us when audio is ready to accept new samples. This + // pointer is created in StreamCreated(). + scoped_ptr<base::SyncSocket> socket_; + + // Sample buffer in shared memory. This pointer is created in + // StreamCreated(). The memory is only mapped when the audio thread is + // created. + scoped_ptr<base::SharedMemory> shared_memory_; + + // The size of the sample buffer in bytes. + size_t shared_memory_size_; + + // When the callback is set, this thread is spawned for calling it. + scoped_ptr<base::DelegateSimpleThread> audio_input_thread_; + + // Callback to call when audio is ready to produce new samples. + PPB_AudioInput_Callback callback_; + + // User data pointer passed verbatim to the callback function. + void* user_data_; +}; + +} // namespace ppapi + +#endif // PPAPI_SHARED_IMPL_AUDIO_INPUT_IMPL_H_ diff --git a/ppapi/shared_impl/resource.h b/ppapi/shared_impl/resource.h index 247287f..19c909c 100644 --- a/ppapi/shared_impl/resource.h +++ b/ppapi/shared_impl/resource.h @@ -16,9 +16,11 @@ // All resource types should be added here. This implements our hand-rolled // RTTI system since we don't compile with "real" RTTI. #define FOR_ALL_PPAPI_RESOURCE_APIS(F) \ + F(PPB_Audio_API) \ F(PPB_AudioConfig_API) \ + F(PPB_AudioInput_API) \ + F(PPB_AudioInputTrusted_API) \ F(PPB_AudioTrusted_API) \ - F(PPB_Audio_API) \ F(PPB_Broker_API) \ F(PPB_Buffer_API) \ F(PPB_BufferTrusted_API) \ diff --git a/ppapi/thunk/interfaces_ppb_public_dev.h b/ppapi/thunk/interfaces_ppb_public_dev.h index 574c954..7ef9f30 100644 --- a/ppapi/thunk/interfaces_ppb_public_dev.h +++ b/ppapi/thunk/interfaces_ppb_public_dev.h @@ -7,6 +7,7 @@ #include "ppapi/thunk/interfaces_preamble.h" +PROXIED_API(PPB_AudioInput) PROXIED_API(PPB_Buffer) PROXIED_API(PPB_Context3D) PROXIED_API(PPB_CursorControl) @@ -23,6 +24,8 @@ PROXIED_API(PPB_VideoCapture) PROXIED_API(PPB_VideoDecoder) UNPROXIED_API(PPB_Widget) +PROXIED_IFACE(PPB_AudioInput, PPB_AUDIO_INPUT_DEV_INTERFACE_0_1, + PPB_AudioInput_Dev) PROXIED_IFACE(NoAPIName, PPB_IME_INPUT_EVENT_DEV_INTERFACE_0_1, PPB_IMEInputEvent_Dev) PROXIED_IFACE(PPB_Buffer, PPB_BUFFER_DEV_INTERFACE_0_4, PPB_Buffer_Dev) diff --git a/ppapi/thunk/ppb_audio_input_api.h b/ppapi/thunk/ppb_audio_input_api.h new file mode 100644 index 0000000..f42f0d5 --- /dev/null +++ b/ppapi/thunk/ppb_audio_input_api.h @@ -0,0 +1,33 @@ +// Copyright (c) 2011 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. + +#ifndef PPAPI_THUNK_AUDIO_INPUT_API_H_ +#define PPAPI_THUNK_AUDIO_INPUT_API_H_ + +#include "ppapi/c/dev/ppb_audio_input_dev.h" +#include "ppapi/c/pp_completion_callback.h" +#include "ppapi/thunk/ppapi_thunk_export.h" + +namespace ppapi { +namespace thunk { + +class PPB_AudioInput_API { + public: + virtual ~PPB_AudioInput_API() {} + + virtual PP_Resource GetCurrentConfig() = 0; + virtual PP_Bool StartCapture() = 0; + virtual PP_Bool StopCapture() = 0; + + // Trusted API. + virtual int32_t OpenTrusted(PP_Resource config_id, + PP_CompletionCallback create_callback) = 0; + virtual int32_t GetSyncSocket(int* sync_socket) = 0; + virtual int32_t GetSharedMemory(int* shm_handle, uint32_t* shm_size) = 0; +}; + +} // namespace thunk +} // namespace ppapi + +#endif // PPAPI_THUNK_AUDIO_INPUT_API_H_ diff --git a/ppapi/thunk/ppb_audio_input_thunk.cc b/ppapi/thunk/ppb_audio_input_thunk.cc new file mode 100644 index 0000000..7b6f31c --- /dev/null +++ b/ppapi/thunk/ppb_audio_input_thunk.cc @@ -0,0 +1,74 @@ +// Copyright (c) 2011 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 "ppapi/c/pp_errors.h" +#include "ppapi/thunk/common.h" +#include "ppapi/thunk/enter.h" +#include "ppapi/thunk/ppb_audio_input_api.h" +#include "ppapi/thunk/resource_creation_api.h" +#include "ppapi/thunk/thunk.h" + +namespace ppapi { +namespace thunk { + +namespace { + +typedef EnterResource<PPB_AudioInput_API> EnterAudioInput; + +PP_Resource Create(PP_Instance instance, + PP_Resource config_id, + PPB_AudioInput_Callback callback, + void* user_data) { + EnterFunction<ResourceCreationAPI> enter(instance, true); + if (enter.failed()) + return 0; + + return enter.functions()->CreateAudioInput(instance, config_id, + callback, user_data); +} + +PP_Bool IsAudioInput(PP_Resource resource) { + EnterAudioInput enter(resource, false); + return PP_FromBool(enter.succeeded()); +} + +PP_Resource GetCurrentConfiguration(PP_Resource audio_id) { + EnterAudioInput enter(audio_id, true); + if (enter.failed()) + return 0; + return enter.object()->GetCurrentConfig(); +} + +PP_Bool StartCapture(PP_Resource audio_input) { + EnterAudioInput enter(audio_input, true); + if (enter.failed()) + return PP_FALSE; + + return enter.object()->StartCapture(); +} + +PP_Bool StopCapture(PP_Resource audio_input) { + EnterAudioInput enter(audio_input, true); + if (enter.failed()) + return PP_FALSE; + + return enter.object()->StopCapture(); +} + +const PPB_AudioInput_Dev g_ppb_audioinput_thunk = { + &Create, + &IsAudioInput, + &GetCurrentConfiguration, + &StartCapture, + &StopCapture +}; + +} // namespace + +const PPB_AudioInput_Dev* GetPPB_AudioInput_Dev_Thunk() { + return &g_ppb_audioinput_thunk; +} + +} // namespace thunk +} // namespace ppapi diff --git a/ppapi/thunk/ppb_audio_input_trusted_thunk.cc b/ppapi/thunk/ppb_audio_input_trusted_thunk.cc new file mode 100644 index 0000000..1de878c --- /dev/null +++ b/ppapi/thunk/ppb_audio_input_trusted_thunk.cc @@ -0,0 +1,67 @@ +// Copyright (c) 2011 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 "ppapi/c/pp_errors.h" +#include "ppapi/c/trusted/ppb_audio_input_trusted_dev.h" +#include "ppapi/thunk/common.h" +#include "ppapi/thunk/enter.h" +#include "ppapi/thunk/ppb_audio_input_api.h" +#include "ppapi/thunk/resource_creation_api.h" +#include "ppapi/thunk/thunk.h" + +namespace ppapi { +namespace thunk { + +namespace { + +typedef EnterResource<PPB_AudioInput_API> EnterAudioInput; + +PP_Resource Create(PP_Instance instance_id) { + EnterFunction<ResourceCreationAPI> enter(instance_id, true); + if (enter.failed()) + return 0; + return enter.functions()->CreateAudioInputTrusted(instance_id); +} + +int32_t Open(PP_Resource audio_id, + PP_Resource config_id, + PP_CompletionCallback create_callback) { + EnterAudioInput enter(audio_id, true); + if (enter.failed()) + return MayForceCallback(create_callback, PP_ERROR_BADRESOURCE); + int32_t result = enter.object()->OpenTrusted(config_id, create_callback); + return MayForceCallback(create_callback, result); +} + +int32_t GetSyncSocket(PP_Resource audio_id, int* sync_socket) { + EnterAudioInput enter(audio_id, true); + if (enter.failed()) + return PP_ERROR_BADRESOURCE; + return enter.object()->GetSyncSocket(sync_socket); +} + +int32_t GetSharedMemory(PP_Resource audio_id, + int* shm_handle, + uint32_t* shm_size) { + EnterAudioInput enter(audio_id, true); + if (enter.failed()) + return PP_ERROR_BADRESOURCE; + return enter.object()->GetSharedMemory(shm_handle, shm_size); +} + +const PPB_AudioInputTrusted_Dev g_ppb_audioinput_trusted_thunk = { + &Create, + &Open, + &GetSyncSocket, + &GetSharedMemory, +}; + +} // namespace + +const PPB_AudioInputTrusted_Dev* GetPPB_AudioInputTrusted_Thunk() { + return &g_ppb_audioinput_trusted_thunk; +} + +} // namespace thunk +} // namespace ppapi diff --git a/ppapi/thunk/resource_creation_api.h b/ppapi/thunk/resource_creation_api.h index dd37bed..b9e26d5 100644 --- a/ppapi/thunk/resource_creation_api.h +++ b/ppapi/thunk/resource_creation_api.h @@ -5,6 +5,7 @@ #ifndef PPAPI_THUNK_RESOURCE_CREATION_API_H_ #define PPAPI_THUNK_RESOURCE_CREATION_API_H_ +#include "ppapi/c/dev/ppb_audio_input_dev.h" #include "ppapi/c/dev/ppb_file_chooser_dev.h" #include "ppapi/c/dev/ppb_video_layer_dev.h" #include "ppapi/c/pp_bool.h" @@ -43,10 +44,16 @@ class ResourceCreationAPI { PP_Resource config_id, PPB_Audio_Callback audio_callback, void* user_data) = 0; - virtual PP_Resource CreateAudioTrusted(PP_Instance instace) = 0; + virtual PP_Resource CreateAudioTrusted(PP_Instance instance) = 0; virtual PP_Resource CreateAudioConfig(PP_Instance instance, PP_AudioSampleRate sample_rate, uint32_t sample_frame_count) = 0; + virtual PP_Resource CreateAudioInput( + PP_Instance instance, + PP_Resource config_id, + PPB_AudioInput_Callback audio_input_callback, + void* user_data) = 0; + virtual PP_Resource CreateAudioInputTrusted(PP_Instance instance) = 0; virtual PP_Resource CreateBroker(PP_Instance instance) = 0; virtual PP_Resource CreateBuffer(PP_Instance instance, uint32_t size) = 0; virtual PP_Resource CreateContext3D(PP_Instance instance, diff --git a/ppapi/thunk/thunk.h b/ppapi/thunk/thunk.h index 8990b94..5f6a62c 100644 --- a/ppapi/thunk/thunk.h +++ b/ppapi/thunk/thunk.h @@ -27,6 +27,7 @@ #undef PROXIED_IFACE #undef IFACE +struct PPB_AudioInputTrusted_Dev; struct PPB_AudioTrusted; struct PPB_BrokerTrusted; struct PPB_BufferTrusted; @@ -52,6 +53,8 @@ namespace thunk { // Old-style thunk getters. Only put trusted/private stuff here (it hasn't // yet been converted to the new system). Otherwise, add the declaration to // the appropriate interfaces_*.h file. +PPAPI_THUNK_EXPORT const PPB_AudioInputTrusted_Dev* + GetPPB_AudioInputTrusted_Thunk(); PPAPI_THUNK_EXPORT const PPB_AudioTrusted* GetPPB_AudioTrusted_Thunk(); PPAPI_THUNK_EXPORT const PPB_BrokerTrusted* GetPPB_Broker_Thunk(); PPAPI_THUNK_EXPORT const PPB_BufferTrusted* GetPPB_BufferTrusted_Thunk(); diff --git a/webkit/glue/webkit_glue.gypi b/webkit/glue/webkit_glue.gypi index d93de09..cf27588 100644 --- a/webkit/glue/webkit_glue.gypi +++ b/webkit/glue/webkit_glue.gypi @@ -196,6 +196,8 @@ '../plugins/plugin_constants.h', '../plugins/plugin_switches.cc', '../plugins/plugin_switches.h', + '../plugins/ppapi/audio_helper.cc', + '../plugins/ppapi/audio_helper.h', '../plugins/ppapi/callbacks.cc', '../plugins/ppapi/callbacks.h', '../plugins/ppapi/common.h', @@ -234,6 +236,8 @@ '../plugins/ppapi/ppapi_webplugin_impl.h', '../plugins/ppapi/ppb_audio_impl.cc', '../plugins/ppapi/ppb_audio_impl.h', + '../plugins/ppapi/ppb_audio_input_impl.cc', + '../plugins/ppapi/ppb_audio_input_impl.h', '../plugins/ppapi/ppb_broker_impl.cc', '../plugins/ppapi/ppb_broker_impl.h', '../plugins/ppapi/ppb_buffer_impl.cc', diff --git a/webkit/plugins/ppapi/audio_helper.cc b/webkit/plugins/ppapi/audio_helper.cc new file mode 100644 index 0000000..a077e5b --- /dev/null +++ b/webkit/plugins/ppapi/audio_helper.cc @@ -0,0 +1,95 @@ +// Copyright (c) 2011 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 "ppapi/c/pp_completion_callback.h" +#include "webkit/plugins/ppapi/audio_helper.h" +#include "webkit/plugins/ppapi/common.h" +#include "webkit/plugins/ppapi/resource_helper.h" + +namespace webkit { +namespace ppapi { + +// AudioHelper ----------------------------------------------------------------- + +AudioHelper::AudioHelper() + : create_callback_pending_(false), + shared_memory_size_for_create_callback_(0) { + create_callback_ = PP_MakeCompletionCallback(NULL, NULL); +} + +AudioHelper::~AudioHelper() { + // If the completion callback hasn't fired yet, do so here + // with an error condition. + if (create_callback_pending_) { + PP_RunCompletionCallback(&create_callback_, PP_ERROR_ABORTED); + create_callback_pending_ = false; + } +} + +int32_t AudioHelper::GetSyncSocketImpl(int* sync_socket) { + if (socket_for_create_callback_.get()) { +#if defined(OS_POSIX) + *sync_socket = socket_for_create_callback_->handle(); +#elif defined(OS_WIN) + *sync_socket = reinterpret_cast<int>(socket_for_create_callback_->handle()); +#else + #error "Platform not supported." +#endif + return PP_OK; + } + return PP_ERROR_FAILED; +} + +int32_t AudioHelper::GetSharedMemoryImpl(int* shm_handle, uint32_t* shm_size) { + if (shared_memory_for_create_callback_.get()) { +#if defined(OS_POSIX) + *shm_handle = shared_memory_for_create_callback_->handle().fd; +#elif defined(OS_WIN) + *shm_handle = reinterpret_cast<int>( + shared_memory_for_create_callback_->handle()); +#else + #error "Platform not supported." +#endif + *shm_size = shared_memory_size_for_create_callback_; + return PP_OK; + } + return PP_ERROR_FAILED; +} + +void AudioHelper::StreamCreated( + base::SharedMemoryHandle shared_memory_handle, + size_t shared_memory_size, + base::SyncSocket::Handle socket_handle) { + if (create_callback_pending_) { + // Trusted side of proxy can specify a callback to recieve handles. In + // this case we don't need to map any data or start the thread since it + // will be handled by the proxy. + shared_memory_for_create_callback_.reset( + new base::SharedMemory(shared_memory_handle, false)); + shared_memory_size_for_create_callback_ = shared_memory_size; + socket_for_create_callback_.reset(new base::SyncSocket(socket_handle)); + + PP_RunCompletionCallback(&create_callback_, 0); + create_callback_pending_ = false; + + // It might be nice to close the handles here to free up some system + // resources, but we can't since there's a race condition. The handles must + // be valid until they're sent over IPC, which is done from the I/O thread + // which will often get done after this code executes. We could do + // something more elaborate like an ACK from the plugin or post a task to + // the I/O thread and back, but this extra complexity doesn't seem worth it + // just to clean up these handles faster. + } else { + OnSetStreamInfo(shared_memory_handle, shared_memory_size, socket_handle); + } +} + +void AudioHelper::SetCallbackInfo(bool create_callback_pending, + PP_CompletionCallback create_callback) { + create_callback_pending_ = create_callback_pending; + create_callback_ = create_callback; +} + +} // namespace ppapi +} // namespace webkit diff --git a/webkit/plugins/ppapi/audio_helper.h b/webkit/plugins/ppapi/audio_helper.h new file mode 100644 index 0000000..5d5df54 --- /dev/null +++ b/webkit/plugins/ppapi/audio_helper.h @@ -0,0 +1,67 @@ +// Copyright (c) 2011 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. + +#ifndef WEBKIT_PLUGINS_PPAPI_AUDIO_HELPER_H_ +#define WEBKIT_PLUGINS_PPAPI_AUDIO_HELPER_H_ + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "base/shared_memory.h" +#include "base/sync_socket.h" +#include "ppapi/c/pp_completion_callback.h" +#include "ppapi/shared_impl/resource.h" +#include "ppapi/shared_impl/scoped_pp_resource.h" +#include "webkit/plugins/ppapi/plugin_delegate.h" +#include "webkit/plugins/ppapi/ppapi_plugin_instance.h" + +namespace webkit { +namespace ppapi { + +class AudioHelper : public PluginDelegate::PlatformAudioCommonClient { + public: + AudioHelper(); + virtual ~AudioHelper(); + + // |PluginDelegate::PlatformAudioCommonClient| implementation. + virtual void StreamCreated(base::SharedMemoryHandle shared_memory_handle, + size_t shared_memory_size_, + base::SyncSocket::Handle socket) OVERRIDE; + + void SetCallbackInfo(bool create_callback_pending, + PP_CompletionCallback create_callback); + + protected: + // TODO(viettrungluu): This is all very poorly thought out. Refactor. + + // To be called by implementations of |PPB_Audio_API|/|PPB_AudioInput_API|. + int32_t GetSyncSocketImpl(int* sync_socket); + int32_t GetSharedMemoryImpl(int* shm_handle, uint32_t* shm_size); + + // To be implemented by subclasses to call their |SetStreamInfo()|. + virtual void OnSetStreamInfo(base::SharedMemoryHandle shared_memory_handle, + size_t shared_memory_size, + base::SyncSocket::Handle socket_handle) = 0; + + private: + // Is a create callback pending to fire? + bool create_callback_pending_; + + // Trusted callback invoked from StreamCreated. + PP_CompletionCallback create_callback_; + + // When a create callback is being issued, these will save the info for + // querying from the callback. The proxy uses this to get the handles to the + // other process instead of mapping them in the renderer. These will be + // invalid all other times. + scoped_ptr<base::SharedMemory> shared_memory_for_create_callback_; + size_t shared_memory_size_for_create_callback_; + scoped_ptr<base::SyncSocket> socket_for_create_callback_; + + DISALLOW_COPY_AND_ASSIGN(AudioHelper); +}; + +} // namespace ppapi +} // namespace webkit + +#endif // WEBKIT_PLUGINS_PPAPI_AUDIO_HELPER_H_ diff --git a/webkit/plugins/ppapi/mock_plugin_delegate.cc b/webkit/plugins/ppapi/mock_plugin_delegate.cc index 4a914bd..80594fc 100644 --- a/webkit/plugins/ppapi/mock_plugin_delegate.cc +++ b/webkit/plugins/ppapi/mock_plugin_delegate.cc @@ -71,7 +71,14 @@ MockPluginDelegate::CreateVideoCapture( MockPluginDelegate::PlatformAudio* MockPluginDelegate::CreateAudio( uint32_t sample_rate, uint32_t sample_count, - PlatformAudio::Client* client) { + PlatformAudioCommonClient* client) { + return NULL; +} + +MockPluginDelegate::PlatformAudioInput* MockPluginDelegate::CreateAudioInput( + uint32_t sample_rate, + uint32_t sample_count, + PlatformAudioCommonClient* client) { return NULL; } diff --git a/webkit/plugins/ppapi/mock_plugin_delegate.h b/webkit/plugins/ppapi/mock_plugin_delegate.h index 0988ebe..3670792 100644 --- a/webkit/plugins/ppapi/mock_plugin_delegate.h +++ b/webkit/plugins/ppapi/mock_plugin_delegate.h @@ -34,7 +34,11 @@ class MockPluginDelegate : public PluginDelegate { media::VideoCapture::EventHandler* handler); virtual PlatformAudio* CreateAudio(uint32_t sample_rate, uint32_t sample_count, - PlatformAudio::Client* client); + PlatformAudioCommonClient* client); + virtual PlatformAudioInput* CreateAudioInput( + uint32_t sample_rate, + uint32_t sample_count, + PlatformAudioCommonClient* client); virtual PpapiBroker* ConnectToPpapiBroker(PPB_Broker_Impl* client); virtual void NumberOfFindResultsChanged(int identifier, int total, diff --git a/webkit/plugins/ppapi/plugin_delegate.h b/webkit/plugins/ppapi/plugin_delegate.h index 6f76384..65506e7 100644 --- a/webkit/plugins/ppapi/plugin_delegate.h +++ b/webkit/plugins/ppapi/plugin_delegate.h @@ -180,19 +180,21 @@ class PluginDelegate { virtual bool Echo(const base::Callback<void()>& callback) = 0; }; - class PlatformAudio { - public: - class Client { - protected: - virtual ~Client() {} + // The (interface for the) client used by |PlatformAudio| and + // |PlatformAudioInput|. + class PlatformAudioCommonClient { + protected: + virtual ~PlatformAudioCommonClient() {} - public: - // Called when the stream is created. - virtual void StreamCreated(base::SharedMemoryHandle shared_memory_handle, - size_t shared_memory_size, - base::SyncSocket::Handle socket) = 0; - }; + public: + // Called when the stream is created. + virtual void StreamCreated(base::SharedMemoryHandle shared_memory_handle, + size_t shared_memory_size, + base::SyncSocket::Handle socket) = 0; + }; + class PlatformAudio { + public: // Starts the playback. Returns false on error or if called before the // stream is created or after the stream is closed. virtual bool StartPlayback() = 0; @@ -209,6 +211,24 @@ class PluginDelegate { virtual ~PlatformAudio() {} }; + class PlatformAudioInput { + public: + // Starts the playback. Returns false on error or if called before the + // stream is created or after the stream is closed. + virtual bool StartCapture() = 0; + + // Stops the capture. Returns false on error or if called before the stream + // is created or after the stream is closed. + virtual bool StopCapture() = 0; + + // Closes the stream. Make sure to call this before the object is + // destructed. + virtual void ShutDown() = 0; + + protected: + virtual ~PlatformAudioInput() {} + }; + // Interface for PlatformVideoDecoder is directly inherited from general media // VideoDecodeAccelerator interface. class PlatformVideoDecoder : public media::VideoDecodeAccelerator { @@ -285,7 +305,13 @@ class PluginDelegate { // to clean up the corresponding resources allocated during this call. virtual PlatformAudio* CreateAudio(uint32_t sample_rate, uint32_t sample_count, - PlatformAudio::Client* client) = 0; + PlatformAudioCommonClient* client) = 0; + + // The caller is responsible for calling Shutdown() on the returned pointer + // to clean up the corresponding resources allocated during this call. + virtual PlatformAudioInput* CreateAudioInput(uint32_t sample_rate, + uint32_t sample_count, + PlatformAudioCommonClient* client) = 0; // A pointer is returned immediately, but it is not ready to be used until // BrokerConnected has been called. diff --git a/webkit/plugins/ppapi/plugin_module.cc b/webkit/plugins/ppapi/plugin_module.cc index 2fedc53..01cbee3 100644 --- a/webkit/plugins/ppapi/plugin_module.cc +++ b/webkit/plugins/ppapi/plugin_module.cc @@ -13,6 +13,7 @@ #include "base/message_loop.h" #include "base/message_loop_proxy.h" #include "base/time.h" +#include "ppapi/c/dev/ppb_audio_input_dev.h" #include "ppapi/c/dev/ppb_buffer_dev.h" #include "ppapi/c/dev/ppb_char_set_dev.h" #include "ppapi/c/dev/ppb_console_dev.h" @@ -75,6 +76,7 @@ #include "ppapi/c/private/ppb_tcp_socket_private.h" #include "ppapi/c/private/ppb_udp_socket_private.h" #include "ppapi/c/private/ppb_uma_private.h" +#include "ppapi/c/trusted/ppb_audio_input_trusted_dev.h" #include "ppapi/c/trusted/ppb_audio_trusted.h" #include "ppapi/c/trusted/ppb_broker_trusted.h" #include "ppapi/c/trusted/ppb_buffer_trusted.h" @@ -259,6 +261,8 @@ const void* GetInterface(const char* name) { // Please keep alphabetized by interface macro name with "special" stuff at // the bottom. + if (strcmp(name, PPB_AUDIO_INPUT_TRUSTED_DEV_INTERFACE) == 0) + return ::ppapi::thunk::GetPPB_AudioInputTrusted_Thunk(); if (strcmp(name, PPB_AUDIO_TRUSTED_INTERFACE) == 0) return ::ppapi::thunk::GetPPB_AudioTrusted_Thunk(); if (strcmp(name, PPB_BUFFER_TRUSTED_INTERFACE) == 0) diff --git a/webkit/plugins/ppapi/ppb_audio_impl.cc b/webkit/plugins/ppapi/ppb_audio_impl.cc index 6cc1cd0..c92c9b1 100644 --- a/webkit/plugins/ppapi/ppb_audio_impl.cc +++ b/webkit/plugins/ppapi/ppb_audio_impl.cc @@ -28,10 +28,7 @@ namespace ppapi { PPB_Audio_Impl::PPB_Audio_Impl(PP_Instance instance) : Resource(instance), - audio_(NULL), - create_callback_pending_(false), - shared_memory_size_for_create_callback_(0) { - create_callback_ = PP_MakeCompletionCallback(NULL, NULL); + audio_(NULL) { } PPB_Audio_Impl::~PPB_Audio_Impl() { @@ -44,13 +41,6 @@ PPB_Audio_Impl::~PPB_Audio_Impl() { audio_->ShutDown(); audio_ = NULL; } - - // If the completion callback hasn't fired yet, do so here - // with an error condition. - if (create_callback_pending_) { - PP_RunCompletionCallback(&create_callback_, PP_ERROR_ABORTED); - create_callback_pending_ = false; - } } // static @@ -141,67 +131,25 @@ int32_t PPB_Audio_Impl::OpenTrusted(PP_Resource config, // At this point, we are guaranteeing ownership of the completion // callback. Audio promises to fire the completion callback // once and only once. - create_callback_ = create_callback; - create_callback_pending_ = true; + SetCallbackInfo(true, create_callback); + return PP_OK_COMPLETIONPENDING; } int32_t PPB_Audio_Impl::GetSyncSocket(int* sync_socket) { - if (socket_for_create_callback_.get()) { -#if defined(OS_POSIX) - *sync_socket = socket_for_create_callback_->handle(); -#elif defined(OS_WIN) - *sync_socket = reinterpret_cast<int>(socket_for_create_callback_->handle()); -#else - #error "Platform not supported." -#endif - return PP_OK; - } - return PP_ERROR_FAILED; + return GetSyncSocketImpl(sync_socket); } -int32_t PPB_Audio_Impl::GetSharedMemory(int* shm_handle, uint32_t* shm_size) { - if (shared_memory_for_create_callback_.get()) { -#if defined(OS_POSIX) - *shm_handle = shared_memory_for_create_callback_->handle().fd; -#elif defined(OS_WIN) - *shm_handle = reinterpret_cast<int>( - shared_memory_for_create_callback_->handle()); -#else - #error "Platform not supported." -#endif - *shm_size = shared_memory_size_for_create_callback_; - return PP_OK; - } - return PP_ERROR_FAILED; +int32_t PPB_Audio_Impl::GetSharedMemory(int* shm_handle, + uint32_t* shm_size) { + return GetSharedMemoryImpl(shm_handle, shm_size); } -void PPB_Audio_Impl::StreamCreated( +void PPB_Audio_Impl::OnSetStreamInfo( base::SharedMemoryHandle shared_memory_handle, size_t shared_memory_size, base::SyncSocket::Handle socket_handle) { - if (create_callback_pending_) { - // Trusted side of proxy can specify a callback to recieve handles. In - // this case we don't need to map any data or start the thread since it - // will be handled by the proxy. - shared_memory_for_create_callback_.reset( - new base::SharedMemory(shared_memory_handle, false)); - shared_memory_size_for_create_callback_ = shared_memory_size; - socket_for_create_callback_.reset(new base::SyncSocket(socket_handle)); - - PP_RunCompletionCallback(&create_callback_, 0); - create_callback_pending_ = false; - - // It might be nice to close the handles here to free up some system - // resources, but we can't since there's a race condition. The handles must - // be valid until they're sent over IPC, which is done from the I/O thread - // which will often get done after this code executes. We could do - // something more elaborate like an ACK from the plugin or post a task to - // the I/O thread and back, but this extra complexity doesn't seem worth it - // just to clean up these handles faster. - } else { - SetStreamInfo(shared_memory_handle, shared_memory_size, socket_handle); - } + SetStreamInfo(shared_memory_handle, shared_memory_size, socket_handle); } } // namespace ppapi diff --git a/webkit/plugins/ppapi/ppb_audio_impl.h b/webkit/plugins/ppapi/ppb_audio_impl.h index 3be3f8a..aa8e7f7 100644 --- a/webkit/plugins/ppapi/ppb_audio_impl.h +++ b/webkit/plugins/ppapi/ppb_audio_impl.h @@ -17,6 +17,7 @@ #include "ppapi/shared_impl/audio_impl.h" #include "ppapi/shared_impl/scoped_pp_resource.h" #include "ppapi/shared_impl/resource.h" +#include "webkit/plugins/ppapi/audio_helper.h" #include "webkit/plugins/ppapi/plugin_delegate.h" #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" @@ -27,7 +28,7 @@ namespace ppapi { // AudioImpl so it can be shared with the proxy. class PPB_Audio_Impl : public ::ppapi::Resource, public ::ppapi::AudioImpl, - public PluginDelegate::PlatformAudio::Client { + public AudioHelper { public: // Trusted initialization. You must call Init after this. // @@ -61,10 +62,10 @@ class PPB_Audio_Impl : public ::ppapi::Resource, virtual int32_t GetSharedMemory(int* shm_handle, uint32_t* shm_size) OVERRIDE; private: - // PluginDelegate::PlatformAudio::Client implementation. - virtual void StreamCreated(base::SharedMemoryHandle shared_memory_handle, - size_t shared_memory_size_, - base::SyncSocket::Handle socket); + // AudioHelper implementation. + virtual void OnSetStreamInfo(base::SharedMemoryHandle shared_memory_handle, + size_t shared_memory_size_, + base::SyncSocket::Handle socket); // AudioConfig used for creating this Audio object. We own a ref. ::ppapi::ScopedPPResource config_; @@ -73,20 +74,6 @@ class PPB_Audio_Impl : public ::ppapi::Resource, // own this pointer but are responsible for calling Shutdown on it. PluginDelegate::PlatformAudio* audio_; - // Is a create callback pending to fire? - bool create_callback_pending_; - - // Trusted callback invoked from StreamCreated. - PP_CompletionCallback create_callback_; - - // When a create callback is being issued, these will save the info for - // querying from the callback. The proxy uses this to get the handles to the - // other process instead of mapping them in the renderer. These will be - // invalid all other times. - scoped_ptr<base::SharedMemory> shared_memory_for_create_callback_; - size_t shared_memory_size_for_create_callback_; - scoped_ptr<base::SyncSocket> socket_for_create_callback_; - DISALLOW_COPY_AND_ASSIGN(PPB_Audio_Impl); }; diff --git a/webkit/plugins/ppapi/ppb_audio_input_impl.cc b/webkit/plugins/ppapi/ppb_audio_input_impl.cc new file mode 100644 index 0000000..590dd81 --- /dev/null +++ b/webkit/plugins/ppapi/ppb_audio_input_impl.cc @@ -0,0 +1,160 @@ +// Copyright (c) 2011 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 "webkit/plugins/ppapi/ppb_audio_input_impl.h" + +#include "base/logging.h" +#include "ppapi/c/dev/ppb_audio_input_dev.h" +#include "ppapi/c/pp_completion_callback.h" +#include "ppapi/c/ppb_audio_config.h" +#include "ppapi/c/trusted/ppb_audio_input_trusted_dev.h" +#include "ppapi/shared_impl/resource_tracker.h" +#include "ppapi/thunk/enter.h" +#include "ppapi/thunk/ppb_audio_config_api.h" +#include "ppapi/thunk/thunk.h" +#include "webkit/plugins/ppapi/common.h" +#include "webkit/plugins/ppapi/resource_helper.h" + +using ppapi::PpapiGlobals; +using ppapi::thunk::EnterResourceNoLock; +using ppapi::thunk::PPB_AudioInput_API; +using ppapi::thunk::PPB_AudioConfig_API; + +namespace webkit { +namespace ppapi { + +// PPB_AudioInput_Impl --------------------------------------------------------- + +PPB_AudioInput_Impl::PPB_AudioInput_Impl(PP_Instance instance) + : Resource(instance), + audio_input_(NULL) { +} + +PPB_AudioInput_Impl::~PPB_AudioInput_Impl() { + // Calling ShutDown() makes sure StreamCreated cannot be called anymore and + // releases the audio data associated with the pointer. Note however, that + // until ShutDown returns, StreamCreated may still be called. This will be + // OK since we'll just immediately clean up the data it stored later in this + // destructor. + if (audio_input_) { + audio_input_->ShutDown(); + audio_input_ = NULL; + } +} + +// static +PP_Resource PPB_AudioInput_Impl::Create(PP_Instance instance, + PP_Resource config, + PPB_AudioInput_Callback audio_input_callback, + void* user_data) { + scoped_refptr<PPB_AudioInput_Impl> + audio_input(new PPB_AudioInput_Impl(instance)); + if (!audio_input->Init(config, audio_input_callback, user_data)) + return 0; + return audio_input->GetReference(); +} + +PPB_AudioInput_API* PPB_AudioInput_Impl::AsPPB_AudioInput_API() { + return this; +} + +bool PPB_AudioInput_Impl::Init(PP_Resource config, + PPB_AudioInput_Callback callback, + void* user_data) { + // Validate the config and keep a reference to it. + EnterResourceNoLock<PPB_AudioConfig_API> enter(config, true); + if (enter.failed()) + return false; + config_ = config; + + if (!callback) + return false; + SetCallback(callback, user_data); + + PluginDelegate* plugin_delegate = ResourceHelper::GetPluginDelegate(this); + if (!plugin_delegate) + return false; + + // When the stream is created, we'll get called back on StreamCreated(). + CHECK(!audio_input_); + audio_input_ = plugin_delegate->CreateAudioInput( + enter.object()->GetSampleRate(), + enter.object()->GetSampleFrameCount(), + this); + return audio_input_ != NULL; +} + +PP_Resource PPB_AudioInput_Impl::GetCurrentConfig() { + // AddRef on behalf of caller, while keeping a ref for ourselves. + PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(config_); + return config_; +} + +PP_Bool PPB_AudioInput_Impl::StartCapture() { + if (!audio_input_) + return PP_FALSE; + if (capturing()) + return PP_TRUE; + SetStartCaptureState(); + return BoolToPPBool(audio_input_->StartCapture()); +} + +PP_Bool PPB_AudioInput_Impl::StopCapture() { + if (!audio_input_) + return PP_FALSE; + if (!capturing()) + return PP_TRUE; + if (!audio_input_->StopCapture()) + return PP_FALSE; + SetStopCaptureState(); + return PP_TRUE; +} + +int32_t PPB_AudioInput_Impl::OpenTrusted(PP_Resource config, + PP_CompletionCallback create_callback) { + // Validate the config and keep a reference to it. + EnterResourceNoLock<PPB_AudioConfig_API> enter(config, true); + if (enter.failed()) + return PP_ERROR_FAILED; + config_ = config; + + PluginDelegate* plugin_delegate = ResourceHelper::GetPluginDelegate(this); + if (!plugin_delegate) + return PP_ERROR_FAILED; + + // When the stream is created, we'll get called back on StreamCreated(). + DCHECK(!audio_input_); + audio_input_ = plugin_delegate->CreateAudioInput( + enter.object()->GetSampleRate(), + enter.object()->GetSampleFrameCount(), + this); + + if (!audio_input_) + return PP_ERROR_FAILED; + + // At this point, we are guaranteeing ownership of the completion + // callback. Audio promises to fire the completion callback + // once and only once. + SetCallbackInfo(true, create_callback); + return PP_OK_COMPLETIONPENDING; +} + +int32_t PPB_AudioInput_Impl::GetSyncSocket(int* sync_socket) { + return GetSyncSocketImpl(sync_socket); +} + +int32_t PPB_AudioInput_Impl::GetSharedMemory(int* shm_handle, + uint32_t* shm_size) { + return GetSharedMemoryImpl(shm_handle, shm_size); +} + +void PPB_AudioInput_Impl::OnSetStreamInfo( + base::SharedMemoryHandle shared_memory_handle, + size_t shared_memory_size, + base::SyncSocket::Handle socket_handle) { + SetStreamInfo(shared_memory_handle, shared_memory_size, socket_handle); +} + +} // namespace ppapi +} // namespace webkit diff --git a/webkit/plugins/ppapi/ppb_audio_input_impl.h b/webkit/plugins/ppapi/ppb_audio_input_impl.h new file mode 100644 index 0000000..9fdf0cd --- /dev/null +++ b/webkit/plugins/ppapi/ppb_audio_input_impl.h @@ -0,0 +1,83 @@ +// Copyright (c) 2011 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. + +#ifndef WEBKIT_PLUGINS_PPAPI_PPB_AUDIO_INPUT_IMPL_H_ +#define WEBKIT_PLUGINS_PPAPI_PPB_AUDIO_INPUT_IMPL_H_ + +#include "base/basictypes.h" +#include "base/memory/ref_counted.h" +#include "base/shared_memory.h" +#include "base/sync_socket.h" +#include "ppapi/c/dev/ppb_audio_input_dev.h" +#include "ppapi/c/pp_completion_callback.h" +#include "ppapi/c/trusted/ppb_audio_input_trusted_dev.h" +#include "ppapi/shared_impl/audio_config_impl.h" +#include "ppapi/shared_impl/audio_input_impl.h" +#include "ppapi/shared_impl/resource.h" +#include "ppapi/shared_impl/scoped_pp_resource.h" +#include "webkit/plugins/ppapi/audio_helper.h" +#include "webkit/plugins/ppapi/plugin_delegate.h" +#include "webkit/plugins/ppapi/ppapi_plugin_instance.h" + +namespace webkit { +namespace ppapi { + +// Some of the backend functionality of this class is implemented by the +// AudioInputImpl so it can be shared with the proxy. +class PPB_AudioInput_Impl : public ::ppapi::Resource, + public ::ppapi::AudioInputImpl, + public AudioHelper { + public: + // Trusted initialization. You must call Init after this. + // + // Untrusted initialization should just call the static Create() function + // to properly create & initialize this class. + explicit PPB_AudioInput_Impl(PP_Instance instance); + + virtual ~PPB_AudioInput_Impl(); + + // Creation function for untrusted plugins. This handles all initialization + // and will return 0 on failure. + static PP_Resource Create(PP_Instance instance, + PP_Resource config_id, + PPB_AudioInput_Callback audio_input_callback, + void* user_data); + + // Initialization function for non-trusted init. + bool Init(PP_Resource config_id, + PPB_AudioInput_Callback callback, void* user_data); + + // Resource overrides. + virtual ::ppapi::thunk::PPB_AudioInput_API* AsPPB_AudioInput_API() OVERRIDE; + + // PPB_AudioInput_API implementation. + virtual PP_Resource GetCurrentConfig() OVERRIDE; + virtual PP_Bool StartCapture() OVERRIDE; + virtual PP_Bool StopCapture() OVERRIDE; + + virtual int32_t OpenTrusted(PP_Resource config_id, + PP_CompletionCallback create_callback) OVERRIDE; + virtual int32_t GetSyncSocket(int* sync_socket) OVERRIDE; + virtual int32_t GetSharedMemory(int* shm_handle, uint32_t* shm_size) OVERRIDE; + + private: + // AudioHelper implementation. + virtual void OnSetStreamInfo(base::SharedMemoryHandle shared_memory_handle, + size_t shared_memory_size_, + base::SyncSocket::Handle socket) OVERRIDE; + + // AudioConfig used for creating this AudioInput object. We own a ref. + ::ppapi::ScopedPPResource config_; + + // PluginDelegate audio input object that we delegate audio IPC through. + // We don't own this pointer but are responsible for calling Shutdown on it. + PluginDelegate::PlatformAudioInput* audio_input_; + + DISALLOW_COPY_AND_ASSIGN(PPB_AudioInput_Impl); +}; + +} // namespace ppapi +} // namespace webkit + +#endif // WEBKIT_PLUGINS_PPAPI_PPB_AUDIO_INPUT_IMPL_H_ diff --git a/webkit/plugins/ppapi/resource_creation_impl.cc b/webkit/plugins/ppapi/resource_creation_impl.cc index bf74fc9..2a79845 100644 --- a/webkit/plugins/ppapi/resource_creation_impl.cc +++ b/webkit/plugins/ppapi/resource_creation_impl.cc @@ -10,6 +10,7 @@ #include "ppapi/shared_impl/var.h" #include "webkit/plugins/ppapi/common.h" #include "webkit/plugins/ppapi/ppb_audio_impl.h" +#include "webkit/plugins/ppapi/ppb_audio_input_impl.h" #include "webkit/plugins/ppapi/ppb_broker_impl.h" #include "webkit/plugins/ppapi/ppb_buffer_impl.h" #include "webkit/plugins/ppapi/ppb_context_3d_impl.h" @@ -73,6 +74,20 @@ PP_Resource ResourceCreationImpl::CreateAudioTrusted( return (new PPB_Audio_Impl(instance))->GetReference(); } +PP_Resource ResourceCreationImpl::CreateAudioInput( + PP_Instance instance, + PP_Resource config_id, + PPB_AudioInput_Callback audio_input_callback, + void* user_data) { + return PPB_AudioInput_Impl::Create(instance, config_id, + audio_input_callback, user_data); +} + +PP_Resource ResourceCreationImpl::CreateAudioInputTrusted( + PP_Instance instance) { + return (new PPB_AudioInput_Impl(instance))->GetReference(); +} + PP_Resource ResourceCreationImpl::CreateBroker(PP_Instance instance) { return (new PPB_Broker_Impl(instance))->GetReference(); } diff --git a/webkit/plugins/ppapi/resource_creation_impl.h b/webkit/plugins/ppapi/resource_creation_impl.h index a769a8e..a7a1e44 100644 --- a/webkit/plugins/ppapi/resource_creation_impl.h +++ b/webkit/plugins/ppapi/resource_creation_impl.h @@ -29,10 +29,16 @@ class ResourceCreationImpl : public ::ppapi::FunctionGroupBase, PP_Resource config_id, PPB_Audio_Callback audio_callback, void* user_data) OVERRIDE; - virtual PP_Resource CreateAudioTrusted(PP_Instance instace) OVERRIDE; + virtual PP_Resource CreateAudioTrusted(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateAudioConfig(PP_Instance instance, PP_AudioSampleRate sample_rate, uint32_t sample_frame_count) OVERRIDE; + virtual PP_Resource CreateAudioInput( + PP_Instance instance, + PP_Resource config_id, + PPB_AudioInput_Callback audio_input_callback, + void* user_data) OVERRIDE; + virtual PP_Resource CreateAudioInputTrusted(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateBroker(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateBuffer(PP_Instance instance, uint32_t size) OVERRIDE; |