📄 auhal.c
字号:
/***************************************************************************** * auhal.c: AUHAL output plugin ***************************************************************************** * Copyright (C) 2005 VideoLAN * $Id$ * * 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <string.h>#include <stdlib.h>#include <vlc/vlc.h>#include <vlc/aout.h>#include "aout_internal.h"#include <CoreAudio/CoreAudio.h>#include <CoreAudio/CoreAudioTypes.h>#include <AudioUnit/AudioUnitProperties.h>#include <AudioUnit/AudioUnitParameters.h>#include <AudioUnit/AudioOutputUnit.h>#include <AudioToolbox/AudioFormat.h>#define STREAM_FORMAT_MSG( 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/***************************************************************************** * 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? */ Component au_component; /* The Audiocomponent we use */ AudioUnit au_unit; /* The AudioUnit we use */ mtime_t clock_diff; uint8_t p_remainder_buffer[BUFSIZE]; uint32_t i_read_bytes; uint32_t i_total_bytes; audio_date_t end_date_t; };/***************************************************************************** * Local prototypes. *****************************************************************************/static int Open ( vlc_object_t * );static void Close ( vlc_object_t * );static void Play ( aout_instance_t *);static int Probe ( aout_instance_t * );static int DeviceDigitalMode ( aout_instance_t *, AudioDeviceID );int AudioDeviceHasOutput ( AudioDeviceID );static int DigitalInit ( aout_instance_t * );static OSStatus RenderCallbackAnalog ( vlc_object_t *, AudioUnitRenderActionFlags *, const AudioTimeStamp *, unsigned int, unsigned int, AudioBufferList *);static OSStatus HardwareListener ( AudioHardwarePropertyID, 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( "coreaudio-dev", -1, NULL, ADEV_TEXT, ADEV_LONGTEXT, VLC_FALSE ); vlc_module_end();/***************************************************************************** * Open: open a HAL AudioUnit *****************************************************************************/static int Open( vlc_object_t * p_this ){ OSStatus err = noErr; ComponentDescription desc; UInt32 i_param_size,i; struct aout_sys_t *p_sys; vlc_value_t val; aout_instance_t *p_aout = (aout_instance_t *)p_this; /* Allocate structure */ p_sys = (struct aout_sys_t *)malloc( sizeof( struct aout_sys_t ) ); if( p_sys == NULL ) { msg_Err( p_aout, "out of memory" ); return( VLC_ENOMEM ); } memset( p_sys, 0, sizeof( struct aout_sys_t ) ); p_sys->b_digital = VLC_FALSE; /* We assume we are not digital */ p_aout->output.p_sys = p_sys; p_aout->output.pf_play = Play; aout_FormatPrint( p_aout, "VLC is looking for:\n", (audio_sample_format_t *)&p_aout->output.output ); /* Build a list of devices */ if( var_Type( p_aout, "audio-device" ) == 0 ) { Probe( p_aout ); /*if( Probe( p_aout ) != VLC_SUCCESS ); { msg_Err( p_aout, "Probe failed" ); free( p_sys ); return VLC_EGENERIC; }*/ } /* What device do we want? */ if( var_Get( p_aout, "audio-device", &val ) < 0 ) { msg_Err( p_aout, "audio-device var does not exist" ); free( p_sys ); return( VLC_ENOVAR ); } p_sys->i_selected_dev = val.i_int; /* what is vlc format? if digital, take digital route else AUHAL route */ DeviceDigitalMode( p_aout, p_sys->i_selected_dev ); /*if( DeviceDigitalMode( p_aout, p_sys->i_selected_dev ) != VLC_SUCCESS ); { msg_Err( p_aout, "DeviceDigitalMode failed" ); free( p_sys ); return VLC_EGENERIC; } */ if( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) && p_sys->b_supports_digital ) { p_sys->b_digital = VLC_TRUE; p_aout->output.output.i_format = VLC_FOURCC('s','p','d','i'); msg_Dbg( p_aout, "we found a digital stream, and we WANT a digital stream" ); } else if( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) && !p_sys->b_supports_digital ) { msg_Dbg( p_aout, "we had requested a digital stream, but it's not possible for this device" ); } /* If analog only start setting up AUHAL */ /* 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_Err( p_aout, "we cannot find our HAL component" ); free( p_sys ); return VLC_EGENERIC; } err = OpenAComponent( p_sys->au_component, &p_sys->au_unit ); if( err ) { msg_Err( p_aout, "we cannot find our HAL component" ); free( p_sys ); return VLC_EGENERIC; } /* Enable IO for the component */ /* Set the device */ verify_noerr( AudioUnitSetProperty( p_sys->au_unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &p_sys->i_selected_dev, sizeof(p_sys->i_selected_dev))); /* Get the current format */ AudioStreamBasicDescription DeviceFormat; i_param_size = sizeof(AudioStreamBasicDescription); verify_noerr( AudioUnitGetProperty( p_sys->au_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &DeviceFormat, &i_param_size )); msg_Dbg( p_aout, STREAM_FORMAT_MSG( "current format is " , DeviceFormat ) ); /* Get the channel layout */ AudioChannelLayout *layout; verify_noerr( AudioUnitGetPropertyInfo( p_sys->au_unit, kAudioDevicePropertyPreferredChannelLayout, kAudioUnitScope_Output, 0, &i_param_size, NULL )); layout = (AudioChannelLayout *)malloc( i_param_size); verify_noerr( AudioUnitGetProperty( p_sys->au_unit, kAudioDevicePropertyPreferredChannelLayout, kAudioUnitScope_Output, 0, layout, &i_param_size )); /* Lets fill out the ChannelLayout */ if( layout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap) { msg_Dbg( p_aout, "bitmap defined channellayout" ); verify_noerr( AudioFormatGetProperty( kAudioFormatProperty_ChannelLayoutForBitmap, sizeof( UInt32), &layout->mChannelBitmap, &i_param_size, layout )); } else if( layout->mChannelLayoutTag != kAudioChannelLayoutTag_UseChannelDescriptions ) { msg_Dbg( p_aout, "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 ); p_aout->output.output.i_physical_channels = 0; for( i = 0; i < layout->mNumberChannelDescriptions; i++ ) { msg_Dbg( p_aout, "This is channel: %d", (int)layout->mChannelDescriptions[i].mChannelLabel ); switch( layout->mChannelDescriptions[i].mChannelLabel ) { case kAudioChannelLabel_Left:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -