OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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_device.h" | 5 #include "content/renderer/media/audio_device.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/debug/trace_event.h" | 8 #include "base/debug/trace_event.h" |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "base/threading/thread_restrictions.h" | |
11 #include "base/time.h" | 10 #include "base/time.h" |
12 #include "content/common/child_process.h" | 11 #include "content/common/child_process.h" |
13 #include "content/common/media/audio_messages.h" | 12 #include "content/common/media/audio_messages.h" |
14 #include "content/common/view_messages.h" | 13 #include "content/common/view_messages.h" |
15 #include "content/renderer/render_thread_impl.h" | 14 #include "content/renderer/render_thread_impl.h" |
16 #include "media/audio/audio_output_controller.h" | 15 #include "media/audio/audio_output_controller.h" |
17 #include "media/audio/audio_util.h" | 16 #include "media/audio/audio_util.h" |
18 | 17 |
19 AudioDevice::AudioDevice() | 18 AudioDevice::AudioDevice() |
20 : buffer_size_(0), | 19 : buffer_size_(0), |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 // Takes care of the case when Stop() is called before OnLowLatencyCreated(). | 237 // Takes care of the case when Stop() is called before OnLowLatencyCreated(). |
239 if (!stream_id_) { | 238 if (!stream_id_) { |
240 base::SharedMemory::CloseHandle(handle); | 239 base::SharedMemory::CloseHandle(handle); |
241 // Close the socket handler. | 240 // Close the socket handler. |
242 base::SyncSocket socket(socket_handle); | 241 base::SyncSocket socket(socket_handle); |
243 return; | 242 return; |
244 } | 243 } |
245 | 244 |
246 shared_memory_handle_ = handle; | 245 shared_memory_handle_ = handle; |
247 memory_length_ = length; | 246 memory_length_ = length; |
248 audio_socket_.reset(new base::CancelableSyncSocket(socket_handle)); | 247 audio_socket_ = new AudioSocket(socket_handle); |
249 | 248 |
250 audio_thread_.reset( | 249 audio_thread_.reset( |
251 new base::DelegateSimpleThread(this, "renderer_audio_thread")); | 250 new base::DelegateSimpleThread(this, "renderer_audio_thread")); |
252 audio_thread_->Start(); | 251 audio_thread_->Start(); |
253 | 252 |
254 // We handle the case where Play() and/or Pause() may have been called | 253 // We handle the case where Play() and/or Pause() may have been called |
255 // multiple times before OnLowLatencyCreated() gets called. | 254 // multiple times before OnLowLatencyCreated() gets called. |
256 is_started_ = true; | 255 is_started_ = true; |
257 if (play_on_start_) | 256 if (play_on_start_) |
258 PlayOnIOThread(); | 257 PlayOnIOThread(); |
259 } | 258 } |
260 | 259 |
261 void AudioDevice::OnVolume(double volume) { | 260 void AudioDevice::OnVolume(double volume) { |
262 NOTIMPLEMENTED(); | 261 NOTIMPLEMENTED(); |
263 } | 262 } |
264 | 263 |
265 void AudioDevice::Send(IPC::Message* message) { | 264 void AudioDevice::Send(IPC::Message* message) { |
266 filter_->Send(message); | 265 filter_->Send(message); |
267 } | 266 } |
268 | 267 |
269 // Our audio thread runs here. | 268 // Our audio thread runs here. |
270 void AudioDevice::Run() { | 269 void AudioDevice::Run() { |
271 audio_thread_->SetThreadPriority(base::kThreadPriority_RealtimeAudio); | 270 audio_thread_->SetThreadPriority(base::kThreadPriority_RealtimeAudio); |
272 | 271 |
273 base::SharedMemory shared_memory(shared_memory_handle_, false); | 272 base::SharedMemory shared_memory(shared_memory_handle_, false); |
274 shared_memory.Map(media::TotalSharedMemorySizeInBytes(memory_length_)); | 273 shared_memory.Map(media::TotalSharedMemorySizeInBytes(memory_length_)); |
275 base::CancelableSyncSocket* audio_socket = audio_socket_.get(); | 274 scoped_refptr<AudioSocket> audio_socket(audio_socket_); |
276 | 275 |
| 276 int pending_data; |
277 const int samples_per_ms = static_cast<int>(sample_rate_) / 1000; | 277 const int samples_per_ms = static_cast<int>(sample_rate_) / 1000; |
278 const int bytes_per_ms = channels_ * (bits_per_sample_ / 8) * samples_per_ms; | 278 const int bytes_per_ms = channels_ * (bits_per_sample_ / 8) * samples_per_ms; |
279 | 279 |
280 while (true) { | 280 while (sizeof(pending_data) == |
281 uint32 pending_data = 0; | 281 audio_socket->socket()->Receive(&pending_data, sizeof(pending_data))) { |
282 size_t bytes_read = audio_socket->Receive(&pending_data, | 282 if (pending_data == media::AudioOutputController::kPauseMark) { |
283 sizeof(pending_data)); | 283 memset(shared_memory.memory(), 0, memory_length_); |
284 if (bytes_read != sizeof(pending_data)) { | 284 media::SetActualDataSizeInBytes(&shared_memory, memory_length_, 0); |
285 DCHECK_EQ(bytes_read, 0U); | 285 continue; |
| 286 } else if (pending_data < 0) { |
286 break; | 287 break; |
287 } | 288 } |
288 | 289 |
289 if (pending_data == | |
290 static_cast<uint32>(media::AudioOutputController::kPauseMark)) { | |
291 memset(shared_memory.memory(), 0, memory_length_); | |
292 media::SetActualDataSizeInBytes(&shared_memory, memory_length_, 0); | |
293 continue; | |
294 } | |
295 | |
296 // Convert the number of pending bytes in the render buffer | 290 // Convert the number of pending bytes in the render buffer |
297 // into milliseconds. | 291 // into milliseconds. |
298 audio_delay_milliseconds_ = pending_data / bytes_per_ms; | 292 audio_delay_milliseconds_ = pending_data / bytes_per_ms; |
299 size_t num_frames = FireRenderCallback( | 293 size_t num_frames = FireRenderCallback( |
300 reinterpret_cast<int16*>(shared_memory.memory())); | 294 reinterpret_cast<int16*>(shared_memory.memory())); |
301 | 295 |
302 // Let the host know we are done. | 296 // Let the host know we are done. |
303 media::SetActualDataSizeInBytes(&shared_memory, | 297 media::SetActualDataSizeInBytes(&shared_memory, |
304 memory_length_, | 298 memory_length_, |
305 num_frames * channels_ * sizeof(int16)); | 299 num_frames * channels_ * sizeof(int16)); |
306 } | 300 } |
| 301 audio_socket->Close(); |
307 } | 302 } |
308 | 303 |
309 size_t AudioDevice::FireRenderCallback(int16* data) { | 304 size_t AudioDevice::FireRenderCallback(int16* data) { |
310 TRACE_EVENT0("audio", "AudioDevice::FireRenderCallback"); | 305 TRACE_EVENT0("audio", "AudioDevice::FireRenderCallback"); |
311 | 306 |
312 size_t num_frames = 0; | 307 size_t num_frames = 0; |
313 if (callback_) { | 308 if (callback_) { |
314 // Update the audio-delay measurement then ask client to render audio. | 309 // Update the audio-delay measurement then ask client to render audio. |
315 num_frames = callback_->Render(audio_data_, | 310 num_frames = callback_->Render(audio_data_, |
316 buffer_size_, | 311 buffer_size_, |
317 audio_delay_milliseconds_); | 312 audio_delay_milliseconds_); |
318 | 313 |
319 // Interleave, scale, and clip to int16. | 314 // Interleave, scale, and clip to int16. |
320 // TODO(crogers): avoid converting to integer here, and pass the data | 315 // TODO(crogers): avoid converting to integer here, and pass the data |
321 // to the browser process as float, so we don't lose precision for | 316 // to the browser process as float, so we don't lose precision for |
322 // audio hardware which has better than 16bit precision. | 317 // audio hardware which has better than 16bit precision. |
323 media::InterleaveFloatToInt16(audio_data_, | 318 media::InterleaveFloatToInt16(audio_data_, |
324 data, | 319 data, |
325 buffer_size_); | 320 buffer_size_); |
326 } | 321 } |
327 return num_frames; | 322 return num_frames; |
328 } | 323 } |
329 | 324 |
330 void AudioDevice::ShutDownAudioThread() { | 325 void AudioDevice::ShutDownAudioThread() { |
331 DCHECK_EQ(MessageLoop::current(), ChildProcess::current()->io_message_loop()); | 326 DCHECK_EQ(MessageLoop::current(), ChildProcess::current()->io_message_loop()); |
332 | 327 |
333 if (audio_thread_.get()) { | 328 if (audio_thread_.get()) { |
334 // Close the socket to terminate the main thread function in the | 329 // Close the socket to terminate the main thread function in the |
335 // audio thread. | 330 // audio thread. |
336 audio_socket_->Shutdown(); // Stops blocking Receive calls. | 331 audio_socket_->Close(); |
337 // TODO(tommi): We must not do this from the IO thread. Fix. | 332 audio_socket_ = NULL; |
338 base::ThreadRestrictions::ScopedAllowIO allow_wait; | |
339 audio_thread_->Join(); | 333 audio_thread_->Join(); |
340 audio_thread_.reset(NULL); | 334 audio_thread_.reset(NULL); |
341 audio_socket_.reset(); | |
342 } | 335 } |
343 } | 336 } |
OLD | NEW |