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

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: Fix 8ch+ discrete layouts. 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
« no previous file with comments | « media/audio/mac/audio_auhal_mac.h ('k') | media/base/channel_layout.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <cstddef>
10 #include <string> 11 #include <string>
11 12
12 #include "base/bind.h" 13 #include "base/bind.h"
13 #include "base/bind_helpers.h" 14 #include "base/bind_helpers.h"
14 #include "base/logging.h" 15 #include "base/logging.h"
15 #include "base/mac/mac_logging.h" 16 #include "base/mac/mac_logging.h"
16 #include "base/metrics/histogram_macros.h" 17 #include "base/metrics/histogram_macros.h"
17 #include "base/strings/stringprintf.h" 18 #include "base/strings/stringprintf.h"
18 #include "base/trace_event/trace_event.h" 19 #include "base/trace_event/trace_event.h"
19 #include "media/audio/mac/audio_manager_mac.h" 20 #include "media/audio/mac/audio_manager_mac.h"
20 #include "media/base/audio_pull_fifo.h" 21 #include "media/base/audio_pull_fifo.h"
21 #include "media/base/audio_timestamp_helper.h" 22 #include "media/base/audio_timestamp_helper.h"
22 23
23 namespace media { 24 namespace media {
24 25
26 // Mapping from Chrome's channel layout to CoreAudio layout. This must match the
27 // layout of the Channels enum in |channel_layout.h|
28 static const AudioChannelLabel kCoreAudioChannelMapping[] = {
29 kAudioChannelLabel_Left,
30 kAudioChannelLabel_Right,
31 kAudioChannelLabel_Center,
32 kAudioChannelLabel_LFEScreen,
33 kAudioChannelLabel_LeftSurround,
34 kAudioChannelLabel_RightSurround,
35 kAudioChannelLabel_LeftCenter,
36 kAudioChannelLabel_RightCenter,
37 kAudioChannelLabel_CenterSurround,
38 kAudioChannelLabel_LeftSurroundDirect,
39 kAudioChannelLabel_RightSurroundDirect,
40 };
41 static_assert(0 == LEFT && 1 == RIGHT && 2 == CENTER && 3 == LFE &&
42 4 == BACK_LEFT &&
43 5 == BACK_RIGHT &&
44 6 == LEFT_OF_CENTER &&
45 7 == RIGHT_OF_CENTER &&
46 8 == BACK_CENTER &&
47 9 == SIDE_LEFT &&
48 10 == SIDE_RIGHT &&
49 10 == CHANNELS_MAX,
50 "Channel positions must match CoreAudio channel order.");
51
25 static void WrapBufferList(AudioBufferList* buffer_list, 52 static void WrapBufferList(AudioBufferList* buffer_list,
26 AudioBus* bus, 53 AudioBus* bus,
27 int frames) { 54 int frames) {
28 DCHECK(buffer_list); 55 DCHECK(buffer_list);
29 DCHECK(bus); 56 DCHECK(bus);
30 const int channels = bus->channels(); 57 const int channels = bus->channels();
31 const int buffer_list_channels = buffer_list->mNumberBuffers; 58 const int buffer_list_channels = buffer_list->mNumberBuffers;
32 CHECK_EQ(channels, buffer_list_channels); 59 CHECK_EQ(channels, buffer_list_channels);
33 60
34 // Copy pointers from AudioBufferList. 61 // Copy pointers from AudioBufferList.
(...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after
528 kAudioUnitProperty_SetRenderCallback, 555 kAudioUnitProperty_SetRenderCallback,
529 kAudioUnitScope_Input, 556 kAudioUnitScope_Input,
530 0, 557 0,
531 &callback, 558 &callback,
532 sizeof(callback)); 559 sizeof(callback));
533 if (result != noErr) { 560 if (result != noErr) {
534 CloseAudioUnit(); 561 CloseAudioUnit();
535 return false; 562 return false;
536 } 563 }
537 564
565 SetAudioChannelLayout();
566
538 result = AudioUnitInitialize(audio_unit_); 567 result = AudioUnitInitialize(audio_unit_);
539 if (result != noErr) { 568 if (result != noErr) {
540 OSSTATUS_DLOG(ERROR, result) << "AudioUnitInitialize() failed."; 569 OSSTATUS_DLOG(ERROR, result) << "AudioUnitInitialize() failed.";
541 CloseAudioUnit(); 570 CloseAudioUnit();
542 return false; 571 return false;
543 } 572 }
544 573
545 return true; 574 return true;
546 } 575 }
547 576
548 void AUHALStream::CloseAudioUnit() { 577 void AUHALStream::CloseAudioUnit() {
549 DCHECK(thread_checker_.CalledOnValidThread()); 578 DCHECK(thread_checker_.CalledOnValidThread());
550 if (!audio_unit_) 579 if (!audio_unit_)
551 return; 580 return;
552 581
553 OSStatus result = AudioUnitUninitialize(audio_unit_); 582 OSStatus result = AudioUnitUninitialize(audio_unit_);
554 OSSTATUS_DLOG_IF(ERROR, result != noErr, result) 583 OSSTATUS_DLOG_IF(ERROR, result != noErr, result)
555 << "AudioUnitUninitialize() failed."; 584 << "AudioUnitUninitialize() failed.";
556 result = AudioComponentInstanceDispose(audio_unit_); 585 result = AudioComponentInstanceDispose(audio_unit_);
557 OSSTATUS_DLOG_IF(ERROR, result != noErr, result) 586 OSSTATUS_DLOG_IF(ERROR, result != noErr, result)
558 << "AudioComponentInstanceDispose() failed."; 587 << "AudioComponentInstanceDispose() failed.";
559 audio_unit_ = 0; 588 audio_unit_ = 0;
560 } 589 }
561 590
591 void AUHALStream::SetAudioChannelLayout() {
592 DCHECK(audio_unit_);
593
594 // AudioChannelLayout is structure ending in a variable length array, so we
595 // can't directly allocate one. Instead compute the size and and allocate one
596 // inside of a byte array.
597 //
598 // Code modeled after example from Apple documentation here:
599 // https://developer.apple.com/library/content/qa/qa1627/_index.html
600 const size_t layout_size =
601 offsetof(AudioChannelLayout, mChannelDescriptions[params_.channels()]);
602 std::unique_ptr<uint8_t[]> layout_storage(new uint8_t[layout_size]);
603 memset(layout_storage.get(), 0, layout_size);
604 AudioChannelLayout* channel_layout =
605 reinterpret_cast<AudioChannelLayout*>(layout_storage.get());
606
607 channel_layout->mNumberChannelDescriptions = params_.channels();
608 channel_layout->mChannelLayoutTag =
609 kAudioChannelLayoutTag_UseChannelDescriptions;
610 AudioChannelDescription* descriptions = channel_layout->mChannelDescriptions;
611
612 if (params_.channel_layout() == CHANNEL_LAYOUT_DISCRETE) {
613 // For the discrete case just assume common input mappings; once we run out
614 // of known channels mark them as unknown.
615 for (int ch = 0; ch < params_.channels(); ++ch) {
616 descriptions[ch].mChannelLabel = ch > CHANNELS_MAX
617 ? kAudioChannelLabel_Unknown
618 : kCoreAudioChannelMapping[ch];
619 descriptions[ch].mChannelFlags = kAudioChannelFlags_AllOff;
620 }
621 } else if (params_.channel_layout() == CHANNEL_LAYOUT_MONO) {
622 // CoreAudio has a special label for mono.
623 DCHECK_EQ(params_.channels(), 1);
624 descriptions[0].mChannelLabel = kAudioChannelLabel_Mono;
625 descriptions[0].mChannelFlags = kAudioChannelFlags_AllOff;
626 } else {
627 for (int ch = 0; ch <= CHANNELS_MAX; ++ch) {
628 const int order =
629 ChannelOrder(params_.channel_layout(), static_cast<Channels>(ch));
630 if (order == -1)
631 continue;
632 descriptions[order].mChannelLabel = kCoreAudioChannelMapping[ch];
633 descriptions[order].mChannelFlags = kAudioChannelFlags_AllOff;
634 }
635 }
636
637 OSStatus result = AudioUnitSetProperty(
638 audio_unit_, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Input,
639 0, channel_layout, layout_size);
640 if (result != noErr) {
641 OSSTATUS_DLOG(ERROR, result)
642 << "Failed to set audio channel layout. Using default layout.";
643 }
644 }
645
562 } // namespace media 646 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/mac/audio_auhal_mac.h ('k') | media/base/channel_layout.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698