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; |
scherkus (not reviewing)
2011/06/07 22:43:22
double checking.. intended change?
annacc
2011/06/07 23:09:45
Yep, acts the same way, just looks prettier.
| |
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 allChannelsUnknown = true; | |
scherkus (not reviewing)
2011/06/07 22:43:22
unix_hacker style: all_channels_unknown
annacc
2011/06/07 23:09:45
Arg, I forget your crazy conventions. :) Thanks.
| |
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 = |
179 case kAudioChannelLabel_Left: | 186 core_channel_layout->mChannelDescriptions[i].mChannelLabel; |
180 core_channel_orderings_[LEFT] = i; | 187 if (label != kAudioChannelLabel_Unknown) { |
scherkus (not reviewing)
2011/06/07 22:43:22
nit: instead check for opposite condition + contin
annacc
2011/06/07 23:09:45
Done.
| |
181 channel_remap_[i] = kChannelOrderings[source_layout_][LEFT]; | 188 allChannelsUnknown = false; |
182 break; | 189 switch (label) { |
183 case kAudioChannelLabel_Right: | 190 case kAudioChannelLabel_Left: |
184 core_channel_orderings_[RIGHT] = i; | 191 core_channel_orderings_[LEFT] = i; |
185 channel_remap_[i] = kChannelOrderings[source_layout_][RIGHT]; | 192 channel_remap_[i] = kChannelOrderings[source_layout_][LEFT]; |
186 break; | 193 break; |
187 case kAudioChannelLabel_Center: | 194 case kAudioChannelLabel_Right: |
188 core_channel_orderings_[CENTER] = i; | 195 core_channel_orderings_[RIGHT] = i; |
189 channel_remap_[i] = kChannelOrderings[source_layout_][CENTER]; | 196 channel_remap_[i] = kChannelOrderings[source_layout_][RIGHT]; |
190 break; | 197 break; |
191 case kAudioChannelLabel_LFEScreen: | 198 case kAudioChannelLabel_Center: |
192 core_channel_orderings_[LFE] = i; | 199 core_channel_orderings_[CENTER] = i; |
193 channel_remap_[i] = kChannelOrderings[source_layout_][LFE]; | 200 channel_remap_[i] = kChannelOrderings[source_layout_][CENTER]; |
194 break; | 201 break; |
195 case kAudioChannelLabel_LeftSurround: | 202 case kAudioChannelLabel_LFEScreen: |
196 core_channel_orderings_[SIDE_LEFT] = i; | 203 core_channel_orderings_[LFE] = i; |
197 channel_remap_[i] = kChannelOrderings[source_layout_][SIDE_LEFT]; | 204 channel_remap_[i] = kChannelOrderings[source_layout_][LFE]; |
198 break; | 205 break; |
199 case kAudioChannelLabel_RightSurround: | 206 case kAudioChannelLabel_LeftSurround: |
200 core_channel_orderings_[SIDE_RIGHT] = i; | 207 core_channel_orderings_[SIDE_LEFT] = i; |
201 channel_remap_[i] = kChannelOrderings[source_layout_][SIDE_RIGHT]; | 208 channel_remap_[i] = kChannelOrderings[source_layout_][SIDE_LEFT]; |
202 break; | 209 break; |
203 case kAudioChannelLabel_LeftCenter: | 210 case kAudioChannelLabel_RightSurround: |
204 core_channel_orderings_[LEFT_OF_CENTER] = i; | 211 core_channel_orderings_[SIDE_RIGHT] = i; |
205 channel_remap_[i] = kChannelOrderings[source_layout_][LEFT_OF_CENTER]; | 212 channel_remap_[i] = kChannelOrderings[source_layout_][SIDE_RIGHT]; |
206 break; | 213 break; |
207 case kAudioChannelLabel_RightCenter: | 214 case kAudioChannelLabel_LeftCenter: |
208 core_channel_orderings_[RIGHT_OF_CENTER] = i; | 215 core_channel_orderings_[LEFT_OF_CENTER] = i; |
209 channel_remap_[i] = kChannelOrderings[source_layout_][RIGHT_OF_CENTER]; | 216 channel_remap_[i] = kChannelOrderings[source_layout_][LEFT_OF_CENTER]; |
210 break; | 217 break; |
211 case kAudioChannelLabel_CenterSurround: | 218 case kAudioChannelLabel_RightCenter: |
212 core_channel_orderings_[BACK_CENTER] = i; | 219 core_channel_orderings_[RIGHT_OF_CENTER] = i; |
213 channel_remap_[i] = kChannelOrderings[source_layout_][BACK_CENTER]; | 220 channel_remap_[i] = |
214 break; | 221 kChannelOrderings[source_layout_][RIGHT_OF_CENTER]; |
215 case kAudioChannelLabel_RearSurroundLeft: | 222 break; |
216 core_channel_orderings_[BACK_LEFT] = i; | 223 case kAudioChannelLabel_CenterSurround: |
217 channel_remap_[i] = kChannelOrderings[source_layout_][BACK_LEFT]; | 224 core_channel_orderings_[BACK_CENTER] = i; |
218 break; | 225 channel_remap_[i] = kChannelOrderings[source_layout_][BACK_CENTER]; |
219 case kAudioChannelLabel_RearSurroundRight: | 226 break; |
220 core_channel_orderings_[BACK_RIGHT] = i; | 227 case kAudioChannelLabel_RearSurroundLeft: |
221 channel_remap_[i] = kChannelOrderings[source_layout_][BACK_RIGHT]; | 228 core_channel_orderings_[BACK_LEFT] = i; |
222 break; | 229 channel_remap_[i] = kChannelOrderings[source_layout_][BACK_LEFT]; |
223 default: | 230 break; |
224 DLOG(WARNING) << "Channel label not supported"; | 231 case kAudioChannelLabel_RearSurroundRight: |
225 channel_remap_[i] = kEmptyChannel; | 232 core_channel_orderings_[BACK_RIGHT] = i; |
226 break; | 233 channel_remap_[i] = kChannelOrderings[source_layout_][BACK_RIGHT]; |
234 break; | |
235 case kAudioChannelLabel_Unknown: | |
236 channel_remap_[i] = kEmptyChannel; | |
237 break; | |
238 default: | |
239 DLOG(WARNING) << "Channel label not supported"; | |
240 channel_remap_[i] = kEmptyChannel; | |
241 break; | |
242 } | |
227 } | 243 } |
228 } | 244 } |
229 | 245 |
230 // Check if we need to adjust the layout. | 246 // Check if we need to swizzle or adjust the layout from source to device. |
231 // If the device has a BACK_LEFT and no SIDE_LEFT and the source has | 247 should_swizzle_ = false; |
232 // a SIDE_LEFT but no BACK_LEFT, then move (and preserve the channel). | |
233 // e.g. CHANNEL_LAYOUT_5POINT1 -> CHANNEL_LAYOUT_5POINT1_BACK | |
234 CheckForAdjustedLayout(SIDE_LEFT, BACK_LEFT); | |
235 // Same for SIDE_RIGHT -> BACK_RIGHT. | |
236 CheckForAdjustedLayout(SIDE_RIGHT, BACK_RIGHT); | |
237 // Move BACK_LEFT to SIDE_LEFT. | |
238 // e.g. CHANNEL_LAYOUT_5POINT1_BACK -> CHANNEL_LAYOUT_5POINT1 | |
239 CheckForAdjustedLayout(BACK_LEFT, SIDE_LEFT); | |
240 // Same for BACK_RIGHT -> SIDE_RIGHT. | |
241 CheckForAdjustedLayout(BACK_RIGHT, SIDE_RIGHT); | |
242 // Move SIDE_LEFT to LEFT_OF_CENTER. | |
243 // e.g. CHANNEL_LAYOUT_7POINT1 -> CHANNEL_LAYOUT_7POINT1_WIDE | |
244 CheckForAdjustedLayout(SIDE_LEFT, LEFT_OF_CENTER); | |
245 // Same for SIDE_RIGHT -> RIGHT_OF_CENTER. | |
246 CheckForAdjustedLayout(SIDE_RIGHT, RIGHT_OF_CENTER); | |
247 // Move LEFT_OF_CENTER to SIDE_LEFT. | |
248 // e.g. CHANNEL_LAYOUT_7POINT1_WIDE -> CHANNEL_LAYOUT_7POINT1 | |
249 CheckForAdjustedLayout(LEFT_OF_CENTER, SIDE_LEFT); | |
250 // Same for RIGHT_OF_CENTER -> SIDE_RIGHT. | |
251 CheckForAdjustedLayout(RIGHT_OF_CENTER, SIDE_RIGHT); | |
252 | 248 |
253 // Check if we will need to swizzle from source to device layout (maybe not!). | 249 if (!allChannelsUnknown) { |
scherkus (not reviewing)
2011/06/07 22:43:22
nit: check for opposite condition and return early
annacc
2011/06/07 23:09:45
Done.
| |
254 should_swizzle_ = false; | 250 // Check if we need to adjust the layout. |
255 for (int i = 0; i < num_core_channels_; ++i) { | 251 // If the device has a BACK_LEFT and no SIDE_LEFT and the source has |
256 if (kChannelOrderings[source_layout_][i] != core_channel_orderings_[i]) { | 252 // a SIDE_LEFT but no BACK_LEFT, then move (and preserve the channel). |
257 should_swizzle_ = true; | 253 // e.g. CHANNEL_LAYOUT_5POINT1 -> CHANNEL_LAYOUT_5POINT1_BACK |
258 break; | 254 CheckForAdjustedLayout(SIDE_LEFT, BACK_LEFT); |
255 // Same for SIDE_RIGHT -> BACK_RIGHT. | |
256 CheckForAdjustedLayout(SIDE_RIGHT, BACK_RIGHT); | |
257 // Move BACK_LEFT to SIDE_LEFT. | |
258 // e.g. CHANNEL_LAYOUT_5POINT1_BACK -> CHANNEL_LAYOUT_5POINT1 | |
259 CheckForAdjustedLayout(BACK_LEFT, SIDE_LEFT); | |
260 // Same for BACK_RIGHT -> SIDE_RIGHT. | |
261 CheckForAdjustedLayout(BACK_RIGHT, SIDE_RIGHT); | |
262 // Move SIDE_LEFT to LEFT_OF_CENTER. | |
263 // e.g. CHANNEL_LAYOUT_7POINT1 -> CHANNEL_LAYOUT_7POINT1_WIDE | |
264 CheckForAdjustedLayout(SIDE_LEFT, LEFT_OF_CENTER); | |
265 // Same for SIDE_RIGHT -> RIGHT_OF_CENTER. | |
266 CheckForAdjustedLayout(SIDE_RIGHT, RIGHT_OF_CENTER); | |
267 // Move LEFT_OF_CENTER to SIDE_LEFT. | |
268 // e.g. CHANNEL_LAYOUT_7POINT1_WIDE -> CHANNEL_LAYOUT_7POINT1 | |
269 CheckForAdjustedLayout(LEFT_OF_CENTER, SIDE_LEFT); | |
270 // Same for 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); | |
275 | |
276 for (int i = 0; i < num_core_channels_; ++i) { | |
277 if (kChannelOrderings[source_layout_][i] != core_channel_orderings_[i]) { | |
278 should_swizzle_ = true; | |
279 break; | |
280 } | |
259 } | 281 } |
260 } | 282 } |
261 | 283 |
262 return true; | 284 return true; |
263 } | 285 } |
264 | 286 |
265 void PCMQueueOutAudioOutputStream::Close() { | 287 void PCMQueueOutAudioOutputStream::Close() { |
266 // It is valid to call Close() before calling Open(), thus audio_queue_ | 288 // It is valid to call Close() before calling Open(), thus audio_queue_ |
267 // might be NULL. | 289 // might be NULL. |
268 if (audio_queue_) { | 290 if (audio_queue_) { |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
468 HandleError(err); | 490 HandleError(err); |
469 return; | 491 return; |
470 } | 492 } |
471 } | 493 } |
472 err = AudioQueueStart(audio_queue_, NULL); | 494 err = AudioQueueStart(audio_queue_, NULL); |
473 if (err != noErr) { | 495 if (err != noErr) { |
474 HandleError(err); | 496 HandleError(err); |
475 return; | 497 return; |
476 } | 498 } |
477 } | 499 } |
OLD | NEW |