X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmodules%2Fresample%2Ffilter_resample.c;h=c2d56bdba902d1467c7aaac4171db6d3b9da3c4e;hb=11ceb3a29fd27c05bfac2b05463eff1790309a81;hp=b4fd13d77e56fa8f736694435230cffb1ea70114;hpb=0942454258a07166839a999c71b6fa35785ac70a;p=mlt diff --git a/src/modules/resample/filter_resample.c b/src/modules/resample/filter_resample.c index b4fd13d7..c2d56bdb 100644 --- a/src/modules/resample/filter_resample.c +++ b/src/modules/resample/filter_resample.c @@ -18,88 +18,88 @@ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "filter_resample.h" - +#include #include +#include #include #include #include -#define __USE_ISOC99 1 -#include +#include -#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 a frame - mlt_properties properties = mlt_frame_properties( frame ); - int output_rate = mlt_properties_get_int( properties, "resample.frequency" ); - SRC_STATE *state = mlt_properties_get_data( properties, "resample.state", NULL ); - SRC_DATA data; - float *input_buffer = mlt_properties_get_data( properties, "resample.input_buffer", NULL ); - float *output_buffer = mlt_properties_get_data( properties, "resample.output_buffer", NULL ); - int i; + // Get the filter service + mlt_filter filter = mlt_frame_pop_audio( frame ); + + // Get the filter properties + mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter ); + + // Get the resample information + int output_rate = mlt_properties_get_int( filter_properties, "frequency" ); + // If no resample frequency is specified, default to requested value if ( output_rate == 0 ) output_rate = *frequency; - // Restore the original get_audio - frame->get_audio = mlt_properties_get_data( properties, "resample.get_audio", NULL ); - // Get the producer's audio - mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples ); - - //fprintf( stderr, "resample_get_audio: output_rate %d\n", output_rate ); - - // Return now if now work to do - if ( output_rate == *frequency ) - return 0; - - // Convert to floating point - for ( i = 0; i < *samples * *channels; ++i ) - input_buffer[ i ] = ( float )( (*buffer)[ i ] ) / 32768; - - // Resample - data.data_in = input_buffer; - data.data_out = output_buffer; - 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 ) + 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 && *frequency > 0 && *channels > 0 ) { - if ( data.output_frames_gen > *samples ) + 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 ); + + mlt_service_lock( MLT_FILTER_SERVICE(filter) ); + + 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; + + SRC_STATE *state = mlt_properties_get_data( filter_properties, "state", NULL ); + if ( !state || mlt_properties_get_int( filter_properties, "channels" ) != *channels ) + { + // 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 ) { - *buffer = (int16_t*) malloc( data.output_frames_gen * *channels * 2 ); - mlt_properties_set_data( properties, "audio", *buffer, *channels * data.output_frames_gen * 2, free, NULL ); + // Update output variables + *samples = data.output_frames_gen; + *frequency = output_rate; + *buffer = data.data_out; } - *samples = data.output_frames_gen; - *frequency = output_rate; - - // Convert from floating back to signed 16bit - for ( i = 0; i < *samples * *channels; ++i ) + else { - float sample = output_buffer[ i ]; - if ( sample > 1.0 ) - sample = 1.0; - if ( sample < -1.0 ) - sample = -1.0; - if ( sample >= 0 ) - (*buffer)[ i ] = lrint( 32767.0 * sample ); - else - (*buffer)[ i ] = lrint( 32768.0 * sample ); + 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) ); } - else - fprintf( stderr, "resample_get_audio: %s %d,%d,%d\n", src_strerror( i ), *frequency, *samples, output_rate ); - - return 0; + + return error; } /** Filter processing. @@ -107,24 +107,11 @@ static int resample_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form static mlt_frame filter_process( mlt_filter this, mlt_frame frame ) { - mlt_properties properties = mlt_filter_properties( this ); - mlt_properties frame_props = mlt_frame_properties( frame ); - - // Propogate the frequency property if supplied - if ( mlt_properties_get( properties, "frequency" ) != NULL ) - mlt_properties_set_int( frame_props, "resample.frequency", mlt_properties_get_int( properties, "frequency" ) ); - - // Propogate the other properties - mlt_properties_set_int( frame_props, "resample.channels", mlt_properties_get_int( properties, "channels" ) ); - mlt_properties_set_data( frame_props, "resample.state", mlt_properties_get_data( properties, "state", NULL ), 0, NULL, NULL ); - mlt_properties_set_data( frame_props, "resample.input_buffer", mlt_properties_get_data( properties, "input_buffer", NULL ), 0, NULL, NULL ); - mlt_properties_set_data( frame_props, "resample.output_buffer", mlt_properties_get_data( properties, "output_buffer", NULL ), 0, NULL, NULL ); - - // Backup the original get_audio (it's still needed) - mlt_properties_set_data( frame_props, "resample.get_audio", frame->get_audio, 0, NULL, NULL ); - - // Override the get_audio method - frame->get_audio = resample_get_audio; + if ( mlt_frame_is_test_audio( frame ) == 0 ) + { + mlt_frame_push_audio( frame, this ); + mlt_frame_push_audio( frame, resample_get_audio ); + } return frame; } @@ -132,24 +119,22 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame ) /** Constructor for the filter. */ -mlt_filter filter_resample_init( char *arg ) +mlt_filter filter_resample_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ) { - mlt_filter this = calloc( sizeof( struct mlt_filter_s ), 1 ); - if ( this != NULL && mlt_filter_init( this, NULL ) == 0 ) + mlt_filter this = mlt_filter_new( ); + if ( this != NULL ) { int error; SRC_STATE *state = src_new( RESAMPLE_TYPE, 2 /* channels */, &error ); if ( error == 0 ) { + 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", - malloc( BUFFER_LEN ), BUFFER_LEN, free, NULL ); - mlt_properties_set_data( mlt_filter_properties( this ), "output_buffer", - malloc( BUFFER_LEN ), BUFFER_LEN, free, 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 ), "output_buffer", output_buffer, BUFFER_LEN, mlt_pool_release, NULL ); } else { @@ -158,4 +143,3 @@ mlt_filter filter_resample_init( char *arg ) } return this; } -