📄 coreaudio.c
字号:
/***************************************************************************** * coreaudio.c: CoreAudio output plugin ***************************************************************************** * Copyright (C) 2002-2004 VideoLAN * $Id: coreaudio.c 10101 2005-03-02 16:47:31Z robux4 $ * * Authors: Colin Delacroix <colin@zoy.org> * Jon Lech Johansen <jon-vl@nanocrew.net> * Christophe Massiot <massiot@via.ecp.fr> * Heiko Panther <heiko.panther@web.de> * * 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>#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/***************************************************************************** * aout_class_t ****************************************************************************/enum AudioDeviceClass{ AudioDeviceClassA52 = 1 << 0, AudioDeviceClassPCM = 1 << 1};static struct aout_class_t{ UInt32 mFormatID; UInt32 mChannelsPerFrame; enum AudioDeviceClass class; const char * psz_class;}aout_classes[] ={ { /* old A/52 format type */ 'IAC3', 2, AudioDeviceClassA52, "Digital A/52" }, { /* new A/52 format type */ kAudioFormat60958AC3, 2, AudioDeviceClassA52, "Digital A/52" }, { kAudioFormatLinearPCM, 2, AudioDeviceClassPCM, "Stereo PCM" }, { kAudioFormatLinearPCM, 1, AudioDeviceClassPCM, "Mono PCM" }, { kAudioFormatLinearPCM, 4, AudioDeviceClassPCM, "4 Channel PCM" }, { kAudioFormatLinearPCM, 6, AudioDeviceClassPCM, "6 Channel PCM" }, { kAudioFormatLinearPCM, 8, AudioDeviceClassPCM, "8 Channel PCM" }}; #define N_AOUT_CLASSES (sizeof(aout_classes)/sizeof(aout_classes[0]))/***************************************************************************** * aout_option_t ****************************************************************************/struct aout_option_t{ char sz_option[64]; UInt32 i_dev, i_idx; UInt32 i_sdx, i_cdx; AudioStreamID i_sid;};/***************************************************************************** * aout_dev_t ****************************************************************************/struct aout_dev_t{ AudioDeviceID devid; char * psz_device_name; UInt32 i_streams; UInt32 * pi_streams; AudioStreamBasicDescription ** pp_streams;};/***************************************************************************** * 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{ vlc_mutex_t lock; vlc_bool_t b_hwinfo; UInt32 i_def_dev; UInt32 i_devices; struct aout_dev_t * p_devices; UInt32 i_sel_opt; UInt32 i_options; struct aout_option_t * p_options; AudioDeviceID devid; UInt32 i_stream_index; AudioStreamBasicDescription stream_format; UInt32 b_dev_alive; vlc_bool_t b_revert_sfmt; AudioStreamBasicDescription sfmt_revert; UInt32 i_bufframe_size; mtime_t clock_diff;};/***************************************************************************** * Local prototypes. *****************************************************************************/static int InitHardwareInfo ( aout_instance_t * p_aout );static int InitDeviceInfo ( UInt32 i_dev, aout_instance_t * p_aout ); static void FreeDeviceInfo ( UInt32 i_dev, aout_instance_t * p_aout ); static void FreeHardwareInfo ( aout_instance_t * p_aout );static int InitDevice ( aout_instance_t * p_aout );static void FreeDevice ( aout_instance_t * p_aout );static int GetStreamID ( AudioDeviceID devid, UInt32 i_idx, AudioStreamID * p_sid );static int InitStreamInfo ( UInt32 i_dev, aout_instance_t * p_aout, UInt32 i_idx );static void FreeStreamInfo ( UInt32 i_dev, aout_instance_t * p_aout, UInt32 i_idx );static void InitDeviceVar ( aout_instance_t * p_aout, int i_option, vlc_bool_t b_change );static int Open ( vlc_object_t * );static void Close ( vlc_object_t * );static void Play ( aout_instance_t * p_aout );static OSStatus IOCallback ( AudioDeviceID inDevice, const AudioTimeStamp * inNow, const void * inInputData, const AudioTimeStamp * inInputTime, AudioBufferList * outOutputData, const AudioTimeStamp * inOutputTime, void * threadGlobals );static OSStatus HardwareListener ( AudioHardwarePropertyID inPropertyID, void * inClientData );static OSStatus DeviceListener ( AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, void * inClientData );static OSStatus StreamListener ( AudioStreamID inStream, UInt32 inChannel, AudioDevicePropertyID inPropertyID, void * inClientData );/***************************************************************************** * 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( "CoreAudio" ); set_description( _("CoreAudio output") ); set_capability( "audio output", 100 ); 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 CoreAudio HAL device *****************************************************************************/static int Open( vlc_object_t * p_this ){ OSStatus err; UInt32 i_param_size; struct aout_sys_t * p_sys; aout_instance_t * p_aout = (aout_instance_t *)p_this; struct aout_option_t * p_option; UInt32 i_startingChannel; /* 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_aout->output.p_sys = p_sys; p_aout->output.pf_play = Play; vlc_mutex_init( p_aout, &p_sys->lock ); if( InitHardwareInfo( p_aout ) ) { msg_Err( p_aout, "InitHardwareInfo failed" ); vlc_mutex_destroy( &p_sys->lock ); free( (void *)p_sys ); return( VLC_EGENERIC ); } if( var_Type( p_aout, "audio-device" ) == 0 ) { InitDeviceVar( p_aout, config_GetInt( p_aout, "coreaudio-dev" ), VLC_FALSE ); } if( InitDevice( p_aout ) ) { msg_Err( p_aout, "InitDevice failed" ); FreeHardwareInfo( p_aout ); vlc_mutex_destroy( &p_sys->lock ); free( (void *)p_sys ); return( VLC_EGENERIC ); } /* get starting channel for the selected stream */ p_option = &p_sys->p_options[p_sys->i_sel_opt]; i_param_size = sizeof( UInt32 ); err = AudioStreamGetProperty( p_option->i_sid, 0, kAudioStreamPropertyStartingChannel, &i_param_size, &i_startingChannel ); if( err != noErr ) { msg_Err( p_aout, "failed to get channel number: [%4.4s]", (char *)&err ); FreeDevice( p_aout ); FreeHardwareInfo( p_aout ); vlc_mutex_destroy( &p_sys->lock ); free( (void *)p_sys ); return( VLC_EGENERIC ); } msg_Dbg( p_aout, "starting channel: [%ld]", i_startingChannel ); /* Get a description of the stream format */ i_param_size = sizeof( AudioStreamBasicDescription ); err = AudioDeviceGetProperty( p_sys->devid, i_startingChannel, FALSE, kAudioDevicePropertyStreamFormat, &i_param_size, &p_sys->stream_format ); if( err != noErr ) { msg_Err( p_aout, "failed to get stream format: [%4.4s]", (char *)&err ); FreeDevice( p_aout ); FreeHardwareInfo( p_aout ); vlc_mutex_destroy( &p_sys->lock ); free( (void *)p_sys ); return( VLC_EGENERIC ); } /* Set the output sample rate */ p_aout->output.output.i_rate = (unsigned int)p_sys->stream_format.mSampleRate; msg_Dbg( p_aout, STREAM_FORMAT_MSG( "using format", p_sys->stream_format ) ); /* Get the bufframe size */ i_param_size = sizeof( p_sys->i_bufframe_size ); err = AudioDeviceGetProperty( p_sys->devid, i_startingChannel, FALSE, kAudioDevicePropertyBufferFrameSize, &i_param_size, &p_sys->i_bufframe_size ); if( err != noErr ) { msg_Err( p_aout, "failed to get bufframe size: [%4.4s]", (char *)&err ); FreeDevice( p_aout ); FreeHardwareInfo( p_aout ); vlc_mutex_destroy( &p_sys->lock ); free( (void *)p_sys ); return( VLC_EGENERIC ); } msg_Dbg( p_aout, "device bufframe size: [%ld]", p_sys->i_bufframe_size ); msg_Dbg( p_aout, "device buffer index: [%ld]", p_sys->i_stream_index ); /* If we do AC3 over SPDIF, set buffer size to one AC3 frame */ if( ( p_sys->stream_format.mFormatID == kAudioFormat60958AC3 || p_sys->stream_format.mFormatID == 'IAC3' ) && p_sys->i_bufframe_size != A52_FRAME_NB ) { p_sys->i_bufframe_size = A52_FRAME_NB; i_param_size = sizeof( p_sys->i_bufframe_size ); err = AudioDeviceSetProperty( p_sys->devid, 0, 0, FALSE, kAudioDevicePropertyBufferFrameSize, i_param_size, &p_sys->i_bufframe_size ); if( err != noErr ) { msg_Err( p_aout, "failed to set bufframe size (%ld): [%4.4s]", p_sys->i_bufframe_size, (char *)&err ); FreeDevice( p_aout ); FreeHardwareInfo( p_aout ); vlc_mutex_destroy( &p_sys->lock ); free( (void *)p_sys ); return( VLC_EGENERIC ); } msg_Dbg( p_aout, "device bufframe size set to: [%ld]", p_sys->i_bufframe_size ); } switch( p_sys->stream_format.mFormatID ) { case kAudioFormatLinearPCM: p_aout->output.output.i_format = VLC_FOURCC('f','l','3','2'); switch( p_sys->stream_format.mChannelsPerFrame ) { case 1: p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -