[vlc-devel] [PATCH] auhal: fixed digital audio output

Ron Frederick ronf at timeheart.net
Sun Jul 24 03:22:38 CEST 2011


On Jul 23, 2011, at 5:24 PM, Ron Frederick wrote:
> On Jul 18, 2011, at 3:08 AM, Felix Kühne wrote:
>> Hi there,
>> 
>> On 18.07.2011, at 08:42, David Fuhrmann wrote:
>> 
>>> Since vlc 1.1.11 digital audio output (ac3, dts) is broken on mac os. The following patch fixes the problem. It is tested with mac os 10.6, vlc 1.1.11 and various audio formats.
>> 
>> Thanks a lot for the patch. I had to re-write the AUHAL API parts of this module to ensure compatibility with future Mac OS X releases. Due to a lack of an optical audio testing device, these mistakes weren't caught.
>> 
>> Your patch was applied to the stable and unstable branches of VLC and will be part of tonight's nightly builds available at nightlies.videolan.org.
> 
> Unfortunately, this still isn't working for me under 10.6.8. While it now tries to send encoded output again, the audio stutters on the files I've tried, as if maybe it isn't sending the data at the right rate. Going back to 1.1.11, the audio from the same files plays smoothly over the optical audio out but only in stereo.
> 
> I also gave Lion a quick try on another machine and optical audio output didn't seem to work at all, in either stereo or surround.


I did a little more digging into this, and the problem appears to be that it is selecting the wrong output format. In particular, I can see it selecting 96000 Hz for a sample rate instead of 48000 Hz:

a52 debug: A/52 channels:6 samplerate:48000 bitrate:384000
main debug: VLC is looking for: 'a52 ' 48000 Hz 3F2R/LFE frame=1536 samples/1536 bytes
auhal debug: found 3 audio device(s)
auhal debug: DevID: 260 DevName: Built-in Microphone
auhal debug: this device is INPUT only. skipping...
auhal debug: DevID: 258 DevName: Built-in Input
auhal debug: this device is INPUT only. skipping...
auhal debug: DevID: 262 DevName: Built-in Output
auhal debug: found 23 stream formats
auhal debug: supported format: [96000][mcpl][12][4][1][4][2][16]
auhal debug: supported format: [88200][mcpl][12][4][1][4][2][16]
auhal debug: supported format: [48000][mcpl][12][4][1][4][2][16]
auhal debug: supported format: [44100][mcpl][12][4][1][4][2][16]
auhal debug: supported format: [32000][mcpl][12][4][1][4][2][16]
auhal debug: supported format: [96000][mcpl][4][8][1][8][2][20]
auhal debug: supported format: [88200][mcpl][4][8][1][8][2][20]
auhal debug: supported format: [48000][mcpl][4][8][1][8][2][20]
auhal debug: supported format: [44100][mcpl][4][8][1][8][2][20]
auhal debug: supported format: [32000][mcpl][4][8][1][8][2][20]
auhal debug: supported format: [96000][mcpl][4][8][1][8][2][24]
auhal debug: supported format: [88200][mcpl][4][8][1][8][2][24]
auhal debug: supported format: [48000][mcpl][4][8][1][8][2][24]
auhal debug: supported format: [44100][mcpl][4][8][1][8][2][24]
auhal debug: supported format: [32000][mcpl][4][8][1][8][2][24]
auhal debug: supported format: [96000][mcpl][9][8][1][8][2][32]
auhal debug: supported format: [88200][mcpl][9][8][1][8][2][32]
auhal debug: supported format: [48000][mcpl][9][8][1][8][2][32]
auhal debug: supported format: [44100][mcpl][9][8][1][8][2][32]
auhal debug: supported format: [32000][mcpl][9][8][1][8][2][32]
auhal debug: supported format: [96000][3cac][76][6144][1536][0][2][16]
auhal debug: supported format: [48000][3cac][76][6144][1536][0][2][16]
auhal debug: supported format: [44100][3cac][76][6144][1536][0][2][16]
auhal debug: audio device supports digital output
auhal debug: original stream format: [0][    ][4076007936][4076007936][4076007936][4076007936][4076007936][4076007936]
auhal debug: setting stream format: [96000][3cac][76][6144][1536][0][2][16]
auhal debug: reached timeout
auhal debug: actual format in use: [96000][3cac][76][6144][1536][0][2][16]

