[vlc-commits] coreaudio: factor AudioUnit initialization

Thomas Guillem git at videolan.org
Wed Mar 1 17:49:52 CET 2017


vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Tue Feb 28 13:02:25 2017 +0100| [854a3caea195dfc9eaa3622fc1171cbf9244c217] | committer: Thomas Guillem

coreaudio: factor AudioUnit initialization

Factor StartAnalog for both iOS and macOS into au_Initialize().

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=854a3caea195dfc9eaa3622fc1171cbf9244c217
---

 modules/audio_output/audiounit_ios.m    |  86 +-----
 modules/audio_output/auhal.c            | 428 +----------------------------
 modules/audio_output/coreaudio_common.c | 469 ++++++++++++++++++++++++++++++++
 modules/audio_output/coreaudio_common.h |   8 +-
 4 files changed, 493 insertions(+), 498 deletions(-)

diff --git a/modules/audio_output/audiounit_ios.m b/modules/audio_output/audiounit_ios.m
index 451d3c1..1c757ca 100644
--- a/modules/audio_output/audiounit_ios.m
+++ b/modules/audio_output/audiounit_ios.m
@@ -165,28 +165,6 @@ Play(audio_output_t * p_aout, block_t * p_block)
         ca_Play(p_aout, p_block);
 }
 
-/*****************************************************************************
- * RenderCallback: This function is called everytime the AudioUnit wants
- * us to provide some more audio data.
- * Don't print anything during normal playback, calling blocking function from
- * this callback is not allowed.
- *****************************************************************************/
-static OSStatus
-RenderCallback(void *p_data, AudioUnitRenderActionFlags *ioActionFlags,
-               const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber,
-               UInt32 inNumberFrames, AudioBufferList *ioData)
-{
-    VLC_UNUSED(ioActionFlags);
-    VLC_UNUSED(inTimeStamp);
-    VLC_UNUSED(inBusNumber);
-    VLC_UNUSED(inNumberFrames);
-
-    ca_Render(p_data, ioData->mBuffers[0].mData,
-              ioData->mBuffers[0].mDataByteSize);
-
-    return noErr;
-}
-
 #pragma mark initialization
 
 /*
@@ -196,13 +174,15 @@ static int
 StartAnalog(audio_output_t *p_aout, audio_sample_format_t *fmt)
 {
     struct aout_sys_t           *p_sys = p_aout->sys;
-    AURenderCallbackStruct      callback;
     OSStatus status;
 
     /* Activate the AVAudioSession */
     if (avas_SetActive(p_aout, true, 0) != VLC_SUCCESS)
         return VLC_EGENERIC;
 
+    fmt->i_format = VLC_CODEC_FL32;
+    fmt->i_physical_channels = fmt->i_original_channels = AOUT_CHANS_STEREO;
+
     p_sys->au_unit = au_NewOutputInstance(p_aout, kAudioUnitSubType_RemoteIO);
     if (p_sys->au_unit == NULL)
         goto error;
@@ -214,64 +194,12 @@ StartAnalog(audio_output_t *p_aout, audio_sample_format_t *fmt)
     if (status != noErr)
         msg_Warn(p_aout, "failed to set IO mode (%i)", (int)status);
 
-    /* Get the current format */
-    AudioStreamBasicDescription streamDescription;
-    streamDescription.mSampleRate = fmt->i_rate;
-    fmt->i_format = VLC_CODEC_FL32;
-    fmt->i_physical_channels = fmt->i_original_channels = AOUT_CHANS_STEREO;
-    streamDescription.mFormatID = kAudioFormatLinearPCM;
-    streamDescription.mFormatFlags = kAudioFormatFlagsNativeFloatPacked; // FL32
-    streamDescription.mChannelsPerFrame = aout_FormatNbChannels(fmt);
-    streamDescription.mFramesPerPacket = 1;
-    streamDescription.mBitsPerChannel = 32;
-    streamDescription.mBytesPerFrame = streamDescription.mBitsPerChannel * streamDescription.mChannelsPerFrame / 8;
-    streamDescription.mBytesPerPacket = streamDescription.mBytesPerFrame * streamDescription.mFramesPerPacket;
-
-    /* Set the desired format */
-    status = AudioUnitSetProperty(p_sys->au_unit,
-                                  kAudioUnitProperty_StreamFormat,
-                                  kAudioUnitScope_Input, 0, &streamDescription,
-                                  sizeof(streamDescription));
-    if (status != noErr) {
-        msg_Err(p_aout, "failed to set stream format (%i)", (int)status);
-        goto error;
-    }
-    msg_Dbg(p_aout, STREAM_FORMAT_MSG("we set the AU format: " , streamDescription));
-
-    /* Retrieve actual format */
-    status = AudioUnitGetProperty(p_sys->au_unit,
-                                  kAudioUnitProperty_StreamFormat,
-                                  kAudioUnitScope_Input, 0, &streamDescription,
-                                  & (UInt32) { sizeof(streamDescription) });
-    if (status != noErr)
-        msg_Warn(p_aout, "failed to verify stream format (%i)", (int)status);
-    msg_Dbg(p_aout, STREAM_FORMAT_MSG("the actual set AU format is " , streamDescription));
-
-    /* Do the last VLC aout setups */
-    aout_FormatPrepare(fmt);
-
-    /* set the IOproc callback */
-    callback.inputProc = RenderCallback;
-    callback.inputProcRefCon = p_aout;
-
-    status = AudioUnitSetProperty(p_sys->au_unit,
-                                  kAudioUnitProperty_SetRenderCallback,
-                                  kAudioUnitScope_Input, 0, &callback,
-                                  sizeof(callback));
-    if (status != noErr) {
-        msg_Err(p_aout, "render callback setup failed (%i)", (int)status);
-        goto error;
-    }
-
-    /* AU init */
-    status = AudioUnitInitialize(p_sys->au_unit);
-    if (status != noErr) {
-        msg_Err(p_aout, "failed to init AudioUnit (%i)", (int)status);
+    int ret = au_Initialize(p_aout, p_sys->au_unit, fmt, NULL);
+    if (ret != VLC_SUCCESS)
         goto error;
-    }
 
