⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 auhal.c

📁 uclinux 下的vlc播放器源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/***************************************************************************** * auhal.c: AUHAL and Coreaudio output plugin ***************************************************************************** * Copyright (C) 2005 the VideoLAN team * $Id: auhal.c 14997 2006-03-31 15:15:07Z fkuehne $ * * Authors: Derk-Jan Hartman <hartman at videolan dot org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. *  * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <string.h>#include <stdlib.h>#include <unistd.h>#include <vlc/vlc.h>#include <vlc/aout.h>#include "aout_internal.h"#include <CoreAudio/CoreAudio.h>#include <AudioUnit/AudioUnitProperties.h>#include <AudioUnit/AudioUnitParameters.h>#include <AudioUnit/AudioOutputUnit.h>#include <AudioToolbox/AudioFormat.h>#define STREAM_FORMAT_MSG( pre, sfm ) \    pre "[%ld][%4.4s][%ld][%ld][%ld][%ld][%ld][%ld]", \    (UInt32)sfm.mSampleRate, (char *)&sfm.mFormatID, \    sfm.mFormatFlags, sfm.mBytesPerPacket, \    sfm.mFramesPerPacket, sfm.mBytesPerFrame, \    sfm.mChannelsPerFrame, sfm.mBitsPerChannel#define STREAM_FORMAT_MSG_FULL( pre, sfm ) \    pre ":\nsamplerate: [%ld]\nFormatID: [%4.4s]\nFormatFlags: [%ld]\nBypesPerPacket: [%ld]\nFramesPerPacket: [%ld]\nBytesPerFrame: [%ld]\nChannelsPerFrame: [%ld]\nBitsPerChannel[%ld]", \    (UInt32)sfm.mSampleRate, (char *)&sfm.mFormatID, \    sfm.mFormatFlags, sfm.mBytesPerPacket, \    sfm.mFramesPerPacket, sfm.mBytesPerFrame, \    sfm.mChannelsPerFrame, sfm.mBitsPerChannel#define BUFSIZE 0xffffff#define AOUT_VAR_SPDIF_FLAG 0xf00000/* * TODO: * - clean up the debug info * - clean up C99'isms * - be better at changing stream setup or devices setup changes while playing. * - fix 6.1 and 7.1 *//***************************************************************************** * aout_sys_t: private audio output method descriptor ***************************************************************************** * This structure is part of the audio output thread descriptor. * It describes the CoreAudio specific properties of an output thread. *****************************************************************************/struct aout_sys_t{    AudioDeviceID               i_default_dev;  /* Keeps DeviceID of defaultOutputDevice */    AudioDeviceID               i_selected_dev; /* Keeps DeviceID of the selected device */    UInt32                      i_devices;      /* Number of CoreAudio Devices */    vlc_bool_t                  b_supports_digital;/* Does the currently selected device support digital mode? */    vlc_bool_t                  b_digital;      /* Are we running in digital mode? */    mtime_t                     clock_diff;     /* Difference between VLC clock and Device clock */    /* AUHAL specific */    Component                   au_component;   /* The Audiocomponent we use */    AudioUnit                   au_unit;        /* The AudioUnit we use */    uint8_t                     p_remainder_buffer[BUFSIZE];    uint32_t                    i_read_bytes;    uint32_t                    i_total_bytes;    /* CoreAudio SPDIF mode specific */    pid_t                       i_hog_pid;      /* The keep the pid of our hog status */    AudioStreamID               i_stream_id;    /* The StreamID that has a cac3 streamformat */    int                         i_stream_index; /* The index of i_stream_id in an AudioBufferList */    AudioStreamBasicDescription stream_format;  /* The format we changed the stream to */    AudioStreamBasicDescription sfmt_revert;    /* The original format of the stream */    vlc_bool_t                  b_revert;       /* Wether we need to revert the stream format */    vlc_bool_t                  b_changed_mixing;/* Wether we need to set the mixing mode back */};/***************************************************************************** * Local prototypes. *****************************************************************************/static int      Open                    ( vlc_object_t * );static int      OpenAnalog              ( aout_instance_t * );static int      OpenSPDIF               ( aout_instance_t * );static void     Close                   ( vlc_object_t * );static void     Play                    ( aout_instance_t * );static void     Probe                   ( aout_instance_t * );static int      AudioDeviceHasOutput    ( AudioDeviceID );static int      AudioDeviceSupportsDigital( aout_instance_t *, AudioDeviceID );static int      AudioStreamSupportsDigital( aout_instance_t *, AudioStreamID );static int      AudioStreamChangeFormat ( aout_instance_t *, AudioStreamID, AudioStreamBasicDescription );static OSStatus RenderCallbackAnalog    ( vlc_object_t *, AudioUnitRenderActionFlags *, const AudioTimeStamp *,                                          unsigned int, unsigned int, AudioBufferList *);static OSStatus RenderCallbackSPDIF     ( AudioDeviceID, const AudioTimeStamp *, const void *, const AudioTimeStamp *,                                          AudioBufferList *, const AudioTimeStamp *, void * );static OSStatus HardwareListener        ( AudioHardwarePropertyID, void *);static OSStatus StreamListener          ( AudioStreamID, UInt32,                                          AudioDevicePropertyID, void * );static int      AudioDeviceCallback     ( vlc_object_t *, const char *,                                          vlc_value_t, vlc_value_t, void * );/***************************************************************************** * Module descriptor *****************************************************************************/#define ADEV_TEXT N_("Audio Device")#define ADEV_LONGTEXT N_("Choose a number corresponding to the number of an " \    "audio device, as listed in your 'Audio Device' menu. This device will " \    "then be used by default for audio playback.")vlc_module_begin();    set_shortname( "auhal" );    set_description( _("HAL AudioUnit output") );    set_capability( "audio output", 101 );    set_category( CAT_AUDIO );    set_subcategory( SUBCAT_AUDIO_AOUT );    set_callbacks( Open, Close );    add_integer( "macosx-audio-device", 0, NULL, ADEV_TEXT, ADEV_LONGTEXT, VLC_FALSE ); vlc_module_end();/***************************************************************************** * Open: open macosx audio output *****************************************************************************/static int Open( vlc_object_t * p_this ){    OSStatus                err = noErr;    UInt32                  i_param_size = 0;    struct aout_sys_t       *p_sys = NULL;    vlc_bool_t              b_alive = VLC_FALSE;    vlc_value_t             val;    aout_instance_t         *p_aout = (aout_instance_t *)p_this;    /* Allocate structure */    p_aout->output.p_sys = malloc( sizeof( aout_sys_t ) );    if( p_aout->output.p_sys == NULL )    {        msg_Err( p_aout, "out of memory" );        return( VLC_ENOMEM );    }    p_sys = p_aout->output.p_sys;    p_sys->i_default_dev = 0;    p_sys->i_selected_dev = 0;    p_sys->i_devices = 0;    p_sys->b_supports_digital = VLC_FALSE;    p_sys->b_digital = VLC_FALSE;    p_sys->au_component = NULL;    p_sys->au_unit = NULL;    p_sys->clock_diff = (mtime_t) 0;    p_sys->i_read_bytes = 0;    p_sys->i_total_bytes = 0;    p_sys->i_hog_pid = -1;    p_sys->i_stream_id = 0;    p_sys->i_stream_index = -1;    p_sys->b_revert = VLC_FALSE;    p_sys->b_changed_mixing = VLC_FALSE;    memset( p_sys->p_remainder_buffer, 0, sizeof(uint8_t) * BUFSIZE );    p_aout->output.pf_play = Play;        aout_FormatPrint( p_aout, "VLC is looking for:", (audio_sample_format_t *)&p_aout->output.output );        /* Persistent device variable */    if( var_Type( p_aout->p_vlc, "macosx-audio-device" ) == 0 )    {        var_Create( p_aout->p_vlc, "macosx-audio-device", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );    }    /* Build a list of devices */    if( var_Type( p_aout, "audio-device" ) == 0 )    {        Probe( p_aout );    }    /* What device do we want? */    if( var_Get( p_aout, "audio-device", &val ) < 0 )    {        msg_Err( p_aout, "audio-device var does not exist. device probe failed." );        goto error;    }    p_sys->i_selected_dev = val.i_int & ~AOUT_VAR_SPDIF_FLAG; /* remove SPDIF flag to get the true DeviceID */    p_sys->b_supports_digital = ( val.i_int & AOUT_VAR_SPDIF_FLAG ) ? VLC_TRUE : VLC_FALSE;    /* Check if the desired device is alive and usable */    /* TODO: add a callback to the device to alert us if the device dies */    i_param_size = sizeof( b_alive );    err = AudioDeviceGetProperty( p_sys->i_selected_dev, 0, FALSE,                                  kAudioDevicePropertyDeviceIsAlive,                                  &i_param_size, &b_alive );    if( err != noErr )    {        msg_Err( p_aout, "could not check whether device is alive: %4.4s", (char *)&err );        goto error;    }    if( b_alive == VLC_FALSE )    {        msg_Warn( p_aout, "selected audio device is not alive, switching to default device" );         p_sys->i_selected_dev = p_sys->i_default_dev;    }    i_param_size = sizeof( p_sys->i_hog_pid );    err = AudioDeviceGetProperty( p_sys->i_selected_dev, 0, FALSE,                                  kAudioDevicePropertyHogMode,                                  &i_param_size, &p_sys->i_hog_pid );    if( err != noErr )    {        /* This is not a fatal error. Some drivers simply don't support this property */        msg_Warn( p_aout, "could not check whether device is hogged: %4.4s",                 (char *)&err );        p_sys->i_hog_pid = -1;    }    if( p_sys->i_hog_pid != -1 && p_sys->i_hog_pid != getpid() )    {        msg_Err( p_aout, "Selected audio device is exclusively in use by another program." );        goto error;    }    /* Check for Digital mode or Analog output mode */    if( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) && p_sys->b_supports_digital )    {        if( OpenSPDIF( p_aout ) )            return VLC_SUCCESS;    }    else    {        if( OpenAnalog( p_aout ) )            return VLC_SUCCESS;    }error:    /* If we reach this, this aout has failed */    var_Destroy( p_aout, "audio-device" );    if( p_sys ) free( p_sys );    return VLC_EGENERIC;}/***************************************************************************** * Open: open and setup a HAL AudioUnit to do analog (multichannel) audio output *****************************************************************************/static int OpenAnalog( aout_instance_t *p_aout ){    struct aout_sys_t           *p_sys = p_aout->output.p_sys;    OSStatus                    err = noErr;    UInt32                      i_param_size = 0, i = 0;    int                         i_original;     ComponentDescription        desc;    AudioStreamBasicDescription DeviceFormat;    AudioChannelLayout          *layout;    AudioChannelLayout          new_layout;    AURenderCallbackStruct      input;    /* Lets go find our Component */    desc.componentType = kAudioUnitType_Output;    desc.componentSubType = kAudioUnitSubType_HALOutput;    desc.componentManufacturer = kAudioUnitManufacturer_Apple;    desc.componentFlags = 0;    desc.componentFlagsMask = 0;    p_sys->au_component = FindNextComponent( NULL, &desc );    if( p_sys->au_component == NULL )    {        msg_Warn( p_aout, "we cannot find our HAL component" );        return VLC_FALSE;    }    err = OpenAComponent( p_sys->au_component, &p_sys->au_unit );    if( err != noErr )    {        msg_Warn( p_aout, "we cannot open our HAL component" );        return VLC_FALSE;    }        /* Set the device we will use for this output unit */    err = AudioUnitSetProperty( p_sys->au_unit,                         kAudioOutputUnitProperty_CurrentDevice,                         kAudioUnitScope_Global,                         0,                         &p_sys->i_selected_dev,                         sizeof( AudioDeviceID ));                             if( err != noErr )    {        msg_Warn( p_aout, "we cannot select the audio device" );        return VLC_FALSE;    }                             /* Get the current format */    i_param_size = sizeof(AudioStreamBasicDescription);    err = AudioUnitGetProperty( p_sys->au_unit,                                   kAudioUnitProperty_StreamFormat,                                   kAudioUnitScope_Input,                                   0,                                   &DeviceFormat,                                   &i_param_size );                                       if( err != noErr ) return VLC_FALSE;    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);        verify_noerr( AudioUnitGetProperty( p_sys->au_unit,                                       kAudioDevicePropertyPreferredChannelLayout,                                       kAudioUnitScope_Output,                                       0,                                       layout,                                       &i_param_size ));                                               /* 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 */            verify_noerr( AudioFormatGetProperty( kAudioFormatProperty_ChannelLayoutForBitmap,                                    sizeof( UInt32), &layout->mChannelBitmap,                                    &i_param_size,                                    layout ));        }        else if( layout->mChannelLayoutTag != kAudioChannelLayoutTag_UseChannelDescriptions )        {            /* layouttags defined channellayout */            verify_noerr( AudioFormatGetProperty( kAudioFormatProperty_ChannelLayoutForTag,                                    sizeof( AudioChannelLayoutTag ), &layout->mChannelLayoutTag,                                    &i_param_size,                                    layout ));        }         msg_Dbg( p_aout, "layout of AUHAL has %d channels" , (int)layout->mNumberChannelDescriptions );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -