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

Side by Side Diff: content/renderer/media/audio_input_device.cc

Issue 8659040: There is a racing between SyncSocket::Receive in audio_thread_ and SyncSocket::Close in renderer ... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: update Created 9 years 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/media/audio_input_device.h" 5 #include "content/renderer/media/audio_input_device.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/message_loop.h" 8 #include "base/message_loop.h"
9 #include "base/time.h" 9 #include "base/time.h"
10 #include "content/common/child_process.h" 10 #include "content/common/child_process.h"
11 #include "content/common/media/audio_messages.h" 11 #include "content/common/media/audio_messages.h"
12 #include "content/common/view_messages.h" 12 #include "content/common/view_messages.h"
13 #include "content/renderer/render_thread_impl.h" 13 #include "content/renderer/render_thread_impl.h"
14 #include "media/audio/audio_manager_base.h" 14 #include "media/audio/audio_manager_base.h"
15 #include "media/audio/audio_util.h" 15 #include "media/audio/audio_util.h"
16 16
17 AudioInputDevice::AudioInputDevice(size_t buffer_size, 17 AudioInputDevice::AudioInputDevice(size_t buffer_size,
18 int channels, 18 int channels,
19 double sample_rate, 19 double sample_rate,
20 CaptureCallback* callback, 20 CaptureCallback* callback,
21 CaptureEventHandler* event_handler) 21 CaptureEventHandler* event_handler)
22 : callback_(callback), 22 : callback_(callback),
23 event_handler_(event_handler), 23 event_handler_(event_handler),
24 audio_delay_milliseconds_(0), 24 audio_delay_milliseconds_(0),
25 volume_(1.0), 25 volume_(1.0),
26 stream_id_(0), 26 stream_id_(0),
27 session_id_(0), 27 session_id_(0),
28 pending_device_ready_(false) { 28 pending_device_ready_(false),
29 memory_length_(0) {
29 filter_ = RenderThreadImpl::current()->audio_input_message_filter(); 30 filter_ = RenderThreadImpl::current()->audio_input_message_filter();
30 audio_data_.reserve(channels); 31 audio_data_.reserve(channels);
31 #if defined(OS_MACOSX) 32 #if defined(OS_MACOSX)
32 VLOG(1) << "Using AUDIO_PCM_LOW_LATENCY as input mode on Mac OS X."; 33 VLOG(1) << "Using AUDIO_PCM_LOW_LATENCY as input mode on Mac OS X.";
33 audio_parameters_.format = AudioParameters::AUDIO_PCM_LOW_LATENCY; 34 audio_parameters_.format = AudioParameters::AUDIO_PCM_LOW_LATENCY;
34 #elif defined(OS_WIN) 35 #elif defined(OS_WIN)
35 VLOG(1) << "Using AUDIO_PCM_LOW_LATENCY as input mode on Windows."; 36 VLOG(1) << "Using AUDIO_PCM_LOW_LATENCY as input mode on Windows.";
36 audio_parameters_.format = AudioParameters::AUDIO_PCM_LOW_LATENCY; 37 audio_parameters_.format = AudioParameters::AUDIO_PCM_LOW_LATENCY;
37 #else 38 #else
38 // TODO(henrika): add support for AUDIO_PCM_LOW_LATENCY on Linux as well. 39 // TODO(henrika): add support for AUDIO_PCM_LOW_LATENCY on Linux as well.
(...skipping 25 matching lines...) Expand all
64 } 65 }
65 66
66 void AudioInputDevice::SetDevice(int session_id) { 67 void AudioInputDevice::SetDevice(int session_id) {
67 VLOG(1) << "SetDevice (session_id=" << session_id << ")"; 68 VLOG(1) << "SetDevice (session_id=" << session_id << ")";
68 ChildProcess::current()->io_message_loop()->PostTask( 69 ChildProcess::current()->io_message_loop()->PostTask(
69 FROM_HERE, 70 FROM_HERE,
70 base::Bind(&AudioInputDevice::SetSessionIdOnIOThread, this, 71 base::Bind(&AudioInputDevice::SetSessionIdOnIOThread, this,
71 session_id)); 72 session_id));
72 } 73 }
73 74
74 bool AudioInputDevice::Stop() { 75 void AudioInputDevice::Stop() {
76 DCHECK(MessageLoop::current() != ChildProcess::current()->io_message_loop());
75 VLOG(1) << "Stop()"; 77 VLOG(1) << "Stop()";
76 // Max waiting time for Stop() to complete. If this time limit is passed, 78 // Max waiting time for Stop() to complete. If this time limit is passed,
77 // we will stop waiting and return false. It ensures that Stop() can't block 79 // we will stop waiting and return false. It ensures that Stop() can't block
78 // the calling thread forever. 80 // the calling thread forever.
79 const base::TimeDelta kMaxTimeOut = base::TimeDelta::FromMilliseconds(1000); 81 const base::TimeDelta kMaxTimeOut = base::TimeDelta::FromMilliseconds(1000);
80 82
81 base::WaitableEvent completion(false, false); 83 base::WaitableEvent completion(false, false);
82 84
83 ChildProcess::current()->io_message_loop()->PostTask( 85 ChildProcess::current()->io_message_loop()->PostTask(
84 FROM_HERE, 86 FROM_HERE,
85 base::Bind(&AudioInputDevice::ShutDownOnIOThread, this, 87 base::Bind(&AudioInputDevice::ShutDownOnIOThread, this,
86 &completion)); 88 &completion));
87 89
88 // We wait here for the IO task to be completed to remove race conflicts 90 // We wait here for the IO task to be completed to remove race conflicts
89 // with OnLowLatencyCreated() and to ensure that Stop() acts as a synchronous 91 // with OnLowLatencyCreated() and to ensure that Stop() acts as a synchronous
90 // function call. 92 // function call.
91 if (completion.TimedWait(kMaxTimeOut)) { 93 if (!completion.TimedWait(kMaxTimeOut)) {
92 if (audio_thread_.get()) {
93 // Terminate the main thread function in the audio thread.
94 socket_->Close();
95 // Wait for the audio thread to exit.
96 audio_thread_->Join();
97 // Ensures that we can call Stop() multiple times.
98 audio_thread_.reset(NULL);
99 }
100 } else {
101 LOG(ERROR) << "Failed to shut down audio input on IO thread"; 94 LOG(ERROR) << "Failed to shut down audio input on IO thread";
102 return false;
103 } 95 }
104 96
105 return true; 97 if (audio_thread_.get()) {
98 // Terminate the main thread function in the audio thread.
99 {
100 base::SyncSocket socket(socket_handle_);
101 }
102 // Wait for the audio thread to exit.
103 audio_thread_->Join();
104 // Ensures that we can call Stop() multiple times.
105 audio_thread_.reset(NULL);
106 }
106 } 107 }
107 108
108 bool AudioInputDevice::SetVolume(double volume) { 109 bool AudioInputDevice::SetVolume(double volume) {
109 NOTIMPLEMENTED(); 110 NOTIMPLEMENTED();
110 return false; 111 return false;
111 } 112 }
112 113
113 bool AudioInputDevice::GetVolume(double* volume) { 114 bool AudioInputDevice::GetVolume(double* volume) {
114 NOTIMPLEMENTED(); 115 NOTIMPLEMENTED();
115 return false; 116 return false;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 uint32 length) { 178 uint32 length) {
178 DCHECK(MessageLoop::current() == ChildProcess::current()->io_message_loop()); 179 DCHECK(MessageLoop::current() == ChildProcess::current()->io_message_loop());
179 #if defined(OS_WIN) 180 #if defined(OS_WIN)
180 DCHECK(handle); 181 DCHECK(handle);
181 DCHECK(socket_handle); 182 DCHECK(socket_handle);
182 #else 183 #else
183 DCHECK_GE(handle.fd, 0); 184 DCHECK_GE(handle.fd, 0);
184 DCHECK_GE(socket_handle, 0); 185 DCHECK_GE(socket_handle, 0);
185 #endif 186 #endif
186 DCHECK(length); 187 DCHECK(length);
188 DCHECK(!audio_thread_.get());
187 189
188 VLOG(1) << "OnLowLatencyCreated (stream_id=" << stream_id_ << ")"; 190 VLOG(1) << "OnLowLatencyCreated (stream_id=" << stream_id_ << ")";
189 // Takes care of the case when Stop() is called before OnLowLatencyCreated(). 191 // Takes care of the case when Stop() is called before OnLowLatencyCreated().
190 if (!stream_id_) { 192 if (!stream_id_) {
191 base::SharedMemory::CloseHandle(handle); 193 base::SharedMemory::CloseHandle(handle);
192 // Close the socket handler. 194 // Close the socket handler.
193 base::SyncSocket socket(socket_handle); 195 base::SyncSocket socket(socket_handle);
194 return; 196 return;
195 } 197 }
196 198
197 shared_memory_.reset(new base::SharedMemory(handle, false)); 199 shared_memory_handle_ = handle;
198 shared_memory_->Map(length); 200 memory_length_ = length;
199 201
200 socket_.reset(new base::SyncSocket(socket_handle)); 202 socket_handle_ = socket_handle;
201 203
202 audio_thread_.reset( 204 audio_thread_.reset(
203 new base::DelegateSimpleThread(this, "RendererAudioInputThread")); 205 new base::DelegateSimpleThread(this, "RendererAudioInputThread"));
204 audio_thread_->Start(); 206 audio_thread_->Start();
205 207
206 MessageLoop::current()->PostTask( 208 MessageLoop::current()->PostTask(
207 FROM_HERE, 209 FROM_HERE,
208 base::Bind(&AudioInputDevice::StartOnIOThread, this)); 210 base::Bind(&AudioInputDevice::StartOnIOThread, this));
209 } 211 }
210 212
211 void AudioInputDevice::OnVolume(double volume) { 213 void AudioInputDevice::OnVolume(double volume) {
212 NOTIMPLEMENTED(); 214 NOTIMPLEMENTED();
213 } 215 }
214 216
215 void AudioInputDevice::OnStateChanged(AudioStreamState state) { 217 void AudioInputDevice::OnStateChanged(AudioStreamState state) {
216 DCHECK(MessageLoop::current() == ChildProcess::current()->io_message_loop()); 218 DCHECK(MessageLoop::current() == ChildProcess::current()->io_message_loop());
217 switch (state) { 219 switch (state) {
218 case kAudioStreamPaused: 220 case kAudioStreamPaused:
219 // Do nothing if the stream has been closed. 221 // Do nothing if the stream has been closed.
220 if (!stream_id_) 222 if (!stream_id_)
221 return; 223 return;
222 224
223 filter_->RemoveDelegate(stream_id_); 225 filter_->RemoveDelegate(stream_id_);
224 226
225 // Joining the audio thread will be quite soon, since the stream has 227 // Joining the audio thread will be quite soon, since the stream has
226 // been closed before. 228 // been closed before.
227 if (audio_thread_.get()) { 229 if (audio_thread_.get()) {
228 socket_->Close(); 230 {
231 base::SyncSocket socket(socket_handle_);
232 }
229 audio_thread_->Join(); 233 audio_thread_->Join();
230 audio_thread_.reset(NULL); 234 audio_thread_.reset(NULL);
231 } 235 }
232 236
233 if (event_handler_) 237 if (event_handler_)
234 event_handler_->OnDeviceStopped(); 238 event_handler_->OnDeviceStopped();
235 239
236 stream_id_ = 0; 240 stream_id_ = 0;
237 pending_device_ready_ = false; 241 pending_device_ready_ = false;
238 break; 242 break;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 278
275 void AudioInputDevice::Send(IPC::Message* message) { 279 void AudioInputDevice::Send(IPC::Message* message) {
276 filter_->Send(message); 280 filter_->Send(message);
277 } 281 }
278 282
279 // Our audio thread runs here. We receive captured audio samples on 283 // Our audio thread runs here. We receive captured audio samples on
280 // this thread. 284 // this thread.
281 void AudioInputDevice::Run() { 285 void AudioInputDevice::Run() {
282 audio_thread_->SetThreadPriority(base::kThreadPriority_RealtimeAudio); 286 audio_thread_->SetThreadPriority(base::kThreadPriority_RealtimeAudio);
283 287
288 base::SharedMemory shared_memory(shared_memory_handle_, false);
289 shared_memory.Map(memory_length_);
290
291 base::SyncSocket socket(socket_handle_);
292
284 int pending_data; 293 int pending_data;
285 const int samples_per_ms = 294 const int samples_per_ms =
286 static_cast<int>(audio_parameters_.sample_rate) / 1000; 295 static_cast<int>(audio_parameters_.sample_rate) / 1000;
287 const int bytes_per_ms = audio_parameters_.channels * 296 const int bytes_per_ms = audio_parameters_.channels *
288 (audio_parameters_.bits_per_sample / 8) * samples_per_ms; 297 (audio_parameters_.bits_per_sample / 8) * samples_per_ms;
289 298
290 while (sizeof(pending_data) == socket_->Receive(&pending_data, 299 while ((sizeof(pending_data) == socket.Receive(&pending_data,
291 sizeof(pending_data)) && 300 sizeof(pending_data))) &&
292 pending_data >= 0) { 301 (pending_data >= 0)) {
293 // TODO(henrika): investigate the provided |pending_data| value 302 // TODO(henrika): investigate the provided |pending_data| value
294 // and ensure that it is actually an accurate delay estimation. 303 // and ensure that it is actually an accurate delay estimation.
295 304
296 // Convert the number of pending bytes in the capture buffer 305 // Convert the number of pending bytes in the capture buffer
297 // into milliseconds. 306 // into milliseconds.
298 audio_delay_milliseconds_ = pending_data / bytes_per_ms; 307 audio_delay_milliseconds_ = pending_data / bytes_per_ms;
299 308
300 FireCaptureCallback(); 309 FireCaptureCallback(reinterpret_cast<int16*>(shared_memory.memory()));
301 } 310 }
302 } 311 }
303 312
304 void AudioInputDevice::FireCaptureCallback() { 313 void AudioInputDevice::FireCaptureCallback(int16* input_audio) {
305 if (!callback_) 314 if (!callback_)
306 return; 315 return;
307 316
308 const size_t number_of_frames = audio_parameters_.samples_per_packet; 317 const size_t number_of_frames = audio_parameters_.samples_per_packet;
309 318
310 // Read 16-bit samples from shared memory (browser writes to it).
311 int16* input_audio = static_cast<int16*>(shared_memory_data());
312 const int bytes_per_sample = sizeof(input_audio[0]); 319 const int bytes_per_sample = sizeof(input_audio[0]);
313 320
314 // Deinterleave each channel and convert to 32-bit floating-point 321 // Deinterleave each channel and convert to 32-bit floating-point
315 // with nominal range -1.0 -> +1.0. 322 // with nominal range -1.0 -> +1.0.
316 for (int channel_index = 0; channel_index < audio_parameters_.channels; 323 for (int channel_index = 0; channel_index < audio_parameters_.channels;
317 ++channel_index) { 324 ++channel_index) {
318 media::DeinterleaveAudioChannel(input_audio, 325 media::DeinterleaveAudioChannel(input_audio,
319 audio_data_[channel_index], 326 audio_data_[channel_index],
320 audio_parameters_.channels, 327 audio_parameters_.channels,
321 channel_index, 328 channel_index,
322 bytes_per_sample, 329 bytes_per_sample,
323 number_of_frames); 330 number_of_frames);
324 } 331 }
325 332
326 // Deliver captured data to the client in floating point format 333 // Deliver captured data to the client in floating point format
327 // and update the audio-delay measurement. 334 // and update the audio-delay measurement.
328 callback_->Capture(audio_data_, 335 callback_->Capture(audio_data_,
329 number_of_frames, 336 number_of_frames,
330 audio_delay_milliseconds_); 337 audio_delay_milliseconds_);
331 } 338 }
OLDNEW
« no previous file with comments | « content/renderer/media/audio_input_device.h ('k') | content/renderer/media/webrtc_audio_device_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698