-    int ret = ca_Init(p_aout, fmt, AUDIO_BUFFER_SIZE_IN_SECONDS * fmt->i_rate *
-                      fmt->i_bytes_per_frame);
+    ret = ca_Init(p_aout, fmt, AUDIO_BUFFER_SIZE_IN_SECONDS * fmt->i_rate *
+                  fmt->i_bytes_per_frame);
     if (ret != VLC_SUCCESS)
     {
         AudioUnitUninitialize(p_sys->au_unit);
diff --git a/modules/audio_output/auhal.c b/modules/audio_output/auhal.c
index 256a94a..eb6607e 100644
--- a/modules/audio_output/auhal.c
+++ b/modules/audio_output/auhal.c
@@ -910,29 +910,6 @@ MuteSet(audio_output_t * p_aout, bool mute)
 #pragma mark -
 #pragma mark actual playback
 
-/*****************************************************************************
- * RenderCallbackAnalog: This function is called everytime the AudioUnit wants
- * us to provide some more audio data.
- * Don't print anything during normal playback, calling blocking function from
- * this callback is not allowed.
- *****************************************************************************/
-static OSStatus
-RenderCallbackAnalog(void *p_data, AudioUnitRenderActionFlags *ioActionFlags,
-                     const AudioTimeStamp *inTimeStamp,
-                     UInt32 inBusNumber, UInt32 inNumberFrames,
-                     AudioBufferList *ioData)
-{
-    VLC_UNUSED(ioActionFlags);
-    VLC_UNUSED(inTimeStamp);
-    VLC_UNUSED(inBusNumber);
-    VLC_UNUSED(inNumberFrames);
-
-    ca_Render(p_data, ioData->mBuffers[0].mData,
-              ioData->mBuffers[0].mDataByteSize);
-
-    return noErr;
-}
-
 /*
  * RenderCallbackSPDIF: callback for SPDIF audio output
  */
@@ -970,16 +947,8 @@ StartAnalog(audio_output_t *p_aout, audio_sample_format_t *fmt)
 {
     struct aout_sys_t           *p_sys = p_aout->sys;
     OSStatus                    err = noErr;
-    UInt32                      i_param_size = 0;
-    int                         i_original;
-    AudioStreamBasicDescription DeviceFormat;
-    AudioChannelLayout          *layout;
-    AURenderCallbackStruct      input;
-    p_sys->c.chans_to_reorder = 0;
-
-    SInt32 currentMinorSystemVersion;
-    if (Gestalt(gestaltSystemVersionMinor, &currentMinorSystemVersion) != noErr)
-        msg_Err(p_aout, "failed to check OSX version");
+    UInt32                      i_param_size;
+    AudioChannelLayout          *layout = NULL;
 
     p_sys->au_unit = au_NewOutputInstance(p_aout, kAudioUnitSubType_HALOutput);
     if (p_sys->au_unit == NULL)
@@ -998,416 +967,39 @@ StartAnalog(audio_output_t *p_aout, audio_sample_format_t *fmt)
         goto error;
     }
 
-    /* Get the current format */
-    i_param_size = sizeof(AudioStreamBasicDescription);
-
-    err = AudioUnitGetProperty(p_sys->au_unit,  kAudioUnitProperty_StreamFormat,
-                               kAudioUnitScope_Output, 0, &DeviceFormat,
-                               &i_param_size);
-
-    if (err != noErr)
-    {
-        msg_Err(p_aout, "failed to detect supported stream formats [%4.4s]",
-                (const char *)&err);
-        goto error;
-    }
-    else
-        msg_Dbg(p_aout, STREAM_FORMAT_MSG("current format is: ", DeviceFormat));
-
     /* Get the channel layout of the device side of the unit (vlc -> unit ->
      * device) */
     err = AudioUnitGetPropertyInfo(p_sys->au_unit,
                                    kAudioDevicePropertyPreferredChannelLayout,
                                    kAudioUnitScope_Output, 0, &i_param_size,
                                    NULL);
-
     if (err == noErr)
     {
         layout = (AudioChannelLayout *)malloc(i_param_size);
+        if (layout == NULL)
+            goto error;
 
         OSStatus err =
             AudioUnitGetProperty(p_sys->au_unit,
                                  kAudioDevicePropertyPreferredChannelLayout,
                                  kAudioUnitScope_Output, 0, layout,
                                  &i_param_size);
-
         if (err != noErr)
             goto error;
-
-        /* We need to "fill out" the ChannelLayout, because there are multiple
-         * ways that it can be set */
-        if (layout->mChannelLayoutTag ==
-            kAudioChannelLayoutTag_UseChannelBitmap)
-        {
-            /* bitmap defined channellayout */
-            err =
-             AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForBitmap,
-                                    sizeof(UInt32), &layout->mChannelBitmap,
-                                    &i_param_size, layout);
-        }
-        else if (layout->mChannelLayoutTag !=
-                 kAudioChannelLayoutTag_UseChannelDescriptions)
-        {
-            /* layouttags defined channellayout */
-            err =
-                AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForTag,
-                                       sizeof(AudioChannelLayoutTag),
-                                       &layout->mChannelLayoutTag,
-                                       &i_param_size, layout);
-        }
-
-        if (err != noErr || layout->mNumberChannelDescriptions == 0)
-        {
-            msg_Err(p_aout, "insufficient number of output channels");
-            free(layout);
-            goto error;
-        }
-
-        msg_Dbg(p_aout, "layout of AUHAL has %i channels" ,
-                layout->mNumberChannelDescriptions);
-
-        /* Initialize the VLC core channel count */
-        fmt->i_physical_channels = 0;
-        i_original = fmt->i_original_channels & AOUT_CHAN_PHYSMASK;
-
-        if (i_original == AOUT_CHAN_CENTER
-         || layout->mNumberChannelDescriptions < 2)
-        {
-            /* We only need Mono or cannot output more than 1 channel */
-            fmt->i_physical_channels = AOUT_CHAN_CENTER;
-        }
-        else if (i_original == (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)
-              || layout->mNumberChannelDescriptions < 3)
-        {
-            /* We only need Stereo or cannot output more than 2 channels */
-            fmt->i_physical_channels = AOUT_CHANS_STEREO;
-        }
-        else
-        {
-            // maps auhal channels to vlc ones
-            static const unsigned i_auhal_channel_mapping[] = {
-                [kAudioChannelLabel_Left]           = AOUT_CHAN_LEFT,
-                [kAudioChannelLabel_Right]          = AOUT_CHAN_RIGHT,
-                [kAudioChannelLabel_Center]         = AOUT_CHAN_CENTER,
-                [kAudioChannelLabel_LFEScreen]      = AOUT_CHAN_LFE,
-                [kAudioChannelLabel_LeftSurround]   = AOUT_CHAN_REARLEFT,
-                [kAudioChannelLabel_RightSurround]  = AOUT_CHAN_REARRIGHT,
-                /* needs to be swapped with rear */
-                [kAudioChannelLabel_RearSurroundLeft]  = AOUT_CHAN_MIDDLELEFT,
-                /* needs to be swapped with rear */
-                [kAudioChannelLabel_RearSurroundRight] = AOUT_CHAN_MIDDLERIGHT,
-                [kAudioChannelLabel_CenterSurround] = AOUT_CHAN_REARCENTER
-            };
-
-            /* We want more than stereo and we can do that */
-            for (unsigned i = 0; i < layout->mNumberChannelDescriptions; i++)
-            {
-#ifndef NDEBUG
-                msg_Dbg(p_aout, "this is channel: %d",
-                        (int)layout->mChannelDescriptions[i].mChannelLabel);
-#endif
-
-                AudioChannelLabel chan =
-                    layout->mChannelDescriptions[i].mChannelLabel;
-                const size_t i_auhal_size = sizeof(i_auhal_channel_mapping)
-                                          / sizeof(i_auhal_channel_mapping[0]);
-                if (chan < i_auhal_size && i_auhal_channel_mapping[chan] > 0)
-                    fmt->i_physical_channels |= i_auhal_channel_mapping[chan];
-                else
-                    msg_Dbg(p_aout, "found nonrecognized channel %d at index "
-                            "%d", chan, i);
-            }
-            if (fmt->i_physical_channels == 0)
-            {
-                fmt->i_physical_channels = AOUT_CHANS_STEREO;
-                msg_Err(p_aout, "You should configure your speaker layout with "
-                        "Audio Midi Setup in /Applications/Utilities. VLC will "
-                        "output Stereo only.");
-                vlc_dialog_display_error(p_aout,
-                    _("Audio device is not configured"), "%s",
-                    _("You should configure your speaker layout with "
-                    "\"Audio Midi Setup\" in /Applications/"
-                    "Utilities. VLC will output Stereo only."));
-            }
-        }
-        free(layout);
     }
     else
