OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 // TODO(hclam): Several changes need to be made to this code: | 5 // TODO(hclam): Several changes need to be made to this code: |
6 // 1. We should host AudioRendererHost on a dedicated audio thread. Doing | 6 // 1. We should host AudioRendererHost on a dedicated audio thread. Doing |
7 // so we don't have to worry about blocking method calls such as | 7 // so we don't have to worry about blocking method calls such as |
8 // play / stop an audio stream. | 8 // play / stop an audio stream. |
9 // 2. Move locked data structures into a separate structure that sanity | 9 // 2. Move locked data structures into a separate structure that sanity |
10 // checks access by different threads that use it. | 10 // checks access by different threads that use it. |
11 // | 11 // |
12 // SEMANTICS OF |state_| | 12 // SEMANTICS OF |state_| |
13 // Note that |state_| of IPCAudioSource is accessed on two thread. Namely | 13 // Note that |state_| of IPCAudioSource is accessed on two thread. Namely |
14 // the IO thread and the audio thread. IO thread is the thread on which | 14 // the IO thread and the audio thread. IO thread is the thread on which |
15 // IPAudioSource::Play(), IPCAudioSource::Pause() are called. Audio thread | 15 // IPAudioSource::Play(), IPCAudioSource::Pause() are called. Audio thread |
16 // is a thread operated by the audio hardware for requesting data. | 16 // is a thread operated by the audio hardware for requesting data. |
17 // It is important that |state_| is only written on the IO thread because | 17 // It is important that |state_| is only written on the IO thread because |
18 // reading of such state in Play() and Pause() is not protected. However, | 18 // reading of such state in Play() and Pause() is not protected. However, |
19 // since OnMoreData() is called on the audio thread and reads |state_| | 19 // since OnMoreData() is called on the audio thread and reads |state_| |
20 // variable. Writing to this variable needs to be protected in Play() | 20 // variable. Writing to this variable needs to be protected in Play() |
21 // and Pause(). | 21 // and Pause(). |
22 | 22 |
23 #include "base/histogram.h" | 23 #include "base/histogram.h" |
24 #include "base/lock.h" | 24 #include "base/lock.h" |
25 #include "base/process.h" | 25 #include "base/process.h" |
26 #include "base/shared_memory.h" | 26 #include "base/shared_memory.h" |
27 #include "base/waitable_event.h" | 27 #include "base/waitable_event.h" |
28 #include "chrome/browser/chrome_thread.h" | |
29 #include "chrome/browser/renderer_host/audio_renderer_host.h" | 28 #include "chrome/browser/renderer_host/audio_renderer_host.h" |
30 #include "chrome/common/render_messages.h" | 29 #include "chrome/common/render_messages.h" |
31 #include "ipc/ipc_logging.h" | 30 #include "ipc/ipc_logging.h" |
32 | 31 |
33 namespace { | 32 namespace { |
34 | 33 |
35 // This constant governs the hardware audio buffer size, this value should be | 34 // This constant governs the hardware audio buffer size, this value should be |
36 // choosen carefully and is platform specific. | 35 // choosen carefully and is platform specific. |
37 const int kSamplesPerHardwarePacket = 8192; | 36 const int kSamplesPerHardwarePacket = 8192; |
38 | 37 |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 SubmitPacketRequest(NULL); | 327 SubmitPacketRequest(NULL); |
329 } | 328 } |
330 | 329 |
331 //----------------------------------------------------------------------------- | 330 //----------------------------------------------------------------------------- |
332 // AudioRendererHost implementations. | 331 // AudioRendererHost implementations. |
333 | 332 |
334 AudioRendererHost::AudioRendererHost() | 333 AudioRendererHost::AudioRendererHost() |
335 : process_id_(0), | 334 : process_id_(0), |
336 process_handle_(0), | 335 process_handle_(0), |
337 ipc_sender_(NULL) { | 336 ipc_sender_(NULL) { |
338 // Make sure we perform actual initialization operations in the thread where | 337 // Increase the ref count of this object so it is active until we do |
339 // this object should live. | 338 // Release(). |
340 ChromeThread::PostTask( | 339 AddRef(); |
341 ChromeThread::IO, FROM_HERE, | |
342 NewRunnableMethod(this, &AudioRendererHost::OnInitialized)); | |
343 } | 340 } |
344 | 341 |
345 AudioRendererHost::~AudioRendererHost() { | 342 AudioRendererHost::~AudioRendererHost() { |
| 343 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); |
346 DCHECK(sources_.empty()); | 344 DCHECK(sources_.empty()); |
347 } | 345 } |
348 | 346 |
349 void AudioRendererHost::Destroy() { | 347 void AudioRendererHost::Destroy() { |
350 // Post a message to the thread where this object should live and do the | 348 // Post a message to the thread where this object should live and do the |
351 // actual operations there. | 349 // actual operations there. |
352 ChromeThread::PostTask( | 350 ChromeThread::PostTask( |
353 ChromeThread::IO, FROM_HERE, | 351 ChromeThread::IO, FROM_HERE, |
354 NewRunnableMethod(this, &AudioRendererHost::OnDestroyed)); | 352 NewRunnableMethod(this, &AudioRendererHost::OnDestroyed)); |
355 } | 353 } |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
491 int stream_id, size_t packet_size) { | 489 int stream_id, size_t packet_size) { |
492 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); | 490 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); |
493 IPCAudioSource* source = Lookup(msg.routing_id(), stream_id); | 491 IPCAudioSource* source = Lookup(msg.routing_id(), stream_id); |
494 if (source) { | 492 if (source) { |
495 source->NotifyPacketReady(packet_size); | 493 source->NotifyPacketReady(packet_size); |
496 } else { | 494 } else { |
497 SendErrorMessage(msg.routing_id(), stream_id); | 495 SendErrorMessage(msg.routing_id(), stream_id); |
498 } | 496 } |
499 } | 497 } |
500 | 498 |
501 void AudioRendererHost::OnInitialized() { | |
502 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); | |
503 // Increase the ref count of this object so it is active until we do | |
504 // Release(). | |
505 AddRef(); | |
506 } | |
507 | |
508 void AudioRendererHost::OnDestroyed() { | 499 void AudioRendererHost::OnDestroyed() { |
509 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); | 500 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); |
510 ipc_sender_ = NULL; | 501 ipc_sender_ = NULL; |
511 process_handle_ = 0; | 502 process_handle_ = 0; |
512 process_id_ = 0; | 503 process_id_ = 0; |
513 DestroyAllSources(); | 504 DestroyAllSources(); |
514 // Decrease the reference to this object, which may lead to self-destruction. | 505 // Decrease the reference to this object, which may lead to self-destruction. |
515 Release(); | 506 Release(); |
516 } | 507 } |
517 | 508 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
572 | 563 |
573 void AudioRendererHost::DestroySource(IPCAudioSource* source) { | 564 void AudioRendererHost::DestroySource(IPCAudioSource* source) { |
574 if (ChromeThread::CurrentlyOn(ChromeThread::IO)) { | 565 if (ChromeThread::CurrentlyOn(ChromeThread::IO)) { |
575 OnDestroySource(source); | 566 OnDestroySource(source); |
576 } else { | 567 } else { |
577 ChromeThread::PostTask( | 568 ChromeThread::PostTask( |
578 ChromeThread::IO, FROM_HERE, | 569 ChromeThread::IO, FROM_HERE, |
579 NewRunnableMethod(this, &AudioRendererHost::OnDestroySource, source)); | 570 NewRunnableMethod(this, &AudioRendererHost::OnDestroySource, source)); |
580 } | 571 } |
581 } | 572 } |
OLD | NEW |