| 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 continue; |
| 189 } |
| 190 all_channels_unknown = false; |
| 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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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; |
| 223 default: | 236 default: |
| 224 DLOG(WARNING) << "Channel label not supported"; | 237 DLOG(WARNING) << "Channel label not supported"; |
| 225 channel_remap_[i] = kEmptyChannel; | 238 channel_remap_[i] = kEmptyChannel; |
| 226 break; | 239 break; |
| 227 } | 240 } |
| 228 } | 241 } |
| 229 | 242 |
| 243 if (all_channels_unknown) { |
| 244 return true; |
| 245 } |
| 246 |
| 230 // Check if we need to adjust the layout. | 247 // Check if we need to adjust the layout. |
| 231 // If the device has a BACK_LEFT and no SIDE_LEFT and the source has | 248 // 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). | 249 // a SIDE_LEFT but no BACK_LEFT, then move (and preserve the channel). |
| 233 // e.g. CHANNEL_LAYOUT_5POINT1 -> CHANNEL_LAYOUT_5POINT1_BACK | 250 // e.g. CHANNEL_LAYOUT_5POINT1 -> CHANNEL_LAYOUT_5POINT1_BACK |
| 234 CheckForAdjustedLayout(SIDE_LEFT, BACK_LEFT); | 251 CheckForAdjustedLayout(SIDE_LEFT, BACK_LEFT); |
| 235 // Same for SIDE_RIGHT -> BACK_RIGHT. | 252 // Same for SIDE_RIGHT -> BACK_RIGHT. |
| 236 CheckForAdjustedLayout(SIDE_RIGHT, BACK_RIGHT); | 253 CheckForAdjustedLayout(SIDE_RIGHT, BACK_RIGHT); |
| 237 // Move BACK_LEFT to SIDE_LEFT. | 254 // Move BACK_LEFT to SIDE_LEFT. |
| 238 // e.g. CHANNEL_LAYOUT_5POINT1_BACK -> CHANNEL_LAYOUT_5POINT1 | 255 // e.g. CHANNEL_LAYOUT_5POINT1_BACK -> CHANNEL_LAYOUT_5POINT1 |
| 239 CheckForAdjustedLayout(BACK_LEFT, SIDE_LEFT); | 256 CheckForAdjustedLayout(BACK_LEFT, SIDE_LEFT); |
| 240 // Same for BACK_RIGHT -> SIDE_RIGHT. | 257 // Same for BACK_RIGHT -> SIDE_RIGHT. |
| 241 CheckForAdjustedLayout(BACK_RIGHT, SIDE_RIGHT); | 258 CheckForAdjustedLayout(BACK_RIGHT, SIDE_RIGHT); |
| 242 // Move SIDE_LEFT to LEFT_OF_CENTER. | 259 // Move SIDE_LEFT to LEFT_OF_CENTER. |
| 243 // e.g. CHANNEL_LAYOUT_7POINT1 -> CHANNEL_LAYOUT_7POINT1_WIDE | 260 // e.g. CHANNEL_LAYOUT_7POINT1 -> CHANNEL_LAYOUT_7POINT1_WIDE |
| 244 CheckForAdjustedLayout(SIDE_LEFT, LEFT_OF_CENTER); | 261 CheckForAdjustedLayout(SIDE_LEFT, LEFT_OF_CENTER); |
| 245 // Same for SIDE_RIGHT -> RIGHT_OF_CENTER. | 262 // Same for SIDE_RIGHT -> RIGHT_OF_CENTER. |
| 246 CheckForAdjustedLayout(SIDE_RIGHT, RIGHT_OF_CENTER); | 263 CheckForAdjustedLayout(SIDE_RIGHT, RIGHT_OF_CENTER); |
| 247 // Move LEFT_OF_CENTER to SIDE_LEFT. | 264 // Move LEFT_OF_CENTER to SIDE_LEFT. |
| 248 // e.g. CHANNEL_LAYOUT_7POINT1_WIDE -> CHANNEL_LAYOUT_7POINT1 | 265 // e.g. CHANNEL_LAYOUT_7POINT1_WIDE -> CHANNEL_LAYOUT_7POINT1 |
| 249 CheckForAdjustedLayout(LEFT_OF_CENTER, SIDE_LEFT); | 266 CheckForAdjustedLayout(LEFT_OF_CENTER, SIDE_LEFT); |
| 250 // Same for RIGHT_OF_CENTER -> SIDE_RIGHT. | 267 // Same for RIGHT_OF_CENTER -> SIDE_RIGHT. |
| 251 CheckForAdjustedLayout(RIGHT_OF_CENTER, SIDE_RIGHT); | 268 CheckForAdjustedLayout(RIGHT_OF_CENTER, SIDE_RIGHT); |
| 269 // For MONO -> STEREO, move audio to LEFT and RIGHT if applicable. |
| 270 CheckForAdjustedLayout(CENTER, LEFT); |
| 271 CheckForAdjustedLayout(CENTER, RIGHT); |
| 252 | 272 |
| 253 // Check if we will need to swizzle from source to device layout (maybe not!). | 273 // Check if we will need to swizzle from source to device layout (maybe not!). |
| 254 should_swizzle_ = false; | 274 should_swizzle_ = false; |
| 255 for (int i = 0; i < num_core_channels_; ++i) { | 275 for (int i = 0; i < num_core_channels_; ++i) { |
| 256 if (kChannelOrderings[source_layout_][i] != core_channel_orderings_[i]) { | 276 if (kChannelOrderings[source_layout_][i] != core_channel_orderings_[i]) { |
| 257 should_swizzle_ = true; | 277 should_swizzle_ = true; |
| 258 break; | 278 break; |
| 259 } | 279 } |
| 260 } | 280 } |
| 261 | 281 |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 468 HandleError(err); | 488 HandleError(err); |
| 469 return; | 489 return; |
| 470 } | 490 } |
| 471 } | 491 } |
| 472 err = AudioQueueStart(audio_queue_, NULL); | 492 err = AudioQueueStart(audio_queue_, NULL); |
| 473 if (err != noErr) { | 493 if (err != noErr) { |
| 474 HandleError(err); | 494 HandleError(err); |
| 475 return; | 495 return; |
| 476 } | 496 } |
| 477 } | 497 } |
| OLD | NEW |