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

Side by Side Diff: media/audio/mac/audio_auhal_mac.cc

Issue 2683033003: Tell CoreAudio how to interpret Chrome's channel layout. (Closed)
Patch Set: Created 3 years, 10 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
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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_auhal_mac.h" 5 #include "media/audio/mac/audio_auhal_mac.h"
6 6
7 #include <CoreServices/CoreServices.h> 7 #include <CoreServices/CoreServices.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <string> 10 #include <string>
11 11
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/bind_helpers.h" 13 #include "base/bind_helpers.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/mac/mac_logging.h" 15 #include "base/mac/mac_logging.h"
16 #include "base/metrics/histogram_macros.h" 16 #include "base/metrics/histogram_macros.h"
17 #include "base/strings/stringprintf.h" 17 #include "base/strings/stringprintf.h"
18 #include "base/trace_event/trace_event.h" 18 #include "base/trace_event/trace_event.h"
19 #include "media/audio/mac/audio_manager_mac.h" 19 #include "media/audio/mac/audio_manager_mac.h"
20 #include "media/base/audio_pull_fifo.h" 20 #include "media/base/audio_pull_fifo.h"
21 #include "media/base/audio_timestamp_helper.h" 21 #include "media/base/audio_timestamp_helper.h"
22 22
23 namespace media { 23 namespace media {
24 24
25 // Mapping from Chrome's channel layout to CoreAudio layout. This must match the
26 // layout of the Channels enum in |channel_layout.h|
27 static const AudioChannelLabel kCoreAudioChannelMapping[] = {
28 kAudioChannelLabel_Left,
29 kAudioChannelLabel_Right,
30 kAudioChannelLabel_Center,
31 kAudioChannelLabel_LFEScreen,
32 kAudioChannelLabel_LeftSurround,
33 kAudioChannelLabel_RightSurround,
34 kAudioChannelLabel_LeftCenter,
35 kAudioChannelLabel_RightCenter,
36 kAudioChannelLabel_CenterSurround,
37 kAudioChannelLabel_LeftSurroundDirect,
38 kAudioChannelLabel_RightSurroundDirect,
39 };
40 static_assert(0 == LEFT && 1 == RIGHT && 2 == CENTER && 3 == LFE &&
41 4 == BACK_LEFT &&
42 5 == BACK_RIGHT &&
43 6 == LEFT_OF_CENTER &&
44 7 == RIGHT_OF_CENTER &&
45 8 == BACK_CENTER &&
46 9 == SIDE_LEFT &&
47 10 == SIDE_RIGHT,
48 "Channel positions must max OSX channel order.");
Avi (use Gerrit) 2017/02/09 02:44:38 "must match"? (And it's "macOS" nowadays.)
DaleCurtis 2017/02/09 03:18:38 Done, switched to CoreAudio like we use elsewhere
49
25 static void WrapBufferList(AudioBufferList* buffer_list, 50 static void WrapBufferList(AudioBufferList* buffer_list,
26 AudioBus* bus, 51 AudioBus* bus,
27 int frames) { 52 int frames) {
28 DCHECK(buffer_list); 53 DCHECK(buffer_list);
29 DCHECK(bus); 54 DCHECK(bus);
30 const int channels = bus->channels(); 55 const int channels = bus->channels();
31 const int buffer_list_channels = buffer_list->mNumberBuffers; 56 const int buffer_list_channels = buffer_list->mNumberBuffers;
32 CHECK_EQ(channels, buffer_list_channels); 57 CHECK_EQ(channels, buffer_list_channels);
33 58
34 // Copy pointers from AudioBufferList. 59 // Copy pointers from AudioBufferList.
(...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after
528 kAudioUnitProperty_SetRenderCallback, 553 kAudioUnitProperty_SetRenderCallback,
529 kAudioUnitScope_Input, 554 kAudioUnitScope_Input,
530 0, 555 0,
531 &callback, 556 &callback,
532 sizeof(callback)); 557 sizeof(callback));
533 if (result != noErr) { 558 if (result != noErr) {
534 CloseAudioUnit(); 559 CloseAudioUnit();
535 return false; 560 return false;
536 } 561 }
537 562
563 SetAudioChannelLayout();
564
538 result = AudioUnitInitialize(audio_unit_); 565 result = AudioUnitInitialize(audio_unit_);
539 if (result != noErr) { 566 if (result != noErr) {
540 OSSTATUS_DLOG(ERROR, result) << "AudioUnitInitialize() failed."; 567 OSSTATUS_DLOG(ERROR, result) << "AudioUnitInitialize() failed.";
541 CloseAudioUnit(); 568 CloseAudioUnit();
542 return false; 569 return false;
543 } 570 }
544 571
545 return true; 572 return true;
546 } 573 }
547 574
548 void AUHALStream::CloseAudioUnit() { 575 void AUHALStream::CloseAudioUnit() {
549 DCHECK(thread_checker_.CalledOnValidThread()); 576 DCHECK(thread_checker_.CalledOnValidThread());
550 if (!audio_unit_) 577 if (!audio_unit_)
551 return; 578 return;
552 579
553 OSStatus result = AudioUnitUninitialize(audio_unit_); 580 OSStatus result = AudioUnitUninitialize(audio_unit_);
554 OSSTATUS_DLOG_IF(ERROR, result != noErr, result) 581 OSSTATUS_DLOG_IF(ERROR, result != noErr, result)
555 << "AudioUnitUninitialize() failed."; 582 << "AudioUnitUninitialize() failed.";
556 result = AudioComponentInstanceDispose(audio_unit_); 583 result = AudioComponentInstanceDispose(audio_unit_);
557 OSSTATUS_DLOG_IF(ERROR, result != noErr, result) 584 OSSTATUS_DLOG_IF(ERROR, result != noErr, result)
558 << "AudioComponentInstanceDispose() failed."; 585 << "AudioComponentInstanceDispose() failed.";
559 audio_unit_ = 0; 586 audio_unit_ = 0;
560 } 587 }
561 588
589 void AUHALStream::SetAudioChannelLayout() {
590 DCHECK(audio_unit_);
591
592 // Code modeled after example from Apple documentation here:
593 // https://developer.apple.com/library/content/qa/qa1627/_index.html
Avi (use Gerrit) 2017/02/09 02:44:38 Can you clarify in the comments why it appears you
DaleCurtis 2017/02/09 03:18:38 I thought (1) would prevent this, but offsetof() w
594 #define FIELD_OFFSET(type, field) ((size_t) & ((type*)0)->field)
595 const size_t layout_size = FIELD_OFFSET(
596 AudioChannelLayout, mChannelDescriptions[params_.channels()]);
597 #undef FIELD_OFFSET
598
599 std::unique_ptr<uint8_t[]> layout_storage(new uint8_t[layout_size]);
600 memset(layout_storage.get(), 0, layout_size);
601 AudioChannelLayout* channel_layout =
602 reinterpret_cast<AudioChannelLayout*>(layout_storage.get());
603
604 channel_layout->mNumberChannelDescriptions = params_.channels();
605 channel_layout->mChannelLayoutTag =
606 kAudioChannelLayoutTag_UseChannelDescriptions;
607 AudioChannelDescription* descriptions = channel_layout->mChannelDescriptions;
608
609 if (params_.channel_layout() == CHANNEL_LAYOUT_DISCRETE) {
610 // For the discrete case just assume common input mappings.
611 for (int ch = 0; ch <= CHANNELS_MAX; ++ch) {
612 descriptions[ch].mChannelLabel = kCoreAudioChannelMapping[ch];
613 descriptions[ch].mChannelFlags = kAudioChannelFlags_AllOff;
614 }
615 } else if (params_.channel_layout() == CHANNEL_LAYOUT_MONO) {
616 // CoreAudio has a special label for mono.
617 DCHECK_EQ(params_.channels(), 1);
618 descriptions[0].mChannelLabel = kAudioChannelLabel_Mono;
619 descriptions[0].mChannelFlags = kAudioChannelFlags_AllOff;
620 } else {
621 for (int ch = 0; ch <= CHANNELS_MAX; ++ch) {
622 const int order =
623 ChannelOrder(params_.channel_layout(), static_cast<Channels>(ch));
624 if (order == -1)
625 continue;
626 descriptions[order].mChannelLabel = kCoreAudioChannelMapping[ch];
627 descriptions[order].mChannelFlags = kAudioChannelFlags_AllOff;
628 }
629 }
630
631 OSStatus result = AudioUnitSetProperty(
632 audio_unit_, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Input,
633 0, channel_layout, layout_size);
634 if (result != noErr) {
635 OSSTATUS_DLOG(ERROR, result)
636 << "Failed to set audio channel layout. Using default layout.";
637 }
638 }
639
562 } // namespace media 640 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698