OLD | NEW |
---|---|
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 audio_event_(true, false) { | |
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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
83 ChildProcess::current()->io_message_loop()->PostTask( | 84 ChildProcess::current()->io_message_loop()->PostTask( |
84 FROM_HERE, | 85 FROM_HERE, |
85 base::Bind(&AudioInputDevice::ShutDownOnIOThread, this, | 86 base::Bind(&AudioInputDevice::ShutDownOnIOThread, this, |
86 &completion)); | 87 &completion)); |
87 | 88 |
88 // We wait here for the IO task to be completed to remove race conflicts | 89 // 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 | 90 // with OnLowLatencyCreated() and to ensure that Stop() acts as a synchronous |
90 // function call. | 91 // function call. |
91 if (completion.TimedWait(kMaxTimeOut)) { | 92 if (completion.TimedWait(kMaxTimeOut)) { |
92 if (audio_thread_.get()) { | 93 if (audio_thread_.get()) { |
93 // Terminate the main thread function in the audio thread. | 94 // Signal the |audio_event_| to terminate the main thread function. |
94 socket_->Close(); | 95 audio_event_.Signal(); |
95 // Wait for the audio thread to exit. | 96 // Wait for the audio thread to exit. |
96 audio_thread_->Join(); | 97 audio_thread_->Join(); |
97 // Ensures that we can call Stop() multiple times. | 98 // Ensures that we can call Stop() multiple times. |
98 audio_thread_.reset(NULL); | 99 audio_thread_.reset(NULL); |
99 } | 100 } |
100 } else { | 101 } else { |
101 LOG(ERROR) << "Failed to shut down audio input on IO thread"; | 102 LOG(ERROR) << "Failed to shut down audio input on IO thread"; |
Ami GONE FROM CHROMIUM
2011/11/29 20:38:16
This is incorrect code - quoting WaitableEvent::Ti
| |
102 return false; | 103 return false; |
103 } | 104 } |
104 | 105 |
105 return true; | 106 return true; |
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 } |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
192 // Close the socket handler. | 193 // Close the socket handler. |
193 base::SyncSocket socket(socket_handle); | 194 base::SyncSocket socket(socket_handle); |
194 return; | 195 return; |
195 } | 196 } |
196 | 197 |
197 shared_memory_.reset(new base::SharedMemory(handle, false)); | 198 shared_memory_.reset(new base::SharedMemory(handle, false)); |
198 shared_memory_->Map(length); | 199 shared_memory_->Map(length); |
199 | 200 |
200 socket_.reset(new base::SyncSocket(socket_handle)); | 201 socket_.reset(new base::SyncSocket(socket_handle)); |
201 | 202 |
203 audio_event_.Reset(); | |
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) { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
280 // this thread. | 282 // this thread. |
281 void AudioInputDevice::Run() { | 283 void AudioInputDevice::Run() { |
282 audio_thread_->SetThreadPriority(base::kThreadPriority_RealtimeAudio); | 284 audio_thread_->SetThreadPriority(base::kThreadPriority_RealtimeAudio); |
283 | 285 |
284 int pending_data; | 286 int pending_data; |
285 const int samples_per_ms = | 287 const int samples_per_ms = |
286 static_cast<int>(audio_parameters_.sample_rate) / 1000; | 288 static_cast<int>(audio_parameters_.sample_rate) / 1000; |
287 const int bytes_per_ms = audio_parameters_.channels * | 289 const int bytes_per_ms = audio_parameters_.channels * |
288 (audio_parameters_.bits_per_sample / 8) * samples_per_ms; | 290 (audio_parameters_.bits_per_sample / 8) * samples_per_ms; |
289 | 291 |
290 while (sizeof(pending_data) == socket_->Receive(&pending_data, | 292 while (!audio_event_.IsSignaled() && |
Ami GONE FROM CHROMIUM
2011/11/29 17:48:32
I'm not super-familiar with the audio codebase, bu
tommi (sloooow) - chröme
2011/11/29 20:11:32
Hey Ami,
A couple of questions inline:
On 2011/1
Ami GONE FROM CHROMIUM
2011/11/29 20:38:16
The problem is with the other case; IsSignaled() m
no longer working on chromium
2011/11/30 17:02:55
Event is thread safe. In the case you mentioned ab
| |
293 sizeof(pending_data) == socket_->Receive(&pending_data, | |
291 sizeof(pending_data)) && | 294 sizeof(pending_data)) && |
292 pending_data >= 0) { | 295 pending_data >= 0) { |
293 // TODO(henrika): investigate the provided |pending_data| value | 296 // TODO(henrika): investigate the provided |pending_data| value |
294 // and ensure that it is actually an accurate delay estimation. | 297 // and ensure that it is actually an accurate delay estimation. |
295 | 298 |
296 // Convert the number of pending bytes in the capture buffer | 299 // Convert the number of pending bytes in the capture buffer |
297 // into milliseconds. | 300 // into milliseconds. |
298 audio_delay_milliseconds_ = pending_data / bytes_per_ms; | 301 audio_delay_milliseconds_ = pending_data / bytes_per_ms; |
299 | 302 |
300 FireCaptureCallback(); | 303 FireCaptureCallback(); |
301 } | 304 } |
305 | |
306 // Close the socket. | |
307 socket_->Close(); | |
302 } | 308 } |
303 | 309 |
304 void AudioInputDevice::FireCaptureCallback() { | 310 void AudioInputDevice::FireCaptureCallback() { |
305 if (!callback_) | 311 if (!callback_) |
306 return; | 312 return; |
307 | 313 |
308 const size_t number_of_frames = audio_parameters_.samples_per_packet; | 314 const size_t number_of_frames = audio_parameters_.samples_per_packet; |
309 | 315 |
310 // Read 16-bit samples from shared memory (browser writes to it). | 316 // Read 16-bit samples from shared memory (browser writes to it). |
311 int16* input_audio = static_cast<int16*>(shared_memory_data()); | 317 int16* input_audio = static_cast<int16*>(shared_memory_data()); |
(...skipping 10 matching lines...) Expand all Loading... | |
322 bytes_per_sample, | 328 bytes_per_sample, |
323 number_of_frames); | 329 number_of_frames); |
324 } | 330 } |
325 | 331 |
326 // Deliver captured data to the client in floating point format | 332 // Deliver captured data to the client in floating point format |
327 // and update the audio-delay measurement. | 333 // and update the audio-delay measurement. |
328 callback_->Capture(audio_data_, | 334 callback_->Capture(audio_data_, |
329 number_of_frames, | 335 number_of_frames, |
330 audio_delay_milliseconds_); | 336 audio_delay_milliseconds_); |
331 } | 337 } |
OLD | NEW |