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

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: 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 596cd0694e0b8f8772ee46e2e948354f8d5c7567..80d22b590cfe23007871a55cdbfb27ef1968a07d 100644
--- a/content/renderer/pepper/pepper_platform_audio_input_impl.cc
+++ b/content/renderer/pepper/pepper_platform_audio_input_impl.cc
@@ -10,13 +10,15 @@
#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) {
no longer working on chromium 2012/03/16 14:33:23 why do we need a new shutdown_called flag? can we
yzshen1 2012/03/17 09:32:56 ShutDown() may be called before stream_id_ is set
no longer working on chromium 2012/03/18 00:38:59 Do I miss something here? It looks to me they all
yzshen1 2012/03/19 21:47:54 OpenDevice() and OnDeviceOpened() happens on the m
filter_ = RenderThreadImpl::current()->audio_input_message_filter();
}
@@ -25,16 +27,21 @@ PepperPlatformAudioInputImpl::~PepperPlatformAudioInputImpl() {
// the I/O thread!
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,
uint32_t sample_rate,
uint32_t sample_count,
- webkit::ppapi::PluginDelegate::PlatformAudioCommonClient* client) {
+ webkit::ppapi::PluginDelegate::PlatformAudioInputClient* client) {
scoped_refptr<PepperPlatformAudioInputImpl> audio_input(
new PepperPlatformAudioInputImpl);
- if (audio_input->Initialize(sample_rate, sample_count, client)) {
+ if (audio_input->Initialize(plugin_delegate, device_id, sample_rate,
+ sample_count, client)) {
// Balanced by Release invoked in
// PepperPlatformAudioInputImpl::ShutDownOnIOThread().
return audio_input.release();
@@ -43,20 +50,26 @@ PepperPlatformAudioInputImpl* PepperPlatformAudioInputImpl::Create(
}
bool PepperPlatformAudioInputImpl::StartCapture() {
no longer working on chromium 2012/03/16 14:33:23 It looks like this function has no way to return f
yzshen1 2012/03/17 09:32:56 Done.
+ DCHECK(main_message_loop_proxy_->BelongsToCurrentThread());
+
ChildProcess::current()->io_message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&PepperPlatformAudioInputImpl::StartCaptureOnIOThread, this));
+ FROM_HERE,
+ base::Bind(&PepperPlatformAudioInputImpl::StartCaptureOnIOThread, this));
return true;
}
bool PepperPlatformAudioInputImpl::StopCapture() {
no longer working on chromium 2012/03/16 14:33:23 void?
yzshen1 2012/03/17 09:32:56 Done.
+ DCHECK(main_message_loop_proxy_->BelongsToCurrentThread());
+
ChildProcess::current()->io_message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&PepperPlatformAudioInputImpl::StopCaptureOnIOThread, this));
+ FROM_HERE,
+ base::Bind(&PepperPlatformAudioInputImpl::StopCaptureOnIOThread, this));
return true;
}
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,54 +79,98 @@ void PepperPlatformAudioInputImpl::ShutDown() {
}
bool PepperPlatformAudioInputImpl::Initialize(
no longer working on chromium 2012/03/16 14:33:23 void?
yzshen1 2012/03/17 09:32:56 I changed two DCHECKs to input parameter validatio
+ const base::WeakPtr<PepperPluginDelegateImpl>& plugin_delegate,
+ const std::string& device_id,
uint32_t sample_rate,
uint32_t sample_count,
- webkit::ppapi::PluginDelegate::PlatformAudioCommonClient* client) {
+ webkit::ppapi::PluginDelegate::PlatformAudioInputClient* client) {
+ DCHECK(main_message_loop_proxy_->BelongsToCurrentThread());
+
+ DCHECK(plugin_delegate);
DCHECK(client);
- // Make sure we don't call init more than once.
- DCHECK_EQ(0, stream_id_);
+ plugin_delegate_ = plugin_delegate;
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;
+ 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,
- 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_));
no longer working on chromium 2012/03/16 14:33:23 What happens if we are in the middle of starting t
yzshen1 2012/03/17 09:32:56 Thanks for pointing this out! This class doesn't
no longer working on chromium 2012/03/18 00:38:59 Thanks for clarification.
}
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_));
no longer working on chromium 2012/03/16 14:33:23 same situation here, we need to do similar things
yzshen1 2012/03/17 09:32:56 Please see my comment above. On 2012/03/16 14:33:2
}
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;
- filter_->Send(new AudioInputHostMsg_CloseStream(stream_id_));
- filter_->RemoveDelegate(stream_id_);
- stream_id_ = 0;
+ if (stream_id_) {
+ 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
no longer working on chromium 2012/03/16 14:33:23 What does this Release() do? We execute CloseDevic
yzshen1 2012/03/17 09:32:56 This is a ref-counted object, Release() decreases
no longer working on chromium 2012/03/18 00:38:59 True, I know it is safe due to PepperPlatformAudio
yzshen1 2012/03/19 21:47:54 I try to maintain the following order: open device
// PepperPluginDelegateImpl::CreateAudioInput.
@@ -135,9 +192,17 @@ void PepperPlatformAudioInputImpl::OnStreamCreated(
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_)
+ 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);
+ }
} else {
+ // 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,
@@ -151,5 +216,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());
+
+ succeeded = succeeded && plugin_delegate_;
+ if (succeeded) {
+ 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();
no longer working on chromium 2012/03/16 14:33:23 shall we still send the notification when plugin_d
yzshen1 2012/03/17 09:32:56 As long as client_ is not NULL, I think it makes s
+ }
+}
+
+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