Commit 13484ed0 authored by Christophe Massiot's avatar Christophe Massiot

* Support for Darwin CoreAudio, courtesy of Colin Delacroix [MacOS X port] ;

* Added warnings for ac3 mantissa (we still have problems with AC3 on
MacOS X) ;
* Renamed WriteResource to avoid a namespace clash with Darwin's
WriteResource.
parent b004a661
......@@ -663,7 +663,7 @@ lib/macosx.so: $(PLUGIN_MACOSX)
$(CC) $(PCFLAGS) $(PLCFLAGS) -o $@ $^
lib/darwin.so: $(PLUGIN_DARWIN)
$(CC) $(PCFLAGS) $(PLCFLAGS) -o $@ $^
$(CC) $(PCFLAGS) $(PLCFLAGS) -o $@ $^ -framework CoreAudio
lib/dsp.so: $(PLUGIN_DSP)
$(CC) $(PCFLAGS) $(PLCFLAGS) -o $@ $^
......
......@@ -86,6 +86,6 @@ int CloseResourceFile ( resource_file_t *p_file );
int SeekResource ( resource_file_t *p_file, char *psz_name, int i_type );
int ReadResource ( resource_file_t *p_file, char *psz_name, int i_type,
size_t max_size, byte_t *p_data );
int WriteResource ( resource_file_t *p_file, char *psz_name, int i_type,
int vlc_WriteResource ( resource_file_t *p_file, char *psz_name, int i_type,
size_t size, byte_t *p_data );
......@@ -36,10 +36,18 @@
#include "audio_output.h" /* aout_thread_t */
#include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
#include "main.h"
#include "modules.h"
#include <Carbon/Carbon.h>
#include <CoreAudio/AudioHardware.h>
#include <sys/fcntl.h>
#define WRITE_AUDIO_OUTPUT_TO_FILE 0
/*****************************************************************************
* aout_sys_t: private audio output method descriptor
*****************************************************************************
......@@ -48,7 +56,17 @@
*****************************************************************************/
typedef struct aout_sys_s
{
#if WRITE_AUDIO_OUTPUT_TO_FILE
int fd; // debug
#endif
// unsigned long sizeOfDataInMemory; // size in bytes of the 32 bit float data stored in memory
Ptr p_Data; // Ptr to the 32 bit float data stored in memory
// Ptr currentDataLocationPtr; // location of the next chunk of data to send to the HAL
AudioDeviceID device; // the default device
UInt32 ui_deviceBufferSize; // bufferSize returned by kAudioDevicePropertyBufferSize
AudioStreamBasicDescription deviceFormat; // info about the default device
vlc_mutex_t mutex_lock;
vlc_cond_t cond_sync;
} aout_sys_t;
/*****************************************************************************
......@@ -62,6 +80,14 @@ static void aout_Play ( aout_thread_t *p_aout,
byte_t *buffer, int i_size );
static void aout_Close ( aout_thread_t *p_aout );
OSStatus appIOProc( AudioDeviceID inDevice, const AudioTimeStamp* inNow,
const void* inInputData, const AudioTimeStamp* inInputTime,
AudioBufferList* outOutputData, const AudioTimeStamp* inOutputTime,
void* appGlobals );
void Convert16BitIntegerTo32Float( Ptr in16BitDataPtr, Ptr out32BitDataPtr, UInt32 totalBytes );
void Convert16BitIntegerTo32FloatWithByteSwap( Ptr in16BitDataPtr, Ptr out32BitDataPtr, UInt32 totalBytes );
void Convert8BitIntegerTo32Float( Ptr in8BitDataPtr, Ptr out32BitDataPtr, UInt32 totalBytes );
/*****************************************************************************
* Functions exported as capabilities. They are declared as static so that
* we don't pollute the namespace too much.
......@@ -91,16 +117,83 @@ static int aout_Probe( probedata_t *p_data )
}
/*****************************************************************************
* aout_Open: opens a dummy audio device
* aout_Open: opens a HAL audio device
*****************************************************************************/
static int aout_Open( aout_thread_t *p_aout )
{
OSStatus err = noErr;
UInt32 count, bufferSize;
AudioDeviceID device = kAudioDeviceUnknown;
AudioStreamBasicDescription format;
/* Allocate structure */
p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
if( p_aout->p_sys == NULL )
{
intf_ErrMsg("aout error: %s", strerror(ENOMEM) );
return( 1 );
}
/* Initialize some variables */
p_aout->i_format = AOUT_FORMAT_DEFAULT;
p_aout->i_channels = 1 + main_GetIntVariable( AOUT_STEREO_VAR,
AOUT_STEREO_DEFAULT );
p_aout->l_rate = main_GetIntVariable( AOUT_RATE_VAR,
AOUT_RATE_DEFAULT );
p_aout->p_sys->device = kAudioDeviceUnknown;
p_aout->p_sys->p_Data = nil;
// p_aout->p_sys->currentDataLocationPtr = nil;
// get the default output device for the HAL
// it is required to pass the size of the data to be returned
count = sizeof( p_aout->p_sys->device );
err = AudioHardwareGetProperty( kAudioHardwarePropertyDefaultOutputDevice,
&count, (void *) &device);
if( err == noErr)
{
// get the buffersize that the default device uses for IO
// it is required to pass the size of the data to be returned
count = sizeof(p_aout->p_sys->ui_deviceBufferSize);
err = AudioDeviceGetProperty( device, 0, false,
kAudioDevicePropertyBufferSize,
&count, &bufferSize);
if( err == noErr )
{
// get a description of the data format used by the default device
// it is required to pass the size of the data to be returned
count = sizeof(p_aout->p_sys->deviceFormat);
err = AudioDeviceGetProperty( device, 0, false,
kAudioDevicePropertyStreamFormat,
&count, &format);
if( err == noErr )
{
if( format.mFormatID != kAudioFormatLinearPCM ) return paramErr;
// everything is ok so fill in p_sys
p_aout->p_sys->device = device;
p_aout->p_sys->ui_deviceBufferSize = bufferSize;
p_aout->p_sys->deviceFormat = format;
}
}
}
if (err != noErr) return err;
p_aout->p_sys->ui_deviceBufferSize = 2 * 2 * sizeof(s16)
* ((s64)p_aout->l_rate * AOUT_BUFFER_DURATION) / 1000000;
// p_aout->p_sys->sizeOfDataInMemory = p_aout->p_sys->ui_deviceBufferSize;
p_aout->p_sys->p_Data = NewPtrClear( p_aout->p_sys->ui_deviceBufferSize );
if( p_aout->p_sys->p_Data == nil ) return paramErr;
#if WRITE_AUDIO_OUTPUT_TO_FILE
p_aout->p_sys->fd = open( "/Users/bofh/audio-darwin.pcm", O_RDWR|O_CREAT );
intf_ErrMsg( "open(...) -> %d", p_aout->p_sys->fd );
#endif
vlc_cond_init( &p_aout->p_sys->cond_sync );
vlc_mutex_init( &p_aout->p_sys->mutex_lock );
return( 0 );
}
......@@ -110,7 +203,89 @@ static int aout_Open( aout_thread_t *p_aout )
*****************************************************************************/
static int aout_SetFormat( aout_thread_t *p_aout )
{
return( 0 );
OSStatus err = noErr;
UInt32 count,
bufferSize = p_aout->p_sys->ui_deviceBufferSize;
AudioStreamBasicDescription format;
// get the buffersize that the default device uses for IO
// it is required to pass the size of the data to be returned
count = sizeof( bufferSize );
err = AudioDeviceSetProperty( p_aout->p_sys->device, 0, 0, false,
kAudioDevicePropertyBufferSize,
count, &bufferSize);
intf_ErrMsg( "AudioDeviceSetProperty( buffersize = %d ) -> %d", bufferSize, err );
if( err == noErr )
{
p_aout->p_sys->ui_deviceBufferSize = bufferSize;
// get a description of the data format used by the default device
// it is required to pass the size of the data to be returned
count = sizeof( format );
/*
err = AudioDeviceGetProperty( p_aout->p_sys->device, 0, false,
kAudioDevicePropertyStreamFormat,
&count, &format);
*/
if( err == noErr )
{
// intf_ErrMsg( "audio output format is %i", p_aout->i_format );
if( format.mFormatID != kAudioFormatLinearPCM ) return paramErr;
switch( p_aout->i_format )
{
case AOUT_FMT_U8:
break;
case AOUT_FMT_S16_LE: /* Little endian signed 16 */
// intf_ErrMsg( "This means Little endian signed 16" );
break;
case AOUT_FMT_S16_BE: /* Big endian signed 16 */
// intf_ErrMsg( "This means Big endian signed 16" );
// format.mFormatFlags &= ~kLinearPCMFormatFlagIsFloat;
// format.mFormatFlags |= kLinearPCMFormatFlagIsFloat;
// format.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
// format.mFormatFlags &= ~kLinearPCMFormatFlagIsBigEndian;
// format.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
break;
case AOUT_FMT_S8:
break;
case AOUT_FMT_U16_LE: /* Little endian U16 */
// intf_ErrMsg( "This means Little endian U16" );
break;
case AOUT_FMT_U16_BE: /* Big endian U16 */
// intf_ErrMsg( "This means Big endian U16" );
break;
default:
; // intf_ErrMsg( "This means Unknown aout format" );
}
format.mSampleRate = p_aout->l_rate;
format.mChannelsPerFrame = p_aout->i_channels;
err = AudioDeviceSetProperty( p_aout->p_sys->device, 0, 0, false,
kAudioDevicePropertyStreamFormat,
count, &format);
/*
intf_ErrMsg( "AudioDeviceSetProperty( mFormatFlags = %x, "
"mSampleRate = %f, "
"mChannelsPerFrame = %d ) "
"-> %d",
format.mFormatFlags,
format.mSampleRate,
format.mChannelsPerFrame,
err );
*/
}
}
err = AudioDeviceAddIOProc( p_aout->p_sys->device,
(AudioDeviceIOProc)appIOProc,
(void *)p_aout->p_sys );
if( err == noErr )
err = AudioDeviceStart( p_aout->p_sys->device, (AudioDeviceIOProc)appIOProc );
return( err );
}
/*****************************************************************************
......@@ -118,15 +293,53 @@ static int aout_SetFormat( aout_thread_t *p_aout )
*****************************************************************************/
static long aout_GetBufInfo( aout_thread_t *p_aout, long l_buffer_limit )
{
return( sizeof(s16) * l_buffer_limit + 1 ); /* value big enough to sleep */
return( 0 ); // Send data as soon as possible
/*
* Tune me ?
*
return ( p_aout->p_sys->p_Data
+ p_aout->p_sys->sizeOfDataInMemory
- p_aout->p_sys->currentDataLocationPtr
- p_aout->p_sys->ui_deviceBufferSize );
*/
}
/*****************************************************************************
* appIOProc : callback for audio output
*****************************************************************************/
OSStatus appIOProc( AudioDeviceID inDevice, const AudioTimeStamp* inNow,
const void* inInputData, const AudioTimeStamp* inInputTime,
AudioBufferList* outOutputData, const AudioTimeStamp* inOutputTime,
void* appGlobals )
{
aout_sys_t* p_sys = appGlobals;
vlc_mutex_lock( &p_sys->mutex_lock );
vlc_cond_signal( &p_sys->cond_sync );
// move data into output data buffer
BlockMoveData( p_sys->p_Data,
outOutputData->mBuffers[ 0 ].mData,
p_sys->ui_deviceBufferSize );
vlc_mutex_unlock( &p_sys->mutex_lock );
return( noErr );
}
/*****************************************************************************
* aout_Play: pretends to play a sound
* aout_Play: plays a sound
*****************************************************************************/
static void aout_Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
{
;
#if WRITE_AUDIO_OUTPUT_TO_FILE
write( p_aout->p_sys->fd, buffer, i_size );
// intf_ErrMsg( "write() -> %d", write( p_aout->p_sys->fd, buffer, i_size ) );
#else
Convert16BitIntegerTo32Float( buffer, p_aout->p_sys->p_Data, i_size );
vlc_cond_wait( &p_aout->p_sys->cond_sync, &p_aout->p_sys->mutex_lock );
#endif
}
/*****************************************************************************
......@@ -134,6 +347,87 @@ static void aout_Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
*****************************************************************************/
static void aout_Close( aout_thread_t *p_aout )
{
;
OSStatus err = noErr;
// stop playing sound through the device
err = AudioDeviceStop( p_aout->p_sys->device, (AudioDeviceIOProc)appIOProc );
if (err != noErr) return;
// remove the IO proc from the device
err = AudioDeviceRemoveIOProc( p_aout->p_sys->device, (AudioDeviceIOProc)appIOProc );
if (err != noErr) return;
// vlc_cond_signal( &p_aout->p_sys->cond_sync );
DisposePtr( p_aout->p_sys->p_Data );
return;
}
/*****************************************************************************
* Convert16BitIntegerTo32Float
*****************************************************************************/
void Convert16BitIntegerTo32Float( Ptr in16BitDataPtr, Ptr out32BitDataPtr,
UInt32 totalBytes )
{
UInt32 i, samples = totalBytes / 2 /* each 16 bit sample is 2 bytes */;
SInt16 *inDataPtr = (SInt16 *) in16BitDataPtr;
Float32 *outDataPtr = (Float32 *) out32BitDataPtr;
for( i = 0 ; i < samples ; i++ )
{
*outDataPtr = (Float32)(*inDataPtr);
if( *outDataPtr > 0 )
*outDataPtr /= 32767.0;
else
*outDataPtr /= 32768.0;
outDataPtr++;
inDataPtr++;
}
}
/*****************************************************************************
* Convert16BitIntegerTo32FloatWithByteSwap
*****************************************************************************/
void Convert16BitIntegerTo32FloatWithByteSwap( Ptr in16BitDataPtr,
Ptr out32BitDataPtr,
UInt32 totalBytes )
{
UInt32 i, samples = totalBytes / 2 /* each 16 bit sample is 2 bytes */;
SInt16 *inDataPtr = (SInt16 *) in16BitDataPtr;
Float32 *outDataPtr = (Float32 *) out32BitDataPtr;
for( i = 0 ; i < samples ; i++ )
{
*outDataPtr = (Float32)CFSwapInt16LittleToHost(*inDataPtr);
if( *outDataPtr > 0 )
*outDataPtr /= 32767.0;
else
*outDataPtr /= 32768.0;
outDataPtr++;
inDataPtr++;
}
}
/*****************************************************************************
* Convert8BitIntegerTo32Float
*****************************************************************************/
void Convert8BitIntegerTo32Float( Ptr in8BitDataPtr, Ptr out32BitDataPtr,
UInt32 totalBytes )
{
UInt32 i, samples = totalBytes;
SInt8 *inDataPtr = (SInt8 *) in8BitDataPtr;
Float32 *outDataPtr = (Float32 *) out32BitDataPtr;
for( i = 0 ; i < samples ; i++ )
{
*outDataPtr = (Float32)(*inDataPtr);
if( *outDataPtr > 0 )
*outDataPtr /= 32767.0;
else
*outDataPtr /= 32768.0;
outDataPtr++;
inDataPtr++;
}
}
......@@ -61,7 +61,7 @@ void _M( aout_getfunctions )( function_list_t * p_function_list );
MODULE_INIT
{
p_module->psz_name = MODULE_STRING;
p_module->psz_longname = "Darwin sound support module";
p_module->psz_longname = "Darwin HAL sound support module";
p_module->psz_version = VERSION;
p_module->i_capabilities = MODULE_CAPABILITY_NULL
......
......@@ -286,7 +286,7 @@ static __inline__ float float_get (ac3dec_t * p_ac3dec, u16 bap, u16 exp)
if ((group_code = bitstream_get(&(p_ac3dec->bit_stream),5)) >= 27)
{
intf_WarnMsg ( 1, "ac3dec error: invalid mantissa" );
intf_WarnMsg ( 1, "ac3dec error: invalid mantissa (1)" );
}
p_ac3dec->mantissa.q_1[ 1 ] = q_1_1[ group_code ];
......@@ -304,7 +304,7 @@ static __inline__ float float_get (ac3dec_t * p_ac3dec, u16 bap, u16 exp)
if ((group_code = bitstream_get(&(p_ac3dec->bit_stream),7)) >= 125)
{
intf_WarnMsg ( 1, "ac3dec error: invalid mantissa" );
intf_WarnMsg ( 1, "ac3dec error: invalid mantissa (2)" );
}
p_ac3dec->mantissa.q_2[ 1 ] = q_2_1[ group_code ];
......@@ -317,7 +317,7 @@ static __inline__ float float_get (ac3dec_t * p_ac3dec, u16 bap, u16 exp)
case 3:
if ((group_code = bitstream_get(&(p_ac3dec->bit_stream),3)) >= 7)
{
intf_WarnMsg ( 1, "ac3dec error: invalid mantissa" );
intf_WarnMsg ( 1, "ac3dec error: invalid mantissa (3)" );
}
return (q_3[group_code] * exp_lut[exp]);
......@@ -330,7 +330,7 @@ static __inline__ float float_get (ac3dec_t * p_ac3dec, u16 bap, u16 exp)
if ((group_code = bitstream_get(&(p_ac3dec->bit_stream),7)) >= 121)
{
intf_WarnMsg ( 1, "ac3dec error: invalid mantissa" );
intf_WarnMsg ( 1, "ac3dec error: invalid mantissa (4)" );
}
p_ac3dec->mantissa.q_4[ 0 ] = q_4_1[ group_code ];
......@@ -342,7 +342,7 @@ static __inline__ float float_get (ac3dec_t * p_ac3dec, u16 bap, u16 exp)
case 5:
if ((group_code = bitstream_get(&(p_ac3dec->bit_stream),4)) >= 15)
{
intf_WarnMsg ( 1, "ac3dec error: invalid mantissa" );
intf_WarnMsg ( 1, "ac3dec error: invalid mantissa (5)" );
}
return (q_5[group_code] * exp_lut[exp]);
......
......@@ -366,7 +366,8 @@ int ReadResource( resource_file_t *p_file, char *psz_name, int i_type,
*****************************************************************************
* Messages type: rsc, major code 107
*****************************************************************************/
int WriteResource( resource_file_t *p_file, char *psz_name, int i_type,
/* Darwin port : namespace clash with Darwin's WriteResource */
int vlc_WriteResource( resource_file_t *p_file, char *psz_name, int i_type,
size_t size, byte_t *p_data )
{
int i_index; /* resource index */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment