Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1947)

Unified Diff: content/renderer/pepper/pepper_platform_audio_input_impl.cc

Issue 9705056: PepperPlatformAudioInputImpl: support audio input device selection. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: sync&resolve again Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/renderer/pepper/pepper_platform_audio_input_impl.cc
diff --git a/content/renderer/pepper/pepper_platform_audio_input_impl.cc b/content/renderer/pepper/pepper_platform_audio_input_impl.cc
index 099e7d032265a6dbfb0f4705aac7b189c473e62e..f6c3244740f7a44c5a4fabeffa1bc4d4e3f27c29 100644
--- a/content/renderer/pepper/pepper_platform_audio_input_impl.cc
+++ b/content/renderer/pepper/pepper_platform_audio_input_impl.cc
@@ -10,31 +10,41 @@
#include "build/build_config.h"
#include "content/common/child_process.h"
#include "content/common/media/audio_messages.h"
+#include "content/renderer/pepper/pepper_plugin_delegate_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "media/audio/audio_manager_base.h"
PepperPlatformAudioInputImpl::PepperPlatformAudioInputImpl()
: client_(NULL),
stream_id_(0),
- main_message_loop_proxy_(base::MessageLoopProxy::current()) {
+ main_message_loop_proxy_(base::MessageLoopProxy::current()),
+ shutdown_called_(false) {
filter_ = RenderThreadImpl::current()->audio_input_message_filter();
}
PepperPlatformAudioInputImpl::~PepperPlatformAudioInputImpl() {
- // Make sure we have been shut down. Warning: this will usually happen on
- // the I/O thread!
+ // Make sure we have been shut down. Warning: this may happen on the I/O
+ // thread!
+ // Although these members should be accessed on a specific thread (either the
+ // main thread or the I/O thread), it should be fine to examine their value
+ // here.
DCHECK_EQ(0, stream_id_);
DCHECK(!client_);
+ DCHECK(label_.empty());
+ DCHECK(shutdown_called_);
}
// static
PepperPlatformAudioInputImpl* PepperPlatformAudioInputImpl::Create(
+ const base::WeakPtr<PepperPluginDelegateImpl>& plugin_delegate,
+ const std::string& device_id,
int sample_rate,
int frames_per_buffer,
- webkit::ppapi::PluginDelegate::PlatformAudioCommonClient* client) {
+ webkit::ppapi::PluginDelegate::PlatformAudioInputClient* client) {
scoped_refptr<PepperPlatformAudioInputImpl> audio_input(
new PepperPlatformAudioInputImpl);
- if (audio_input->Initialize(sample_rate, frames_per_buffer, client)) {
+ if (audio_input->Initialize(plugin_delegate, device_id, sample_rate,
+ frames_per_buffer, client)) {
// Balanced by Release invoked in
// PepperPlatformAudioInputImpl::ShutDownOnIOThread().
return audio_input.release();
@@ -42,21 +52,25 @@ PepperPlatformAudioInputImpl* PepperPlatformAudioInputImpl::Create(
return NULL;
}
-bool PepperPlatformAudioInputImpl::StartCapture() {
+void PepperPlatformAudioInputImpl::StartCapture() {
+ DCHECK(main_message_loop_proxy_->BelongsToCurrentThread());
+
ChildProcess::current()->io_message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&PepperPlatformAudioInputImpl::StartCaptureOnIOThread, this));
- return true;
+ FROM_HERE,
+ base::Bind(&PepperPlatformAudioInputImpl::StartCaptureOnIOThread, this));
}
-bool PepperPlatformAudioInputImpl::StopCapture() {
+void PepperPlatformAudioInputImpl::StopCapture() {
+ DCHECK(main_message_loop_proxy_->BelongsToCurrentThread());
+
ChildProcess::current()->io_message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&PepperPlatformAudioInputImpl::StopCaptureOnIOThread, this));
- return true;
+ FROM_HERE,
+ base::Bind(&PepperPlatformAudioInputImpl::StopCaptureOnIOThread, this));
}
void PepperPlatformAudioInputImpl::ShutDown() {
+ DCHECK(main_message_loop_proxy_->BelongsToCurrentThread());
+
// 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;
@@ -66,51 +80,95 @@ void PepperPlatformAudioInputImpl::ShutDown() {
}
bool PepperPlatformAudioInputImpl::Initialize(
+ const base::WeakPtr<PepperPluginDelegateImpl>& plugin_delegate,
+ const std::string& device_id,
int sample_rate,
int frames_per_buffer,
- webkit::ppapi::PluginDelegate::PlatformAudioCommonClient* client) {
- DCHECK(client);
- // Make sure we don't call init more than once.
- DCHECK_EQ(0, stream_id_);
+ webkit::ppapi::PluginDelegate::PlatformAudioInputClient* client) {
+ DCHECK(main_message_loop_proxy_->BelongsToCurrentThread());
+
+ if (!plugin_delegate || !client)
+ return false;
+ plugin_delegate_ = plugin_delegate;
client_ = client;
- AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
- CHANNEL_LAYOUT_MONO,
- sample_rate, 16, frames_per_buffer);
+ params_.Reset(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
+ sample_rate, 16, frames_per_buffer);
- ChildProcess::current()->io_message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&PepperPlatformAudioInputImpl::InitializeOnIOThread,
- this, params));
+ if (device_id.empty()) {
+ // Use the default device.
+ ChildProcess::current()->io_message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&PepperPlatformAudioInputImpl::InitializeOnIOThread,
+ this, 0));
+ } else {
+ // We need to open the device and obtain the label and session ID before
+ // initializing.
+ plugin_delegate_->OpenDevice(
+ PP_DEVICETYPE_DEV_AUDIOCAPTURE, device_id,
+ base::Bind(&PepperPlatformAudioInputImpl::OnDeviceOpened, this));
+ }
return true;
}
-void PepperPlatformAudioInputImpl::InitializeOnIOThread(
- const AudioParameters& params) {
+void PepperPlatformAudioInputImpl::InitializeOnIOThread(int session_id) {
+ DCHECK(ChildProcess::current()->io_message_loop_proxy()->
+ BelongsToCurrentThread());
+
+ if (shutdown_called_)
+ return;
+
+ // Make sure we don't call init more than once.
+ DCHECK_EQ(0, stream_id_);
stream_id_ = filter_->AddDelegate(this);
- filter_->Send(new AudioInputHostMsg_CreateStream(
- stream_id_, params, AudioManagerBase::kDefaultDeviceId));
+ DCHECK_NE(0, stream_id_);
+
+ if (!session_id) {
+ // We will be notified by OnStreamCreated().
+ filter_->Send(new AudioInputHostMsg_CreateStream(
+ stream_id_, params_, AudioManagerBase::kDefaultDeviceId));
+ } else {
+ // We will be notified by OnDeviceReady().
+ filter_->Send(new AudioInputHostMsg_StartDevice(stream_id_, session_id));
+ }
}
void PepperPlatformAudioInputImpl::StartCaptureOnIOThread() {
+ DCHECK(ChildProcess::current()->io_message_loop_proxy()->
+ BelongsToCurrentThread());
+
if (stream_id_)
filter_->Send(new AudioInputHostMsg_RecordStream(stream_id_));
}
void PepperPlatformAudioInputImpl::StopCaptureOnIOThread() {
+ DCHECK(ChildProcess::current()->io_message_loop_proxy()->
+ BelongsToCurrentThread());
+
+ // TODO(yzshen): We cannot re-start capturing if the stream is closed.
if (stream_id_)
filter_->Send(new AudioInputHostMsg_CloseStream(stream_id_));
}
void PepperPlatformAudioInputImpl::ShutDownOnIOThread() {
+ DCHECK(ChildProcess::current()->io_message_loop_proxy()->
+ BelongsToCurrentThread());
+
// Make sure we don't call shutdown more than once.
- if (!stream_id_)
+ if (shutdown_called_)
return;
+ shutdown_called_ = true;
+
+ if (stream_id_) {
+ filter_->Send(new AudioInputHostMsg_CloseStream(stream_id_));
+ filter_->RemoveDelegate(stream_id_);
+ stream_id_ = 0;
+ }
- filter_->Send(new AudioInputHostMsg_CloseStream(stream_id_));
- filter_->RemoveDelegate(stream_id_);
- stream_id_ = 0;
+ main_message_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&PepperPlatformAudioInputImpl::CloseDevice, this));
Release(); // Release for the delegate, balances out the reference taken in
// PepperPluginDelegateImpl::CreateAudioInput.
@@ -129,16 +187,24 @@ void PepperPlatformAudioInputImpl::OnStreamCreated(
#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 {
+ if (base::MessageLoopProxy::current() != main_message_loop_proxy_) {
+ // No need to check |shutdown_called_| here. If shutdown has occurred,
+ // |client_| will be NULL and the handles will be cleaned up on the main
+ // thread.
main_message_loop_proxy_->PostTask(
FROM_HERE,
base::Bind(&PepperPlatformAudioInputImpl::OnStreamCreated, this,
handle, socket_handle, length));
+ } else {
+ // 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 {
+ // Clean up the handles.
+ base::SyncSocket temp_socket(socket_handle);
+ base::SharedMemory temp_shared_memory(handle, false);
+ }
}
}
@@ -148,5 +214,62 @@ void PepperPlatformAudioInputImpl::OnVolume(double volume) {
void PepperPlatformAudioInputImpl::OnStateChanged(AudioStreamState state) {
}
-void PepperPlatformAudioInputImpl::OnDeviceReady(const std::string&) {
+void PepperPlatformAudioInputImpl::OnDeviceReady(const std::string& device_id) {
+ DCHECK(ChildProcess::current()->io_message_loop_proxy()->
+ BelongsToCurrentThread());
+
+ if (shutdown_called_)
+ return;
+
+ if (device_id.empty()) {
+ main_message_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&PepperPlatformAudioInputImpl::NotifyStreamCreationFailed,
+ this));
+ } else {
+ // We will be notified by OnStreamCreated().
+ filter_->Send(new AudioInputHostMsg_CreateStream(stream_id_, params_,
+ device_id));
+ }
+}
+
+void PepperPlatformAudioInputImpl::OnDeviceOpened(int request_id,
+ bool succeeded,
+ const std::string& label) {
+ DCHECK(main_message_loop_proxy_->BelongsToCurrentThread());
+
+ if (succeeded && plugin_delegate_) {
+ DCHECK(!label.empty());
+ label_ = label;
+
+ if (client_) {
+ int session_id = plugin_delegate_->GetSessionID(
+ PP_DEVICETYPE_DEV_AUDIOCAPTURE, label);
+ ChildProcess::current()->io_message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&PepperPlatformAudioInputImpl::InitializeOnIOThread,
+ this, session_id));
+ } else {
+ // Shutdown has occurred.
+ CloseDevice();
+ }
+ } else {
+ NotifyStreamCreationFailed();
+ }
+}
+
+void PepperPlatformAudioInputImpl::CloseDevice() {
+ DCHECK(main_message_loop_proxy_->BelongsToCurrentThread());
+
+ if (plugin_delegate_ && !label_.empty()) {
+ plugin_delegate_->CloseDevice(label_);
+ label_.clear();
+ }
+}
+
+void PepperPlatformAudioInputImpl::NotifyStreamCreationFailed() {
+ DCHECK(main_message_loop_proxy_->BelongsToCurrentThread());
+
+ if (client_)
+ client_->StreamCreationFailed();
}

Powered by Google App Engine
This is Rietveld 408576698