diff options
author | viettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-18 00:14:24 +0000 |
---|---|---|
committer | viettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-18 00:14:24 +0000 |
commit | 1f8a089555312f281aa4074141e0945096d2a621 (patch) | |
tree | 32ace48d91e7eb290bd2b8df39e7fbc17282fcdf /ppapi/proxy | |
parent | fc2436bac6a8e5f6839f6e62e8680a15e7d592eb (diff) | |
download | chromium_src-1f8a089555312f281aa4074141e0945096d2a621.zip chromium_src-1f8a089555312f281aa4074141e0945096d2a621.tar.gz chromium_src-1f8a089555312f281aa4074141e0945096d2a621.tar.bz2 |
Revert 110602 - Revert 110587 - Microphone support for Pepper Flash.
[I think the Windows shared builders just need to be clobbered.]
[Committing for pbrophy@adobe.com. Original review:
http://codereview.chromium.org/8138008/ .]
This change supports audio capture from the microphone and supplies the data
through a Pepper interface. Its enumeration is limited to the default audio
device that uses mono 44.1kHz.
TBR=tony@chromium.org
Review URL: http://codereview.chromium.org/8574029
TBR=viettrungluu@chromium.org
Review URL: http://codereview.chromium.org/8569003
TBR=ajwong@chromium.org
Review URL: http://codereview.chromium.org/8561003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@110609 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/proxy')
-rw-r--r-- | ppapi/proxy/interface_list.cc | 2 | ||||
-rw-r--r-- | ppapi/proxy/ppapi_messages.h | 18 | ||||
-rw-r--r-- | ppapi/proxy/ppb_audio_input_proxy.cc | 334 | ||||
-rw-r--r-- | ppapi/proxy/ppb_audio_input_proxy.h | 86 | ||||
-rw-r--r-- | ppapi/proxy/resource_creation_proxy.cc | 17 | ||||
-rw-r--r-- | ppapi/proxy/resource_creation_proxy.h | 8 |
6 files changed, 465 insertions, 0 deletions
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, |