mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
swr: Add API to make resample engine selectable.
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
parent
e8e575633f
commit
5a5d70748c
@ -195,7 +195,7 @@ static int build_filter(ResampleContext *c, void *filter, double factor, int tap
|
|||||||
return 0;
|
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 cutoff, enum AVSampleFormat format, enum SwrFilterType filter_type, int kaiser_beta){
|
||||||
double factor= FFMIN(out_rate * cutoff / in_rate, 1.0);
|
double factor= FFMIN(out_rate * cutoff / in_rate, 1.0);
|
||||||
int phase_count= 1<<phase_shift;
|
int phase_count= 1<<phase_shift;
|
||||||
@ -259,28 +259,14 @@ error:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void swri_resample_free(ResampleContext **c){
|
static void resample_free(ResampleContext **c){
|
||||||
if(!*c)
|
if(!*c)
|
||||||
return;
|
return;
|
||||||
av_freep(&(*c)->filter_bank);
|
av_freep(&(*c)->filter_bank);
|
||||||
av_freep(c);
|
av_freep(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensation_distance){
|
static int set_compensation(ResampleContext *c, 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;
|
|
||||||
c->compensation_distance= compensation_distance;
|
c->compensation_distance= compensation_distance;
|
||||||
if (compensation_distance)
|
if (compensation_distance)
|
||||||
c->dst_incr = c->ideal_dst_incr - c->ideal_dst_incr * (int64_t)sample_delta / 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
|
#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 i, ret= -1;
|
||||||
int av_unused mm_flags = av_get_cpu_flags();
|
int av_unused mm_flags = av_get_cpu_flags();
|
||||||
int need_emms= 0;
|
int need_emms= 0;
|
||||||
@ -348,17 +334,20 @@ int swri_multiple_resample(ResampleContext *c, AudioData *dst, int dst_size, Aud
|
|||||||
return ret;
|
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;
|
ResampleContext *c = s->resample;
|
||||||
if(c){
|
int64_t num = s->in_buffer_count - (c->filter_length-1)/2;
|
||||||
int64_t num = s->in_buffer_count - (c->filter_length-1)/2;
|
num <<= c->phase_shift;
|
||||||
num <<= c->phase_shift;
|
num -= c->index;
|
||||||
num -= c->index;
|
num *= c->src_incr;
|
||||||
num *= c->src_incr;
|
num -= c->frac;
|
||||||
num -= c->frac;
|
return av_rescale(num, base, s->in_sample_rate*(int64_t)c->src_incr << c->phase_shift);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 },
|
{"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 },
|
{"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 },
|
{"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"
|
{"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 },
|
, 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."
|
{"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-> in_convert);
|
||||||
swri_audio_convert_free(&s->out_convert);
|
swri_audio_convert_free(&s->out_convert);
|
||||||
swri_audio_convert_free(&s->full_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);
|
swri_rematrix_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,13 +261,20 @@ av_cold int swr_init(struct SwrContext *s){
|
|||||||
return AVERROR(EINVAL);
|
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-> in, s-> in_sample_fmt);
|
||||||
set_audiodata_fmt(&s->out, s->out_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)){
|
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
|
}else
|
||||||
swri_resample_free(&s->resample);
|
s->resampler->free(&s->resample);
|
||||||
if( s->int_sample_fmt != AV_SAMPLE_FMT_S16P
|
if( s->int_sample_fmt != AV_SAMPLE_FMT_S16P
|
||||||
&& s->int_sample_fmt != AV_SAMPLE_FMT_S32P
|
&& s->int_sample_fmt != AV_SAMPLE_FMT_S32P
|
||||||
&& s->int_sample_fmt != AV_SAMPLE_FMT_FLTP
|
&& 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;
|
int ret, size, consumed;
|
||||||
if(!s->resample_in_constraint && s->in_buffer_count){
|
if(!s->resample_in_constraint && s->in_buffer_count){
|
||||||
buf_set(&tmp, &s->in_buffer, s->in_buffer_index);
|
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;
|
out_count -= ret;
|
||||||
ret_sum += ret;
|
ret_sum += ret;
|
||||||
buf_set(&out, &out, 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){
|
if(in_count && !s->in_buffer_count){
|
||||||
s->in_buffer_index=0;
|
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;
|
out_count -= ret;
|
||||||
ret_sum += ret;
|
ret_sum += ret;
|
||||||
buf_set(&out, &out, ret);
|
buf_set(&out, &out, ret);
|
||||||
@ -771,6 +781,34 @@ int swr_inject_silence(struct SwrContext *s, int count){
|
|||||||
return ret;
|
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){
|
int64_t swr_next_pts(struct SwrContext *s, int64_t pts){
|
||||||
if(pts == INT64_MIN)
|
if(pts == INT64_MIN)
|
||||||
return s->outpts;
|
return s->outpts;
|
||||||
|
@ -114,6 +114,12 @@ enum SwrDitherType {
|
|||||||
SWR_DITHER_NB, ///< not part of API/ABI
|
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 */
|
/** Resampling Filter Types */
|
||||||
enum SwrFilterType {
|
enum SwrFilterType {
|
||||||
SWR_FILTER_TYPE_CUBIC, /**< Cubic */
|
SWR_FILTER_TYPE_CUBIC, /**< Cubic */
|
||||||
|
@ -67,6 +67,7 @@ struct SwrContext {
|
|||||||
enum AVMatrixEncoding matrix_encoding; /**< matrixed stereo encoding */
|
enum AVMatrixEncoding matrix_encoding; /**< matrixed stereo encoding */
|
||||||
const int *channel_map; ///< channel index (or -1 if muted channel) map
|
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)
|
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;
|
enum SwrDitherType dither_method;
|
||||||
int dither_pos;
|
int dither_pos;
|
||||||
float dither_scale;
|
float dither_scale;
|
||||||
@ -104,6 +105,7 @@ struct SwrContext {
|
|||||||
struct AudioConvert *out_convert; ///< output conversion context
|
struct AudioConvert *out_convert; ///< output conversion context
|
||||||
struct AudioConvert *full_convert; ///< full conversion context (single conversion for input and output)
|
struct AudioConvert *full_convert; ///< full conversion context (single conversion for input and output)
|
||||||
struct ResampleContext *resample; ///< resampling context
|
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
|
float matrix[SWR_CH_MAX][SWR_CH_MAX]; ///< floating point rematrixing coefficients
|
||||||
uint8_t *native_matrix;
|
uint8_t *native_matrix;
|
||||||
@ -122,10 +124,23 @@ struct SwrContext {
|
|||||||
/* TODO: callbacks for ASM optimizations */
|
/* 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);
|
typedef struct ResampleContext * (* resample_init_func)(struct ResampleContext *c, int out_rate, int in_rate, int filter_size, int phase_shift, int linear,
|
||||||
void swri_resample_free(struct ResampleContext **c);
|
double cutoff, enum AVSampleFormat format, enum SwrFilterType filter_type, int kaiser_beta);
|
||||||
int swri_multiple_resample(struct ResampleContext *c, AudioData *dst, int dst_size, AudioData *src, int src_size, int *consumed);
|
typedef void (* resample_free_func)(struct ResampleContext **c);
|
||||||
void swri_resample_compensate(struct ResampleContext *c, int sample_delta, int compensation_distance);
|
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_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_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);
|
int swri_resample_float(struct ResampleContext *c, float *dst, const float *src, int *consumed, int src_size, int dst_size, int update_ctx);
|
||||||
|
Loading…
Reference in New Issue
Block a user