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 "media/audio/audio_manager_base.h" | 5 #include "media/audio/audio_manager_base.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/message_loop_proxy.h" | 8 #include "base/message_loop_proxy.h" |
9 #include "base/threading/thread.h" | 9 #include "base/threading/thread.h" |
10 #include "media/audio/audio_output_dispatcher.h" | 10 #include "media/audio/audio_output_dispatcher.h" |
11 #include "media/audio/audio_output_proxy.h" | 11 #include "media/audio/audio_output_proxy.h" |
12 #include "media/audio/fake_audio_input_stream.h" | 12 #include "media/audio/fake_audio_input_stream.h" |
13 #include "media/audio/fake_audio_output_stream.h" | 13 #include "media/audio/fake_audio_output_stream.h" |
14 | 14 |
15 static const int kStreamCloseDelaySeconds = 5; | 15 static const int kStreamCloseDelaySeconds = 5; |
16 | 16 |
17 // Default maximum number of output streams that can be open simultaneously | 17 // Default maximum number of output streams that can be open simultaneously |
18 // for all platforms. | 18 // for all platforms. |
19 static const int kDefaultMaxOutputStreams = 15; | 19 static const int kDefaultMaxOutputStreams = 16; |
| 20 |
| 21 // Default maximum number of input streams that can be open simultaneously |
| 22 // for all platforms. |
| 23 static const int kDefaultMaxInputStreams = 16; |
20 | 24 |
21 static const int kMaxInputChannels = 2; | 25 static const int kMaxInputChannels = 2; |
22 | 26 |
23 const char AudioManagerBase::kDefaultDeviceName[] = "Default"; | 27 const char AudioManagerBase::kDefaultDeviceName[] = "Default"; |
24 const char AudioManagerBase::kDefaultDeviceId[] = "default"; | 28 const char AudioManagerBase::kDefaultDeviceId[] = "default"; |
25 | 29 |
26 AudioManagerBase::AudioManagerBase() | 30 AudioManagerBase::AudioManagerBase() |
27 : num_active_input_streams_(0), | 31 : num_active_input_streams_(0), |
28 max_num_output_streams_(kDefaultMaxOutputStreams), | 32 max_num_output_streams_(kDefaultMaxOutputStreams), |
29 num_output_streams_(0) { | 33 max_num_input_streams_(kDefaultMaxInputStreams), |
| 34 num_output_streams_(0), |
| 35 num_input_streams_(0) { |
30 } | 36 } |
31 | 37 |
32 AudioManagerBase::~AudioManagerBase() { | 38 AudioManagerBase::~AudioManagerBase() { |
33 Shutdown(); | 39 // The platform specific AudioManager implementation must have already |
| 40 // stopped the audio thread. Otherwise, we may destroy audio streams before |
| 41 // stopping the thread, resulting an unexpected behavior. |
| 42 // This way we make sure activities of the audio streams are all stopped |
| 43 // before we destroy them. |
| 44 CHECK(!audio_thread_.get()); |
34 // All the output streams should have been deleted. | 45 // All the output streams should have been deleted. |
35 DCHECK_EQ(0, num_output_streams_); | 46 DCHECK_EQ(0, num_output_streams_); |
| 47 // All the input streams should have been deleted. |
| 48 DCHECK_EQ(0, num_input_streams_); |
36 } | 49 } |
37 | 50 |
38 void AudioManagerBase::Init() { | 51 void AudioManagerBase::Init() { |
39 base::AutoLock lock(audio_thread_lock_); | 52 base::AutoLock lock(audio_thread_lock_); |
40 DCHECK(!audio_thread_.get()); | 53 DCHECK(!audio_thread_.get()); |
41 audio_thread_.reset(new base::Thread("AudioThread")); | 54 audio_thread_.reset(new base::Thread("AudioThread")); |
42 CHECK(audio_thread_->Start()); | 55 CHECK(audio_thread_->Start()); |
43 } | 56 } |
44 | 57 |
45 string16 AudioManagerBase::GetAudioInputDeviceModel() { | 58 string16 AudioManagerBase::GetAudioInputDeviceModel() { |
(...skipping 10 matching lines...) Expand all Loading... |
56 if (!params.IsValid()) { | 69 if (!params.IsValid()) { |
57 DLOG(ERROR) << "Audio parameters are invalid"; | 70 DLOG(ERROR) << "Audio parameters are invalid"; |
58 return NULL; | 71 return NULL; |
59 } | 72 } |
60 | 73 |
61 // Limit the number of audio streams opened. This is to prevent using | 74 // Limit the number of audio streams opened. This is to prevent using |
62 // excessive resources for a large number of audio streams. More | 75 // excessive resources for a large number of audio streams. More |
63 // importantly it prevents instability on certain systems. | 76 // importantly it prevents instability on certain systems. |
64 // See bug: http://crbug.com/30242. | 77 // See bug: http://crbug.com/30242. |
65 if (num_output_streams_ >= max_num_output_streams_) { | 78 if (num_output_streams_ >= max_num_output_streams_) { |
66 DLOG(ERROR) << "Number of opened audio streams " << num_output_streams_ | 79 DLOG(ERROR) << "Number of opened output audio streams " |
67 << " exceed the max allowed number " << max_num_output_streams_; | 80 << num_output_streams_ |
| 81 << " exceed the max allowed number " |
| 82 << max_num_output_streams_; |
68 return NULL; | 83 return NULL; |
69 } | 84 } |
70 | 85 |
71 AudioOutputStream* stream = NULL; | 86 AudioOutputStream* stream = NULL; |
72 if (params.format == AudioParameters::AUDIO_MOCK) { | 87 if (params.format == AudioParameters::AUDIO_MOCK) { |
73 stream = FakeAudioOutputStream::MakeFakeStream(params); | 88 stream = FakeAudioOutputStream::MakeFakeStream(this, params); |
74 } else if (params.format == AudioParameters::AUDIO_PCM_LINEAR) { | 89 } else if (params.format == AudioParameters::AUDIO_PCM_LINEAR) { |
75 num_output_streams_++; | |
76 stream = MakeLinearOutputStream(params); | 90 stream = MakeLinearOutputStream(params); |
77 } else if (params.format == AudioParameters::AUDIO_PCM_LOW_LATENCY) { | 91 } else if (params.format == AudioParameters::AUDIO_PCM_LOW_LATENCY) { |
78 num_output_streams_++; | |
79 stream = MakeLowLatencyOutputStream(params); | 92 stream = MakeLowLatencyOutputStream(params); |
80 } | 93 } |
81 | 94 |
| 95 if (stream) |
| 96 ++num_output_streams_; |
| 97 |
82 return stream; | 98 return stream; |
83 } | 99 } |
84 | 100 |
85 AudioInputStream* AudioManagerBase::MakeAudioInputStream( | 101 AudioInputStream* AudioManagerBase::MakeAudioInputStream( |
86 const AudioParameters& params, const std::string& device_id) { | 102 const AudioParameters& params, const std::string& device_id) { |
87 if (!params.IsValid() || (params.channels > kMaxInputChannels) || | 103 if (!params.IsValid() || (params.channels > kMaxInputChannels) || |
88 device_id.empty()) { | 104 device_id.empty()) { |
89 DLOG(ERROR) << "Audio parameters are invalid for device " << device_id; | 105 DLOG(ERROR) << "Audio parameters are invalid for device " << device_id; |
90 return NULL; | 106 return NULL; |
91 } | 107 } |
92 | 108 |
| 109 if (num_input_streams_ >= max_num_input_streams_) { |
| 110 DLOG(ERROR) << "Number of opened input audio streams " |
| 111 << num_input_streams_ |
| 112 << " exceed the max allowed number " << max_num_input_streams_; |
| 113 return NULL; |
| 114 } |
| 115 |
93 AudioInputStream* stream = NULL; | 116 AudioInputStream* stream = NULL; |
94 if (params.format == AudioParameters::AUDIO_MOCK) { | 117 if (params.format == AudioParameters::AUDIO_MOCK) { |
95 stream = FakeAudioInputStream::MakeFakeStream(params); | 118 stream = FakeAudioInputStream::MakeFakeStream(this, params); |
96 } else if (params.format == AudioParameters::AUDIO_PCM_LINEAR) { | 119 } else if (params.format == AudioParameters::AUDIO_PCM_LINEAR) { |
97 stream = MakeLinearInputStream(params, device_id); | 120 stream = MakeLinearInputStream(params, device_id); |
98 } else if (params.format == AudioParameters::AUDIO_PCM_LOW_LATENCY) { | 121 } else if (params.format == AudioParameters::AUDIO_PCM_LOW_LATENCY) { |
99 stream = MakeLowLatencyInputStream(params, device_id); | 122 stream = MakeLowLatencyInputStream(params, device_id); |
100 } | 123 } |
101 | 124 |
| 125 if (stream) |
| 126 ++num_input_streams_; |
| 127 |
102 return stream; | 128 return stream; |
103 } | 129 } |
104 | 130 |
105 AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy( | 131 AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy( |
106 const AudioParameters& params) { | 132 const AudioParameters& params) { |
107 DCHECK(GetMessageLoop()->BelongsToCurrentThread()); | 133 DCHECK(GetMessageLoop()->BelongsToCurrentThread()); |
108 | 134 |
109 scoped_refptr<AudioOutputDispatcher>& dispatcher = | 135 scoped_refptr<AudioOutputDispatcher>& dispatcher = |
110 output_dispatchers_[params]; | 136 output_dispatchers_[params]; |
111 if (!dispatcher) | 137 if (!dispatcher) |
(...skipping 18 matching lines...) Expand all Loading... |
130 // TODO(xians) : Have a clearer destruction path for the AudioOutputStream. | 156 // TODO(xians) : Have a clearer destruction path for the AudioOutputStream. |
131 // For example, pass the ownership to AudioManager so it can delete the | 157 // For example, pass the ownership to AudioManager so it can delete the |
132 // streams. | 158 // streams. |
133 num_output_streams_--; | 159 num_output_streams_--; |
134 delete stream; | 160 delete stream; |
135 } | 161 } |
136 | 162 |
137 void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) { | 163 void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) { |
138 DCHECK(stream); | 164 DCHECK(stream); |
139 // TODO(xians) : Have a clearer destruction path for the AudioInputStream. | 165 // TODO(xians) : Have a clearer destruction path for the AudioInputStream. |
| 166 num_input_streams_--; |
140 delete stream; | 167 delete stream; |
141 } | 168 } |
142 | 169 |
143 void AudioManagerBase::IncreaseActiveInputStreamCount() { | 170 void AudioManagerBase::IncreaseActiveInputStreamCount() { |
144 base::AtomicRefCountInc(&num_active_input_streams_); | 171 base::AtomicRefCountInc(&num_active_input_streams_); |
145 } | 172 } |
146 | 173 |
147 void AudioManagerBase::DecreaseActiveInputStreamCount() { | 174 void AudioManagerBase::DecreaseActiveInputStreamCount() { |
148 DCHECK(IsRecordingInProcess()); | 175 DCHECK(IsRecordingInProcess()); |
149 base::AtomicRefCountDec(&num_active_input_streams_); | 176 base::AtomicRefCountDec(&num_active_input_streams_); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 // both physical audio stream objects that belong to the dispatcher as | 219 // both physical audio stream objects that belong to the dispatcher as |
193 // well as the message loop of the audio thread that will soon go away. | 220 // well as the message loop of the audio thread that will soon go away. |
194 // So, better crash now than later. | 221 // So, better crash now than later. |
195 CHECK(dispatcher->HasOneRef()) << "AudioOutputProxies are still alive"; | 222 CHECK(dispatcher->HasOneRef()) << "AudioOutputProxies are still alive"; |
196 dispatcher = NULL; | 223 dispatcher = NULL; |
197 } | 224 } |
198 } | 225 } |
199 | 226 |
200 output_dispatchers_.clear(); | 227 output_dispatchers_.clear(); |
201 } | 228 } |
OLD | NEW |