* Updated coreaudio resampler. will play small lpcm samples, but still crashes sometimes.
authorDerk-Jan Hartman <hartman@videolan.org>
Sun, 7 Nov 2004 20:01:54 +0000 (20:01 +0000)
committerDerk-Jan Hartman <hartman@videolan.org>
Sun, 7 Nov 2004 20:01:54 +0000 (20:01 +0000)
  problem is writing to freed memory???
  possibly related to dropped buffers?

modules/audio_filter/resampler/coreaudio.c

index 94fddea..6353498 100644 (file)
@@ -2,7 +2,7 @@
  * coreaudio.c resampler based on CoreAudio's AudioConverter
  *****************************************************************************
  * Copyright (C) 2003 VideoLAN
- * $Id: coreaudio.c,v 1.5 2004/03/03 20:39:51 gbazin Exp $
+ * $Id$
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Jon Lech Johansen <jon-vl@nanocrew.net>
@@ -56,6 +56,13 @@ struct aout_filter_sys_t
     AudioConverterRef   s_converter;
     unsigned int i_remainder;
     unsigned int i_first_rate;
+
+    uint32_t p_bufferized[32768];
+    int i_bufferized;
+    int32_t p_output[32768];
+    int i_output;
+
+    audio_date_t end_date;
 };
 
 /*****************************************************************************
@@ -187,6 +194,8 @@ static int Create( vlc_object_t *p_this )
     /* We don't want a new buffer to be created because we're not sure we'll
      * actually need to resample anything. */
     p_filter->b_in_place = VLC_FALSE;
+    p_sys->i_bufferized = 0;
+    p_sys->i_output = 0;
 
     return VLC_SUCCESS;
 }
@@ -220,15 +229,14 @@ static void Close( vlc_object_t * p_this )
  * DoWork: convert a buffer
  *****************************************************************************/
 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 )
+                    aout_buffer_t * p_in_buf, aout_buffer_t * p_real_out_buf )
 {
     struct aout_filter_sys_t * p_sys = p_filter->p_sys;
-    int32_t *p_in = (int32_t *)p_in_buf->p_buffer;
+    int32_t *p_in = p_sys->p_bufferized;
     int32_t *p_out;
-    UInt32 i_output_size;
-    unsigned int i_out_nb, i_wanted_nb, i_new_rate;
+    int i_input_samples;
     OSErr err;
-    aout_buffer_t * p_middle_buf;
+    unsigned int i_out_nb;
 
     unsigned int i_nb_channels = aout_FormatNbChannels( &p_filter->input );
 
@@ -243,54 +251,109 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
         }
         p_filter->b_continuity = VLC_TRUE;
         p_sys->i_remainder = 0;
+        aout_DateInit( &p_filter->p_sys->end_date, p_filter->output.i_rate ); 
     }
 #endif
 
-    i_out_nb = (p_in_buf->i_nb_samples * p_filter->output.i_rate
-                 + p_sys->i_remainder) / p_sys->i_first_rate;
-    p_sys->i_remainder = (p_in_buf->i_nb_samples * p_filter->output.i_rate
-                 + p_sys->i_remainder) % p_sys->i_first_rate;
+    memcpy( p_sys->p_bufferized + p_sys->i_bufferized * i_nb_channels,
+            p_in_buf->p_buffer,
+            __MIN(p_in_buf->i_nb_samples * 4 * i_nb_channels,
+                  sizeof(p_sys->p_bufferized)
+                     - p_sys->i_bufferized * 4 * i_nb_channels) );
+    p_sys->i_bufferized += p_in_buf->i_nb_samples;
+    i_input_samples = p_sys->i_bufferized;
 
