Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(238)

Side by Side Diff: media/audio/mac/audio_manager_mac.cc

Issue 9570014: Move some generic functions to AudioManagerBase to be inherited by platform-specific AudioManager*** (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: changed the GetMaxOutputStreamsAllowed Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 <CoreAudio/AudioHardware.h> 5 #include <CoreAudio/AudioHardware.h>
6 6
7 #include "base/mac/mac_logging.h" 7 #include "base/mac/mac_logging.h"
8 #include "base/mac/mac_util.h" 8 #include "base/mac/mac_util.h"
9 #include "base/mac/scoped_cftyperef.h" 9 #include "base/mac/scoped_cftyperef.h"
10 #include "base/sys_string_conversions.h" 10 #include "base/sys_string_conversions.h"
11 #include "media/audio/fake_audio_input_stream.h"
12 #include "media/audio/fake_audio_output_stream.h"
13 #include "media/audio/mac/audio_input_mac.h" 11 #include "media/audio/mac/audio_input_mac.h"
14 #include "media/audio/mac/audio_low_latency_input_mac.h" 12 #include "media/audio/mac/audio_low_latency_input_mac.h"
15 #include "media/audio/mac/audio_low_latency_output_mac.h" 13 #include "media/audio/mac/audio_low_latency_output_mac.h"
16 #include "media/audio/mac/audio_manager_mac.h" 14 #include "media/audio/mac/audio_manager_mac.h"
17 #include "media/audio/mac/audio_output_mac.h" 15 #include "media/audio/mac/audio_output_mac.h"
18 #include "media/base/limits.h" 16 #include "media/base/limits.h"
19 17
20 static const int kMaxInputChannels = 2; 18 static const int kMaxInputChannels = 2;
21 19
22 // Maximum number of output streams that can be open simultaneously. 20 // Maximum number of output streams that can be open simultaneously.
23 static const size_t kMaxOutputStreams = 50; 21 static const int kMaxOutputStreams = 50;
24 22
25 // By experiment the maximum number of audio streams allowed in Leopard 23 // By experiment the maximum number of audio streams allowed in Leopard
26 // is 18. But we put a slightly smaller number just to be safe. 24 // is 18. But we put a slightly smaller number just to be safe.
27 static const size_t kMaxOutputStreamsLeopard = 15; 25 static const int kMaxOutputStreamsLeopard = 15;
28
29 // Initialized to ether |kMaxOutputStreams| or |kMaxOutputStreamsLeopard|.
30 static size_t g_max_output_streams = 0;
31
32 // Returns the number of audio streams allowed. This is a practical limit to
33 // prevent failure caused by too many audio streams opened.
34 static size_t GetMaxAudioOutputStreamsAllowed() {
35 if (g_max_output_streams == 0) {
36 // We are hitting a bug in Leopard where too many audio streams will cause
37 // a deadlock in the AudioQueue API when starting the stream. Unfortunately
38 // there's no way to detect it within the AudioQueue API, so we put a
39 // special hard limit only for Leopard.
40 // See bug: http://crbug.com/30242
41 if (base::mac::IsOSLeopardOrEarlier()) {
42 g_max_output_streams = kMaxOutputStreamsLeopard;
43 } else {
44 // In OS other than OSX Leopard, the number of audio streams
45 // allowed is a lot more.
46 g_max_output_streams = kMaxOutputStreams;
47 }
48 }
49
50 return g_max_output_streams;
51 }
52 26
53 static bool HasAudioHardware(AudioObjectPropertySelector selector) { 27 static bool HasAudioHardware(AudioObjectPropertySelector selector) {
54 AudioDeviceID output_device_id = kAudioObjectUnknown; 28 AudioDeviceID output_device_id = kAudioObjectUnknown;
55 const AudioObjectPropertyAddress property_address = { 29 const AudioObjectPropertyAddress property_address = {
56 selector, 30 selector,
57 kAudioObjectPropertyScopeGlobal, // mScope 31 kAudioObjectPropertyScopeGlobal, // mScope
58 kAudioObjectPropertyElementMaster // mElement 32 kAudioObjectPropertyElementMaster // mElement
59 }; 33 };
60 size_t output_device_id_size = sizeof(output_device_id); 34 size_t output_device_id_size = sizeof(output_device_id);
61 OSStatus err = AudioObjectGetPropertyData(kAudioObjectSystemObject, 35 OSStatus err = AudioObjectGetPropertyData(kAudioObjectSystemObject,
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 } 202 }
229 203
230 if (result) { 204 if (result) {
231 OSSTATUS_DLOG(WARNING, result) << "Unable to query device " << device_id 205 OSSTATUS_DLOG(WARNING, result) << "Unable to query device " << device_id
232 << " for AudioDeviceID"; 206 << " for AudioDeviceID";
233 } 207 }
234 208
235 return audio_device_id; 209 return audio_device_id;
236 } 210 }
237 211
238 AudioManagerMac::AudioManagerMac() 212 AudioManagerMac::AudioManagerMac() {
239 : num_output_streams_(0) { 213 // We are hitting a bug in Leopard where too many audio streams will cause
214 // a deadlock in the AudioQueue API when starting the stream. Unfortunately
215 // there's no way to detect it within the AudioQueue API, so we put a
216 // special hard limit only for Leopard.
217 // See bug: http://crbug.com/30242
218 // In OS other than OSX Leopard, the number of audio streams
219 // allowed is a lot more.
220 int max_output_stream = base::mac::IsOSLeopardOrEarlier() ?
221 kMaxOutputStreamsLeopard : kMaxOutputStreams;
222 SetMaxOutputStreamsAllowed(max_output_stream);
240 } 223 }
241 224
242 AudioManagerMac::~AudioManagerMac() { 225 AudioManagerMac::~AudioManagerMac() {
243 } 226 }
244 227
245 bool AudioManagerMac::HasAudioOutputDevices() { 228 bool AudioManagerMac::HasAudioOutputDevices() {
246 return HasAudioHardware(kAudioHardwarePropertyDefaultOutputDevice); 229 return HasAudioHardware(kAudioHardwarePropertyDefaultOutputDevice);
247 } 230 }
248 231
249 bool AudioManagerMac::HasAudioInputDevices() { 232 bool AudioManagerMac::HasAudioInputDevices() {
(...skipping 12 matching lines...) Expand all
262 // Prepend the default device to the list since we always want it to be 245 // Prepend the default device to the list since we always want it to be
263 // on the top of the list for all platforms. There is no duplicate 246 // on the top of the list for all platforms. There is no duplicate
264 // counting here since the default device has been abstracted out before. 247 // counting here since the default device has been abstracted out before.
265 media::AudioDeviceName name; 248 media::AudioDeviceName name;
266 name.device_name = AudioManagerBase::kDefaultDeviceName; 249 name.device_name = AudioManagerBase::kDefaultDeviceName;
267 name.unique_id = AudioManagerBase::kDefaultDeviceId; 250 name.unique_id = AudioManagerBase::kDefaultDeviceId;
268 device_names->push_front(name); 251 device_names->push_front(name);
269 } 252 }
270 } 253 }
271 254
272 AudioOutputStream* AudioManagerMac::MakeAudioOutputStream(
273 const AudioParameters& params) {
274 if (!params.IsValid())
275 return NULL;
276
277 // Limit the number of audio streams opened. This is to prevent using
278 // excessive resources for a large number of audio streams. More
279 // importantly it prevents instability on certain systems.
280 // See bug: http://crbug.com/30242
281 if (num_output_streams_ >= GetMaxAudioOutputStreamsAllowed()) {
282 return NULL;
283 }
284
285 if (params.format == AudioParameters::AUDIO_MOCK) {
286 return FakeAudioOutputStream::MakeFakeStream(params);
287 } else if (params.format == AudioParameters::AUDIO_PCM_LINEAR) {
288 num_output_streams_++;
289 return new PCMQueueOutAudioOutputStream(this, params);
290 } else if (params.format == AudioParameters::AUDIO_PCM_LOW_LATENCY) {
291 num_output_streams_++;
292 return new AUAudioOutputStream(this, params);
293 }
294 return NULL;
295 }
296
297 AudioInputStream* AudioManagerMac::MakeAudioInputStream(
298 const AudioParameters& params, const std::string& device_id) {
299 if (!params.IsValid() || (params.channels > kMaxInputChannels) ||
300 device_id.empty())
301 return NULL;
302
303 if (params.format == AudioParameters::AUDIO_MOCK) {
304 return FakeAudioInputStream::MakeFakeStream(params);
305 } else if (params.format == AudioParameters::AUDIO_PCM_LINEAR) {
306 return new PCMQueueInAudioInputStream(this, params);
307 } else if (params.format == AudioParameters::AUDIO_PCM_LOW_LATENCY) {
308 // Gets the AudioDeviceID that refers to the AudioDevice with the device
309 // unique id. This AudioDeviceID is used to set the device for Audio Unit.
310 AudioDeviceID audio_device_id = GetAudioDeviceIdByUId(true, device_id);
311 if (audio_device_id != kAudioObjectUnknown)
312 return new AUAudioInputStream(this, params, audio_device_id);
313 }
314 return NULL;
315 }
316
317 void AudioManagerMac::MuteAll() { 255 void AudioManagerMac::MuteAll() {
318 // TODO(cpu): implement. 256 // TODO(cpu): implement.
319 } 257 }
320 258
321 void AudioManagerMac::UnMuteAll() { 259 void AudioManagerMac::UnMuteAll() {
322 // TODO(cpu): implement. 260 // TODO(cpu): implement.
323 } 261 }
324 262
325 // Called by the stream when it has been released by calling Close(). 263 AudioOutputStream* AudioManagerMac::MakeLinearOutputStream(
326 void AudioManagerMac::ReleaseOutputStream(AudioOutputStream* stream) { 264 const AudioParameters& params) {
327 DCHECK(stream); 265 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format);
328 num_output_streams_--; 266 return new PCMQueueOutAudioOutputStream(this, params);
329 delete stream;
330 } 267 }
331 268
332 // Called by the stream when it has been released by calling Close(). 269 AudioOutputStream* AudioManagerMac::MakeLowLatencyOutputStream(
333 void AudioManagerMac::ReleaseInputStream(AudioInputStream* stream) { 270 const AudioParameters& params) {
334 delete stream; 271 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format);
272 return new AUAudioOutputStream(this, params);
273 }
274
275 AudioInputStream* AudioManagerMac::MakeLinearInputStream(
276 const AudioParameters& params, const std::string& device_id) {
277 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format);
278 return new PCMQueueInAudioInputStream(this, params);
279 }
280
281 AudioInputStream* AudioManagerMac::MakeLowLatencyInputStream(
282 const AudioParameters& params, const std::string& device_id) {
283 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format);
284 // Gets the AudioDeviceID that refers to the AudioDevice with the device
285 // unique id. This AudioDeviceID is used to set the device for Audio Unit.
286 AudioDeviceID audio_device_id = GetAudioDeviceIdByUId(true, device_id);
287 AudioInputStream* stream = NULL;
288 if (audio_device_id != kAudioObjectUnknown)
289 stream = new AUAudioInputStream(this, params, audio_device_id);
290
291 return stream;
335 } 292 }
336 293
337 AudioManager* CreateAudioManager() { 294 AudioManager* CreateAudioManager() {
338 return new AudioManagerMac(); 295 return new AudioManagerMac();
339 } 296 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698