Chromium Code Reviews| 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 |