Signed-off-by: Michael Niedermayer <michaelni@gmx.at>tags/n1.1
| @@ -195,7 +195,7 @@ static int build_filter(ResampleContext *c, void *filter, double factor, int tap | |||
| return 0; | |||
| } | |||
| ResampleContext *swri_resample_init(ResampleContext *c, int out_rate, int in_rate, int filter_size, int phase_shift, int linear, | |||
| static ResampleContext *resample_init(ResampleContext *c, int out_rate, int in_rate, int filter_size, int phase_shift, int linear, | |||
| double cutoff, enum AVSampleFormat format, enum SwrFilterType filter_type, int kaiser_beta){ | |||
| double factor= FFMIN(out_rate * cutoff / in_rate, 1.0); | |||
| int phase_count= 1<<phase_shift; | |||
| @@ -259,28 +259,14 @@ error: | |||
| return NULL; | |||
| } | |||
| void swri_resample_free(ResampleContext **c){ | |||
| static void resample_free(ResampleContext **c){ | |||
| if(!*c) | |||
| return; | |||
| av_freep(&(*c)->filter_bank); | |||
| av_freep(c); | |||
| } | |||
| int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensation_distance){ | |||
| ResampleContext *c; | |||
| int ret; | |||
| if (!s || compensation_distance < 0) | |||
| return AVERROR(EINVAL); | |||
| if (!compensation_distance && sample_delta) | |||
| return AVERROR(EINVAL); | |||
| if (!s->resample) { | |||
| s->flags |= SWR_FLAG_RESAMPLE; | |||
| ret = swr_init(s); | |||
| if (ret < 0) | |||
| return ret; | |||
| } | |||
| c= s->resample; | |||
| static int set_compensation(ResampleContext *c, int sample_delta, int compensation_distance){ | |||
| c->compensation_distance= compensation_distance; | |||
| if (compensation_distance) | |||
| c->dst_incr = c->ideal_dst_incr - c->ideal_dst_incr * (int64_t)sample_delta / compensation_distance; | |||
| @@ -322,7 +308,7 @@ int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensatio | |||
| #endif // HAVE_MMXEXT_INLINE | |||
| int swri_multiple_resample(ResampleContext *c, AudioData *dst, int dst_size, AudioData *src, int src_size, int *consumed){ | |||
| static int multiple_resample(ResampleContext *c, AudioData *dst, int dst_size, AudioData *src, int src_size, int *consumed){ | |||
| int i, ret= -1; | |||
| int av_unused mm_flags = av_get_cpu_flags(); | |||
| int need_emms= 0; | |||
| @@ -348,17 +334,20 @@ int swri_multiple_resample(ResampleContext *c, AudioData *dst, int dst_size, Aud | |||
| return ret; | |||
| } | |||
| int64_t swr_get_delay(struct SwrContext *s, int64_t base){ | |||
| static int64_t get_delay(struct SwrContext *s, int64_t base){ | |||
| ResampleContext *c = s->resample; | |||
| if(c){ | |||
| int64_t num = s->in_buffer_count - (c->filter_length-1)/2; | |||
| num <<= c->phase_shift; | |||
| num -= c->index; | |||
| num *= c->src_incr; | |||
| num -= c->frac; | |||
| return av_rescale(num, base, s->in_sample_rate*(int64_t)c->src_incr << c->phase_shift); | |||
| }else{ | |||
| return (s->in_buffer_count*base + (s->in_sample_rate>>1))/ s->in_sample_rate; | |||
| } | |||
| int64_t num = s->in_buffer_count - (c->filter_length-1)/2; | |||
| num <<= c->phase_shift; | |||
| num -= c->index; | |||
| num *= c->src_incr; | |||
| num -= c->frac; | |||
| return av_rescale(num, base, s->in_sample_rate*(int64_t)c->src_incr << c->phase_shift); | |||
| } | |||
| struct Resampler const swri_resampler={ | |||
| resample_init, | |||
| resample_free, | |||
| multiple_resample, | |||
| set_compensation, | |||
| get_delay, | |||
| }; | |||
| @@ -84,6 +84,8 @@ static const AVOption options[]={ | |||
| {"phase_shift" , "set resampling phase shift" , OFFSET(phase_shift) , AV_OPT_TYPE_INT , {.i64=10 }, 0 , 30 , PARAM }, | |||
| {"linear_interp" , "enable linear interpolation" , OFFSET(linear_interp) , AV_OPT_TYPE_INT , {.i64=0 }, 0 , 1 , PARAM }, | |||
| {"cutoff" , "set cutoff frequency ratio" , OFFSET(cutoff) , AV_OPT_TYPE_DOUBLE,{.dbl=0.8 }, 0 , 1 , PARAM }, | |||
| {"resampler" , "set resampling Engine" , OFFSET(engine) , AV_OPT_TYPE_INT , {.i64=0 }, 0 , SWR_ENGINE_NB-1, PARAM, "resampler"}, | |||
| {"swr" , "select SW Resampler" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_ENGINE_SWR }, INT_MIN, INT_MAX , PARAM, "resampler"}, | |||
| {"min_comp" , "set minimum difference between timestamps and audio data (in seconds) below which no timestamp compensation of either kind is applied" | |||
| , OFFSET(min_compensation),AV_OPT_TYPE_FLOAT ,{.dbl=FLT_MAX }, 0 , FLT_MAX , PARAM }, | |||
| {"min_hard_comp" , "set minimum difference between timestamps and audio data (in seconds) to trigger padding/trimming the data." | |||
| @@ -205,7 +207,8 @@ av_cold void swr_free(SwrContext **ss){ | |||
| swri_audio_convert_free(&s-> in_convert); | |||
| swri_audio_convert_free(&s->out_convert); | |||
| swri_audio_convert_free(&s->full_convert); | |||
| swri_resample_free(&s->resample); | |||
| if (s->resampler) | |||
| s->resampler->free(&s->resample); | |||
| swri_rematrix_free(s); | |||
| } | |||
| @@ -258,13 +261,20 @@ av_cold int swr_init(struct SwrContext *s){ | |||
| return AVERROR(EINVAL); | |||
| } | |||
| switch(s->engine){ | |||
| case SWR_ENGINE_SWR : s->resampler = &swri_resampler; break; | |||
| default: | |||
| av_log(s, AV_LOG_ERROR, "Requested resampling engine is unavailable\n"); | |||
| return AVERROR(EINVAL); | |||
| } | |||
| set_audiodata_fmt(&s-> in, s-> in_sample_fmt); | |||
| set_audiodata_fmt(&s->out, s->out_sample_fmt); | |||
| if (s->out_sample_rate!=s->in_sample_rate || (s->flags & SWR_FLAG_RESAMPLE)){ | |||
| s->resample = swri_resample_init(s->resample, s->out_sample_rate, s->in_sample_rate, s->filter_size, s->phase_shift, s->linear_interp, s->cutoff, s->int_sample_fmt, s->filter_type, s->kaiser_beta); | |||
| s->resample = s->resampler->init(s->resample, s->out_sample_rate, s->in_sample_rate, s->filter_size, s->phase_shift, s->linear_interp, s->cutoff, s->int_sample_fmt, s->filter_type, s->kaiser_beta); | |||
| }else | |||
| swri_resample_free(&s->resample); | |||
| s->resampler->free(&s->resample); | |||
| if( s->int_sample_fmt != AV_SAMPLE_FMT_S16P | |||
| && s->int_sample_fmt != AV_SAMPLE_FMT_S32P | |||
| && s->int_sample_fmt != AV_SAMPLE_FMT_FLTP | |||
| @@ -463,7 +473,7 @@ static int resample(SwrContext *s, AudioData *out_param, int out_count, | |||
| int ret, size, consumed; | |||
| if(!s->resample_in_constraint && s->in_buffer_count){ | |||
| buf_set(&tmp, &s->in_buffer, s->in_buffer_index); | |||
| ret= swri_multiple_resample(s->resample, &out, out_count, &tmp, s->in_buffer_count, &consumed); | |||
| ret= s->resampler->multiple_resample(s->resample, &out, out_count, &tmp, s->in_buffer_count, &consumed); | |||
| out_count -= ret; | |||
| ret_sum += ret; | |||
| buf_set(&out, &out, ret); | |||
| @@ -483,7 +493,7 @@ static int resample(SwrContext *s, AudioData *out_param, int out_count, | |||
| if(in_count && !s->in_buffer_count){ | |||
| s->in_buffer_index=0; | |||
| ret= swri_multiple_resample(s->resample, &out, out_count, &in, in_count, &consumed); | |||
| ret= s->resampler->multiple_resample(s->resample, &out, out_count, &in, in_count, &consumed); | |||
| out_count -= ret; | |||
| ret_sum += ret; | |||
| buf_set(&out, &out, ret); | |||
| @@ -771,6 +781,34 @@ int swr_inject_silence(struct SwrContext *s, int count){ | |||
| return ret; | |||
| } | |||
| int64_t swr_get_delay(struct SwrContext *s, int64_t base){ | |||
| if (s->resampler && s->resample){ | |||
| return s->resampler->get_delay(s, base); | |||
| }else{ | |||
| return (s->in_buffer_count*base + (s->in_sample_rate>>1))/ s->in_sample_rate; | |||
| } | |||
| } | |||
| int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensation_distance){ | |||
| int ret; | |||
| if (!s || compensation_distance < 0) | |||
| return AVERROR(EINVAL); | |||
| if (!compensation_distance && sample_delta) | |||
| return AVERROR(EINVAL); | |||
| if (!s->resample) { | |||
| s->flags |= SWR_FLAG_RESAMPLE; | |||
| ret = swr_init(s); | |||
| if (ret < 0) | |||
| return ret; | |||
| } | |||
| if (!s->resampler->set_compensation){ | |||
| return AVERROR(EINVAL); | |||
| }else{ | |||
| return s->resampler->set_compensation(s->resample, sample_delta, compensation_distance); | |||
| } | |||
| } | |||
| int64_t swr_next_pts(struct SwrContext *s, int64_t pts){ | |||
| if(pts == INT64_MIN) | |||
| return s->outpts; | |||
| @@ -114,6 +114,12 @@ enum SwrDitherType { | |||
| SWR_DITHER_NB, ///< not part of API/ABI | |||
| }; | |||
| /** Resampling Engines */ | |||
| enum SwrEngine { | |||
| SWR_ENGINE_SWR, /**< SW Resampler */ | |||
| SWR_ENGINE_NB, ///< not part of API/ABI | |||
| }; | |||
| /** Resampling Filter Types */ | |||
| enum SwrFilterType { | |||
| SWR_FILTER_TYPE_CUBIC, /**< Cubic */ | |||
| @@ -67,6 +67,7 @@ struct SwrContext { | |||
| enum AVMatrixEncoding matrix_encoding; /**< matrixed stereo encoding */ | |||
| const int *channel_map; ///< channel index (or -1 if muted channel) map | |||
| int used_ch_count; ///< number of used input channels (mapped channel count if channel_map, otherwise in.ch_count) | |||
| enum SwrEngine engine; | |||
| enum SwrDitherType dither_method; | |||
| int dither_pos; | |||
| float dither_scale; | |||
| @@ -104,6 +105,7 @@ struct SwrContext { | |||
| struct AudioConvert *out_convert; ///< output conversion context | |||
| struct AudioConvert *full_convert; ///< full conversion context (single conversion for input and output) | |||
| struct ResampleContext *resample; ///< resampling context | |||
| struct Resampler const *resampler; ///< resampler virtual function table | |||
| float matrix[SWR_CH_MAX][SWR_CH_MAX]; ///< floating point rematrixing coefficients | |||
| uint8_t *native_matrix; | |||
| @@ -122,10 +124,23 @@ struct SwrContext { | |||
| /* TODO: callbacks for ASM optimizations */ | |||
| }; | |||
| struct ResampleContext *swri_resample_init(struct ResampleContext *, int out_rate, int in_rate, int filter_size, int phase_shift, int linear, double cutoff, enum AVSampleFormat, enum SwrFilterType, int kaiser_beta); | |||
| void swri_resample_free(struct ResampleContext **c); | |||
| int swri_multiple_resample(struct ResampleContext *c, AudioData *dst, int dst_size, AudioData *src, int src_size, int *consumed); | |||
| void swri_resample_compensate(struct ResampleContext *c, int sample_delta, int compensation_distance); | |||
| typedef struct ResampleContext * (* resample_init_func)(struct ResampleContext *c, int out_rate, int in_rate, int filter_size, int phase_shift, int linear, | |||
| double cutoff, enum AVSampleFormat format, enum SwrFilterType filter_type, int kaiser_beta); | |||
| typedef void (* resample_free_func)(struct ResampleContext **c); | |||
| typedef int (* multiple_resample_func)(struct ResampleContext *c, AudioData *dst, int dst_size, AudioData *src, int src_size, int *consumed); | |||
| typedef int (* set_compensation_func)(struct ResampleContext *c, int sample_delta, int compensation_distance); | |||
| typedef int64_t (* get_delay_func)(struct SwrContext *s, int64_t base); | |||
| struct Resampler { | |||
| resample_init_func init; | |||
| resample_free_func free; | |||
| multiple_resample_func multiple_resample; | |||
| set_compensation_func set_compensation; | |||
| get_delay_func get_delay; | |||
| }; | |||
| extern struct Resampler const swri_resampler; | |||
| int swri_resample_int16(struct ResampleContext *c, int16_t *dst, const int16_t *src, int *consumed, int src_size, int dst_size, int update_ctx); | |||
| int swri_resample_int32(struct ResampleContext *c, int32_t *dst, const int32_t *src, int *consumed, int src_size, int dst_size, int update_ctx); | |||
| int swri_resample_float(struct ResampleContext *c, float *dst, const float *src, int *consumed, int src_size, int dst_size, int update_ctx); | |||