]> git.sesse.net Git - mlt/blobdiff - src/modules/resample/filter_resample.c
Add a refresh property to videostab2 filter.
[mlt] / src / modules / resample / filter_resample.c
index 9ff4d9e17a64b9d90c67f1ec97b07c83751f71b5..c2d56bdba902d1467c7aaac4171db6d3b9da3c4e 100644 (file)
 
 #include <framework/mlt_filter.h>
 #include <framework/mlt_frame.h>
+#include <framework/mlt_log.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <samplerate.h>
+#include <string.h>
 
-#define BUFFER_LEN 20480
+// BUFFER_LEN is based on a maximum of 96KHz, 5 fps, 8 channels
+// TODO: dynamically allocate larger buffer size
+#define BUFFER_LEN ((96000/5) * 8 * sizeof(float))
 #define RESAMPLE_TYPE SRC_SINC_FASTEST
 
 /** Get the audio.
 */
 
-static int resample_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int resample_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
 {
-       // Get the properties of the frame
-       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
-
        // Get the filter service
        mlt_filter filter = mlt_frame_pop_audio( frame );
 
@@ -44,113 +45,61 @@ static int resample_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form
 
        // Get the resample information
        int output_rate = mlt_properties_get_int( filter_properties, "frequency" );
-       SRC_STATE *state = mlt_properties_get_data( filter_properties, "state", NULL );
-       float *input_buffer = mlt_properties_get_data( filter_properties, "input_buffer", NULL );
-       float *output_buffer = mlt_properties_get_data( filter_properties, "output_buffer", NULL );
-       int channels_avail = *channels;
-       SRC_DATA data;
-       int i;
 
        // If no resample frequency is specified, default to requested value
        if ( output_rate == 0 )
                output_rate = *frequency;
 
        // Get the producer's audio
-       mlt_frame_get_audio( frame, buffer, format, frequency, &channels_avail, samples );
-
-       // Duplicate channels as necessary
-       if ( channels_avail < *channels )
-       {
-               int size = *channels * *samples * sizeof( int16_t );
-               int16_t *new_buffer = mlt_pool_alloc( size );
-               int j, k = 0;
-               
-               // Duplicate the existing channels
-               for ( i = 0; i < *samples; i++ )
-               {
-                       for ( j = 0; j < *channels; j++ )
-                       {
-                               new_buffer[ ( i * *channels ) + j ] = (*buffer)[ ( i * channels_avail ) + k ];
-                               k = ( k + 1 ) % channels_avail;
-                       }
-               }
-               
-               // Update the audio buffer now - destroys the old
-               mlt_properties_set_data( properties, "audio", new_buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
-               
-               *buffer = new_buffer;
-       }
-       else if ( channels_avail == 6 && *channels == 2 )
-       {
-               // Nasty hack for ac3 5.1 audio - may be a cause of failure?
-               int size = *channels * *samples * sizeof( int16_t );
-               int16_t *new_buffer = mlt_pool_alloc( size );
-               
-               // Drop all but the first *channels
-               for ( i = 0; i < *samples; i++ )
-               {
-                       new_buffer[ ( i * *channels ) + 0 ] = (*buffer)[ ( i * channels_avail ) + 2 ];
-                       new_buffer[ ( i * *channels ) + 1 ] = (*buffer)[ ( i * channels_avail ) + 3 ];
-               }
-
-               // Update the audio buffer now - destroys the old
-               mlt_properties_set_data( properties, "audio", new_buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
-               
-               *buffer = new_buffer;
-       }
+       int error = mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
+       if ( error ) return error;
 
        // Return now if no work to do
-       if ( output_rate != *frequency )
+       if ( output_rate != *frequency && *frequency > 0 && *channels > 0 )
        {
-               float *p = input_buffer;
-               float *end = p + *samples * *channels;
-               int16_t *q = *buffer;
+               mlt_log_debug( MLT_FILTER_SERVICE(filter), "channels %d samples %d frequency %d -> %d\n",
+                       *channels, *samples, *frequency, output_rate );
+
+               // Do not convert to float unless we need to change the rate
+               if ( *format != mlt_audio_f32le )
+                       frame->convert_audio( frame, buffer, format, mlt_audio_f32le );
 
-               // Convert to floating point
-               while( p != end )
-                       *p ++ = ( float )( *q ++ ) / 32768.0;
+               mlt_service_lock( MLT_FILTER_SERVICE(filter) );
 
-               // Resample
-               data.data_in = input_buffer;
-               data.data_out = output_buffer;
+               SRC_DATA data;
+               data.data_in = *buffer;
+               data.data_out = mlt_properties_get_data( filter_properties, "output_buffer", NULL );
                data.src_ratio = ( float ) output_rate / ( float ) *frequency;
                data.input_frames = *samples;
                data.output_frames = BUFFER_LEN / *channels;
                data.end_of_input = 0;
-               i = src_process( state, &data );
-               if ( i == 0 )
+
+               SRC_STATE *state = mlt_properties_get_data( filter_properties, "state", NULL );
+               if ( !state || mlt_properties_get_int( filter_properties, "channels" ) != *channels )
                {
-                       if ( data.output_frames_gen > *samples )
-                       {
-                               *buffer = mlt_pool_realloc( *buffer, data.output_frames_gen * *channels * sizeof( int16_t ) );
-                               mlt_properties_set_data( properties, "audio", *buffer, *channels * data.output_frames_gen * 2, mlt_pool_release, NULL );
-                       }
+                       // Recreate the resampler if the number of channels changed
+                       state = src_new( RESAMPLE_TYPE, *channels, &error );
+                       mlt_properties_set_data( filter_properties, "state", state, 0, (mlt_destructor) src_delete, NULL );
+                       mlt_properties_set_int( filter_properties, "channels", *channels );
+               }
 
+               // Resample the audio
+               error = src_process( state, &data );
+               if ( !error )
+               {
+                       // Update output variables
                        *samples = data.output_frames_gen;
                        *frequency = output_rate;
-
-                       p = output_buffer;
-                       q = *buffer;
-                       end = p + *samples * *channels;
-                       
-                       // Convert from floating back to signed 16bit
-                       while( p != end )
-                       {
-                               if ( *p > 1.0 )
-                                       *p = 1.0;
-                               if ( *p < -1.0 )
-                                       *p = -1.0;
-                               if ( *p > 0 )
-                                       *q ++ = 32767 * *p ++;
-                               else
-                                       *q ++ = 32768 * *p ++;
-                       }
+                       *buffer = data.data_out;
                }
                else
-                       fprintf( stderr, "resample_get_audio: %s %d,%d,%d\n", src_strerror( i ), *frequency, *samples, output_rate );
+               {
+                       mlt_log_error( MLT_FILTER_SERVICE( filter ), "%s %d,%d,%d\n", src_strerror( error ), *frequency, *samples, output_rate );
+               }
+               mlt_service_unlock( MLT_FILTER_SERVICE(filter) );
        }
 
-       return 0;
+       return error;
 }
 
 /** Filter processing.
@@ -179,14 +128,12 @@ mlt_filter filter_resample_init( mlt_profile profile, mlt_service_type type, con
                SRC_STATE *state = src_new( RESAMPLE_TYPE, 2 /* channels */, &error );
                if ( error == 0 )
                {
-                       void *input_buffer = mlt_pool_alloc( BUFFER_LEN );
                        void *output_buffer = mlt_pool_alloc( BUFFER_LEN );
                        this->process = filter_process;
                        if ( arg != NULL )
                                mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "frequency", atoi( arg ) );
                        mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "channels", 2 );
                        mlt_properties_set_data( MLT_FILTER_PROPERTIES( this ), "state", state, 0, (mlt_destructor)src_delete, NULL );
-                       mlt_properties_set_data( MLT_FILTER_PROPERTIES( this ), "input_buffer", input_buffer, BUFFER_LEN, mlt_pool_release, NULL );
                        mlt_properties_set_data( MLT_FILTER_PROPERTIES( this ), "output_buffer", output_buffer, BUFFER_LEN, mlt_pool_release, NULL );
                }
                else