Looking into the code, one problem I see is that it is using a variable that doesn't appear to be set yet when looping over the list of stream formats trying to find a match:

        if( b_digital )
        {
            /* if this stream supports a digital (cac3) format, then go set it. */
            int i_requested_rate_format = -1;
            int i_current_rate_format = -1;
            int i_backup_rate_format = -1;

            p_sys->i_stream_id = p_streams[i];
            p_sys->i_stream_index = i;
            if( !p_sys->b_revert )
            {
                /* Retrieve the original format of this stream first if not done so already */
                i_param_size = sizeof( p_sys->sfmt_revert );
                err = AudioObjectGetPropertyData( p_sys->i_stream_id, &physicalFormatsAddress, 0, NULL, &i_param_size, &p_sys->sfmt_revert );
                if( err != noErr )
                {
                    msg_Err( p_aout, "could not retrieve the original streamformat: [%4.4s]", (char *)&err );
                    continue;
                }
                p_sys->b_revert = true;
            }

            for( int j = 0; j < i_formats; j++ )
            {
                if( p_format_list[j].mFormatID == 'IAC3' ||
                      p_format_list[j].mFormatID == kAudioFormat60958AC3 )
                {
                    if( p_format_list[j].mSampleRate == p_aout->output.output.i_rate )        <--- This isn't set until below.
                    {
                        i_requested_rate_format = j;
                        break;
                    }
                    else if( p_format_list[j].mSampleRate == p_sys->sfmt_revert.mSampleRate )
                    {
                        i_current_rate_format = j;
                    }
                    else
                    {
                        if( i_backup_rate_format < 0 || p_format_list[j].mSampleRate > p_format_list[i_backup_rate_format].mSampleRate )
                            i_backup_rate_format = j;
                    }
                }

            }

            if( i_requested_rate_format >= 0 ) /* We prefer to output at the samplerate of the original audio */
                p_sys->stream_format = p_format_list[i_requested_rate_format];
            else if( i_current_rate_format >= 0 ) /* If not possible, we will try to use the current samplerate of the device */
                p_sys->stream_format = p_format_list[i_current_rate_format];
            else p_sys->stream_format = p_format_list[i_backup_rate_format]; /* And if we have to, any digital format will be just fine (highest rate possible) */
        }
        free( p_format_list );
    }
    free( p_streams );

    msg_Dbg( p_aout, STREAM_FORMAT_MSG( "original stream format: ", p_sys->sfmt_revert ) );

    if( !AudioStreamChangeFormat( p_aout, p_sys->i_stream_id, p_sys->stream_format ) )
        return false;

    /* Set the format flags */
    if( p_sys->stream_format.mFormatFlags & kAudioFormatFlagIsBigEndian )
        p_aout->output.output.i_format = VLC_CODEC_SPDIFB;
    else
        p_aout->output.output.i_format = VLC_CODEC_SPDIFL;
    p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
    p_aout->output.output.i_frame_length = A52_FRAME_NB;
    p_aout->output.i_nb_samples = p_aout->output.output.i_frame_length;
    p_aout->output.output.i_rate = (unsigned int)p_sys->stream_format.mSampleRate;
    aout_FormatPrepare( &p_aout->output.output );
    aout_VolumeNoneInit( p_aout );

In fact, the i_rate parameter there is set based on p_sys->stream_format, but that is set based on the value of i_requested_rate_format, which the above "for" loop is trying to set by comparing against i_rate. I haven't figured out the right way to fix this, though. I need to look through the a52 module to see if it exports its audio format information somewhere that auhal would have access to. If anyone already knows this code, though, I thought I'd share the above in the hopes that it might help you to fix it.
-- 
Ron Frederick
ronf at timeheart.net

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20110723/1c1dd9fd/attachment.html>


More information about the vlc-devel mailing list