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 "media/audio/audio_manager_base.h" | 5 #include "media/audio/audio_manager_base.h" |
6 | |
7 #include "base/bind.h" | |
6 #include "media/audio/audio_output_dispatcher.h" | 8 #include "media/audio/audio_output_dispatcher.h" |
7 #include "media/audio/audio_output_proxy.h" | 9 #include "media/audio/audio_output_proxy.h" |
8 | 10 |
9 static const int kStreamCloseDelayMs = 5000; | 11 static const int kStreamCloseDelayMs = 5000; |
10 | 12 |
11 const char AudioManagerBase::kDefaultDeviceName[] = "Default"; | 13 const char AudioManagerBase::kDefaultDeviceName[] = "Default"; |
12 const char AudioManagerBase::kDefaultDeviceId[] = "default"; | 14 const char AudioManagerBase::kDefaultDeviceId[] = "default"; |
13 | 15 |
14 AudioManagerBase::AudioManagerBase() | 16 AudioManagerBase::AudioManagerBase() |
15 : audio_thread_("AudioThread"), | 17 : audio_thread_("AudioThread"), |
16 initialized_(false), | |
17 num_active_input_streams_(0) { | 18 num_active_input_streams_(0) { |
18 } | 19 } |
19 | 20 |
20 AudioManagerBase::~AudioManagerBase() { | 21 AudioManagerBase::~AudioManagerBase() { |
21 DCHECK(!audio_thread_.IsRunning()); | 22 Shutdown(); |
22 } | 23 } |
23 | 24 |
24 void AudioManagerBase::Init() { | 25 #ifndef NDEBUG |
henrika (OOO until Aug 14)
2011/12/07 10:08:34
Please add some comments here to explain the purpo
tommi (sloooow) - chröme
2011/12/07 12:26:44
There are comments in the header. Please let me k
| |
25 initialized_ = audio_thread_.Start(); | 26 void AudioManagerBase::AddRef() const { |
27 const MessageLoop* loop = audio_thread_.message_loop(); | |
28 DCHECK(loop == NULL || loop != MessageLoop::current()); | |
29 AudioManager::AddRef(); | |
26 } | 30 } |
27 | 31 |
28 void AudioManagerBase::Cleanup() { | 32 void AudioManagerBase::Release() const { |
29 if (initialized_) { | 33 const MessageLoop* loop = audio_thread_.message_loop(); |
30 initialized_ = false; | 34 DCHECK(loop == NULL || loop != MessageLoop::current()); |
31 audio_thread_.Stop(); | 35 AudioManager::Release(); |
32 } | 36 } |
37 #endif | |
38 | |
39 void AudioManagerBase::Init() { | |
40 CHECK(audio_thread_.Start()); | |
henrika (OOO until Aug 14)
2011/12/07 10:08:34
Any point in checking Initialized() here to ensure
tommi (sloooow) - chröme
2011/12/07 12:26:44
audio_thread_.Start() returns true iff the thread
| |
33 } | 41 } |
34 | 42 |
35 string16 AudioManagerBase::GetAudioInputDeviceModel() { | 43 string16 AudioManagerBase::GetAudioInputDeviceModel() { |
36 return string16(); | 44 return string16(); |
37 } | 45 } |
38 | 46 |
39 MessageLoop* AudioManagerBase::GetMessageLoop() { | 47 MessageLoop* AudioManagerBase::GetMessageLoop() { |
40 DCHECK(initialized_); | |
41 return audio_thread_.message_loop(); | 48 return audio_thread_.message_loop(); |
42 } | 49 } |
43 | 50 |
44 AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy( | 51 AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy( |
45 const AudioParameters& params) { | 52 const AudioParameters& params) { |
46 if (!initialized_) | 53 DCHECK_EQ(MessageLoop::current(), GetMessageLoop()); |
54 | |
55 if (!initialized()) | |
47 return NULL; | 56 return NULL; |
48 | 57 |
49 scoped_refptr<AudioOutputDispatcher>& dispatcher = | 58 scoped_refptr<AudioOutputDispatcher>& dispatcher = |
50 output_dispatchers_[params]; | 59 output_dispatchers_[params]; |
51 if (!dispatcher) | 60 if (!dispatcher) |
52 dispatcher = new AudioOutputDispatcher(this, params, kStreamCloseDelayMs); | 61 dispatcher = new AudioOutputDispatcher(this, params, kStreamCloseDelayMs); |
53 | |
54 return new AudioOutputProxy(dispatcher); | 62 return new AudioOutputProxy(dispatcher); |
55 } | 63 } |
56 | 64 |
57 bool AudioManagerBase::CanShowAudioInputSettings() { | 65 bool AudioManagerBase::CanShowAudioInputSettings() { |
58 return false; | 66 return false; |
59 } | 67 } |
60 | 68 |
61 void AudioManagerBase::ShowAudioInputSettings() { | 69 void AudioManagerBase::ShowAudioInputSettings() { |
62 } | 70 } |
63 | 71 |
64 void AudioManagerBase::GetAudioInputDeviceNames( | 72 void AudioManagerBase::GetAudioInputDeviceNames( |
65 media::AudioDeviceNames* device_names) { | 73 media::AudioDeviceNames* device_names) { |
66 } | 74 } |
67 | 75 |
68 void AudioManagerBase::IncreaseActiveInputStreamCount() { | 76 void AudioManagerBase::IncreaseActiveInputStreamCount() { |
69 base::AutoLock auto_lock(active_input_streams_lock_); | 77 base::AtomicRefCountInc(&num_active_input_streams_); |
henrika (OOO until Aug 14)
2011/12/07 10:08:34
Nice!
tommi (sloooow) - chröme
2011/12/07 12:26:44
Thanks! :)
| |
70 ++num_active_input_streams_; | |
71 } | 78 } |
72 | 79 |
73 void AudioManagerBase::DecreaseActiveInputStreamCount() { | 80 void AudioManagerBase::DecreaseActiveInputStreamCount() { |
74 base::AutoLock auto_lock(active_input_streams_lock_); | 81 DCHECK(IsRecordingInProcess()); |
75 DCHECK_GT(num_active_input_streams_, 0); | 82 base::AtomicRefCountDec(&num_active_input_streams_); |
76 --num_active_input_streams_; | |
77 } | 83 } |
78 | 84 |
79 bool AudioManagerBase::IsRecordingInProcess() { | 85 bool AudioManagerBase::IsRecordingInProcess() { |
80 base::AutoLock auto_lock(active_input_streams_lock_); | 86 return !base::AtomicRefCountIsZero(&num_active_input_streams_); |
81 return num_active_input_streams_ > 0; | |
82 } | 87 } |
88 | |
89 void AudioManagerBase::Shutdown() { | |
90 if (!initialized()) | |
91 return; | |
92 | |
93 DCHECK_NE(MessageLoop::current(), GetMessageLoop()); | |
94 | |
95 // We must use base::Unretained since Shutdown might have been called from | |
96 // the destructor and we can't alter the refcount of the object at that point. | |
97 GetMessageLoop()->PostTask(FROM_HERE, base::Bind( | |
98 &AudioManagerBase::ShutdownOnAudioThread, | |
99 base::Unretained(this))); | |
100 // Stop() will wait for any posted messages to be processed first. | |
henrika (OOO until Aug 14)
2011/12/07 10:08:34
Can you add some more information here please. You
tommi (sloooow) - chröme
2011/12/07 12:26:44
Well, this is how the Thread class works, fine or
| |
101 audio_thread_.Stop(); | |
102 } | |
103 | |
104 void AudioManagerBase::ShutdownOnAudioThread() { | |
105 DCHECK_EQ(MessageLoop::current(), GetMessageLoop()); | |
106 | |
107 AudioOutputDispatchersMap::iterator it = output_dispatchers_.begin(); | |
108 for (; it != output_dispatchers_.end(); ++it) { | |
109 scoped_refptr<AudioOutputDispatcher>& dispatcher = (*it).second; | |
110 if (dispatcher) { | |
111 dispatcher->Shutdown(); | |
112 // All AudioOutputProxies must have been freed before Shutdown is called. | |
113 // If they still exist, things will go bad. They have direct pointers to | |
114 // both physical audio stream objects that belong to the dispatcher as | |
115 // well as the message loop of the audio thread that will soon go away. | |
116 // So, better crash now than later. | |
117 CHECK(dispatcher->HasOneRef()) << "AudioOutputProxies are still alive"; | |
118 dispatcher = NULL; | |
119 } | |
120 } | |
121 | |
122 output_dispatchers_.clear(); | |
123 } | |
OLD | NEW |