-    {
         msg_Warn(p_aout, "device driver does not support "
                  "kAudioDevicePropertyPreferredChannelLayout - using stereo "
                  "fallback [%4.4s]", (const char *)&err);
-        fmt->i_physical_channels = AOUT_CHANS_STEREO;
-    }
-    fmt->i_original_channels = fmt->i_physical_channels;
-
-    msg_Dbg(p_aout, "selected %d physical channels for device output",
-            aout_FormatNbChannels(fmt));
-    msg_Dbg(p_aout, "VLC will output: %s", aout_FormatPrintChannels(fmt));
-
-    /* Now we set the INPUT layout of the AU */
-    AudioChannelLayout input_layout;
-    memset (&input_layout, 0, sizeof(input_layout));
-    uint32_t chans_out[AOUT_CHAN_MAX];
-
-    /* Some channel abbreviations used below:
-     * L - left
-     * R - right
-     * C - center
-     * Ls - left surround
-     * Rs - right surround
-     * Cs - center surround
-     * Rls - rear left surround
-     * Rrs - rear right surround
-     * Lw - left wide
-     * Rw - right wide
-     * Lsd - left surround direct
-     * Rsd - right surround direct
-     * Lc - left center
-     * Rc - right center
-     * Ts - top surround
-     * Vhl - vertical height left
-     * Vhc - vertical height center
-     * Vhr - vertical height right
-     * Lt - left matrix total. for matrix encoded stereo.
-     * Rt - right matrix total. for matrix encoded stereo. */
-
-    switch(aout_FormatNbChannels(fmt))
-    {
-        case 1:
-            input_layout.mChannelLayoutTag = kAudioChannelLayoutTag_Mono;
-            break;
-        case 2:
-            input_layout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
-            break;
-        case 3:
-            if (fmt->i_physical_channels & AOUT_CHAN_CENTER) /* L R C */
-                input_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_7;
-            else if (fmt->i_physical_channels & AOUT_CHAN_LFE) /* L R LFE */
-                input_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_4;
-            break;
-        case 4:
-            if (fmt->i_physical_channels & (AOUT_CHAN_CENTER | AOUT_CHAN_LFE)) /* L R C LFE */
-                input_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_10;
-            else if (fmt->i_physical_channels & AOUT_CHANS_REAR) /* L R Ls Rs */
-                input_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_3;
-            else if (fmt->i_physical_channels & AOUT_CHANS_CENTER) /* L R C Cs */
-                input_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_3;
-            break;
-        case 5:
-            if (fmt->i_physical_channels & (AOUT_CHAN_CENTER)) /* L R Ls Rs C */
-                input_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_19;
-            else if (fmt->i_physical_channels & (AOUT_CHAN_LFE)) /* L R Ls Rs LFE */
-                input_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_18;
-            break;
-        case 6:
-            if (fmt->i_physical_channels & (AOUT_CHAN_LFE))
-            {
-                /* L R Ls Rs C LFE */
-                input_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_20;
-
-                chans_out[0] = AOUT_CHAN_LEFT;
-                chans_out[1] = AOUT_CHAN_RIGHT;
-                chans_out[2] = AOUT_CHAN_REARLEFT;
-                chans_out[3] = AOUT_CHAN_REARRIGHT;
-                chans_out[4] = AOUT_CHAN_CENTER;
-                chans_out[5] = AOUT_CHAN_LFE;
-
-                p_sys->c.chans_to_reorder =
-                    aout_CheckChannelReorder(NULL, chans_out,
-                                             fmt->i_physical_channels,
-                                             p_sys->c.chan_table);
-                if (p_sys->c.chans_to_reorder)
-                    msg_Dbg(p_aout, "channel reordering needed for 5.1 output");
-            }
-            else
-            {
-                /* L R Ls Rs C Cs */
-                input_layout.mChannelLayoutTag =
-                    kAudioChannelLayoutTag_AudioUnit_6_0;
-
-                chans_out[0] = AOUT_CHAN_LEFT;
-                chans_out[1] = AOUT_CHAN_RIGHT;
-                chans_out[2] = AOUT_CHAN_REARLEFT;
-                chans_out[3] = AOUT_CHAN_REARRIGHT;
-                chans_out[4] = AOUT_CHAN_CENTER;
-                chans_out[5] = AOUT_CHAN_REARCENTER;
-
-                p_sys->c.chans_to_reorder =
-                    aout_CheckChannelReorder(NULL, chans_out,
-                                             fmt->i_physical_channels,
-                                             p_sys->c.chan_table);
-                if (p_sys->c.chans_to_reorder)
-                    msg_Dbg(p_aout, "channel reordering needed for 6.0 output");
-            }
-            break;
-        case 7:
-            /* L R C LFE Ls Rs Cs */
-            input_layout.mChannelLayoutTag = kAudioChannelLayoutTag_MPEG_6_1_A;
-
-            chans_out[0] = AOUT_CHAN_LEFT;
-            chans_out[1] = AOUT_CHAN_RIGHT;
-            chans_out[2] = AOUT_CHAN_CENTER;
-            chans_out[3] = AOUT_CHAN_LFE;
-            chans_out[4] = AOUT_CHAN_REARLEFT;
-            chans_out[5] = AOUT_CHAN_REARRIGHT;
-            chans_out[6] = AOUT_CHAN_REARCENTER;
-
-            p_sys->c.chans_to_reorder =
-                aout_CheckChannelReorder(NULL, chans_out,
-                                         fmt->i_physical_channels,
-                                         p_sys->c.chan_table);
-            if (p_sys->c.chans_to_reorder)
-                msg_Dbg(p_aout, "channel reordering needed for 6.1 output");
-
-            break;
-        case 8:
-            if (fmt->i_physical_channels & (AOUT_CHAN_LFE)
-             || currentMinorSystemVersion < 7)
-            {
-                /* L R C LFE Ls Rs Rls Rrs */
-                input_layout.mChannelLayoutTag =
-                    kAudioChannelLayoutTag_MPEG_7_1_C;
-
-                chans_out[0] = AOUT_CHAN_LEFT;
-                chans_out[1] = AOUT_CHAN_RIGHT;
-                chans_out[2] = AOUT_CHAN_CENTER;
-                chans_out[3] = AOUT_CHAN_LFE;
-                chans_out[4] = AOUT_CHAN_MIDDLELEFT;
-                chans_out[5] = AOUT_CHAN_MIDDLERIGHT;
-                chans_out[6] = AOUT_CHAN_REARLEFT;
-                chans_out[7] = AOUT_CHAN_REARRIGHT;
-
-                if (!(fmt->i_physical_channels & (AOUT_CHAN_LFE)))
-                    msg_Warn(p_aout, "8.0 audio output not supported on OS X "
-                             "10.%i, layout will be incorrect",
-                             currentMinorSystemVersion);
-            }
-#ifdef MAC_OS_X_VERSION_10_7
-            else
-            {
-                /* Lc C Rc L R Ls Cs Rs */
-                input_layout.mChannelLayoutTag =
-                    kAudioChannelLayoutTag_DTS_8_0_B;
-
-                chans_out[0] = AOUT_CHAN_MIDDLELEFT;
-                chans_out[1] = AOUT_CHAN_CENTER;
-                chans_out[2] = AOUT_CHAN_MIDDLERIGHT;
-                chans_out[3] = AOUT_CHAN_LEFT;
-                chans_out[4] = AOUT_CHAN_RIGHT;
-                chans_out[5] = AOUT_CHAN_REARLEFT;
-                chans_out[6] = AOUT_CHAN_REARCENTER;
-                chans_out[7] = AOUT_CHAN_REARRIGHT;
-            }
-#endif
-            p_sys->c.chans_to_reorder =
-                aout_CheckChannelReorder(NULL, chans_out,
-                                         fmt->i_physical_channels,
-                                         p_sys->c.chan_table);
-            if (p_sys->c.chans_to_reorder)
-                msg_Dbg(p_aout, "channel reordering needed for 7.1 / 8.0 output");
-            break;
-        case 9:
-            if (currentMinorSystemVersion < 7)
-            {
-                msg_Warn(p_aout, "8.1 audio output not supported on OS X 10.%i",
-                         currentMinorSystemVersion);
-                break;
-            }
-
-#ifdef MAC_OS_X_VERSION_10_7
-            /* Lc C Rc L R Ls Cs Rs LFE */
-            input_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DTS_8_1_B;
-            chans_out[0] = AOUT_CHAN_MIDDLELEFT;
-            chans_out[1] = AOUT_CHAN_CENTER;
-            chans_out[2] = AOUT_CHAN_MIDDLERIGHT;
-            chans_out[3] = AOUT_CHAN_LEFT;
-            chans_out[4] = AOUT_CHAN_RIGHT;
-            chans_out[5] = AOUT_CHAN_REARLEFT;
-            chans_out[6] = AOUT_CHAN_REARCENTER;
-            chans_out[7] = AOUT_CHAN_REARRIGHT;
-            chans_out[8] = AOUT_CHAN_LFE;
-
-            p_sys->c.chans_to_reorder =
-                aout_CheckChannelReorder(NULL, chans_out,
-                                         fmt->i_physical_channels,
-                                         p_sys->c.chan_table);
-            if (p_sys->c.chans_to_reorder)
-                msg_Dbg(p_aout, "channel reordering needed for 8.1 output");
-#endif
-            break;
-    }
-
-    /* Set up the format to be used */
-    DeviceFormat.mSampleRate = fmt->i_rate;
-    DeviceFormat.mFormatID = kAudioFormatLinearPCM;
-
-    /* We use float 32 since this is VLC's endorsed format */
-    fmt->i_format = VLC_CODEC_FL32;
-    DeviceFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
-    DeviceFormat.mBitsPerChannel = 32;
-    DeviceFormat.mChannelsPerFrame = aout_FormatNbChannels(fmt);
-
-    /* Calculate framesizes and stuff */
-    DeviceFormat.mFramesPerPacket = 1;
-    DeviceFormat.mBytesPerFrame = DeviceFormat.mBitsPerChannel
-                                * DeviceFormat.mChannelsPerFrame / 8;
-    DeviceFormat.mBytesPerPacket = DeviceFormat.mBytesPerFrame
-                                 * DeviceFormat.mFramesPerPacket;
-
-    /* Set the desired format */
-    i_param_size = sizeof(AudioStreamBasicDescription);
-    err = AudioUnitSetProperty(p_sys->au_unit, kAudioUnitProperty_StreamFormat,
-                               kAudioUnitScope_Input, 0, &DeviceFormat,
-                               i_param_size);
-    if (err != noErr)
-        goto error;
-
-    msg_Dbg(p_aout, STREAM_FORMAT_MSG("we set the AU format: " , DeviceFormat));
-
-    /* Retrieve actual format */
-    err = AudioUnitGetProperty(p_sys->au_unit, kAudioUnitProperty_StreamFormat,
-                               kAudioUnitScope_Input, 0, &DeviceFormat,
-                               &i_param_size);
-    if (err != noErr)
-        goto error;
-
-    msg_Dbg(p_aout, STREAM_FORMAT_MSG("the actual set AU format is ",
-            DeviceFormat));
 
     /* Do the last VLC aout setups */
