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

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: fix the memory leak in the alsa unittests 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 26
29 // Initialized to ether |kMaxOutputStreams| or |kMaxOutputStreamsLeopard|. 27 // Initialized to ether |kMaxOutputStreams| or |kMaxOutputStreamsLeopard|.
30 static size_t g_max_output_streams = 0; 28 static int 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 29
53 static bool HasAudioHardware(AudioObjectPropertySelector selector) { 30 static bool HasAudioHardware(AudioObjectPropertySelector selector) {
54 AudioDeviceID output_device_id = kAudioObjectUnknown; 31 AudioDeviceID output_device_id = kAudioObjectUnknown;
55 const AudioObjectPropertyAddress property_address = { 32 const AudioObjectPropertyAddress property_address = {
56 selector, 33 selector,
57 kAudioObjectPropertyScopeGlobal, // mScope 34 kAudioObjectPropertyScopeGlobal, // mScope
58 kAudioObjectPropertyElementMaster // mElement 35 kAudioObjectPropertyElementMaster // mElement
59 }; 36 };
60 size_t output_device_id_size = sizeof(output_device_id); 37 size_t output_device_id_size = sizeof(output_device_id);
61 OSStatus err = AudioObjectGetPropertyData(kAudioObjectSystemObject, 38 OSStatus err = AudioObjectGetPropertyData(kAudioObjectSystemObject,
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 } 205 }
229 206
230 if (result) { 207 if (result) {
231 OSSTATUS_DLOG(WARNING, result) << "Unable to query device " << device_id 208 OSSTATUS_DLOG(WARNING, result) << "Unable to query device " << device_id
232 << " for AudioDeviceID"; 209 << " for AudioDeviceID";
233 } 210 }
234 211
235 return audio_device_id; 212 return audio_device_id;
236 } 213 }
237 214
238 AudioManagerMac::AudioManagerMac() 215 AudioManagerMac::AudioManagerMac() {
239 : num_output_streams_(0) {
240 } 216 }
241 217
242 AudioManagerMac::~AudioManagerMac() { 218 AudioManagerMac::~AudioManagerMac() {
243 } 219 }
244 220
245 bool AudioManagerMac::HasAudioOutputDevices() { 221 bool AudioManagerMac::HasAudioOutputDevices() {
246 return HasAudioHardware(kAudioHardwarePropertyDefaultOutputDevice); 222 return HasAudioHardware(kAudioHardwarePropertyDefaultOutputDevice);
247 } 223 }
248 224
249 bool AudioManagerMac::HasAudioInputDevices() { 225 bool AudioManagerMac::HasAudioInputDevices() {
(...skipping 12 matching lines...) Expand all
262 // Prepend the default device to the list since we always want it to be 238 // 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 239 // 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. 240 // counting here since the default device has been abstracted out before.
265 media::AudioDeviceName name; 241 media::AudioDeviceName name;
266 name.device_name = AudioManagerBase::kDefaultDeviceName; 242 name.device_name = AudioManagerBase::kDefaultDeviceName;
267 name.unique_id = AudioManagerBase::kDefaultDeviceId; 243 name.unique_id = AudioManagerBase::kDefaultDeviceId;
268 device_names->push_front(name); 244 device_names->push_front(name);
269 } 245 }
270 } 246 }
271 247
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() { 248 void AudioManagerMac::MuteAll() {
318 // TODO(cpu): implement. 249 // TODO(cpu): implement.
319 } 250 }
320 251
321 void AudioManagerMac::UnMuteAll() { 252 void AudioManagerMac::UnMuteAll() {
322 // TODO(cpu): implement. 253 // TODO(cpu): implement.
323 } 254 }
324 255
325 // Called by the stream when it has been released by calling Close(). 256 int AudioManagerMac::GetMaxAudioOutputStreamsAllowed() {
326 void AudioManagerMac::ReleaseOutputStream(AudioOutputStream* stream) { 257 if (g_max_output_streams == 0) {
327 DCHECK(stream); 258 // We are hitting a bug in Leopard where too many audio streams will cause
328 num_output_streams_--; 259 // a deadlock in the AudioQueue API when starting the stream. Unfortunately
329 delete stream; 260 // there's no way to detect it within the AudioQueue API, so we put a
261 // special hard limit only for Leopard.
262 // See bug: http://crbug.com/30242
263 if (base::mac::IsOSLeopardOrEarlier()) {
264 g_max_output_streams = kMaxOutputStreamsLeopard;
265 } else {
266 // In OS other than OSX Leopard, the number of audio streams
267 // allowed is a lot more.
268 g_max_output_streams = kMaxOutputStreams;
269 }
270 }
271
272 return g_max_output_streams;
330 } 273 }
331 274
332 // Called by the stream when it has been released by calling Close(). 275 AudioOutputStream* AudioManagerMac::MakeAudioLinearOutputStream(
333 void AudioManagerMac::ReleaseInputStream(AudioInputStream* stream) { 276 const AudioParameters& params) {
334 delete stream; 277 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format);
278 return new PCMQueueOutAudioOutputStream(this, params);
279 }
280
281 AudioOutputStream* AudioManagerMac::MakeAudioLowLatencyOutputStream(
282 const AudioParameters& params) {
283 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format);
284 return new AUAudioOutputStream(this, params);
285 }
286
287 AudioInputStream* AudioManagerMac::MakeAudioLinearInputStream(
288 const AudioParameters& params, const std::string& device_id) {
289 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format);
290 return new PCMQueueInAudioInputStream(this, params);
291 }
292
293 AudioInputStream* AudioManagerMac::MakeAudioLowLatencyInputStream(
294 const AudioParameters& params, const std::string& device_id) {
295 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format);
296 // Gets the AudioDeviceID that refers to the AudioDevice with the device
297 // unique id. This AudioDeviceID is used to set the device for Audio Unit.
298 AudioDeviceID audio_device_id = GetAudioDeviceIdByUId(true, device_id);
299 AudioInputStream* stream = NULL;
300 if (audio_device_id != kAudioObjectUnknown)
301 stream = new AUAudioInputStream(this, params, audio_device_id);
302
303 return stream;
335 } 304 }
336 305
337 AudioManager* CreateAudioManager() { 306 AudioManager* CreateAudioManager() {
338 return new AudioManagerMac(); 307 return new AudioManagerMac();
339 } 308 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698