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 = 15; |
tommi (sloooow) - chröme
2012/03/13 11:06:48
16?
no longer working on chromium
2012/03/13 14:08:59
Done.
| |
20 | 20 |
21 // Default maximum number of input streams that can be open simultaneously | |
22 // for all platforms. | |
23 static const int kDefaultMaxInputStreams = 10; | |
tommi (sloooow) - chröme
2012/03/13 11:06:48
16?
no longer working on chromium
2012/03/13 14:08:59
Done.
| |
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(params); |
74 } else if (params.format == AudioParameters::AUDIO_PCM_LINEAR) { | 89 } else if (params.format == AudioParameters::AUDIO_PCM_LINEAR) { |
75 num_output_streams_++; | 90 ++num_output_streams_; |
tommi (sloooow) - chröme
2012/03/13 10:50:28
I think I made a comment on this in an earlier rev
no longer working on chromium
2012/03/13 14:08:59
Done.
| |
76 stream = MakeLinearOutputStream(params); | 91 stream = MakeLinearOutputStream(params); |
77 } else if (params.format == AudioParameters::AUDIO_PCM_LOW_LATENCY) { | 92 } else if (params.format == AudioParameters::AUDIO_PCM_LOW_LATENCY) { |
78 num_output_streams_++; | 93 ++num_output_streams_; |
79 stream = MakeLowLatencyOutputStream(params); | 94 stream = MakeLowLatencyOutputStream(params); |
80 } | 95 } |
81 | 96 |
82 return stream; | 97 return stream; |
83 } | 98 } |
84 | 99 |
85 AudioInputStream* AudioManagerBase::MakeAudioInputStream( | 100 AudioInputStream* AudioManagerBase::MakeAudioInputStream( |
86 const AudioParameters& params, const std::string& device_id) { | 101 const AudioParameters& params, const std::string& device_id) { |
87 if (!params.IsValid() || (params.channels > kMaxInputChannels) || | 102 if (!params.IsValid() || (params.channels > kMaxInputChannels) || |
88 device_id.empty()) { | 103 device_id.empty()) { |
89 DLOG(ERROR) << "Audio parameters are invalid for device " << device_id; | 104 DLOG(ERROR) << "Audio parameters are invalid for device " << device_id; |
90 return NULL; | 105 return NULL; |
91 } | 106 } |
92 | 107 |
108 if (num_input_streams_ >= max_num_input_streams_) { | |
tommi (sloooow) - chröme
2012/03/13 10:50:28
this change seems unrelated to the bug. Do on a se
tommi (sloooow) - chröme
2012/03/13 11:06:48
as discussed offline, this is OK with me.
no longer working on chromium
2012/03/13 14:08:59
Done.
| |
109 DLOG(ERROR) << "Number of opened input audio streams " | |
110 << num_input_streams_ | |
111 << " exceed the max allowed number " << max_num_input_streams_; | |
112 return NULL; | |
113 } | |
114 | |
93 AudioInputStream* stream = NULL; | 115 AudioInputStream* stream = NULL; |
94 if (params.format == AudioParameters::AUDIO_MOCK) { | 116 if (params.format == AudioParameters::AUDIO_MOCK) { |
95 stream = FakeAudioInputStream::MakeFakeStream(params); | 117 stream = FakeAudioInputStream::MakeFakeStream(params); |
96 } else if (params.format == AudioParameters::AUDIO_PCM_LINEAR) { | 118 } else if (params.format == AudioParameters::AUDIO_PCM_LINEAR) { |
119 ++num_input_streams_; | |
tommi (sloooow) - chröme
2012/03/13 10:50:28
same comment as for the output stream.
no longer working on chromium
2012/03/13 14:08:59
Done.
| |
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) { |
122 ++num_input_streams_; | |
99 stream = MakeLowLatencyInputStream(params, device_id); | 123 stream = MakeLowLatencyInputStream(params, device_id); |
100 } | 124 } |
101 | 125 |
102 return stream; | 126 return stream; |
103 } | 127 } |
104 | 128 |
105 AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy( | 129 AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy( |
106 const AudioParameters& params) { | 130 const AudioParameters& params) { |
107 DCHECK(GetMessageLoop()->BelongsToCurrentThread()); | 131 DCHECK(GetMessageLoop()->BelongsToCurrentThread()); |
108 | 132 |
(...skipping 21 matching lines...) Expand all Loading... | |
130 // TODO(xians) : Have a clearer destruction path for the AudioOutputStream. | 154 // TODO(xians) : Have a clearer destruction path for the AudioOutputStream. |
131 // For example, pass the ownership to AudioManager so it can delete the | 155 // For example, pass the ownership to AudioManager so it can delete the |
132 // streams. | 156 // streams. |
133 num_output_streams_--; | 157 num_output_streams_--; |
134 delete stream; | 158 delete stream; |
135 } | 159 } |
136 | 160 |
137 void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) { | 161 void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) { |
138 DCHECK(stream); | 162 DCHECK(stream); |
139 // TODO(xians) : Have a clearer destruction path for the AudioInputStream. | 163 // TODO(xians) : Have a clearer destruction path for the AudioInputStream. |
164 num_input_streams_--; | |
140 delete stream; | 165 delete stream; |
141 } | 166 } |
142 | 167 |
143 void AudioManagerBase::IncreaseActiveInputStreamCount() { | 168 void AudioManagerBase::IncreaseActiveInputStreamCount() { |
144 base::AtomicRefCountInc(&num_active_input_streams_); | 169 base::AtomicRefCountInc(&num_active_input_streams_); |
145 } | 170 } |
146 | 171 |
147 void AudioManagerBase::DecreaseActiveInputStreamCount() { | 172 void AudioManagerBase::DecreaseActiveInputStreamCount() { |
148 DCHECK(IsRecordingInProcess()); | 173 DCHECK(IsRecordingInProcess()); |
149 base::AtomicRefCountDec(&num_active_input_streams_); | 174 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 | 217 // 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. | 218 // well as the message loop of the audio thread that will soon go away. |
194 // So, better crash now than later. | 219 // So, better crash now than later. |
195 CHECK(dispatcher->HasOneRef()) << "AudioOutputProxies are still alive"; | 220 CHECK(dispatcher->HasOneRef()) << "AudioOutputProxies are still alive"; |
196 dispatcher = NULL; | 221 dispatcher = NULL; |
197 } | 222 } |
198 } | 223 } |
199 | 224 |
200 output_dispatchers_.clear(); | 225 output_dispatchers_.clear(); |
201 } | 226 } |
OLD | NEW |