-    aout_FormatPrepare(fmt);
-
-    /* set the IOproc callback */
-    input.inputProc = RenderCallbackAnalog;
-    input.inputProcRefCon = p_aout;
-
-    err = AudioUnitSetProperty(p_sys->au_unit,
-                               kAudioUnitProperty_SetRenderCallback,
-                               kAudioUnitScope_Input, 0, &input, sizeof(input));
-    if (err != noErr)
-        goto error;
-
-    /* Set the input_layout as the layout VLC will use to feed the AU unit.
-     * Yes, it must be the INPUT scope */
-    err = AudioUnitSetProperty(p_sys->au_unit,
-                               kAudioUnitProperty_AudioChannelLayout,
-                               kAudioUnitScope_Input, 0, &input_layout,
-                               sizeof(input_layout));
-    if (err != noErr)
-        goto error;
-
-    /* AU initiliaze */
-    err = AudioUnitInitialize(p_sys->au_unit);
-    if (err != noErr)
-    {
-        msg_Err(p_aout, "AudioUnitInitialize failed: [%4.4s]",
-                (const char *)&err);
+    fmt->i_format = VLC_CODEC_FL32;
+    int ret = au_Initialize(p_aout, p_sys->au_unit, fmt, layout);
+    if (ret != VLC_SUCCESS)
         goto error;
-    }
 
-    int ret = ca_Init(p_aout, fmt, AUDIO_BUFFER_SIZE_IN_SECONDS * fmt->i_rate *
-                      fmt->i_bytes_per_frame);
+    ret = ca_Init(p_aout, fmt, AUDIO_BUFFER_SIZE_IN_SECONDS * fmt->i_rate *
+                  fmt->i_bytes_per_frame);
     if (ret != VLC_SUCCESS)
     {
         AudioUnitUninitialize(p_sys->au_unit);
@@ -1427,9 +1019,11 @@ StartAnalog(audio_output_t *p_aout, audio_sample_format_t *fmt)
     VolumeSet(p_aout, p_sys->f_volume);
     MuteSet(p_aout, p_sys->b_mute);
 
+    free(layout);
     return VLC_SUCCESS;
 error:
     AudioComponentInstanceDispose(p_sys->au_unit);
+    free(layout);
     return VLC_EGENERIC;
 }
 
diff --git a/modules/audio_output/coreaudio_common.c b/modules/audio_output/coreaudio_common.c
index 0ca4986..e84cbc4 100644
--- a/modules/audio_output/coreaudio_common.c
+++ b/modules/audio_output/coreaudio_common.c
@@ -23,6 +23,12 @@
  *****************************************************************************/
 
 #import "coreaudio_common.h"
+#import <CoreAudio/CoreAudioTypes.h>
+
+#if !TARGET_OS_IPHONE
+#import <CoreServices/CoreServices.h>
+#import <vlc_dialog.h>
+#endif
 
 static inline uint64_t
 BytesToFrames(struct aout_sys_common *p_sys, size_t i_bytes)
@@ -188,6 +194,7 @@ ca_Init(audio_output_t *p_aout, const audio_sample_format_t *fmt,
     p_sys->i_rate = fmt->i_rate;
     p_sys->i_bytes_per_frame = fmt->i_bytes_per_frame;
     p_sys->i_frame_length = fmt->i_frame_length;
+    p_sys->chans_to_reorder = 0;
 
     p_aout->play = ca_Play;
     p_aout->pause = ca_Pause;
@@ -234,3 +241,465 @@ au_NewOutputInstance(audio_output_t *p_aout, OSType comp_sub_type)
     }
     return au;
 }
+
+/*****************************************************************************
+ * RenderCallback: This function is called everytime the AudioUnit wants
+ * us to provide some more audio data.
+ * Don't print anything during normal playback, calling blocking function from
+ * this callback is not allowed.
+ *****************************************************************************/
+static OSStatus
+RenderCallback(void *p_data, AudioUnitRenderActionFlags *ioActionFlags,
+               const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber,
+               UInt32 inNumberFrames, AudioBufferList *ioData)
+{
+    VLC_UNUSED(ioActionFlags);
+    VLC_UNUSED(inTimeStamp);
+    VLC_UNUSED(inBusNumber);
+    VLC_UNUSED(inNumberFrames);
+
+    ca_Render(p_data, ioData->mBuffers[0].mData,
+              ioData->mBuffers[0].mDataByteSize);
+
+    return noErr;
+}
+
+static AudioChannelLayout *
+GetLayoutDescription(audio_output_t *p_aout,
+                     const AudioChannelLayout *outlayout)
+{
+    AudioFormatPropertyID id;
+    UInt32 size;
+    const void *data;
+    /* We need to "fill out" the ChannelLayout, because there are multiple
+     * ways that it can be set */
+    if (outlayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
+    {
+        id = kAudioFormatProperty_ChannelLayoutForBitmap;
+        size = sizeof(UInt32);
+        data = &outlayout->mChannelBitmap;
+    }
+    else
+    {
+        id = kAudioFormatProperty_ChannelLayoutForTag;
+        size = sizeof(AudioChannelLayoutTag);
+        data = &outlayout->mChannelLayoutTag;
+    }
+
+    UInt32 param_size;
+    OSStatus err = AudioFormatGetPropertyInfo(id, size, data, &param_size);
+    if (err != noErr)
+        return NULL;
+
+    AudioChannelLayout *reslayout = malloc(param_size);
+    if (reslayout == NULL)
+        return NULL;
+
+    err = AudioFormatGetProperty(id, size, data, &param_size, reslayout);
+    if (err != noErr || reslayout->mNumberChannelDescriptions == 0)
+    {
+        msg_Err(p_aout, "insufficient number of output channels");
+        free(reslayout);
+        return NULL;
+    }
+
+    return reslayout;
+}
+
+static int
+MapOutputLayout(audio_output_t *p_aout, audio_sample_format_t *fmt,
+                const AudioChannelLayout *outlayout)
+{
+    /* Fill VLC physical_channels from output layout */
+    fmt->i_physical_channels = 0;
+    uint32_t i_original = fmt->i_original_channels & AOUT_CHAN_PHYSMASK;
+    AudioChannelLayout *reslayout = NULL;
+
+    if (outlayout == NULL)
+    {
+        msg_Dbg(p_aout, "not output layout, default to Stereo");
+        fmt->i_physical_channels = AOUT_CHANS_STEREO;
+        goto end;
+    }
+
+    if (outlayout->mChannelLayoutTag !=
+        kAudioChannelLayoutTag_UseChannelDescriptions)
+    {
+        reslayout = GetLayoutDescription(p_aout, outlayout);
+        if (reslayout == NULL)
+            return VLC_EGENERIC;
+        outlayout = reslayout;
+    }
+
+    if (i_original == AOUT_CHAN_CENTER
+     || outlayout->mNumberChannelDescriptions < 2)
+    {
+        /* We only need Mono or cannot output more than 1 channel */
+        fmt->i_physical_channels = AOUT_CHAN_CENTER;
+        msg_Dbg(p_aout, "output layout of AUHAL has 1 channel");
+    }
+    else if (i_original == (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)
+          || outlayout->mNumberChannelDescriptions < 3)
+    {
+        /* We only need Stereo or cannot output more than 2 channels */
+        fmt->i_physical_channels = AOUT_CHANS_STEREO;
+        msg_Dbg(p_aout, "output layout of AUHAL is Stereo");
+    }
+    else
+    {
+        assert(outlayout->mNumberChannelDescriptions > 0);
+
+        msg_Dbg(p_aout, "output layout of AUHAL has %i channels",
+                outlayout->mNumberChannelDescriptions);
+
+        /* maps auhal channels to vlc ones */
+        static const unsigned i_auhal_channel_mapping[] = {
+            [kAudioChannelLabel_Left]           = AOUT_CHAN_LEFT,
+            [kAudioChannelLabel_Right]          = AOUT_CHAN_RIGHT,
+            [kAudioChannelLabel_Center]         = AOUT_CHAN_CENTER,
+            [kAudioChannelLabel_LFEScreen]      = AOUT_CHAN_LFE,
+            [kAudioChannelLabel_LeftSurround]   = AOUT_CHAN_REARLEFT,
+            [kAudioChannelLabel_RightSurround]  = AOUT_CHAN_REARRIGHT,
+            /* needs to be swapped with rear */
+            [kAudioChannelLabel_RearSurroundLeft]  = AOUT_CHAN_MIDDLELEFT,
+            /* needs to be swapped with rear */
+            [kAudioChannelLabel_RearSurroundRight] = AOUT_CHAN_MIDDLERIGHT,
+            [kAudioChannelLabel_CenterSurround] = AOUT_CHAN_REARCENTER
+        };
+        static const size_t i_auhal_size = sizeof(i_auhal_channel_mapping)
+                                         / sizeof(i_auhal_channel_mapping[0]);
+
+        /* We want more than stereo and we can do that */
+        for (unsigned i = 0; i < outlayout->mNumberChannelDescriptions; i++)
+        {
+            AudioChannelLabel chan =
+                outlayout->mChannelDescriptions[i].mChannelLabel;
+#ifndef NDEBUG
+            msg_Dbg(p_aout, "this is channel: %d", (int) chan);
+#endif
+            if (chan < i_auhal_size && i_auhal_channel_mapping[chan] > 0)
+                fmt->i_physical_channels |= i_auhal_channel_mapping[chan];
+            else
+                msg_Dbg(p_aout, "found nonrecognized channel %d at index "
+                        "%d", chan, i);
+        }
+        if (fmt->i_physical_channels == 0)
+        {
+            fmt->i_physical_channels = AOUT_CHANS_STEREO;
+            msg_Err(p_aout, "You should configure your speaker layout with "
+                    "Audio Midi Setup in /Applications/Utilities. VLC will "
+                    "output Stereo only.");
+#if !TARGET_OS_IPHONE
+            vlc_dialog_display_error(p_aout,
+                _("Audio device is not configured"), "%s",
+                _("You should configure your speaker layout with "
+                "\"Audio Midi Setup\" in /Applications/"
+                "Utilities. VLC will output Stereo only."));
+#endif
+        }
+    }
+
+end:
+    free(reslayout);
+    fmt->i_original_channels = fmt->i_physical_channels;
+    aout_FormatPrepare(fmt);
+
+    msg_Dbg(p_aout, "selected %d physical channels for device output",
+            aout_FormatNbChannels(fmt));
+    msg_Dbg(p_aout, "VLC will output: %s", aout_FormatPrintChannels(fmt));
+
+    return VLC_SUCCESS;
+}
+
+static int
+SetupInputLayout(audio_output_t *p_aout, const audio_sample_format_t *fmt,
+                 AudioChannelLayoutTag *inlayout_tag)
+{
+    struct aout_sys_common *p_sys = (struct aout_sys_common *) p_aout->sys;
+    uint32_t chans_out[AOUT_CHAN_MAX];
+
+#if TARGET_OS_IPHONE
+    const bool b_8x_support = false;
+#else
+    SInt32 osx_min_version;
+    if (Gestalt(gestaltSystemVersionMinor, &osx_min_version) != noErr)
+        msg_Err(p_aout, "failed to check OSX version");
+    const bool b_8x_support = osx_min_version >= 7;
+#endif
+
+    /* Some channel abbreviations used below:
+     * L - left
+     * R - right
+     * C - center
+     * Ls - left surround
+     * Rs - right surround
+     * Cs - center surround
+     * Rls - rear left surround
+     * Rrs - rear right surround
+     * Lw - left wide
+     * Rw - right wide
+     * Lsd - left surround direct
+     * Rsd - right surround direct
+     * Lc - left center
+     * Rc - right center
+     * Ts - top surround
+     * Vhl - vertical height left
+     * Vhc - vertical height center
+     * Vhr - vertical height right
+     * Lt - left matrix total. for matrix encoded stereo.
+     * Rt - right matrix total. for matrix encoded stereo. */
+
+    switch (aout_FormatNbChannels(fmt))
+    {
+        case 1:
+            *inlayout_tag = kAudioChannelLayoutTag_Mono;
+            break;
+        case 2:
+            *inlayout_tag = kAudioChannelLayoutTag_Stereo;
+            break;
+        case 3:
+            if (fmt->i_physical_channels & AOUT_CHAN_CENTER) /* L R C */
+                *inlayout_tag = kAudioChannelLayoutTag_DVD_7;
+            else if (fmt->i_physical_channels & AOUT_CHAN_LFE) /* L R LFE */
+                *inlayout_tag = kAudioChannelLayoutTag_DVD_4;
+            break;
+        case 4:
+            if (fmt->i_physical_channels & (AOUT_CHAN_CENTER | AOUT_CHAN_LFE)) /* L R C LFE */
+                *inlayout_tag = kAudioChannelLayoutTag_DVD_10;
+            else if (fmt->i_physical_channels & AOUT_CHANS_REAR) /* L R Ls Rs */
+                *inlayout_tag = kAudioChannelLayoutTag_DVD_3;
+            else if (fmt->i_physical_channels & AOUT_CHANS_CENTER) /* L R C Cs */
+                *inlayout_tag = kAudioChannelLayoutTag_DVD_3;
+            break;
+        case 5:
+            if (fmt->i_physical_channels & (AOUT_CHAN_CENTER)) /* L R Ls Rs C */
+                *inlayout_tag = kAudioChannelLayoutTag_DVD_19;
+            else if (fmt->i_physical_channels & (AOUT_CHAN_LFE)) /* L R Ls Rs LFE */
+                *inlayout_tag = kAudioChannelLayoutTag_DVD_18;
+            break;
+        case 6:
+            if (fmt->i_physical_channels & (AOUT_CHAN_LFE))
+            {
+                /* L R Ls Rs C LFE */
+                *inlayout_tag = kAudioChannelLayoutTag_DVD_20;
+
+                chans_out[0] = AOUT_CHAN_LEFT;
+                chans_out[1] = AOUT_CHAN_RIGHT;
+                chans_out[2] = AOUT_CHAN_REARLEFT;
+                chans_out[3] = AOUT_CHAN_REARRIGHT;
+                chans_out[4] = AOUT_CHAN_CENTER;
+                chans_out[5] = AOUT_CHAN_LFE;
+
+                p_sys->chans_to_reorder =
+                    aout_CheckChannelReorder(NULL, chans_out,
+                                             fmt->i_physical_channels,
+                                             p_sys->chan_table);
+                if (p_sys->chans_to_reorder)
+                    msg_Dbg(p_aout, "channel reordering needed for 5.1 output");
+            }
+            else
+            {
+                /* L R Ls Rs C Cs */
+                *inlayout_tag = kAudioChannelLayoutTag_AudioUnit_6_0;
+
+                chans_out[0] = AOUT_CHAN_LEFT;
+                chans_out[1] = AOUT_CHAN_RIGHT;
+                chans_out[2] = AOUT_CHAN_REARLEFT;
+                chans_out[3] = AOUT_CHAN_REARRIGHT;
+                chans_out[4] = AOUT_CHAN_CENTER;
+                chans_out[5] = AOUT_CHAN_REARCENTER;
+
+                p_sys->chans_to_reorder =
+                    aout_CheckChannelReorder(NULL, chans_out,
+                                             fmt->i_physical_channels,
+                                             p_sys->chan_table);
+                if (p_sys->chans_to_reorder)
+                    msg_Dbg(p_aout, "channel reordering needed for 6.0 output");
+            }
+            break;
+        case 7:
+            /* L R C LFE Ls Rs Cs */
+            *inlayout_tag = kAudioChannelLayoutTag_MPEG_6_1_A;
+
+            chans_out[0] = AOUT_CHAN_LEFT;
+            chans_out[1] = AOUT_CHAN_RIGHT;
+            chans_out[2] = AOUT_CHAN_CENTER;
+            chans_out[3] = AOUT_CHAN_LFE;
+            chans_out[4] = AOUT_CHAN_REARLEFT;
+            chans_out[5] = AOUT_CHAN_REARRIGHT;
+            chans_out[6] = AOUT_CHAN_REARCENTER;
+
+            p_sys->chans_to_reorder =
+                aout_CheckChannelReorder(NULL, chans_out,
+                                         fmt->i_physical_channels,
+                                         p_sys->chan_table);
+            if (p_sys->chans_to_reorder)
+                msg_Dbg(p_aout, "channel reordering needed for 6.1 output");
+
+            break;
+        case 8:
+            if (fmt->i_physical_channels & (AOUT_CHAN_LFE) || !b_8x_support)
+            {
+                /* L R C LFE Ls Rs Rls Rrs */
+                *inlayout_tag = kAudioChannelLayoutTag_MPEG_7_1_C;
+
+                chans_out[0] = AOUT_CHAN_LEFT;
+                chans_out[1] = AOUT_CHAN_RIGHT;
+                chans_out[2] = AOUT_CHAN_CENTER;
+                chans_out[3] = AOUT_CHAN_LFE;
+                chans_out[4] = AOUT_CHAN_MIDDLELEFT;
+                chans_out[5] = AOUT_CHAN_MIDDLERIGHT;
+                chans_out[6] = AOUT_CHAN_REARLEFT;
+                chans_out[7] = AOUT_CHAN_REARRIGHT;
+
+                if (!(fmt->i_physical_channels & (AOUT_CHAN_LFE)))
+                    msg_Warn(p_aout, "8.0 audio output not supported on this "
+                             "device, layout will be incorrect");
+            }
+#ifdef MAC_OS_X_VERSION_10_7
+            else
+            {
+                /* Lc C Rc L R Ls Cs Rs */
+                *inlayout_tag = kAudioChannelLayoutTag_DTS_8_0_B;
+
+                chans_out[0] = AOUT_CHAN_MIDDLELEFT;
+                chans_out[1] = AOUT_CHAN_CENTER;
+                chans_out[2] = AOUT_CHAN_MIDDLERIGHT;
+                chans_out[3] = AOUT_CHAN_LEFT;
+                chans_out[4] = AOUT_CHAN_RIGHT;
+                chans_out[5] = AOUT_CHAN_REARLEFT;
+                chans_out[6] = AOUT_CHAN_REARCENTER;
+                chans_out[7] = AOUT_CHAN_REARRIGHT;
+            }
+#endif
+            p_sys->chans_to_reorder =
+                aout_CheckChannelReorder(NULL, chans_out,
+                                         fmt->i_physical_channels,
+                                         p_sys->chan_table);
+            if (p_sys->chans_to_reorder)
+                msg_Dbg(p_aout, "channel reordering needed for 7.1 / 8.0 output");
+            break;
+        case 9:
+            if (!b_8x_support)
+            {
+                msg_Warn(p_aout, "8.1 audio output not supported on this device");
+                break;
+            }
+
+#ifdef MAC_OS_X_VERSION_10_7
+            /* Lc C Rc L R Ls Cs Rs LFE */
+            *inlayout_tag = kAudioChannelLayoutTag_DTS_8_1_B;
+            chans_out[0] = AOUT_CHAN_MIDDLELEFT;
+            chans_out[1] = AOUT_CHAN_CENTER;
+            chans_out[2] = AOUT_CHAN_MIDDLERIGHT;
+            chans_out[3] = AOUT_CHAN_LEFT;
+            chans_out[4] = AOUT_CHAN_RIGHT;
+            chans_out[5] = AOUT_CHAN_REARLEFT;
+            chans_out[6] = AOUT_CHAN_REARCENTER;
+            chans_out[7] = AOUT_CHAN_REARRIGHT;
+            chans_out[8] = AOUT_CHAN_LFE;
+
+            p_sys->chans_to_reorder =
+                aout_CheckChannelReorder(NULL, chans_out,
+                                         fmt->i_physical_channels,
+                                         p_sys->chan_table);
+            if (p_sys->chans_to_reorder)
+                msg_Dbg(p_aout, "channel reordering needed for 8.1 output");
+#endif
+            break;
+    }
+
+    return VLC_SUCCESS;
+}
+
+int
+au_Initialize(audio_output_t *p_aout, AudioUnit au, audio_sample_format_t *fmt,
+              const AudioChannelLayout *outlayout)
+{
+    assert(fmt->i_format == VLC_CODEC_FL32);
+
+    int ret = MapOutputLayout(p_aout, fmt, outlayout);
+    if (ret != VLC_SUCCESS)
+        return ret;
+
+    AudioChannelLayoutTag inlayout_tag;
+    ret = SetupInputLayout(p_aout, fmt, &inlayout_tag);
+    if (ret != VLC_SUCCESS)
+        return ret;
+
+    /* Set the desired format */
+    AudioStreamBasicDescription desc;
+    desc.mSampleRate = fmt->i_rate;
+    desc.mFormatID = kAudioFormatLinearPCM;
+    desc.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
+    desc.mChannelsPerFrame = aout_FormatNbChannels(fmt);
+    desc.mFramesPerPacket = 1;
+    desc.mBitsPerChannel = 32;
+    desc.mBytesPerFrame = desc.mBitsPerChannel * desc.mChannelsPerFrame / 8;
+    desc.mBytesPerPacket = desc.mBytesPerFrame * desc.mFramesPerPacket;
+
+    OSStatus err = AudioUnitSetProperty(au, kAudioUnitProperty_StreamFormat,
+                                        kAudioUnitScope_Input, 0, &desc,
+                                        sizeof(desc));
+    if (err != noErr)
+    {
+        msg_Err(p_aout, "failed to set stream format [%4.4s]",
+                (const char *)&err);
+        return VLC_EGENERIC;
+    }
+    msg_Dbg(p_aout, STREAM_FORMAT_MSG("Current AU format: " , desc));
+
+    /* Retrieve actual format */
+    err = AudioUnitGetProperty(au, kAudioUnitProperty_StreamFormat,
+                               kAudioUnitScope_Input, 0, &desc,
+                               &(UInt32) { sizeof(desc) });
+    if (err != noErr)
+    {
+        msg_Err(p_aout, "failed to verify stream format [%4.4s]",
+                (const char *)&err);
+        return VLC_EGENERIC;
+    }
+
+    /* Set the IOproc callback */
+    const AURenderCallbackStruct callback = {
+        .inputProc = RenderCallback,
+        .inputProcRefCon = p_aout,
+    };
+
+    err = AudioUnitSetProperty(au, kAudioUnitProperty_SetRenderCallback,
+                               kAudioUnitScope_Input, 0, &callback,
+                               sizeof(callback));
+    if (err != noErr)
+    {
+        msg_Err(p_aout, "failed to setup render callback [%4.4s]",
+                (const char *)&err);
+        return VLC_EGENERIC;
+    }
+
+    /* Set the input_layout as the layout VLC will use to feed the AU unit.
+     * Yes, it must be the INPUT scope */
+    AudioChannelLayout inlayout = {
+        .mChannelLayoutTag = inlayout_tag,
+    };
+    err = AudioUnitSetProperty(au, kAudioUnitProperty_AudioChannelLayout,
+                               kAudioUnitScope_Input, 0, &inlayout,
+                               sizeof(inlayout));
+    if (err != noErr)
+    {
+        msg_Err(p_aout, "failed to setup input layout [%4.4s]",
+                (const char *)&err);
+        return VLC_EGENERIC;
+    }
+
+    /* AU init */
+    err = AudioUnitInitialize(au);
+
+    if (err != noErr)
+    {
+        msg_Err(p_aout, "AudioUnitInitialize failed: [%4.4s]",
+                (const char *)&err);
+        return VLC_EGENERIC;
+    }
+
+    return VLC_SUCCESS;
+}
diff --git a/modules/audio_output/coreaudio_common.h b/modules/audio_output/coreaudio_common.h
index f6a532a..21831cf 100644
--- a/modules/audio_output/coreaudio_common.h
+++ b/modules/audio_output/coreaudio_common.h
@@ -53,11 +53,11 @@ struct aout_sys_common
     int                 i_rate;
     unsigned int        i_bytes_per_frame;
     unsigned int        i_frame_length;
+    uint8_t             chans_to_reorder;
+    uint8_t             chan_table[AOUT_CHAN_MAX];
 
     /* The following need to set by the caller */
 
-    uint8_t             chans_to_reorder;
-    uint8_t             chan_table[AOUT_CHAN_MAX];
     /* The time the device needs to process the data. In samples. */
     uint32_t            i_device_latency;
 };
@@ -78,3 +78,7 @@ int  ca_Init(audio_output_t *p_aout, const audio_sample_format_t *fmt,
 void ca_Clean(audio_output_t *p_aout);
 
 AudioUnit au_NewOutputInstance(audio_output_t *p_aout, OSType comp_sub_type);
+
+int  au_Initialize(audio_output_t *p_aout, AudioUnit au,
+                   audio_sample_format_t *fmt,
+                   const AudioChannelLayout *outlayout);




More information about the vlc-commits mailing list