]> git.sesse.net Git - vlc/commitdiff
Fix the a52 spdif filter, add big endian support to the DTS filter and add big endian...
authorDerk-Jan Hartman <hartman@videolan.org>
Thu, 1 Dec 2005 16:14:18 +0000 (16:14 +0000)
committerDerk-Jan Hartman <hartman@videolan.org>
Thu, 1 Dec 2005 16:14:18 +0000 (16:14 +0000)
modules/audio_filter/converter/a52tospdif.c
modules/audio_filter/converter/dtstospdif.c
modules/audio_output/coreaudio.c

index 6fa5084a5a14fa50fb36f61229dc96bb03c8fd9e..cbed86a51d64ef95d8d27d8add0b4af377fc593f 100644 (file)
@@ -110,9 +110,9 @@ static int Create( vlc_object_t *p_this )
 {
     aout_filter_t * p_filter = (aout_filter_t *)p_this;
 
-    if ( p_filter->input.i_format != VLC_FOURCC('a','5','2',' ')
-          || p_filter->output.i_format != VLC_FOURCC('s','p','d','b')
-          || p_filter->output.i_format != VLC_FOURCC('s','p','d','i') )
+    if ( p_filter->input.i_format != VLC_FOURCC('a','5','2',' ') ||
+         ( p_filter->output.i_format != VLC_FOURCC('s','p','d','b') &&
+           p_filter->output.i_format != VLC_FOURCC('s','p','d','i') ) )
     {
         return -1;
     }
@@ -132,7 +132,7 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
     /* AC3 is natively big endian. Most SPDIF devices have the native endianness of
      * the computersystem. On MAc OS X however, little endian devices are also common.
      */
-    uint32_t syncword, crc1, fscod, frmsizecod, bsid, bsmod, frame_size;
+    uint32_t i_syncword, i_crc1, i_fscod, i_frmsizecod, i_bsid, i_bsmod, i_frame_size;
     static const uint8_t p_sync_le[6] = { 0x72, 0xF8, 0x1F, 0x4E, 0x01, 0x00 };
     static const uint8_t p_sync_be[6] = { 0xF8, 0x72, 0x4E, 0x1F, 0x00, 0x01 };
 #ifndef HAVE_SWAB
@@ -143,34 +143,34 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
     byte_t * p_out = p_out_buf->p_buffer;
 
     /* AC3 header decode */
-    syncword = p_in[0] | (p_in[1] << 8);
-    crc1 = p_in[2] | (p_in[3] << 8);
-    fscod = (p_in[4] >> 6) & 0x3;
-    frmsizecod = p_in[4] & 0x3f;
-    bsid = (p_in[5] >> 3) & 0x1f;
-    bsmod = p_in[5] & 0x7;
-    frame_size = frmsizecod_tbl[frmsizecod].frm_size[fscod];
+    i_syncword = p_in[0] | (p_in[1] << 8);
+    i_crc1 = p_in[2] | (p_in[3] << 8);
+    i_fscod = (p_in[4] >> 6) & 0x3;
+    i_frmsizecod = p_in[4] & 0x3f;
+    i_bsid = (p_in[5] >> 3) & 0x1f;
+    i_bsmod = p_in[5] & 0x7;
+    i_frame_size = frmsizecod_tbl[i_frmsizecod].frm_size[i_fscod];
     
     /* Copy the S/PDIF headers. */
     if( p_filter->output.i_format == VLC_FOURCC('s','p','d','b') )
     {
         p_filter->p_vlc->pf_memcpy( p_out, p_sync_be, 6 );
-        p_out[4] = bsmod;
-        p_out[6] = ((frame_size ) >> 4) & 0xff;
-        p_out[7] = (frame_size << 4) & 0xff;
-        p_filter->p_vlc->pf_memcpy( &p_out[8], p_in, frame_size * 2 );
+        p_out[4] = i_bsmod;
+        p_out[6] = ((i_frame_size ) >> 4) & 0xff;
+        p_out[7] = (i_frame_size << 4) & 0xff;
+        p_filter->p_vlc->pf_memcpy( &p_out[8], p_in, i_frame_size * 2 );
     }
     else
     {
-        memcpy( p_out, p_sync_le, 6 );
-        p_out[5] = bsmod;
-        p_out[6] = (frame_size << 4) & 0xff;
-        p_out[7] = ((frame_size ) >> 4) & 0xff;
+        p_filter->p_vlc->pf_memcpy( p_out, p_sync_le, 6 );
+        p_out[5] = i_bsmod;
+        p_out[6] = (i_frame_size << 4) & 0xff;
+        p_out[7] = ((i_frame_size ) >> 4) & 0xff;
 #ifdef HAVE_SWAB
-        swab( p_in, &p_out[8], frame_size * 2 );
+        swab( p_in, &p_out[8], i_frame_size * 2 );
 #else
         p_tmp = &p_out[8];
-        for( i = frame_size; i-- ; )
+        for( i = i_frame_size; i-- ; )
         {
             p_tmp[0] = p_in[1];
             p_tmp[1] = p_in[0];
index 615bd3e9f95ab4fce5d594fe06ce200accab38f4..0305ba770241ac6a2eaf65f9e57e6e2cc9c94aad 100644 (file)
@@ -79,8 +79,9 @@ static int Create( vlc_object_t *p_this )
 {
     aout_filter_t * p_filter = (aout_filter_t *)p_this;
 
-    if ( p_filter->input.i_format != VLC_FOURCC('d','t','s',' ')
-          || p_filter->output.i_format != VLC_FOURCC('s','p','d','i') )
+    if( p_filter->input.i_format != VLC_FOURCC('d','t','s',' ') ||
+        ( p_filter->output.i_format != VLC_FOURCC('s','p','d','i') &&
+          p_filter->output.i_format != VLC_FOURCC('s','p','d','b') ) )
     {
         return -1;
     }
@@ -117,9 +118,11 @@ static void Close( vlc_object_t * p_this )
 static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
                     aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
 {
+    uint32_t i_ac5_spdif_type = 0;
     uint16_t i_fz = p_in_buf->i_nb_samples * 4;
     uint16_t i_frame, i_length = p_in_buf->i_nb_bytes;
-    static const uint8_t p_sync[6] = { 0x72, 0xF8, 0x1F, 0x4E, 0x00, 0x00 };
+    static const uint8_t p_sync_le[6] = { 0x72, 0xF8, 0x1F, 0x4E, 0x00, 0x00 };
+    static const uint8_t p_sync_be[6] = { 0xF8, 0x72, 0x4E, 0x1F, 0x00, 0x00 };
 
     if( p_in_buf->i_nb_bytes != p_filter->p_sys->i_frame_size )
     {
@@ -156,22 +159,32 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
         byte_t * p_out = p_out_buf->p_buffer + (i_frame * i_fz);
         byte_t * p_in = p_filter->p_sys->p_buf + (i_frame * i_length);
 
-        /* Copy the S/PDIF headers. */
-        memcpy( p_out, p_sync, 6 );
-
         switch( p_in_buf->i_nb_samples )
         {
-            case  512: *(p_out + 4) = 0x0B; break;
-            case 1024: *(p_out + 4) = 0x0C; break;
-            case 2048: *(p_out + 4) = 0x0D; break;
+            case  512: i_ac5_spdif_type = 0x0B; break;
+            case 1024: i_ac5_spdif_type = 0x0C; break;
+            case 2048: i_ac5_spdif_type = 0x0D; break;
         }
 
-        *(p_out + 6) = (i_length * 8) & 0xff;
-        *(p_out + 7) = (i_length * 8) >> 8;
+        /* Copy the S/PDIF headers. */
+        if( p_filter->output.i_format == VLC_FOURCC('s','p','d','b') )
+        {
+            p_filter->p_vlc->pf_memcpy( p_out, p_sync_be, 6 );
+            p_out[5] = i_ac5_spdif_type;
+            p_out[6] = (( i_length ) >> 5 ) & 0xFF;
+            p_out[7] = ( i_length << 3 ) & 0xFF;
+        }
+        else
+        {
+            p_filter->p_vlc->pf_memcpy( p_out, p_sync_le, 6 );
+            p_out[4] = i_ac5_spdif_type;
+            p_out[6] = ( i_length << 3 ) & 0xFF;
+            p_out[7] = (( i_length ) >> 5 ) & 0xFF;
+        }
 
-        if( p_in[0] == 0x1f || p_in[0] == 0x7f )
+        if( (p_in[0] == 0x1f || p_in[0] == 0x7f) && p_filter->output.i_format == VLC_FOURCC('s','p','d','i') )
         {
-            /* We are dealing with a big endian bitstream.
+            /* We are dealing with a big endian bitstream and a little endian output
              * Convert to little endian */
 #ifdef HAVE_SWAB
             swab( p_in, p_out + 8, i_length );
@@ -188,10 +201,16 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
             }
 #endif
         }
+        else if( (p_in[0] == 0x1f || p_in[0] == 0x7f) ||
+                  p_filter->output.i_format == VLC_FOURCC('s','p','d','i') )
+        {
+           /* Big endian stream on Big endian output || little endian stream on little endian output */
+            p_filter->p_vlc->pf_memcpy( p_out + 8, p_in, i_length );
+        }
         else
         {
-            /* Little endian */
-            memcpy( p_out + 8, p_in, i_length );
+            msg_Err( p_filter, "Little endian DTS stream on big endian output not supported" );
+            p_filter->p_vlc->pf_memcpy( p_out + 8, p_in, i_length );
         }
 
         if( i_fz > i_length + 8 )
index 3d1071219394a0fea8d2f5f8766b6e3a865d2271..e445d4c20f53d44bd44f358dc9458f7b9a3e4521 100644 (file)
@@ -158,6 +158,7 @@ struct aout_sys_t
     UInt32                      i_stream_index;
     AudioStreamBasicDescription stream_format;
     UInt32                      b_dev_alive;
+    pid_t                       i_hog_pid;
 
     vlc_bool_t                  b_revert_sfmt;
     AudioStreamBasicDescription sfmt_revert;
@@ -253,6 +254,7 @@ static int Open( vlc_object_t * p_this )
 
     p_aout->output.p_sys = p_sys;
     p_aout->output.pf_play = Play;
+    p_sys->i_hog_pid = -1;
 
     vlc_mutex_init( p_aout, &p_sys->lock );
 
@@ -281,7 +283,6 @@ static int Open( vlc_object_t * p_this )
 
     /* 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,
@@ -337,34 +338,34 @@ static int Open( vlc_object_t * p_this )
         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 );
-    }
+       /* 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 )
     {
@@ -420,7 +421,10 @@ static int Open( vlc_object_t * p_this )
 
     case 'IAC3':
     case kAudioFormat60958AC3:
-        p_aout->output.output.i_format = VLC_FOURCC('s','p','d','i');
+        if( p_sys->stream_format.mFormatFlags & kAudioFormatFlagIsBigEndian )
+            p_aout->output.output.i_format = VLC_FOURCC('s','p','d','b');
+        else
+            p_aout->output.output.i_format = VLC_FOURCC('s','p','d','i');
         p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
         p_aout->output.output.i_frame_length = A52_FRAME_NB;
         p_aout->output.i_nb_samples = p_aout->output.output.i_frame_length;
@@ -584,35 +588,30 @@ static OSStatus IOCallback( AudioDeviceID inDevice,
                             void * threadGlobals )
 {
     aout_buffer_t * p_buffer;
-    AudioTimeStamp  host_time;
     mtime_t         current_date;
 
     aout_instance_t * p_aout = (aout_instance_t *)threadGlobals;
     struct aout_sys_t * p_sys = p_aout->output.p_sys;
 
-    host_time.mFlags = kAudioTimeStampHostTimeValid;
-    AudioDeviceTranslateTime( inDevice, inOutputTime, &host_time );
-
 #if 1
     p_sys->clock_diff = - (mtime_t)
-        AudioConvertHostTimeToNanos( AudioGetCurrentHostTime() ) / 1000; 
+        AudioConvertHostTimeToNanos( inNow->mHostTime ) / 1000; 
     p_sys->clock_diff += mdate();
 #endif
 
     current_date = p_sys->clock_diff +
-                   AudioConvertHostTimeToNanos( host_time.mHostTime ) / 1000;
+                   AudioConvertHostTimeToNanos( inOutputTime->mHostTime ) / 1000;
 
-#define B_SPDI (p_aout->output.output.i_format == VLC_FOURCC('s','p','d','i'))
+#define B_SPDI (p_aout->output.output.i_format == VLC_FOURCC('s','p','d','i') || p_aout->output.output.i_format == VLC_FOURCC('s','p','d','b') )
     p_buffer = aout_OutputNextBuffer( p_aout, current_date, B_SPDI );
 #undef B_SPDI
 
-#define BUFFER outOutputData->mBuffers[ p_sys->i_stream_index ]
+#define BUFFER outOutputData->mBuffers[p_sys->i_stream_index]
     if( p_buffer != NULL )
     {
         /* move data into output data buffer */
         p_aout->p_vlc->pf_memcpy( BUFFER.mData,
                                   p_buffer->p_buffer, p_buffer->i_nb_bytes );
-
         aout_BufferFree( p_buffer );
     }
     else
@@ -993,7 +992,6 @@ static int InitStreamInfo( UInt32 i_dev, aout_instance_t * p_aout,
         msg_Err( p_aout, "GetStreamID(%ld, %ld) failed", i_dev, i_idx );
         return( VLC_EGENERIC );
     }
-
     err = AudioStreamGetPropertyInfo( i_sid, 0,
                                       kAudioStreamPropertyPhysicalFormats,
                                       &i_param_size, NULL );
@@ -1214,6 +1212,81 @@ static int InitDevice( aout_instance_t * p_aout )
 
         vlc_mutex_lock( &w.lock );
 
+               /* If we do AC3 over SPDIF, take hog mode and non mixable mode */
+               if( P_STREAMS[i_stream].mFormatID == kAudioFormat60958AC3 ||
+                       P_STREAMS[i_stream].mFormatID == 'IAC3' )
+               {
+                       UInt32 b_mix;
+
+                       i_param_size = sizeof( p_sys->i_hog_pid );
+                       err = AudioDeviceGetProperty( p_dev->devid, 0, FALSE, kAudioDevicePropertyHogMode,
+                                                                                       &i_param_size, &p_sys->i_hog_pid );
+                       if( !err )
+                       {
+                               msg_Dbg( p_aout, "Current status of hog mode: pid=%d vlc pid=%d\n", (int)p_sys->i_hog_pid, (int)getpid() );
+                               if( p_sys->i_hog_pid != getpid() ) {
+                                       p_sys->i_hog_pid = getpid() ;
+                                       err = AudioDeviceSetProperty( p_dev->devid, 0, 0, FALSE,
+                                                                                                kAudioDevicePropertyHogMode, i_param_size, &p_sys->i_hog_pid );
+                                       if( !err )
+                                       {
+                                               msg_Dbg( p_aout, "Successfully set hog mode - new pid=%d!\n", (int)p_sys->i_hog_pid );
+
+                                               err = AudioDeviceGetProperty( p_dev->devid, 0, FALSE,
+                                                                                                       kAudioDevicePropertyHogMode, &i_param_size, &p_sys->i_hog_pid );
+                                               if( !err )
+                                               {
+                                                       msg_Dbg( p_aout, "Checking new status of hog mode: pid=%d vlc pid=%d\n",
+                                                               (int)p_sys->i_hog_pid, (int)getpid() );
+                                               }
+                                       }
+                               }
+                       }
+                       
+                       if( err != noErr )
+                       {
+                               msg_Err( p_aout, "failed to set hogmode: : [%4.4s]", (char *)&err );
+                               FreeDevice( p_aout );
+                               FreeHardwareInfo( p_aout );
+                               vlc_mutex_destroy( &p_sys->lock );
+                               free( (void *)p_sys );
+                               return( VLC_EGENERIC );
+                       }
+                       /*
+                       i_param_size = sizeof( b_mix );
+                       err = AudioDeviceGetProperty( p_dev->devid, 0, FALSE, kAudioDevicePropertySupportsMixing,
+                                                                                       &i_param_size, &b_mix );
+                                                                                       
+                       if( !err )
+                       {
+                               msg_Dbg( p_aout, "Current status of mix mode: %i\n", (int)b_mix );
+                               b_mix = 0;
+                               err = AudioDeviceSetProperty( p_dev->devid, 0, 0, FALSE,
+                                                                       kAudioDevicePropertySupportsMixing, i_param_size, &b_mix );
+                               if( !err )
+                               {
+                                       msg_Dbg( p_aout, "Successfully set mix mode - new mix=%d!\n", (int)b_mix );
+
+                                       err = AudioDeviceGetProperty( p_dev->devid, 0, FALSE,
+                                                                                               kAudioDevicePropertySupportsMixing, &i_param_size, &b_mix );
+                                       if( !err )
+                                       {
+                                               msg_Dbg( p_aout, "Checking new status of mix mode: %d\n", (int)b_mix );
+                                       }
+                               }
+                       }
+                       
+                       if( err != noErr )
+                       {
+                               msg_Err( p_aout, "failed to set mixmode: : [%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, STREAM_FORMAT_MSG( "setting format",
                                             P_STREAMS[i_stream] ) );
 
@@ -1325,6 +1398,29 @@ static void FreeDevice( aout_instance_t * p_aout )
                 msg_Err( p_aout, "AudioStreamSetProperty revert format failed: [%4.4s]",
                          (char *)&err );
             }
+        }
+               
+               if( (int)p_sys->i_hog_pid != -1 )
+        {
+                       /*UInt32 b_mix = 1;
+                       err = AudioDeviceSetProperty( p_sys->devid, 0, 0, FALSE,
+                                             kAudioDevicePropertySupportsMixing, sizeof(b_mix), &b_mix );
+                       
+                       if( err != noErr )
+            {
+                msg_Err( p_aout, "Resetting mix mode failed: [%4.4s]",
+                         (char *)&err );
+            }
+                       */
+            p_sys->i_hog_pid = (pid_t) -1;
+            err = AudioDeviceSetProperty( p_sys->devid, 0, 0, FALSE,
+                                             kAudioDevicePropertyHogMode, sizeof(p_sys->i_hog_pid), &p_sys->i_hog_pid );
+            
+            if( err != noErr )
+            {
+                msg_Err( p_aout, "Releasing hog mode failed: [%4.4s]",
+                         (char *)&err );
+            } 
         }
     }
 
@@ -1440,8 +1536,9 @@ static OSStatus StreamListener( AudioStreamID inStream,
                                 void * inClientData )
 {
     OSStatus err = noErr;
-
     struct { vlc_mutex_t lock; vlc_cond_t cond; } * w = inClientData;
+    aout_instance_t * p_aout = (aout_instance_t *)inClientData;
+    struct aout_sys_t * p_sys = p_aout->output.p_sys;
 
     switch( inPropertyID )
     {
@@ -1454,7 +1551,6 @@ static OSStatus StreamListener( AudioStreamID inStream,
         default:
             break;
     }
-
     return( err );
 }