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/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/message_loop_proxy.h" | 9 #include "base/message_loop_proxy.h" |
10 #include "base/threading/thread.h" | 10 #include "base/threading/thread.h" |
11 #include "media/audio/audio_output_dispatcher_impl.h" | 11 #include "media/audio/audio_output_dispatcher_impl.h" |
12 #include "media/audio/audio_output_proxy.h" | 12 #include "media/audio/audio_output_proxy.h" |
13 #include "media/audio/audio_output_resampler.h" | 13 #include "media/audio/audio_output_resampler.h" |
14 #include "media/audio/audio_util.h" | 14 #include "media/audio/audio_util.h" |
15 #include "media/audio/fake_audio_input_stream.h" | 15 #include "media/audio/fake_audio_input_stream.h" |
16 #include "media/audio/fake_audio_output_stream.h" | 16 #include "media/audio/fake_audio_output_stream.h" |
17 #include "media/audio/virtual_audio_input_stream.h" | |
18 #include "media/audio/virtual_audio_output_stream.h" | |
17 #include "media/base/media_switches.h" | 19 #include "media/base/media_switches.h" |
18 | 20 |
19 // TODO(dalecurtis): Temporarily disabled while switching pipeline to use float, | 21 // TODO(dalecurtis): Temporarily disabled while switching pipeline to use float, |
20 // http://crbug.com/114700 | 22 // http://crbug.com/114700 |
21 #if defined(ENABLE_AUDIO_MIXER) | 23 #if defined(ENABLE_AUDIO_MIXER) |
22 #include "media/audio/audio_output_mixer.h" | 24 #include "media/audio/audio_output_mixer.h" |
23 #endif | 25 #endif |
24 | 26 |
25 namespace media { | 27 namespace media { |
26 | 28 |
(...skipping 11 matching lines...) Expand all Loading... | |
38 | 40 |
39 const char AudioManagerBase::kDefaultDeviceName[] = "Default"; | 41 const char AudioManagerBase::kDefaultDeviceName[] = "Default"; |
40 const char AudioManagerBase::kDefaultDeviceId[] = "default"; | 42 const char AudioManagerBase::kDefaultDeviceId[] = "default"; |
41 | 43 |
42 AudioManagerBase::AudioManagerBase() | 44 AudioManagerBase::AudioManagerBase() |
43 : num_active_input_streams_(0), | 45 : num_active_input_streams_(0), |
44 max_num_output_streams_(kDefaultMaxOutputStreams), | 46 max_num_output_streams_(kDefaultMaxOutputStreams), |
45 max_num_input_streams_(kDefaultMaxInputStreams), | 47 max_num_input_streams_(kDefaultMaxInputStreams), |
46 num_output_streams_(0), | 48 num_output_streams_(0), |
47 num_input_streams_(0), | 49 num_input_streams_(0), |
48 audio_thread_(new base::Thread("AudioThread")) { | 50 audio_thread_(new base::Thread("AudioThread")), |
51 virtual_audio_input_stream_(NULL) { | |
49 #if defined(OS_WIN) | 52 #if defined(OS_WIN) |
50 audio_thread_->init_com_with_mta(true); | 53 audio_thread_->init_com_with_mta(true); |
51 #endif | 54 #endif |
52 CHECK(audio_thread_->Start()); | 55 CHECK(audio_thread_->Start()); |
53 message_loop_ = audio_thread_->message_loop_proxy(); | 56 message_loop_ = audio_thread_->message_loop_proxy(); |
54 } | 57 } |
55 | 58 |
56 AudioManagerBase::~AudioManagerBase() { | 59 AudioManagerBase::~AudioManagerBase() { |
57 // The platform specific AudioManager implementation must have already | 60 // The platform specific AudioManager implementation must have already |
58 // stopped the audio thread. Otherwise, we may destroy audio streams before | 61 // stopped the audio thread. Otherwise, we may destroy audio streams before |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
93 return NULL; | 96 return NULL; |
94 } | 97 } |
95 | 98 |
96 // If there are no audio output devices we should use a FakeAudioOutputStream | 99 // If there are no audio output devices we should use a FakeAudioOutputStream |
97 // to ensure video playback continues to work. | 100 // to ensure video playback continues to work. |
98 bool audio_output_disabled = | 101 bool audio_output_disabled = |
99 params.format() == AudioParameters::AUDIO_FAKE || | 102 params.format() == AudioParameters::AUDIO_FAKE || |
100 !HasAudioOutputDevices(); | 103 !HasAudioOutputDevices(); |
101 | 104 |
102 AudioOutputStream* stream = NULL; | 105 AudioOutputStream* stream = NULL; |
103 if (audio_output_disabled) { | 106 if (virtual_audio_input_stream_ && |
107 params.format() != AudioParameters::AUDIO_FAKE) { | |
108 // TODO(justinlin): This seems to sometimes be called twice for 1 video. | |
Alpha Left Google
2012/11/28 01:04:47
What should this TODO do?
justinlin
2012/11/28 14:30:31
Right, I'll remove the TODO and fix this.
| |
109 // They both attach, but then one of them detaches prematurely, and the | |
110 // other one doesn't detach which causes a DCHECK fail? | |
111 stream = VirtualAudioOutputStream::MakeStream(this, params, | |
112 virtual_audio_input_stream_); | |
113 } else if (audio_output_disabled) { | |
104 stream = FakeAudioOutputStream::MakeFakeStream(this, params); | 114 stream = FakeAudioOutputStream::MakeFakeStream(this, params); |
105 } else if (params.format() == AudioParameters::AUDIO_PCM_LINEAR) { | 115 } else if (params.format() == AudioParameters::AUDIO_PCM_LINEAR) { |
106 stream = MakeLinearOutputStream(params); | 116 stream = MakeLinearOutputStream(params); |
107 } else if (params.format() == AudioParameters::AUDIO_PCM_LOW_LATENCY) { | 117 } else if (params.format() == AudioParameters::AUDIO_PCM_LOW_LATENCY) { |
108 stream = MakeLowLatencyOutputStream(params); | 118 stream = MakeLowLatencyOutputStream(params); |
109 } | 119 } |
110 | 120 |
111 if (stream) | 121 if (stream) |
112 ++num_output_streams_; | 122 ++num_output_streams_; |
113 | 123 |
114 return stream; | 124 return stream; |
115 } | 125 } |
116 | 126 |
117 AudioInputStream* AudioManagerBase::MakeAudioInputStream( | 127 AudioInputStream* AudioManagerBase::MakeAudioInputStream( |
118 const AudioParameters& params, const std::string& device_id) { | 128 const AudioParameters& params, const std::string& device_id) { |
119 if (!params.IsValid() || (params.channels() > kMaxInputChannels) || | 129 if (!params.IsValid() || (params.channels() > kMaxInputChannels) || |
120 device_id.empty()) { | 130 device_id.empty()) { |
121 DLOG(ERROR) << "Audio parameters are invalid for device " << device_id; | 131 DLOG(ERROR) << "Audio parameters are invalid for device " << device_id; |
122 return NULL; | 132 return NULL; |
123 } | 133 } |
124 | 134 |
125 if (num_input_streams_ >= max_num_input_streams_) { | 135 if (num_input_streams_ >= max_num_input_streams_) { |
126 DLOG(ERROR) << "Number of opened input audio streams " | 136 DLOG(ERROR) << "Number of opened input audio streams " |
127 << num_input_streams_ | 137 << num_input_streams_ |
128 << " exceed the max allowed number " << max_num_input_streams_; | 138 << " exceed the max allowed number " << max_num_input_streams_; |
129 return NULL; | 139 return NULL; |
130 } | 140 } |
131 | 141 |
132 AudioInputStream* stream = NULL; | 142 AudioInputStream* stream = NULL; |
133 if (params.format() == AudioParameters::AUDIO_FAKE) { | 143 if (params.format() == AudioParameters::AUDIO_MIRROR_BROWSER) { |
144 // TODO(justinlin): Currently, we can only support mirroring audio from 1 | |
Alpha Left Google
2012/11/28 01:04:47
No need to mention tab.
You can just mention the
justinlin
2012/11/28 14:30:31
Done.
| |
145 // tab, so subsequent tab capture requests will just get fake audio. | |
146 // Maybe we should just return the same stream and ref-count, so that we | |
147 // only actually destroy the stream when there's no mirroring? | |
148 if (!virtual_audio_input_stream_) { | |
149 virtual_audio_input_stream_ = | |
150 VirtualAudioInputStream::MakeStream(this, params); | |
151 stream = virtual_audio_input_stream_; | |
152 message_loop_->PostTask(FROM_HERE, base::Bind( | |
Alpha Left Google
2012/11/28 01:04:47
What would this task do?
justinlin
2012/11/28 14:30:31
NotifyAllOutputChangeListeners needs to be called
| |
153 &AudioManagerBase::NotifyAllOutputDeviceChangeListeners, | |
154 base::Unretained(this))); | |
155 } else { | |
156 // TODO(justinlin): Maybe we can return NULL if this doesn't cause the | |
Alpha Left Google
2012/11/28 01:04:47
This code doesn't need a TODO isn't it?
justinlin
2012/11/28 14:30:31
Done.
| |
157 // media request to fail? | |
158 stream = FakeAudioInputStream::MakeFakeStream(this, params); | |
159 } | |
160 } else if (params.format() == AudioParameters::AUDIO_FAKE) { | |
134 stream = FakeAudioInputStream::MakeFakeStream(this, params); | 161 stream = FakeAudioInputStream::MakeFakeStream(this, params); |
135 } else if (params.format() == AudioParameters::AUDIO_PCM_LINEAR) { | 162 } else if (params.format() == AudioParameters::AUDIO_PCM_LINEAR) { |
136 stream = MakeLinearInputStream(params, device_id); | 163 stream = MakeLinearInputStream(params, device_id); |
137 } else if (params.format() == AudioParameters::AUDIO_PCM_LOW_LATENCY) { | 164 } else if (params.format() == AudioParameters::AUDIO_PCM_LOW_LATENCY) { |
138 stream = MakeLowLatencyInputStream(params, device_id); | 165 stream = MakeLowLatencyInputStream(params, device_id); |
139 } | 166 } |
140 | 167 |
141 if (stream) | 168 if (stream) |
142 ++num_input_streams_; | 169 ++num_input_streams_; |
143 | 170 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
226 } | 253 } |
227 | 254 |
228 void AudioManagerBase::ShowAudioInputSettings() { | 255 void AudioManagerBase::ShowAudioInputSettings() { |
229 } | 256 } |
230 | 257 |
231 void AudioManagerBase::GetAudioInputDeviceNames( | 258 void AudioManagerBase::GetAudioInputDeviceNames( |
232 media::AudioDeviceNames* device_names) { | 259 media::AudioDeviceNames* device_names) { |
233 } | 260 } |
234 | 261 |
235 void AudioManagerBase::ReleaseOutputStream(AudioOutputStream* stream) { | 262 void AudioManagerBase::ReleaseOutputStream(AudioOutputStream* stream) { |
263 DCHECK(message_loop_->BelongsToCurrentThread()); | |
236 DCHECK(stream); | 264 DCHECK(stream); |
237 // TODO(xians) : Have a clearer destruction path for the AudioOutputStream. | 265 // TODO(xians) : Have a clearer destruction path for the AudioOutputStream. |
238 // For example, pass the ownership to AudioManager so it can delete the | 266 // For example, pass the ownership to AudioManager so it can delete the |
239 // streams. | 267 // streams. |
240 num_output_streams_--; | 268 num_output_streams_--; |
241 delete stream; | 269 delete stream; |
242 } | 270 } |
243 | 271 |
244 void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) { | 272 void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) { |
273 DCHECK(message_loop_->BelongsToCurrentThread()); | |
245 DCHECK(stream); | 274 DCHECK(stream); |
246 // TODO(xians) : Have a clearer destruction path for the AudioInputStream. | 275 // TODO(xians) : Have a clearer destruction path for the AudioInputStream. |
276 | |
277 if (virtual_audio_input_stream_ == stream) { | |
278 virtual_audio_input_stream_->Stop(); | |
279 virtual_audio_input_stream_ = NULL; | |
280 NotifyAllOutputDeviceChangeListeners(); | |
Alpha Left Google
2012/11/28 01:04:47
What should the output streams do? Write a comment
justinlin
2012/11/28 14:30:31
Done.
| |
281 } | |
282 | |
247 num_input_streams_--; | 283 num_input_streams_--; |
248 delete stream; | 284 delete stream; |
249 } | 285 } |
250 | 286 |
251 void AudioManagerBase::IncreaseActiveInputStreamCount() { | 287 void AudioManagerBase::IncreaseActiveInputStreamCount() { |
252 base::AtomicRefCountInc(&num_active_input_streams_); | 288 base::AtomicRefCountInc(&num_active_input_streams_); |
253 } | 289 } |
254 | 290 |
255 void AudioManagerBase::DecreaseActiveInputStreamCount() { | 291 void AudioManagerBase::DecreaseActiveInputStreamCount() { |
256 DCHECK(IsRecordingInProcess()); | 292 DCHECK(IsRecordingInProcess()); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
340 output_listeners_.RemoveObserver(listener); | 376 output_listeners_.RemoveObserver(listener); |
341 } | 377 } |
342 | 378 |
343 void AudioManagerBase::NotifyAllOutputDeviceChangeListeners() { | 379 void AudioManagerBase::NotifyAllOutputDeviceChangeListeners() { |
344 DCHECK(message_loop_->BelongsToCurrentThread()); | 380 DCHECK(message_loop_->BelongsToCurrentThread()); |
345 DVLOG(1) << "Firing OnDeviceChange() notifications."; | 381 DVLOG(1) << "Firing OnDeviceChange() notifications."; |
346 FOR_EACH_OBSERVER(AudioDeviceListener, output_listeners_, OnDeviceChange()); | 382 FOR_EACH_OBSERVER(AudioDeviceListener, output_listeners_, OnDeviceChange()); |
347 } | 383 } |
348 | 384 |
349 } // namespace media | 385 } // namespace media |
OLD | NEW |