History

avfilter/af_axcorrelate: add another algorithm for calculation

Rewrite EOF logic while here.

Paul B Mahol committed 3 years ago

Commit c183f841 parent f0322342 files · +114 −33Browse files

Showing the changes to libavfilter (1 of 2 files). Show all

Unified · Split

libavfilter/af_axcorrelate.c+112−31
@@ -110,7 +110,7 @@ static int xcorrelate_slow_##suffix(AVFilterContext *ctx, \ · 109 unmodified lines
110 AVFrame *out, int available) \110 AVFrame *out, int available) \
111{ \111{ \
112 AudioXCorrelateContext *s = ctx->priv; \112 AudioXCorrelateContext *s = ctx->priv; \
113 const int size = FFMIN(available, s->size); \113 const int size = s->size; \
114 int used; \114 int used; \
115 \115 \
116 for (int ch = 0; ch < out->ch_layout.nb_channels; ch++) { \116 for (int ch = 0; ch < out->ch_layout.nb_channels; ch++) { \
@@ -127,13 +127,13 @@ static int xcorrelate_slow_##suffix(AVFilterContext *ctx, \ · 10 unmodified lines
127 used = 1; \127 used = 1; \
128 } \128 } \
129 \129 \
130 for (int n = 0; n < out->nb_samples; n++) { \130 for (int n = 0; n < out->nb_samples; n++) { \
131 const int idx = available <= s->size ? out->nb_samples - n - 1 : n + size; \131 const int idx = n + size; \
132 \132 \
133 dst[n] = xcorrelate_##suffix(x + n, y + n, \133 dst[n] = xcorrelate_##suffix(x + n, y + n, \
134 sumx[0], sumy[0], \134 sumx[0], sumy[0],\
135 size); \135 size); \
136 \136 \
137 sumx[0] -= x[n]; \137 sumx[0] -= x[n]; \
138 sumx[0] += x[idx]; \138 sumx[0] += x[idx]; \
139 sumy[0] -= y[n]; \139 sumy[0] -= y[n]; \
@@ -147,12 +147,15 @@ static int xcorrelate_slow_##suffix(AVFilterContext *ctx, \ · 7 unmodified lines
147XCORRELATE_SLOW(f, float)147XCORRELATE_SLOW(f, float)
148XCORRELATE_SLOW(d, double)148XCORRELATE_SLOW(d, double)
149 149
150#define XCORRELATE_FAST(suffix, type, zero, small, sqrtfun) \150#define clipf(x) (av_clipf(x, -1.f, 1.f))
151#define clipd(x) (av_clipd(x, -1.0, 1.0))
152
153#define XCORRELATE_FAST(suffix, type, zero, small, sqrtfun, CLIP) \
151static int xcorrelate_fast_##suffix(AVFilterContext *ctx, AVFrame *out, \154static int xcorrelate_fast_##suffix(AVFilterContext *ctx, AVFrame *out, \
152 int available) \155 int available) \
153{ \156{ \
154 AudioXCorrelateContext *s = ctx->priv; \157 AudioXCorrelateContext *s = ctx->priv; \
155 const int size = FFMIN(available, s->size); \158 const int size = s->size; \
156 int used; \159 int used; \
157 \160 \
158 for (int ch = 0; ch < out->ch_layout.nb_channels; ch++) { \161 for (int ch = 0; ch < out->ch_layout.nb_channels; ch++) { \
@@ -171,14 +174,14 @@ static int xcorrelate_fast_##suffix(AVFilterContext *ctx, AVFrame *out, \ · 12 unmodified lines
171 used = 1; \174 used = 1; \
172 } \175 } \
173 \176 \
174 for (int n = 0; n < out->nb_samples; n++) { \177 for (int n = 0; n < out->nb_samples; n++) { \
175 const int idx = available <= s->size ? out->nb_samples - n - 1 : n + size; \178 const int idx = n + size; \
176 type num, den; \179 type num, den; \
177 \180 \
178 num = num_sum[0] / size; \181 num = num_sum[0] / size; \
179 den = sqrtfun((den_sumx[0] * den_sumy[0]) / size / size); \182 den = sqrtfun((den_sumx[0] * den_sumy[0]) / size / size); \
180 \183 \
181 dst[n] = den <= small ? zero : num / den; \184 dst[n] = den <= small ? zero : CLIP(num / den); \
182 \185 \
183 num_sum[0] -= x[n] * y[n]; \186 num_sum[0] -= x[n] * y[n]; \
184 num_sum[0] += x[idx] * y[idx]; \187 num_sum[0] += x[idx] * y[idx]; \
@@ -194,20 +197,82 @@ static int xcorrelate_fast_##suffix(AVFilterContext *ctx, AVFrame *out, \ · 9 unmodified lines
194 return used; \197 return used; \
195}198}
196 199
197XCORRELATE_FAST(f, float, 0.f, 1e-6f, sqrtf)200XCORRELATE_FAST(f, float, 0.f, 1e-6f, sqrtf, clipf)
198XCORRELATE_FAST(d, double, 0.0, 1e-9, sqrt)201XCORRELATE_FAST(d, double, 0.0, 1e-9, sqrt, clipd)
202
203#define XCORRELATE_BEST(suffix, type, zero, small, sqrtfun, FMAX, CLIP) \
204static int xcorrelate_best_##suffix(AVFilterContext *ctx, AVFrame *out, \
205 int available) \
206{ \
207 AudioXCorrelateContext *s = ctx->priv; \
208 const int size = s->size; \
209 int used; \
210 \
211 for (int ch = 0; ch < out->ch_layout.nb_channels; ch++) { \
212 const type *x = (const type *)s->cache[0]->extended_data[ch]; \
213 const type *y = (const type *)s->cache[1]->extended_data[ch]; \
214 type *mean_sumx = (type *)s->mean_sum[0]->extended_data[ch]; \
215 type *mean_sumy = (type *)s->mean_sum[1]->extended_data[ch]; \
216 type *num_sum = (type *)s->num_sum->extended_data[ch]; \
217 type *den_sumx = (type *)s->den_sum[0]->extended_data[ch]; \
218 type *den_sumy = (type *)s->den_sum[1]->extended_data[ch]; \
219 type *dst = (type *)out->extended_data[ch]; \
220 \
221 used = s->used; \
222 if (!used) { \
223 num_sum[0] = square_sum_##suffix(x, y, size); \
224 den_sumx[0] = square_sum_##suffix(x, x, size); \
225 den_sumy[0] = square_sum_##suffix(y, y, size); \
226 mean_sumx[0] = mean_sum_##suffix(x, size); \
227 mean_sumy[0] = mean_sum_##suffix(y, size); \
228 used = 1; \
229 } \
230 \
231 for (int n = 0; n < out->nb_samples; n++) { \
232 const int idx = n + size; \
233 type num, den, xm, ym; \
234 \
235 xm = mean_sumx[0] / size; \
236 ym = mean_sumy[0] / size; \
237 num = num_sum[0] - size * xm * ym; \
238 den = sqrtfun(FMAX(den_sumx[0] - size * xm * xm, zero)) * \
239 sqrtfun(FMAX(den_sumy[0] - size * ym * ym, zero)); \
240 \
241 dst[n] = den <= small ? zero : CLIP(num / den); \
242 \
243 mean_sumx[0]-= x[n]; \
244 mean_sumx[0]+= x[idx]; \
245 mean_sumy[0]-= y[n]; \
246 mean_sumy[0]+= y[idx]; \
247 num_sum[0] -= x[n] * y[n]; \
248 num_sum[0] += x[idx] * y[idx]; \
249 den_sumx[0] -= x[n] * x[n]; \
250 den_sumx[0] += x[idx] * x[idx]; \
251 den_sumx[0] = FMAX(den_sumx[0], zero); \
252 den_sumy[0] -= y[n] * y[n]; \
253 den_sumy[0] += y[idx] * y[idx]; \
254 den_sumy[0] = FMAX(den_sumy[0], zero); \
255 } \
256 } \
257 \
258 return used; \
259}
260
261XCORRELATE_BEST(f, float, 0.f, 1e-6f, sqrtf, fmaxf, clipf)
262XCORRELATE_BEST(d, double, 0.0, 1e-9, sqrt, fmax, clipd)
199 263
200static int activate(AVFilterContext *ctx)264static int activate(AVFilterContext *ctx)
201{265{
202 AudioXCorrelateContext *s = ctx->priv;266 AudioXCorrelateContext *s = ctx->priv;
267 AVFilterLink *outlink = ctx->outputs[0];
203 AVFrame *frame = NULL;268 AVFrame *frame = NULL;
204 int ret, status;269 int ret, status;
205 int available;270 int available;
206 int64_t pts;271 int64_t pts;
207 272
208 FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[0], ctx);273 FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, ctx);
209 274
210 for (int i = 0; i < 2; i++) {275 for (int i = 0; i < 2 && !s->eof; i++) {
211 ret = ff_inlink_consume_frame(ctx->inputs[i], &frame);276 ret = ff_inlink_consume_frame(ctx->inputs[i], &frame);
212 if (ret > 0) {277 if (ret > 0) {
213 if (s->pts == AV_NOPTS_VALUE)278 if (s->pts == AV_NOPTS_VALUE)
@@ -221,20 +286,20 @@ static int activate(AVFilterContext *ctx) · 7 unmodified lines
221 }286 }
222 287
223 available = FFMIN(av_audio_fifo_size(s->fifo[0]), av_audio_fifo_size(s->fifo[1]));288 available = FFMIN(av_audio_fifo_size(s->fifo[0]), av_audio_fifo_size(s->fifo[1]));
224 if (available > s->size || (s->eof && available > 0)) {289 if (available > s->size) {
225 const int out_samples = s->eof ? available : available - s->size;290 const int out_samples = available - s->size;
226 AVFrame *out;291 AVFrame *out;
227 292
228 if (!s->cache[0] || s->cache[0]->nb_samples < available) {293 if (!s->cache[0] || s->cache[0]->nb_samples < available) {
229 av_frame_free(&s->cache[0]);294 av_frame_free(&s->cache[0]);
230 s->cache[0] = ff_get_audio_buffer(ctx->outputs[0], available);295 s->cache[0] = ff_get_audio_buffer(outlink, available);
231 if (!s->cache[0])296 if (!s->cache[0])
232 return AVERROR(ENOMEM);297 return AVERROR(ENOMEM);
233 }298 }
234 299
235 if (!s->cache[1] || s->cache[1]->nb_samples < available) {300 if (!s->cache[1] || s->cache[1]->nb_samples < available) {
236 av_frame_free(&s->cache[1]);301 av_frame_free(&s->cache[1]);
237 s->cache[1] = ff_get_audio_buffer(ctx->outputs[0], available);302 s->cache[1] = ff_get_audio_buffer(outlink, available);
238 if (!s->cache[1])303 if (!s->cache[1])
239 return AVERROR(ENOMEM);304 return AVERROR(ENOMEM);
240 }305 }
@@ -247,7 +312,7 @@ static int activate(AVFilterContext *ctx) · 6 unmodified lines
247 if (ret < 0)312 if (ret < 0)
248 return ret;313 return ret;
249 314
250 out = ff_get_audio_buffer(ctx->outputs[0], out_samples);315 out = ff_get_audio_buffer(outlink, out_samples);
251 if (!out)316 if (!out)
252 return AVERROR(ENOMEM);317 return AVERROR(ENOMEM);
253 318
@@ -259,18 +324,31 @@ static int activate(AVFilterContext *ctx) · 5 unmodified lines
259 av_audio_fifo_drain(s->fifo[0], out_samples);324 av_audio_fifo_drain(s->fifo[0], out_samples);
260 av_audio_fifo_drain(s->fifo[1], out_samples);325 av_audio_fifo_drain(s->fifo[1], out_samples);
261 326
262 return ff_filter_frame(ctx->outputs[0], out);327 return ff_filter_frame(outlink, out);
263 }328 }
264 329
265 for (int i = 0; i < 2 && !s->eof; i++) {330 for (int i = 0; i < 2 && !s->eof; i++) {
266 if (ff_inlink_acknowledge_status(ctx->inputs[i], &status, &pts))331 if (ff_inlink_acknowledge_status(ctx->inputs[i], &status, &pts)) {
332 AVFrame *silence = ff_get_audio_buffer(outlink, s->size);
333
267 s->eof = 1;334 s->eof = 1;
335 if (!silence)
336 return AVERROR(ENOMEM);
337
338 av_audio_fifo_write(s->fifo[0], (void **)silence->extended_data,
339 silence->nb_samples);
340
341 av_audio_fifo_write(s->fifo[1], (void **)silence->extended_data,
342 silence->nb_samples);
343
344 av_frame_free(&silence);
345 }
268 }346 }
269 347
270 if (s->eof &&348 if (s->eof &&
271 (av_audio_fifo_size(s->fifo[0]) <= 0 ||349 (av_audio_fifo_size(s->fifo[0]) <= s->size ||
272 av_audio_fifo_size(s->fifo[1]) <= 0)) {350 av_audio_fifo_size(s->fifo[1]) <= s->size)) {
273 ff_outlink_set_status(ctx->outputs[0], AVERROR_EOF, s->pts);351 ff_outlink_set_status(outlink, AVERROR_EOF, s->pts);
274 return 0;352 return 0;
275 }353 }
276 354
@@ -280,7 +358,7 @@ static int activate(AVFilterContext *ctx) · 3 unmodified lines
280 return 0;358 return 0;
281 }359 }
282 360
283 if (ff_outlink_frame_wanted(ctx->outputs[0]) && !s->eof) {361 if (ff_outlink_frame_wanted(outlink) && !s->eof) {
284 for (int i = 0; i < 2; i++) {362 for (int i = 0; i < 2; i++) {
285 if (av_audio_fifo_size(s->fifo[i]) > s->size)363 if (av_audio_fifo_size(s->fifo[i]) > s->size)
286 continue;364 continue;
@@ -316,12 +394,14 @@ static int config_output(AVFilterLink *outlink) · 29 unmodified lines
316 switch (s->algo) {394 switch (s->algo) {
317 case 0: s->xcorrelate = xcorrelate_slow_f; break;395 case 0: s->xcorrelate = xcorrelate_slow_f; break;
318 case 1: s->xcorrelate = xcorrelate_fast_f; break;396 case 1: s->xcorrelate = xcorrelate_fast_f; break;
397 case 2: s->xcorrelate = xcorrelate_best_f; break;
319 }398 }
320 399
321 if (outlink->format == AV_SAMPLE_FMT_DBLP) {400 if (outlink->format == AV_SAMPLE_FMT_DBLP) {
322 switch (s->algo) {401 switch (s->algo) {
323 case 0: s->xcorrelate = xcorrelate_slow_d; break;402 case 0: s->xcorrelate = xcorrelate_slow_d; break;
324 case 1: s->xcorrelate = xcorrelate_fast_d; break;403 case 1: s->xcorrelate = xcorrelate_fast_d; break;
404 case 2: s->xcorrelate = xcorrelate_best_d; break;
325 }405 }
326 }406 }
327 407
@@ -366,10 +446,11 @@ static const AVFilterPad outputs[] = { · 38 unmodified lines
366#define OFFSET(x) offsetof(AudioXCorrelateContext, x)446#define OFFSET(x) offsetof(AudioXCorrelateContext, x)
367 447
368static const AVOption axcorrelate_options[] = {448static const AVOption axcorrelate_options[] = {
369 { "size", "set segment size", OFFSET(size), AV_OPT_TYPE_INT, {.i64=256}, 2, 131072, AF },449 { "size", "set the segment size", OFFSET(size), AV_OPT_TYPE_INT, {.i64=256}, 2, 131072, AF },
370 { "algo", "set algorithm", OFFSET(algo), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AF, "algo" },450 { "algo", "set the algorithm", OFFSET(algo), AV_OPT_TYPE_INT, {.i64=2}, 0, 2, AF, "algo" },
371 { "slow", "slow algorithm", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "algo" },451 { "slow", "slow algorithm", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "algo" },
372 { "fast", "fast algorithm", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "algo" },452 { "fast", "fast algorithm", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "algo" },
453 { "best", "best algorithm", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "algo" },
373 { NULL }454 { NULL }
374};455};
375 456

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t