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

Unified Diff: content/renderer/media/audio_input_device.cc

Issue 7497025: refactor AudioInputDevice to remove race condition. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: add comments Created 9 years, 5 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/media/audio_input_device.cc
===================================================================
--- content/renderer/media/audio_input_device.cc (revision 94305)
+++ content/renderer/media/audio_input_device.cc (working copy)
@@ -22,8 +22,13 @@
callback_(callback),
audio_delay_milliseconds_(0),
volume_(1.0),
+ capture_thread_("AudioInputDevice"),
henrika_dont_use 2011/07/30 15:50:59 Do we use camel-back style for thread names?
wjia(left Chromium) 2011/08/01 22:40:13 Yes.
+ delegate_event_(false, false),
+ stop_event_(false, false),
stream_id_(0) {
filter_ = RenderThread::current()->audio_input_message_filter();
+ capture_thread_.Start();
+ message_loop_proxy_ = capture_thread_.message_loop_proxy();
henrika_dont_use 2011/07/30 15:50:59 Sorry, again, why not message_loop()? Also, why is
wjia(left Chromium) 2011/08/01 22:40:13 In audio_input_device.h, the difference between Me
audio_data_.reserve(channels);
for (int i = 0; i < channels; ++i) {
float* channel_data = new float[buffer_size];
@@ -32,47 +37,22 @@
}
AudioInputDevice::~AudioInputDevice() {
- // Make sure we have been shut down.
- DCHECK_EQ(0, stream_id_);
Stop();
+ capture_thread_.Stop();
henrika_dont_use 2011/07/30 15:50:59 You did not like DCHECK_EQ(0, stream_id_)?
xians 2011/08/01 11:41:23 It is for thread safety, stream_id_ is only access
wjia(left Chromium) 2011/08/01 22:40:13 Shijing has the answer.
for (int i = 0; i < channels_; ++i)
delete [] audio_data_[i];
}
bool AudioInputDevice::Start() {
- // Make sure we don't call Start() more than once.
- DCHECK_EQ(0, stream_id_);
- if (stream_id_)
- return false;
-
- AudioParameters params;
- // TODO(henrika): add support for low-latency mode?
- params.format = AudioParameters::AUDIO_PCM_LINEAR;
- params.channels = channels_;
- params.sample_rate = static_cast<int>(sample_rate_);
- params.bits_per_sample = bits_per_sample_;
- params.samples_per_packet = buffer_size_;
-
- ChildProcess::current()->io_message_loop()->PostTask(
- FROM_HERE,
- NewRunnableMethod(this, &AudioInputDevice::InitializeOnIOThread, params));
-
+ message_loop_proxy_->PostTask(FROM_HERE,
henrika_dont_use 2011/07/30 15:50:59 Why bool if false is not an option?
wjia(left Chromium) 2011/08/01 22:40:13 I didn't change ADM. ADM should be refactored as w
+ NewRunnableMethod(this, &AudioInputDevice::StartOnCaptureThread));
return true;
}
bool AudioInputDevice::Stop() {
- if (!stream_id_)
- return false;
-
- ChildProcess::current()->io_message_loop()->PostTask(
- FROM_HERE,
- NewRunnableMethod(this, &AudioInputDevice::ShutDownOnIOThread));
-
- if (audio_thread_.get()) {
- socket_->Close();
- audio_thread_->Join();
- }
-
+ message_loop_proxy_->PostTask(FROM_HERE,
henrika_dont_use 2011/07/30 15:50:59 Why bool?
wjia(left Chromium) 2011/08/01 22:40:13 Same reason for Start().
+ NewRunnableMethod(this, &AudioInputDevice::ShutDownOnCaptureThread));
+ stop_event_.Wait();
return true;
}
@@ -86,36 +66,30 @@
return false;
}
-void AudioInputDevice::InitializeOnIOThread(const AudioParameters& params) {
- stream_id_ = filter_->AddDelegate(this);
- Send(new AudioInputHostMsg_CreateStream(stream_id_, params, true));
-}
-
-void AudioInputDevice::StartOnIOThread() {
+void AudioInputDevice::StartOnCaptureThread() {
+ // Make sure we don't call Start() more than once.
henrika_dont_use 2011/07/30 15:50:59 Must we check stream_id on the capture thread? Cou
xians 2011/08/01 11:41:23 ditto, thread safety. On 2011/07/30 15:50:59, hen
if (stream_id_)
- Send(new AudioInputHostMsg_RecordStream(stream_id_));
-}
-
-void AudioInputDevice::ShutDownOnIOThread() {
- // Make sure we don't call shutdown more than once.
- if (!stream_id_)
return;
- filter_->RemoveDelegate(stream_id_);
- Send(new AudioInputHostMsg_CloseStream(stream_id_));
- stream_id_ = 0;
-}
+ AudioParameters params;
+ // TODO(henrika): add support for low-latency mode?
+ params.format = AudioParameters::AUDIO_PCM_LINEAR;
+ params.channels = channels_;
+ params.sample_rate = static_cast<int>(sample_rate_);
+ params.bits_per_sample = bits_per_sample_;
+ params.samples_per_packet = buffer_size_;
-void AudioInputDevice::SetVolumeOnIOThread(double volume) {
- if (stream_id_)
- Send(new AudioInputHostMsg_SetVolume(stream_id_, volume));
+ ChildProcess::current()->io_message_loop_proxy()->PostTask(FROM_HERE,
henrika_dont_use 2011/07/30 15:50:59 why proxy (again) ;-) ? It was jam who initially s
wjia(left Chromium) 2011/08/01 22:40:13 MessageLoopProxy is preferred over MessageLoop.
+ NewRunnableMethod(this, &AudioInputDevice::AddDelegateOnIOThread));
+ delegate_event_.Wait();
henrika_dont_use 2011/07/30 15:50:59 I have only done a quick check so far but it feels
xians 2011/08/01 11:41:23 My understanding is that this delegate_event.Wait(
wjia(left Chromium) 2011/08/01 22:40:13 Shijing has the answer. The delegate has to be add
+
+ Send(new AudioInputHostMsg_CreateStream(stream_id_, params, true));
henrika_dont_use 2011/07/30 15:50:59 Add comment about that true<=>low-latency audio st
wjia(left Chromium) 2011/08/01 22:40:13 ?? There was no comment for this.
}
-void AudioInputDevice::OnLowLatencyCreated(
+void AudioInputDevice::StartRecordingOnCaptureThread(
base::SharedMemoryHandle handle,
base::SyncSocket::Handle socket_handle,
uint32 length) {
- DCHECK(MessageLoop::current() == ChildProcess::current()->io_message_loop());
#if defined(OS_WIN)
DCHECK(handle);
DCHECK(socket_handle);
@@ -125,6 +99,12 @@
#endif
DCHECK(length);
+ if (!stream_id_) {
henrika_dont_use 2011/07/30 15:50:59 How could this happen? If so, can't we detect it e
wjia(left Chromium) 2011/08/01 22:40:13 When Stop is called before OnLowLatencyCreated is
+ base::SharedMemory::CloseHandle(handle);
+ base::SyncSocket socket(socket_handle);
xians 2011/08/01 11:41:23 Sorry, the same question as Henrik has, + why do w
wjia(left Chromium) 2011/08/01 22:40:13 both handles should be closed.
+ return;
+ }
+
shared_memory_.reset(new base::SharedMemory(handle, false));
shared_memory_->Map(length);
@@ -134,17 +114,55 @@
new base::DelegateSimpleThread(this, "renderer_audio_input_thread"));
henrika_dont_use 2011/07/30 15:50:59 Note style for thread name and compare with AudioI
wjia(left Chromium) 2011/08/01 22:40:13 I missed this one copied from previous code. Chang
audio_thread_->Start();
- MessageLoop::current()->PostTask(
- FROM_HERE,
- NewRunnableMethod(this, &AudioInputDevice::StartOnIOThread));
+ Send(new AudioInputHostMsg_RecordStream(stream_id_));
}
+void AudioInputDevice::ShutDownOnCaptureThread() {
+ // Make sure we don't call shutdown more than once.
+ if (!stream_id_) {
+ stop_event_.Signal();
+ return;
+ }
+
+ ChildProcess::current()->io_message_loop_proxy()->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &AudioInputDevice::RemoveDelegateOnIOThread,
+ stream_id_));
+ Send(new AudioInputHostMsg_CloseStream(stream_id_));
henrika_dont_use 2011/07/30 15:50:59 We wait here on Start. Is it not suitable to do so
wjia(left Chromium) 2011/08/01 22:40:13 I moved Wait to a little bit later to allow IO thr
+ stream_id_ = 0;
+
+ if (audio_thread_.get()) {
xians 2011/08/01 11:41:23 shall we have a state here instead? Think about th
wjia(left Chromium) 2011/08/01 22:40:13 Immediately after audio_thread_ is joined, it's se
+ socket_->Close();
+ audio_thread_->Join();
+ audio_thread_.reset(NULL);
henrika_dont_use 2011/07/30 15:50:59 Is NULL really needed here?
wjia(left Chromium) 2011/08/01 22:40:13 yes, in Shijing's exemplary use case, 2nd Shutdown
+ }
+
+ delegate_event_.Wait();
henrika_dont_use 2011/07/30 15:50:59 OK, you wait here instead. Hmm. Not sure why.
wjia(left Chromium) 2011/08/01 22:40:13 Explained as above.
+ stop_event_.Signal();
+}
+
+void AudioInputDevice::SetVolumeOnCaptureThread(double volume) {
+ if (stream_id_)
+ Send(new AudioInputHostMsg_SetVolume(stream_id_, volume));
+}
+
+void AudioInputDevice::OnLowLatencyCreated(
+ base::SharedMemoryHandle handle,
+ base::SyncSocket::Handle socket_handle,
+ uint32 length) {
+ DCHECK(MessageLoop::current() == ChildProcess::current()->io_message_loop());
+ message_loop_proxy_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &AudioInputDevice::StartRecordingOnCaptureThread,
+ handle, socket_handle, length));
+}
+
void AudioInputDevice::OnVolume(double volume) {
NOTIMPLEMENTED();
}
void AudioInputDevice::Send(IPC::Message* message) {
- filter_->Send(message);
+ ChildProcess::current()->io_message_loop_proxy()->PostTask(FROM_HERE,
henrika_dont_use 2011/07/30 15:50:59 It feels more clear to name this SendOnIOThread()
wjia(left Chromium) 2011/08/01 22:40:13 Done.
+ NewRunnableMethod(filter_.get(),
+ &AudioInputMessageFilter::Send, message));
}
// Our audio thread runs here. We receive captured audio samples on
@@ -197,3 +215,13 @@
number_of_frames,
audio_delay_milliseconds_);
}
+
+void AudioInputDevice::AddDelegateOnIOThread() {
+ stream_id_ = filter_->AddDelegate(this);
henrika_dont_use 2011/07/30 15:50:59 Would be nice with a VLOG(1) here. Feels great to
wjia(left Chromium) 2011/08/01 22:40:13 Done.
+ delegate_event_.Signal();
+}
+
+void AudioInputDevice::RemoveDelegateOnIOThread(int32 stream_id) {
+ filter_->RemoveDelegate(stream_id);
henrika_dont_use 2011/07/30 15:50:59 VLOG(1) please.
wjia(left Chromium) 2011/08/01 22:40:13 Done.
+ delegate_event_.Signal();
+}

Powered by Google App Engine
This is Rietveld 408576698