Chromium Code Reviews| 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 |