$OpenBSD$ index ed6d7d6..6b5d512 100644 --- media/libspeex_resampler/src/resample.c.orig Fri Feb 20 15:40:37 2015 +++ media/libspeex_resampler/src/resample.c Fri Feb 20 15:40:37 2015 @@ -579,11 +579,47 @@ static int resampler_basic_interpolate_double(SpeexResamplerState *st, spx_uint3 } #endif -static void update_filter(SpeexResamplerState *st) +/* This resampler is used to produce zero output in situations where memory + for the filter could not be allocated. The expected numbers of input and + output samples are still processed so that callers failing to check error + codes are not surprised, possibly getting into infinite loops. */ +static int resampler_basic_zero(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) { - spx_uint32_t old_length; + int out_sample = 0; + int last_sample = st->last_sample[channel_index]; + spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; + const int out_stride = st->out_stride; + const int int_advance = st->int_advance; + const int frac_advance = st->frac_advance; + const spx_uint32_t den_rate = st->den_rate; + + while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) + { + out[out_stride * out_sample++] = 0; + last_sample += int_advance; + samp_frac_num += frac_advance; + if (samp_frac_num >= den_rate) + { + samp_frac_num -= den_rate; + last_sample++; + } + } + + st->last_sample[channel_index] = last_sample; + st->samp_frac_num[channel_index] = samp_frac_num; + return out_sample; +} + +static int update_filter(SpeexResamplerState *st) +{ + spx_uint32_t old_length = st->filt_len; + spx_uint32_t old_alloc_size = st->mem_alloc_size; + int use_direct; + spx_uint32_t min_sinc_table_length; + spx_uint32_t min_alloc_size; - old_length = st->filt_len; + st->int_advance = st->num_rate/st->den_rate; + st->frac_advance = st->num_rate%st->den_rate; st->oversample = quality_map[st->quality].oversample; st->filt_len = quality_map[st->quality].base_length; @@ -611,20 +647,29 @@ static void update_filter(SpeexResamplerState *st) } #ifdef RESAMPLE_HUGEMEM - if (st->den_rate <= 16*(st->oversample+8)) + use_direct = st->den_rate <= 16*(st->oversample+8); #else /* Choose the resampling type that requires the least amount of memory */ - if (st->den_rate <= (st->oversample+8)) + use_direct = st->filt_len*st->den_rate <= st->filt_len*st->oversample+8; #endif + if (use_direct) + { + min_sinc_table_length = st->filt_len*st->den_rate; + } else { + min_sinc_table_length = st->filt_len*st->oversample+8; + } + if (st->sinc_table_length < min_sinc_table_length) + { + spx_word16_t *sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,min_sinc_table_length*sizeof(spx_word16_t)); + if (!sinc_table) + goto fail; + + st->sinc_table = sinc_table; + st->sinc_table_length = min_sinc_table_length; + } + if (use_direct) { spx_uint32_t i; - if (!st->sinc_table) - st->sinc_table = (spx_word16_t *)speex_alloc(st->filt_len*st->den_rate*sizeof(spx_word16_t)); - else if (st->sinc_table_length < st->filt_len*st->den_rate) - { - st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,st->filt_len*st->den_rate*sizeof(spx_word16_t)); - st->sinc_table_length = st->filt_len*st->den_rate; - } for (i=0;iden_rate;i++) { spx_int32_t j; @@ -644,13 +689,6 @@ static void update_filter(SpeexResamplerState *st) /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff);*/ } else { spx_int32_t i; - if (!st->sinc_table) - st->sinc_table = (spx_word16_t *)speex_alloc((st->filt_len*st->oversample+8)*sizeof(spx_word16_t)); - else if (st->sinc_table_length < st->filt_len*st->oversample+8) - { - st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,(st->filt_len*st->oversample+8)*sizeof(spx_word16_t)); - st->sinc_table_length = st->filt_len*st->oversample+8; - } for (i=-4;i<(spx_int32_t)(st->oversample*st->filt_len+4);i++) st->sinc_table[i+4] = sinc(st->cutoff,(i/(float)st->oversample - st->filt_len/2), st->filt_len, quality_map[st->quality].window_func); #ifdef FIXED_POINT @@ -663,43 +701,35 @@ static void update_filter(SpeexResamplerState *st) #endif /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff);*/ } - st->int_advance = st->num_rate/st->den_rate; - st->frac_advance = st->num_rate%st->den_rate; /* Here's the place where we update the filter memory to take into account the change in filter length. It's probably the messiest part of the code due to handling of lots of corner cases. */ - if (!st->mem) + min_alloc_size = st->filt_len-1 + st->buffer_size; + if (min_alloc_size > st->mem_alloc_size) { - spx_uint32_t i; - st->mem_alloc_size = st->filt_len-1 + st->buffer_size; - st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t)); - for (i=0;inb_channels*st->mem_alloc_size;i++) - st->mem[i] = 0; - /*speex_warning("init filter");*/ - } else if (!st->started) + spx_word16_t *mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*min_alloc_size * sizeof(spx_word16_t)); + if (!mem) + goto fail; + + st->mem = mem; + st->mem_alloc_size = min_alloc_size; + } + if (!st->started) { spx_uint32_t i; - st->mem_alloc_size = st->filt_len-1 + st->buffer_size; - st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t)); for (i=0;inb_channels*st->mem_alloc_size;i++) st->mem[i] = 0; /*speex_warning("reinit filter");*/ } else if (st->filt_len > old_length) { - spx_int32_t i; + spx_uint32_t i; /* Increase the filter length */ /*speex_warning("increase filter size");*/ - int old_alloc_size = st->mem_alloc_size; - if ((st->filt_len-1 + st->buffer_size) > st->mem_alloc_size) + for (i=st->nb_channels;i--;) { - st->mem_alloc_size = st->filt_len-1 + st->buffer_size; - st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t)); - } - for (i=st->nb_channels-1;i>=0;i--) - { - spx_int32_t j; + spx_uint32_t j; spx_uint32_t olen = old_length; /*if (st->magic_samples[i])*/ { @@ -707,7 +737,7 @@ static void update_filter(SpeexResamplerState *st) /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */ olen = old_length + 2*st->magic_samples[i]; - for (j=old_length-2+st->magic_samples[i];j>=0;j--) + for (j=old_length-1+st->magic_samples[i];j--;) st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]] = st->mem[i*old_alloc_size+j]; for (j=0;jmagic_samples[i];j++) st->mem[i*st->mem_alloc_size+j] = 0; @@ -748,7 +778,15 @@ static void update_filter(SpeexResamplerState *st) st->magic_samples[i] += old_magic; } } + return RESAMPLER_ERR_SUCCESS; +fail: + st->resampler_ptr = resampler_basic_zero; + /* st->mem may still contain consumed input samples for the filter. + Restore filt_len so that filt_len - 1 still points to the position after + the last of these samples. */ + st->filt_len = old_length; + return RESAMPLER_ERR_ALLOC_FAILED; } SPX_RESAMPLE_EXPORT SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err) @@ -760,6 +798,8 @@ SPX_RESAMPLE_EXPORT SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t { spx_uint32_t i; SpeexResamplerState *st; + int filter_err; + if (quality > 10 || quality < 0) { if (err) @@ -805,12 +845,16 @@ SPX_RESAMPLE_EXPORT SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t speex_resampler_set_quality(st, quality); speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate); - - update_filter(st); - - st->initialised = 1; + filter_err = update_filter(st); + if (filter_err == RESAMPLER_ERR_SUCCESS) + { + st->initialised = 1; + } else { + speex_resampler_destroy(st); + st = NULL; + } if (err) - *err = RESAMPLER_ERR_SUCCESS; + *err = filter_err; return st; } @@ -909,7 +953,7 @@ SPX_RESAMPLE_EXPORT int speex_resampler_process_float(SpeexResamplerState *st, s } *in_len -= ilen; *out_len -= olen; - return RESAMPLER_ERR_SUCCESS; + return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS; } #ifdef FIXED_POINT @@ -983,7 +1027,7 @@ SPX_RESAMPLE_EXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx *in_len -= ilen; *out_len -= olen; - return RESAMPLER_ERR_SUCCESS; + return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS; } SPX_RESAMPLE_EXPORT int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) @@ -1006,7 +1050,7 @@ SPX_RESAMPLE_EXPORT int speex_resampler_process_interleaved_float(SpeexResampler } st->in_stride = istride_save; st->out_stride = ostride_save; - return RESAMPLER_ERR_SUCCESS; + return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS; } SPX_RESAMPLE_EXPORT int speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) @@ -1029,7 +1073,7 @@ SPX_RESAMPLE_EXPORT int speex_resampler_process_interleaved_int(SpeexResamplerSt } st->in_stride = istride_save; st->out_stride = ostride_save; - return RESAMPLER_ERR_SUCCESS; + return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS; } SPX_RESAMPLE_EXPORT int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate) @@ -1078,7 +1122,7 @@ SPX_RESAMPLE_EXPORT int speex_resampler_set_rate_frac(SpeexResamplerState *st, s } if (st->initialised) - update_filter(st); + return update_filter(st); return RESAMPLER_ERR_SUCCESS; } @@ -1096,7 +1140,7 @@ SPX_RESAMPLE_EXPORT int speex_resampler_set_quality(SpeexResamplerState *st, int return RESAMPLER_ERR_SUCCESS; st->quality = quality; if (st->initialised) - update_filter(st); + return update_filter(st); return RESAMPLER_ERR_SUCCESS; }