|
|
|
@ -31,36 +31,42 @@ typedef struct AudioSDRContext { |
|
|
|
|
double *sum_uv; |
|
|
|
|
|
|
|
|
|
AVFrame *cache[2]; |
|
|
|
|
} AudioSDRContext; |
|
|
|
|
|
|
|
|
|
static int sdr(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) |
|
|
|
|
{ |
|
|
|
|
AudioSDRContext *s = ctx->priv; |
|
|
|
|
AVFrame *u = s->cache[0]; |
|
|
|
|
AVFrame *v = s->cache[1]; |
|
|
|
|
const int channels = u->ch_layout.nb_channels; |
|
|
|
|
const int start = (channels * jobnr) / nb_jobs; |
|
|
|
|
const int end = (channels * (jobnr+1)) / nb_jobs; |
|
|
|
|
const int nb_samples = u->nb_samples; |
|
|
|
|
|
|
|
|
|
for (int ch = start; ch < end; ch++) { |
|
|
|
|
const double *const us = (double *)u->extended_data[ch]; |
|
|
|
|
const double *const vs = (double *)v->extended_data[ch]; |
|
|
|
|
double sum_uv = 0.; |
|
|
|
|
double sum_u = 0.; |
|
|
|
|
|
|
|
|
|
for (int n = 0; n < nb_samples; n++) { |
|
|
|
|
sum_u += us[n] * us[n]; |
|
|
|
|
sum_uv += (us[n] - vs[n]) * (us[n] - vs[n]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
s->sum_uv[ch] += sum_uv; |
|
|
|
|
s->sum_u[ch] += sum_u; |
|
|
|
|
} |
|
|
|
|
int (*filter)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); |
|
|
|
|
} AudioSDRContext; |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
#define SDR_FILTER(name, type) \ |
|
|
|
|
static int sdr_##name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)\
|
|
|
|
|
{ \
|
|
|
|
|
AudioSDRContext *s = ctx->priv; \
|
|
|
|
|
AVFrame *u = s->cache[0]; \
|
|
|
|
|
AVFrame *v = s->cache[1]; \
|
|
|
|
|
const int channels = u->ch_layout.nb_channels; \
|
|
|
|
|
const int start = (channels * jobnr) / nb_jobs; \
|
|
|
|
|
const int end = (channels * (jobnr+1)) / nb_jobs; \
|
|
|
|
|
const int nb_samples = u->nb_samples; \
|
|
|
|
|
\
|
|
|
|
|
for (int ch = start; ch < end; ch++) { \
|
|
|
|
|
const type *const us = (type *)u->extended_data[ch]; \
|
|
|
|
|
const type *const vs = (type *)v->extended_data[ch]; \
|
|
|
|
|
double sum_uv = 0.; \
|
|
|
|
|
double sum_u = 0.; \
|
|
|
|
|
\
|
|
|
|
|
for (int n = 0; n < nb_samples; n++) { \
|
|
|
|
|
sum_u += us[n] * us[n]; \
|
|
|
|
|
sum_uv += (us[n] - vs[n]) * (us[n] - vs[n]); \
|
|
|
|
|
} \
|
|
|
|
|
\
|
|
|
|
|
s->sum_uv[ch] += sum_uv; \
|
|
|
|
|
s->sum_u[ch] += sum_u; \
|
|
|
|
|
} \
|
|
|
|
|
\
|
|
|
|
|
return 0; \
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
SDR_FILTER(fltp, float) |
|
|
|
|
SDR_FILTER(dblp, double) |
|
|
|
|
|
|
|
|
|
static int activate(AVFilterContext *ctx) |
|
|
|
|
{ |
|
|
|
|
AudioSDRContext *s = ctx->priv; |
|
|
|
@ -84,7 +90,7 @@ static int activate(AVFilterContext *ctx) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!ctx->is_disabled) |
|
|
|
|
ff_filter_execute(ctx, sdr, NULL, NULL, |
|
|
|
|
ff_filter_execute(ctx, s->filter, NULL, NULL, |
|
|
|
|
FFMIN(outlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); |
|
|
|
|
|
|
|
|
|
av_frame_free(&s->cache[1]); |
|
|
|
@ -120,6 +126,7 @@ static int config_output(AVFilterLink *outlink) |
|
|
|
|
AudioSDRContext *s = ctx->priv; |
|
|
|
|
|
|
|
|
|
s->channels = inlink->ch_layout.nb_channels; |
|
|
|
|
s->filter = inlink->format == AV_SAMPLE_FMT_FLTP ? sdr_fltp : sdr_dblp; |
|
|
|
|
|
|
|
|
|
s->sum_u = av_calloc(outlink->ch_layout.nb_channels, sizeof(*s->sum_u)); |
|
|
|
|
s->sum_uv = av_calloc(outlink->ch_layout.nb_channels, sizeof(*s->sum_uv)); |
|
|
|
@ -173,5 +180,6 @@ const AVFilter ff_af_asdr = { |
|
|
|
|
AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, |
|
|
|
|
FILTER_INPUTS(inputs), |
|
|
|
|
FILTER_OUTPUTS(outputs), |
|
|
|
|
FILTER_SINGLE_SAMPLEFMT(AV_SAMPLE_FMT_DBLP), |
|
|
|
|
FILTER_SAMPLEFMTS(AV_SAMPLE_FMT_FLTP, |
|
|
|
|
AV_SAMPLE_FMT_DBLP), |
|
|
|
|
}; |
|
|
|
|