]> git.sesse.net Git - vlc/commitdiff
* Support for Darwin CoreAudio, courtesy of Colin Delacroix [MacOS X port] ;
authorChristophe Massiot <massiot@videolan.org>
Tue, 20 Mar 2001 17:36:04 +0000 (17:36 +0000)
committerChristophe Massiot <massiot@videolan.org>
Tue, 20 Mar 2001 17:36:04 +0000 (17:36 +0000)
* 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.

Makefile.in
include/rsc_files.h
plugins/darwin/aout_darwin.c
plugins/darwin/darwin.c
src/ac3_decoder/ac3_mantissa.c
src/misc/rsc_files.c

index 000688f270543e3077cb10b7924382e9ddc16135..c2d02b0112578b06b3bb911c73eee0c55175665d 100644 (file)
@@ -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 $@ $^
index 87a916015848df06e692f9308cc50fbe87c3e786..e8a5a667a006ca8a31f2ef19010c45aabc1b1459 100644 (file)
@@ -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,
-                                          size_t size, byte_t *p_data );
+int                 vlc_WriteResource       ( resource_file_t *p_file, char *psz_name, int i_type,
+                                              size_t size, byte_t *p_data );
 
index 3f9e65e3dc809d41cbf39bc67809bd3662d7fcd0..e883fc5d14a6c2b075d724506f77b1b138c40f66 100644 (file)
 
 #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
  *****************************************************************************
  *****************************************************************************/
 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,17 +117,84 @@ 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_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 );
+*/
 }
 
 /*****************************************************************************
- * aout_Play: pretends to play a sound
+ * 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: 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++;
+    }
+}
index 36fcf8b823e9be7379e3339a33212dc234f114da..3cc81f61cbc309ae54d5e98dae6891547821ec43 100644 (file)
@@ -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
index f59adfa61d82da1bc80fe3eb5ea6251d21f1bc14..0db5604262edfd516cd48be0756e7b0b226a350b 100644 (file)
@@ -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]);
index 344e476db69981d74a2b000c0d87201cd1d619e4..3029cb902c91f88518e5b0e93bd72bea2f4f1629 100644 (file)
@@ -366,8 +366,9 @@ 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,
-                   size_t size, byte_t *p_data )
+/* 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 */
     int i_tmp_index;                             /* temporary resource index */