OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/mac/audio_output_mac.h" | 5 #include "media/audio/mac/audio_output_mac.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
10 #include "media/audio/audio_util.h" | 10 #include "media/audio/audio_util.h" |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
89 // pointer while we operate here. Note that does not mean that the source | 89 // pointer while we operate here. Note that does not mean that the source |
90 // has been destroyed. | 90 // has been destroyed. |
91 AudioSourceCallback* source = source_; | 91 AudioSourceCallback* source = source_; |
92 if (source) | 92 if (source) |
93 source->OnError(this, static_cast<int>(err)); | 93 source->OnError(this, static_cast<int>(err)); |
94 NOTREACHED() << "error code " << err; | 94 NOTREACHED() << "error code " << err; |
95 } | 95 } |
96 | 96 |
97 bool PCMQueueOutAudioOutputStream::Open() { | 97 bool PCMQueueOutAudioOutputStream::Open() { |
98 // Get the default device id. | 98 // Get the default device id. |
99 unsigned int device_id = 0; | 99 AudioObjectID device_id = 0; |
100 AudioObjectPropertyAddress property_address = { | 100 AudioObjectPropertyAddress property_address = { |
101 kAudioHardwarePropertyDefaultOutputDevice, | 101 kAudioHardwarePropertyDefaultOutputDevice, |
102 kAudioObjectPropertyScopeGlobal, | 102 kAudioObjectPropertyScopeGlobal, |
103 kAudioObjectPropertyElementMaster | 103 kAudioObjectPropertyElementMaster |
104 }; | 104 }; |
105 UInt32 device_id_size = sizeof(device_id); | 105 UInt32 device_id_size = sizeof(device_id); |
106 OSStatus err = AudioObjectGetPropertyData(kAudioObjectSystemObject, | 106 OSStatus err = AudioObjectGetPropertyData(kAudioObjectSystemObject, |
107 &property_address, 0, NULL, | 107 &property_address, 0, NULL, |
108 &device_id_size, &device_id); | 108 &device_id_size, &device_id); |
109 if (err != noErr) { | 109 if (err != noErr) { |
110 HandleError(err); | 110 HandleError(err); |
111 return false; | 111 return false; |
112 } | 112 } |
113 // Get the size of the channel layout. | 113 // Get the size of the channel layout. |
114 UInt32 core_layout_size; | 114 UInt32 core_layout_size; |
115 // TODO(annacc): AudioDeviceGetPropertyInfo() is deprecated, but its | |
116 // replacement, AudioObjectGetPropertyDataSize(), doesn't work yet with | |
117 // kAudioDevicePropertyPreferredChannelLayout. | |
115 err = AudioDeviceGetPropertyInfo(device_id, 0, false, | 118 err = AudioDeviceGetPropertyInfo(device_id, 0, false, |
116 kAudioDevicePropertyPreferredChannelLayout, | 119 kAudioDevicePropertyPreferredChannelLayout, |
117 &core_layout_size, NULL); | 120 &core_layout_size, NULL); |
118 if (err != noErr) { | 121 if (err != noErr) { |
119 HandleError(err); | 122 HandleError(err); |
120 return false; | 123 return false; |
121 } | 124 } |
122 // Get the device's channel layout. This layout may vary in sized based on | 125 // Get the device's channel layout. This layout may vary in sized based on |
123 // the number of channels. Use |core_layout_size| to allocate memory. | 126 // the number of channels. Use |core_layout_size| to allocate memory. |
124 scoped_ptr_malloc<AudioChannelLayout> core_channel_layout; | 127 scoped_ptr_malloc<AudioChannelLayout> core_channel_layout; |
125 core_channel_layout.reset( | 128 core_channel_layout.reset( |
126 reinterpret_cast<AudioChannelLayout*>(malloc(core_layout_size))); | 129 reinterpret_cast<AudioChannelLayout*>(malloc(core_layout_size))); |
127 memset(core_channel_layout.get(), 0, core_layout_size); | 130 memset(core_channel_layout.get(), 0, core_layout_size); |
131 // TODO(annacc): AudioDeviceGetProperty() is deprecated, but its | |
132 // replacement, AudioObjectGetPropertyData(), doesn't work yet with | |
133 // kAudioDevicePropertyPreferredChannelLayout. | |
128 err = AudioDeviceGetProperty(device_id, 0, false, | 134 err = AudioDeviceGetProperty(device_id, 0, false, |
129 kAudioDevicePropertyPreferredChannelLayout, | 135 kAudioDevicePropertyPreferredChannelLayout, |
130 &core_layout_size, core_channel_layout.get()); | 136 &core_layout_size, core_channel_layout.get()); |
131 if (err != noErr) { | 137 if (err != noErr) { |
132 HandleError(err); | 138 HandleError(err); |
133 return false; | 139 return false; |
134 } | 140 } |
135 | 141 |
136 num_core_channels_ = | 142 num_core_channels_ = |
137 static_cast<int>(core_channel_layout->mNumberChannelDescriptions); | 143 static_cast<int>(core_channel_layout->mNumberChannelDescriptions); |
(...skipping 29 matching lines...) Expand all Loading... | |
167 err = AudioQueueSetParameter(audio_queue_, kAudioQueueParam_Volume, 1.0); | 173 err = AudioQueueSetParameter(audio_queue_, kAudioQueueParam_Volume, 1.0); |
168 if (err != noErr) { | 174 if (err != noErr) { |
169 HandleError(err); | 175 HandleError(err); |
170 return false; | 176 return false; |
171 } | 177 } |
172 | 178 |
173 // Capture channel layout in a format we can use. | 179 // Capture channel layout in a format we can use. |
174 for (int i = 0; i < CHANNELS_MAX; ++i) | 180 for (int i = 0; i < CHANNELS_MAX; ++i) |
175 core_channel_orderings_[i] = kEmptyChannel; | 181 core_channel_orderings_[i] = kEmptyChannel; |
176 | 182 |
183 bool all_channels_unknown = true; | |
177 for (int i = 0; i < num_core_channels_; ++i) { | 184 for (int i = 0; i < num_core_channels_; ++i) { |
178 switch (core_channel_layout->mChannelDescriptions[i].mChannelLabel) { | 185 AudioChannelLabel label = |
186 core_channel_layout->mChannelDescriptions[i].mChannelLabel; | |
187 if (label == kAudioChannelLabel_Unknown) { | |
188 all_channels_unknown = false; | |
scherkus (not reviewing)
2011/06/07 23:12:15
shouldn't this be outside the if statement?
annacc
2011/06/07 23:34:26
Whoa! Movin' too fast. Good catch!!
| |
189 continue; | |
190 } | |
191 switch (label) { | |
179 case kAudioChannelLabel_Left: | 192 case kAudioChannelLabel_Left: |
180 core_channel_orderings_[LEFT] = i; | 193 core_channel_orderings_[LEFT] = i; |
181 channel_remap_[i] = kChannelOrderings[source_layout_][LEFT]; | 194 channel_remap_[i] = kChannelOrderings[source_layout_][LEFT]; |
182 break; | 195 break; |
183 case kAudioChannelLabel_Right: | 196 case kAudioChannelLabel_Right: |
184 core_channel_orderings_[RIGHT] = i; | 197 core_channel_orderings_[RIGHT] = i; |
185 channel_remap_[i] = kChannelOrderings[source_layout_][RIGHT]; | 198 channel_remap_[i] = kChannelOrderings[source_layout_][RIGHT]; |
186 break; | 199 break; |
187 case kAudioChannelLabel_Center: | 200 case kAudioChannelLabel_Center: |
188 core_channel_orderings_[CENTER] = i; | 201 core_channel_orderings_[CENTER] = i; |
(...skipping 24 matching lines...) Expand all Loading... | |
213 channel_remap_[i] = kChannelOrderings[source_layout_][BACK_CENTER]; | 226 channel_remap_[i] = kChannelOrderings[source_layout_][BACK_CENTER]; |
214 break; | 227 break; |
215 case kAudioChannelLabel_RearSurroundLeft: | 228 case kAudioChannelLabel_RearSurroundLeft: |
216 core_channel_orderings_[BACK_LEFT] = i; | 229 core_channel_orderings_[BACK_LEFT] = i; |
217 channel_remap_[i] = kChannelOrderings[source_layout_][BACK_LEFT]; | 230 channel_remap_[i] = kChannelOrderings[source_layout_][BACK_LEFT]; |
218 break; | 231 break; |
219 case kAudioChannelLabel_RearSurroundRight: | 232 case kAudioChannelLabel_RearSurroundRight: |
220 core_channel_orderings_[BACK_RIGHT] = i; | 233 core_channel_orderings_[BACK_RIGHT] = i; |
221 channel_remap_[i] = kChannelOrderings[source_layout_][BACK_RIGHT]; | 234 channel_remap_[i] = kChannelOrderings[source_layout_][BACK_RIGHT]; |
222 break; | 235 break; |
236 case kAudioChannelLabel_Unknown: | |
scherkus (not reviewing)
2011/06/07 23:12:15
this code will never get executed due to if statem
annacc
2011/06/07 23:34:26
True, it's gone.
| |
237 channel_remap_[i] = kEmptyChannel; | |
238 break; | |
223 default: | 239 default: |
224 DLOG(WARNING) << "Channel label not supported"; | 240 DLOG(WARNING) << "Channel label not supported"; |
225 channel_remap_[i] = kEmptyChannel; | 241 channel_remap_[i] = kEmptyChannel; |
226 break; | 242 break; |
227 } | 243 } |
228 } | 244 } |
229 | 245 |
246 if (all_channels_unknown) { | |
247 return true; | |
248 } | |
249 | |
230 // Check if we need to adjust the layout. | 250 // Check if we need to adjust the layout. |
231 // If the device has a BACK_LEFT and no SIDE_LEFT and the source has | 251 // If the device has a BACK_LEFT and no SIDE_LEFT and the source has |
232 // a SIDE_LEFT but no BACK_LEFT, then move (and preserve the channel). | 252 // a SIDE_LEFT but no BACK_LEFT, then move (and preserve the channel). |
233 // e.g. CHANNEL_LAYOUT_5POINT1 -> CHANNEL_LAYOUT_5POINT1_BACK | 253 // e.g. CHANNEL_LAYOUT_5POINT1 -> CHANNEL_LAYOUT_5POINT1_BACK |
234 CheckForAdjustedLayout(SIDE_LEFT, BACK_LEFT); | 254 CheckForAdjustedLayout(SIDE_LEFT, BACK_LEFT); |
235 // Same for SIDE_RIGHT -> BACK_RIGHT. | 255 // Same for SIDE_RIGHT -> BACK_RIGHT. |
236 CheckForAdjustedLayout(SIDE_RIGHT, BACK_RIGHT); | 256 CheckForAdjustedLayout(SIDE_RIGHT, BACK_RIGHT); |
237 // Move BACK_LEFT to SIDE_LEFT. | 257 // Move BACK_LEFT to SIDE_LEFT. |
238 // e.g. CHANNEL_LAYOUT_5POINT1_BACK -> CHANNEL_LAYOUT_5POINT1 | 258 // e.g. CHANNEL_LAYOUT_5POINT1_BACK -> CHANNEL_LAYOUT_5POINT1 |
239 CheckForAdjustedLayout(BACK_LEFT, SIDE_LEFT); | 259 CheckForAdjustedLayout(BACK_LEFT, SIDE_LEFT); |
240 // Same for BACK_RIGHT -> SIDE_RIGHT. | 260 // Same for BACK_RIGHT -> SIDE_RIGHT. |
241 CheckForAdjustedLayout(BACK_RIGHT, SIDE_RIGHT); | 261 CheckForAdjustedLayout(BACK_RIGHT, SIDE_RIGHT); |
242 // Move SIDE_LEFT to LEFT_OF_CENTER. | 262 // Move SIDE_LEFT to LEFT_OF_CENTER. |
243 // e.g. CHANNEL_LAYOUT_7POINT1 -> CHANNEL_LAYOUT_7POINT1_WIDE | 263 // e.g. CHANNEL_LAYOUT_7POINT1 -> CHANNEL_LAYOUT_7POINT1_WIDE |
244 CheckForAdjustedLayout(SIDE_LEFT, LEFT_OF_CENTER); | 264 CheckForAdjustedLayout(SIDE_LEFT, LEFT_OF_CENTER); |
245 // Same for SIDE_RIGHT -> RIGHT_OF_CENTER. | 265 // Same for SIDE_RIGHT -> RIGHT_OF_CENTER. |
246 CheckForAdjustedLayout(SIDE_RIGHT, RIGHT_OF_CENTER); | 266 CheckForAdjustedLayout(SIDE_RIGHT, RIGHT_OF_CENTER); |
247 // Move LEFT_OF_CENTER to SIDE_LEFT. | 267 // Move LEFT_OF_CENTER to SIDE_LEFT. |
248 // e.g. CHANNEL_LAYOUT_7POINT1_WIDE -> CHANNEL_LAYOUT_7POINT1 | 268 // e.g. CHANNEL_LAYOUT_7POINT1_WIDE -> CHANNEL_LAYOUT_7POINT1 |
249 CheckForAdjustedLayout(LEFT_OF_CENTER, SIDE_LEFT); | 269 CheckForAdjustedLayout(LEFT_OF_CENTER, SIDE_LEFT); |
250 // Same for RIGHT_OF_CENTER -> SIDE_RIGHT. | 270 // Same for RIGHT_OF_CENTER -> SIDE_RIGHT. |
251 CheckForAdjustedLayout(RIGHT_OF_CENTER, SIDE_RIGHT); | 271 CheckForAdjustedLayout(RIGHT_OF_CENTER, SIDE_RIGHT); |
272 // For MONO -> STEREO, move audio to LEFT and RIGHT if applicable. | |
273 CheckForAdjustedLayout(CENTER, LEFT); | |
274 CheckForAdjustedLayout(CENTER, RIGHT); | |
scherkus (not reviewing)
2011/06/07 23:12:15
this code fixes the mono bug?
annacc
2011/06/07 23:34:26
Yes, for people who have speakers already configur
| |
252 | 275 |
253 // Check if we will need to swizzle from source to device layout (maybe not!). | 276 // Check if we will need to swizzle from source to device layout (maybe not!). |
254 should_swizzle_ = false; | 277 should_swizzle_ = false; |
255 for (int i = 0; i < num_core_channels_; ++i) { | 278 for (int i = 0; i < num_core_channels_; ++i) { |
256 if (kChannelOrderings[source_layout_][i] != core_channel_orderings_[i]) { | 279 if (kChannelOrderings[source_layout_][i] != core_channel_orderings_[i]) { |
257 should_swizzle_ = true; | 280 should_swizzle_ = true; |
258 break; | 281 break; |
259 } | 282 } |
260 } | 283 } |
261 | 284 |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
468 HandleError(err); | 491 HandleError(err); |
469 return; | 492 return; |
470 } | 493 } |
471 } | 494 } |
472 err = AudioQueueStart(audio_queue_, NULL); | 495 err = AudioQueueStart(audio_queue_, NULL); |
473 if (err != noErr) { | 496 if (err != noErr) { |
474 HandleError(err); | 497 HandleError(err); |
475 return; | 498 return; |
476 } | 499 } |
477 } | 500 } |
OLD | NEW |