diff options
author | neb@chromium.org <neb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-30 21:24:39 +0000 |
---|---|---|
committer | neb@chromium.org <neb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-30 21:24:39 +0000 |
commit | 937df951109b543a70e5474ee12f20df7b52a8d5 (patch) | |
tree | 7689840b4951acd56c068b48c75fa8fb797525c3 /webkit | |
parent | a6550f16d87527b7963e7e827c64b64bddeaaef2 (diff) | |
download | chromium_src-937df951109b543a70e5474ee12f20df7b52a8d5.zip chromium_src-937df951109b543a70e5474ee12f20df7b52a8d5.tar.gz chromium_src-937df951109b543a70e5474ee12f20df7b52a8d5.tar.bz2 |
Pepper2 audio (trusted side) implementation. Still missing a synchronization for the callback setting, will be done soon.
BUG=none
TEST=test plugin plays music
Review URL: http://codereview.chromium.org/2962003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@54383 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r-- | webkit/glue/plugins/pepper_audio.cc | 191 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_audio.h | 116 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_plugin_delegate.h | 36 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_plugin_module.cc | 7 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_resource.h | 6 | ||||
-rw-r--r-- | webkit/glue/webkit_glue.gypi | 2 |
6 files changed, 358 insertions, 0 deletions
diff --git a/webkit/glue/plugins/pepper_audio.cc b/webkit/glue/plugins/pepper_audio.cc new file mode 100644 index 0000000..2fa13b7 --- /dev/null +++ b/webkit/glue/plugins/pepper_audio.cc @@ -0,0 +1,191 @@ +// Copyright (c) 2010 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/glue/plugins/pepper_audio.h" + +#include "base/logging.h" +#include "third_party/ppapi/c/ppb_audio.h" +#include "third_party/ppapi/c/ppb_audio_trusted.h" + + +namespace pepper { + +namespace { + +// PPB_AudioConfig functions + +PP_Resource CreateStereo16bit(PP_Module module_id, uint32_t sample_rate, + uint32_t sample_frame_count) { + PluginModule* module = PluginModule::FromPPModule(module_id); + if (!module) + return 0; + + scoped_refptr<AudioConfig> config(new AudioConfig(module, sample_rate, + sample_frame_count)); + return config->GetReference(); +} + +uint32_t GetSampleRate(PP_Resource config_id) { + scoped_refptr<AudioConfig> config = Resource::GetAs<AudioConfig>(config_id); + return config ? config->sample_rate() : 0; +} + +uint32_t GetSampleFrameCount(PP_Resource config_id) { + scoped_refptr<AudioConfig> config = Resource::GetAs<AudioConfig>(config_id); + return config ? config->sample_frame_count() : 0; +} + +// PPB_Audio functions + +PP_Resource Create(PP_Instance instance_id, PP_Resource config_id, + PPB_Audio_Callback callback, void* user_data) { + PluginInstance* instance = PluginInstance::FromPPInstance(instance_id); + if (!instance) + return 0; + // TODO(neb): Require callback to be present for untrusted plugins. + scoped_refptr<Audio> audio(new Audio(instance->module())); + if (!audio->Init(instance->delegate(), config_id, callback, user_data)) + return 0; + return audio->GetReference(); +} + +PP_Resource GetCurrentConfiguration(PP_Resource audio_id) { + scoped_refptr<Audio> audio = Resource::GetAs<Audio>(audio_id); + return audio ? audio->GetCurrentConfiguration() : 0; +} + +bool StartPlayback(PP_Resource audio_id) { + scoped_refptr<Audio> audio = Resource::GetAs<Audio>(audio_id); + return audio ? audio->StartPlayback() : false; +} + +bool StopPlayback(PP_Resource audio_id) { + scoped_refptr<Audio> audio = Resource::GetAs<Audio>(audio_id); + return audio ? audio->StopPlayback() : false; +} + +// PPB_AudioTrusted functions + +PP_Resource GetBuffer(PP_Resource audio_id) { + // TODO(neb): Implement me! + return 0; +} + +int GetOSDescriptor(PP_Resource audio_id) { + // TODO(neb): Implement me! + return -1; +} + +const PPB_AudioConfig ppb_audioconfig = { + &CreateStereo16bit, + &GetSampleRate, + &GetSampleFrameCount +}; + +const PPB_Audio ppb_audio = { + &Create, + &GetCurrentConfiguration, + &StartPlayback, + &StopPlayback, +}; + +const PPB_AudioTrusted ppb_audiotrusted = { + &GetBuffer, + &GetOSDescriptor +}; + +} // namespace + +AudioConfig::AudioConfig(PluginModule* module, int32_t sample_rate, + int32_t sample_frame_count) + : Resource(module), + sample_rate_(sample_rate), + sample_frame_count_(sample_frame_count) { +} + +const PPB_AudioConfig* AudioConfig::GetInterface() { + return &ppb_audioconfig; +} + +AudioConfig* AudioConfig::AsAudioConfig() { + return this; +} + +Audio::Audio(PluginModule* module) + : Resource(module), + socket_(NULL), + shared_memory_(NULL), + shared_memory_size_(0), + callback_(NULL), + user_data_(NULL) { +} + +Audio::~Audio() { + // Calling ShutDown() makes sure StreamCreated cannot be called anymore. + audio_->ShutDown(); + // Closing the socket causes the thread to exit - wait for it. + socket_->Close(); + if (audio_thread_.get()) { + audio_thread_->Join(); + audio_thread_.reset(); + } + // Shared memory destructor will unmap the memory automatically. +} + + +const PPB_Audio* Audio::GetInterface() { + return &ppb_audio; +} + +const PPB_AudioTrusted* Audio::GetTrustedInterface() { + return &ppb_audiotrusted; +} + +Audio* Audio::AsAudio() { + return this; +} + +bool Audio::Init(PluginDelegate* plugin_delegate, PP_Resource config_id, + PPB_Audio_Callback callback, void* user_data) { + CHECK(!audio_.get()); + config_ = Resource::GetAs<AudioConfig>(config_id); + if (!config_) + return false; + callback_ = callback; + user_data_ = user_data; + // When the stream is created, we'll get called back in StreamCreated(). + audio_.reset(plugin_delegate->CreateAudio(config_->sample_rate(), + config_->sample_frame_count(), + this)); + return audio_.get() != NULL; +} + +void Audio::StreamCreated(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_); + audio_thread_.reset(new base::DelegateSimpleThread(this, + "plugin_audio_thread")); + audio_thread_->Start(); + } +} + +void Audio::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, user_data_); + } +} + +} // namespace pepper + diff --git a/webkit/glue/plugins/pepper_audio.h b/webkit/glue/plugins/pepper_audio.h new file mode 100644 index 0000000..2164f00 --- /dev/null +++ b/webkit/glue/plugins/pepper_audio.h @@ -0,0 +1,116 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/ref_counted.h" +#include "base/scoped_ptr.h" +#include "base/shared_memory.h" +#include "base/simple_thread.h" +#include "base/sync_socket.h" +#include "third_party/ppapi/c/ppb_audio.h" +#include "third_party/ppapi/c/ppb_audio_config.h" +#include "third_party/ppapi/c/ppb_audio_trusted.h" +#include "webkit/glue/plugins/pepper_plugin_delegate.h" +#include "webkit/glue/plugins/pepper_plugin_instance.h" +#include "webkit/glue/plugins/pepper_plugin_module.h" +#include "webkit/glue/plugins/pepper_resource.h" + +#ifndef WEBKIT_GLUE_PLUGINS_PEPPER_DEVICE_CONTEXT_AUDIO_H_ +#define WEBKIT_GLUE_PLUGINS_PEPPER_DEVICE_CONTEXT_AUDIO_H_ + +namespace pepper { + +class PluginInstance; +class PluginModule; + +class AudioConfig : public Resource { + public: + AudioConfig(PluginModule* module, int32_t sample_rate, + int32_t sample_frame_count); + + static const PPB_AudioConfig* GetInterface(); + + uint32_t sample_rate() { return sample_rate_; } + uint32_t sample_frame_count() { return sample_frame_count_; } + + private: + // Resource override. + virtual AudioConfig* AsAudioConfig(); + + int sample_rate_; + int sample_frame_count_; +}; + +class Audio : public Resource, + public PluginDelegate::PlatformAudio::Client, + public base::DelegateSimpleThread::Delegate { + public: + explicit Audio(PluginModule* module); + virtual ~Audio(); + + static const PPB_Audio* GetInterface(); + static const PPB_AudioTrusted* GetTrustedInterface(); + + bool Init(PluginDelegate* plugin_delegate, PP_Resource config_id, + PPB_Audio_Callback callback, void* user_data); + + PP_Resource GetCurrentConfiguration() { + return config_->GetReference(); + } + + bool StartPlayback() { + // TODO(neb): Make this synchronous. + return audio_->StartPlayback(); + } + + bool StopPlayback() { + // TODO(neb): Make this synchronous. + return audio_->StopPlayback(); + } + + // Resource override. + virtual Audio* AsAudio(); + + private: + // pepper::PluginDelegate::PlatformAudio::Client implementation. + virtual void StreamCreated(base::SharedMemoryHandle shared_memory_handle, + size_t shared_memory_size_, + base::SyncSocket::Handle socket); + // End of pepper::PluginDelegate::PlatformAudio::Client implementation. + + // Audio thread. DelegateSimpleThread::Delegate implementation. + virtual void Run(); + // End of DelegateSimpleThread::Delegate implementation. + + // AudioConfig used for creating this Audio object. + scoped_refptr<AudioConfig> config_; + + // PluginDelegate audio object that we delegate audio IPC through. + scoped_ptr<PluginDelegate::PlatformAudio> audio_; + + // 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_thread_; + + // Callback to call when audio is ready to accept new samples. + volatile PPB_Audio_Callback callback_; + + // User data pointer passed verbatim to the callback function. + void* user_data_; +}; + +} // namespace pepper + +#endif // WEBKIT_GLUE_PLUGINS_PEPPER_DEVICE_CONTEXT_AUDIO_H_ + diff --git a/webkit/glue/plugins/pepper_plugin_delegate.h b/webkit/glue/plugins/pepper_plugin_delegate.h index ffc9d52..18cc312 100644 --- a/webkit/glue/plugins/pepper_plugin_delegate.h +++ b/webkit/glue/plugins/pepper_plugin_delegate.h @@ -5,8 +5,12 @@ #ifndef WEBKIT_GLUE_PLUGINS_PEPPER_PLUGIN_DELEGATE_H_ #define WEBKIT_GLUE_PLUGINS_PEPPER_PLUGIN_DELEGATE_H_ +#include "base/shared_memory.h" +#include "base/sync_socket.h" #include "third_party/ppapi/c/pp_stdint.h" +class AudioMessageFilter; + namespace skia { class PlatformCanvas; } @@ -34,6 +38,33 @@ class PluginDelegate { virtual intptr_t GetSharedMemoryHandle() const = 0; }; + class PlatformAudio { + public: + class Client { + public: + virtual ~Client() {} + + // Called when the stream is created. + virtual void StreamCreated(base::SharedMemoryHandle shared_memory_handle, + size_t shared_memory_size, + base::SyncSocket::Handle socket) = 0; + }; + + virtual ~PlatformAudio() {} + + // 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; + + // Stops the playback. Returns false on error or if called before the stream + // is created or after the stream is closed. + virtual bool StopPlayback() = 0; + + // Closes the stream. Make sure to call this before the object is + // destructed. + virtual void ShutDown() = 0; + }; + // Indicates that the given instance has been created. virtual void InstanceCreated(pepper::PluginInstance* instance) = 0; @@ -52,6 +83,11 @@ class PluginDelegate { // Notifies that the index of the currently selected item has been updated. virtual void DidChangeSelectedFindResult(int identifier, int index) = 0; + + // The caller will own the pointer returned from this. + virtual PlatformAudio* CreateAudio(uint32_t sample_rate, + uint32_t sample_count, + PlatformAudio::Client* client) = 0; }; } // namespace pepper diff --git a/webkit/glue/plugins/pepper_plugin_module.cc b/webkit/glue/plugins/pepper_plugin_module.cc index 8ffd78b..c515cd4 100644 --- a/webkit/glue/plugins/pepper_plugin_module.cc +++ b/webkit/glue/plugins/pepper_plugin_module.cc @@ -34,6 +34,7 @@ #include "third_party/ppapi/c/pp_module.h" #include "third_party/ppapi/c/pp_resource.h" #include "third_party/ppapi/c/pp_var.h" +#include "webkit/glue/plugins/pepper_audio.h" #include "webkit/glue/plugins/pepper_buffer.h" #include "webkit/glue/plugins/pepper_device_context_2d.h" #include "webkit/glue/plugins/pepper_directory_reader.h" @@ -156,6 +157,12 @@ const void* GetInterface(const char* name) { return PluginInstance::GetInterface(); if (strcmp(name, PPB_IMAGEDATA_INTERFACE) == 0) return ImageData::GetInterface(); + if (strcmp(name, PPB_AUDIO_CONFIG_INTERFACE) == 0) + return AudioConfig::GetInterface(); + if (strcmp(name, PPB_AUDIO_INTERFACE) == 0) + return Audio::GetInterface(); + if (strcmp(name, PPB_AUDIO_TRUSTED_INTERFACE) == 0) + return Audio::GetTrustedInterface(); if (strcmp(name, PPB_DEVICECONTEXT2D_INTERFACE) == 0) return DeviceContext2D::GetInterface(); if (strcmp(name, PPB_URLLOADER_INTERFACE) == 0) diff --git a/webkit/glue/plugins/pepper_resource.h b/webkit/glue/plugins/pepper_resource.h index 1acaddcb..ac90f9b 100644 --- a/webkit/glue/plugins/pepper_resource.h +++ b/webkit/glue/plugins/pepper_resource.h @@ -14,6 +14,8 @@ namespace pepper { class Buffer; +class Audio; +class AudioConfig; class DeviceContext2D; class DirectoryReader; class FileChooser; @@ -73,6 +75,8 @@ class Resource : public base::RefCountedThreadSafe<Resource> { // Type-specific getters for individual resource types. These will return // NULL if the resource does not match the specified type. Used by the Cast() // function. + virtual Audio* AsAudio() { return NULL; } + virtual AudioConfig* AsAudioConfig() { return NULL; } virtual Buffer* AsBuffer() { return NULL; } virtual DeviceContext2D* AsDeviceContext2D() { return NULL; } virtual DirectoryReader* AsDirectoryReader() { return NULL; } @@ -117,6 +121,8 @@ class Resource : public base::RefCountedThreadSafe<Resource> { return As##Type(); \ } +DEFINE_RESOURCE_CAST(Audio) +DEFINE_RESOURCE_CAST(AudioConfig) DEFINE_RESOURCE_CAST(Buffer) DEFINE_RESOURCE_CAST(DeviceContext2D) DEFINE_RESOURCE_CAST(DirectoryReader) diff --git a/webkit/glue/webkit_glue.gypi b/webkit/glue/webkit_glue.gypi index 49320fc..f63802d 100644 --- a/webkit/glue/webkit_glue.gypi +++ b/webkit/glue/webkit_glue.gypi @@ -164,6 +164,8 @@ 'plugins/gtk_plugin_container_manager.cc', 'plugins/npapi_extension_thunk.cc', 'plugins/npapi_extension_thunk.h', + 'plugins/pepper_audio.cc', + 'plugins/pepper_audio.h', 'plugins/pepper_buffer.cc', 'plugins/pepper_buffer.h', 'plugins/pepper_device_context_2d.cc', |