-    i_output_size = i_out_nb * 4 * i_nb_channels;
-    if ( i_output_size > p_out_buf->i_size )
+    if ( i_input_samples >= 512 )
     {
-        aout_BufferAlloc( &p_sys->alloc,
+        aout_buffer_t * p_middle_buf, * p_out_buf;
+        UInt32 i_output_size;
+        unsigned int i_wanted_nb, i_new_rate;
+
+        i_out_nb = (i_input_samples * p_filter->output.i_rate
+                     + p_sys->i_remainder) / p_sys->i_first_rate;
+        p_sys->i_remainder = (i_input_samples * p_filter->output.i_rate
+                     + p_sys->i_remainder) % p_sys->i_first_rate;
+    
+        aout_BufferAlloc( &p_filter->output_alloc,
             i_out_nb * 1000000 / p_filter->output.i_rate,
-            NULL, p_middle_buf );
-    }
-    else
-    {
-        p_middle_buf = p_out_buf;
-    }
-    p_out = (int32_t*)p_middle_buf->p_buffer;
-    err = AudioConverterConvertBuffer( p_sys->s_converter,
-        p_in_buf->i_nb_samples * 4 * i_nb_channels, p_in,
-        &i_output_size, p_out );
-    if( err != noErr )
-    {
-        msg_Warn( p_filter, "AudioConverterConvertBuffer failed: [%4.4s] (%u:%u)",
-                 (char *)&err, i_out_nb * 4 * i_nb_channels, i_output_size );
+            NULL, p_out_buf );
+
         i_output_size = i_out_nb * 4 * i_nb_channels;
-        memset( p_out, 0, i_output_size );
-    }
+        if ( i_output_size > p_out_buf->i_size )
+        {
+            aout_BufferAlloc( &p_sys->alloc,
+                i_out_nb * 1000000 / p_filter->output.i_rate,
+                NULL, p_middle_buf );
+        }
+        else
+        {
+            p_middle_buf = p_out_buf;
+        }
+        p_out = (int32_t*)p_middle_buf->p_buffer;
+        err = AudioConverterConvertBuffer( p_sys->s_converter,
+            i_input_samples * 4 * i_nb_channels, p_in,
+            &i_output_size, p_out );
+        if( err != noErr )
+        {
+            msg_Warn( p_filter, "AudioConverterConvertBuffer failed: [%4.4s] (%u:%u)",
+                     (char *)&err, i_out_nb * 4 * i_nb_channels, i_output_size );
+            i_output_size = i_out_nb * 4 * i_nb_channels;
+            memset( p_out, 0, i_output_size );
+        }
+        memmove( p_sys->p_bufferized,
+                 p_sys->p_bufferized + i_input_samples * 4 * i_nb_channels,
+                 (p_sys->i_bufferized - i_input_samples) * 4 * i_nb_channels );
+        p_sys->i_bufferized -= i_input_samples;
+
+        p_middle_buf->i_nb_samples = i_output_size / 4 / i_nb_channels;
+        p_middle_buf->i_nb_bytes = i_output_size;
+        p_middle_buf->start_date = p_in_buf->start_date;
+        p_middle_buf->end_date = p_middle_buf->start_date
+            + p_middle_buf->i_nb_samples * 1000000 / p_filter->output.i_rate;
+    
+        i_wanted_nb = i_input_samples * p_filter->output.i_rate
+                                            / p_filter->input.i_rate;
+        i_new_rate = p_middle_buf->i_nb_samples * p_filter->output.i_rate
+                                            / i_wanted_nb;
+    
+        p_sys->p_secondary_resampler->input.i_rate = i_new_rate;
+        p_sys->p_secondary_resampler->pf_do_work( p_aout,
+            p_sys->p_secondary_resampler, p_middle_buf, p_out_buf );
+    
+        if ( p_middle_buf != p_out_buf )
+        {
+            aout_BufferFree( p_middle_buf );
+        }
+
+        memcpy( p_sys->p_output + p_sys->i_output * i_nb_channels,
+                p_out_buf->p_buffer,
+                __MIN(p_out_buf->i_nb_samples * 4 * i_nb_channels,
+                      sizeof(p_sys->p_output)
+                         - p_sys->i_output * 4 * i_nb_channels) );
+        p_sys->i_output += p_out_buf->i_nb_samples;
 
-    p_middle_buf->i_nb_samples = i_output_size / 4 / i_nb_channels;
-    p_middle_buf->i_nb_bytes = i_output_size;
-    p_middle_buf->start_date = p_in_buf->start_date;
-    p_middle_buf->end_date = p_middle_buf->start_date + p_middle_buf->i_nb_samples *
-        1000000 / p_filter->output.i_rate;
+        aout_BufferFree( p_out_buf );
+    }
 
-    i_wanted_nb = p_in_buf->i_nb_samples * p_filter->output.i_rate
-                                        / p_filter->input.i_rate;
-    i_new_rate = p_middle_buf->i_nb_samples * p_filter->output.i_rate
-                                        / i_wanted_nb;
+    i_out_nb = (p_in_buf->i_nb_samples * p_filter->output.i_rate
+                 + p_sys->i_first_rate - 1) / p_sys->i_first_rate;
+    if ( i_out_nb > p_sys->i_output )
+        i_out_nb = p_sys->i_output;
 
-    p_sys->p_secondary_resampler->input.i_rate = i_new_rate;
-    p_sys->p_secondary_resampler->pf_do_work( p_aout,
-        p_sys->p_secondary_resampler, p_middle_buf, p_out_buf );
+    p_real_out_buf->i_nb_samples = i_out_nb;
+    p_real_out_buf->i_nb_bytes = i_out_nb * 4 * i_nb_channels;
 
-    if ( p_middle_buf != p_out_buf )
+    if( p_in_buf->start_date !=
+        aout_DateGet( &p_filter->p_sys->end_date ) )
     {
-        aout_BufferFree( p_middle_buf );
+        aout_DateSet( &p_filter->p_sys->end_date, p_in_buf->start_date );
     }
+
+    p_real_out_buf->end_date = aout_DateIncrement( &p_filter->p_sys->end_date,
+                                                   i_out_nb );
+    memcpy( p_real_out_buf->p_buffer, p_sys->p_output,
+            i_out_nb * 4 * i_nb_channels );
+    memmove( p_sys->p_output, p_sys->p_output + i_out_nb * i_nb_channels,
+             (p_sys->i_output - i_out_nb) * 4 * i_nb_channels );
+    p_sys->i_output -= i_out_nb;
 }