]> git.sesse.net Git - vlc/blobdiff - modules/audio_filter/resampler/bandlimited.c
Fixed bandlimited invalid writes when downsampling.
[vlc] / modules / audio_filter / resampler / bandlimited.c
index 2f9267bd05651810c0fd672a87c8e5c9939e15ae..18fb3ed1649be2b80e2ee614c46cd77ce91456ca 100644 (file)
@@ -43,6 +43,8 @@
 #include <vlc_filter.h>
 #include <vlc_block.h>
 
+#include <assert.h>
+
 #include "bandlimited.h"
 
 /*****************************************************************************
@@ -161,10 +163,10 @@ static block_t *Resample( filter_t * p_filter, block_t * p_in_buf )
         p_sys->b_first = false;
     }
 
-    int i_in_nb = p_in_buf->i_nb_samples;
-    int i_in, i_out = 0;
+    size_t i_in_nb = p_in_buf->i_nb_samples;
+    size_t i_in, i_out = 0;
     double d_factor, d_scale_factor, d_old_scale_factor;
-    int i_filter_wing;
+    size_t i_filter_wing;
 
 #if 0
     msg_Err( p_filter, "old rate: %i, old factor: %f, old wing: %i, i_in: %i",
@@ -172,24 +174,25 @@ static block_t *Resample( filter_t * p_filter, block_t * p_in_buf )
              p_sys->i_old_wing, i_in_nb );
 #endif
 
-    /* Prepare the source buffer */
-    i_in_nb += (p_sys->i_old_wing * 2);
-
-    float p_in_orig[i_in_nb * p_filter->fmt_in.audio.i_bytes_per_frame / 4],
-         *p_in = p_in_orig;
+    /* Same format in and out... */
+    assert( p_filter->fmt_in.audio.i_bytes_per_frame == i_bytes_per_frame );
 
-    /* Copy all our samples in p_in */
+    /* Prepare the source buffer */
     if( p_sys->i_old_wing )
-    {
-        vlc_memcpy( p_in, p_sys->p_buf,
-                    p_sys->i_old_wing * 2 *
-                      p_filter->fmt_in.audio.i_bytes_per_frame );
+    {   /* Copy all our samples in p_in_buf */
+        /* Normally, there should be enough room for the old wing in the
+         * buffer head room. Otherwise, we need to copy memory anyway. */
+        p_in_buf = block_Realloc( p_in_buf,
+                                  p_sys->i_old_wing * 2 * i_bytes_per_frame,
+                                  p_in_buf->i_buffer );
+        if( unlikely(p_in_buf == NULL) )
+            return NULL;
+        memcpy( p_in_buf->p_buffer, p_sys->p_buf,
+                p_sys->i_old_wing * 2 * i_bytes_per_frame );
     }
-    /* XXX: why i_nb_channels instead of i_bytes_per_frame??? */
-    vlc_memcpy( p_in + p_sys->i_old_wing * 2 * i_nb_channels,
-                p_in_buf->p_buffer,
-                p_in_buf->i_nb_samples * p_filter->fmt_in.audio.i_bytes_per_frame );
-    block_Release( p_in_buf );
+    i_in_nb += (p_sys->i_old_wing * 2);
+    float *p_in = (float *)p_in_buf->p_buffer;
+    const float *p_in_orig = p_in;
 
     /* Make sure the output buffer is reset */
     memset( p_out, 0, p_out_buf->i_buffer );
@@ -212,8 +215,7 @@ static block_t *Resample( filter_t * p_filter, block_t * p_in_buf )
         if( p_sys->d_old_factor == 1 )
         {
             /* Just copy the samples */
-            memcpy( p_out, p_in,
-                    p_filter->fmt_in.audio.i_bytes_per_frame );
+            memcpy( p_out, p_in, i_bytes_per_frame );
             p_in += i_nb_channels;
             p_out += i_nb_channels;
             i_out++;
@@ -222,6 +224,8 @@ static block_t *Resample( filter_t * p_filter, block_t * p_in_buf )
 
         while( p_sys->i_remainder < p_filter->fmt_out.audio.i_rate )
         {
+            if( p_out_buf->i_buffer/i_bytes_per_frame <= i_out )
+                break;
 
             if( p_sys->d_old_factor >= 1 )
             {
@@ -248,16 +252,6 @@ static block_t *Resample( filter_t * p_filter, block_t * p_in_buf )
                     *(p_out+i) *= d_old_scale_factor;
                 }
 #endif
-
-                /* Sanity check */
-                if( p_out_buf->i_buffer/p_filter->fmt_in.audio.i_bytes_per_frame
-                    <= (unsigned int)i_out+1 )
-                {
-                    p_out += i_nb_channels;
-                    i_out++;
-                    p_sys->i_remainder += p_filter->fmt_in.audio.i_rate;
-                    break;
-                }
             }
             else
             {
@@ -296,7 +290,10 @@ static block_t *Resample( filter_t * p_filter, block_t * p_in_buf )
     {
         while( p_sys->i_remainder < p_filter->fmt_out.audio.i_rate )
         {
+            if( p_out_buf->i_buffer/i_bytes_per_frame <= i_out )
+                break;
 
+            assert( i_out < p_out_buf->i_buffer/i_bytes_per_frame );
             if( d_factor >= 1 )
             {
                 /* FilterFloatUP() is faster if we can use it */
@@ -323,15 +320,6 @@ static block_t *Resample( filter_t * p_filter, block_t * p_in_buf )
                     *(p_out+i) *= d_old_scale_factor;
                 }
 #endif
-                /* Sanity check */
-                if( p_out_buf->i_buffer/p_filter->fmt_in.audio.i_bytes_per_frame
-                    <= (unsigned int)i_out+1 )
-                {
-                    p_out += i_nb_channels;
-                    i_out++;
-                    p_sys->i_remainder += p_filter->fmt_in.audio.i_rate;
-                    break;
-                }
             }
             else
             {
@@ -372,8 +360,7 @@ static block_t *Resample( filter_t * p_filter, block_t * p_in_buf )
     /* Buffer i_filter_wing * 2 samples for next time */
     if( p_sys->i_old_wing )
     {
-        size_t newsize = p_sys->i_old_wing * 2
-                         * p_filter->fmt_in.audio.i_bytes_per_frame;
+        size_t newsize = p_sys->i_old_wing * 2 * i_bytes_per_frame;
         if( newsize > p_sys->i_buf_size )
         {
             free( p_sys->p_buf );