[FFmpeg-cvslog] avfilter/avf_showcwt: improve analysis
Paul B Mahol
git at videolan.org
Sat Jul 22 18:59:03 EEST 2023
ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Fri Jul 21 23:11:11 2023 +0200| [e6168e43a2eec4757cc8d7f981f9d29e1f12dbed] | committer: Paul B Mahol
avfilter/avf_showcwt: improve analysis
Make inverse FFT step always power of 2 in size.
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=e6168e43a2eec4757cc8d7f981f9d29e1f12dbed
---
libavfilter/avf_showcwt.c | 78 +++++++++++++++++++++++++----------------------
1 file changed, 42 insertions(+), 36 deletions(-)
diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c
index ee0d697e1e..ef6798e9cf 100644
--- a/libavfilter/avf_showcwt.c
+++ b/libavfilter/avf_showcwt.c
@@ -69,14 +69,10 @@ typedef struct ShowCWTContext {
char *rate_str;
AVRational auto_frame_rate;
AVRational frame_rate;
- AVTXContext **fft;
- AVTXContext **ifft;
- av_tx_fn tx_fn;
- av_tx_fn itx_fn;
- int fft_in_size;
- int fft_out_size;
- int ifft_in_size;
- int ifft_out_size;
+ AVTXContext **fft, **ifft;
+ av_tx_fn tx_fn, itx_fn;
+ int fft_in_size, fft_out_size;
+ int ifft_in_size, ifft_out_size;
int pos;
int64_t in_pts;
int64_t old_pts;
@@ -84,8 +80,7 @@ typedef struct ShowCWTContext {
float *frequency_band;
AVFrame *kernel;
unsigned *index;
- int *kernel_start;
- int *kernel_stop;
+ int *kernel_start, *kernel_stop;
AVFrame *cache;
AVFrame *outpicref;
AVFrame *fft_in;
@@ -105,19 +100,14 @@ typedef struct ShowCWTContext {
int slide;
int new_frame;
int direction;
- int hop_size;
- int hop_index;
- int ihop_size;
- int ihop_index;
- int input_padding_size;
- int input_sample_count;
- int output_padding_size;
- int output_sample_count;
+ int hop_size, ihop_size;
+ int hop_index, ihop_index;
+ int input_padding_size, output_padding_size;
+ int input_sample_count, output_sample_count;
int frequency_band_count;
float logarithmic_basis;
int frequency_scale;
- float minimum_frequency;
- float maximum_frequency;
+ float minimum_frequency, maximum_frequency;
float deviation;
float bar_ratio;
int bar_size;
@@ -585,9 +575,9 @@ static int run_channel_cwt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo
ShowCWTContext *s = ctx->priv;
const int ch = *(int *)arg;
AVComplexFloat *dst = (AVComplexFloat *)s->fft_out->extended_data[ch];
- const int output_sample_count = s->output_sample_count;
+ const int output_padding_size = s->output_padding_size;
const int ihop_size = s->ihop_size;
- const int ioffset = (s->output_padding_size - ihop_size) >> 1;
+ const int ioffset = (output_padding_size - ihop_size) >> 1;
const int count = s->frequency_band_count;
const int start = (count * jobnr) / nb_jobs;
const int end = (count * (jobnr+1)) / nb_jobs;
@@ -611,7 +601,7 @@ static int run_channel_cwt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo
s->fdsp->vector_fmul((float *)dstx, (const float *)srcx,
(const float *)kernelx, FFALIGN(kernel_range * 2, 16));
- memset(isrc, 0, sizeof(*isrc) * output_sample_count);
+ memset(isrc, 0, sizeof(*isrc) * output_padding_size);
for (int i = 0; i < kernel_range; i++) {
const unsigned n = index[i + kernel_start];
@@ -627,9 +617,10 @@ static int run_channel_cwt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo
return 0;
}
-static void compute_kernel(AVFilterContext *ctx)
+static int compute_kernel(AVFilterContext *ctx)
{
ShowCWTContext *s = ctx->priv;
+ const float correction = s->input_padding_size / (float)s->input_sample_count;
const int size = s->input_sample_count;
const float scale_factor = 1.f/(float)size;
const int output_sample_count = s->output_sample_count;
@@ -637,17 +628,18 @@ static void compute_kernel(AVFilterContext *ctx)
int *kernel_start = s->kernel_start;
int *kernel_stop = s->kernel_stop;
unsigned *index = s->index;
+ int kernel_min = INT_MAX;
+ int kernel_max = 0;
for (int y = 0; y < fsize; y++) {
AVComplexFloat *kernel = (AVComplexFloat *)s->kernel->extended_data[y];
- float frequency = s->frequency_band[y*2];
+ float frequency = s->frequency_band[y*2] * correction;
float deviation = 1.f / (s->frequency_band[y*2+1] *
- output_sample_count);
+ output_sample_count * correction);
for (int n = 0; n < size; n++) {
float ff, f = fabsf(n-frequency);
- f = size - fabsf(f - size);
ff = expf(-f*f*deviation) * scale_factor;
kernel[n].re = ff;
kernel[n].im = ff;
@@ -655,21 +647,33 @@ static void compute_kernel(AVFilterContext *ctx)
for (int n = 0; n < size; n++) {
if (kernel[n].re != 0.f) {
+ if (kernel[n].re > FLT_MIN)
+ av_log(ctx, AV_LOG_DEBUG, "out of range kernel\n");
kernel_start[y] = n;
+ kernel_min = FFMIN(kernel_start[y], kernel_min);
break;
}
}
for (int n = 0; n < size; n++) {
if (kernel[size - n - 1].re != 0.f) {
+ if (kernel[size - n - 1].re > FLT_MIN)
+ av_log(ctx, AV_LOG_DEBUG, "out of range kernel\n");
kernel_stop[y] = size - n - 1;
+ kernel_max = FFMAX(kernel_stop[y], kernel_max);
break;
}
}
}
for (int n = 0; n < size; n++)
- index[n] = n % output_sample_count;
+ index[n] = n % s->output_padding_size;
+
+ av_log(ctx, AV_LOG_DEBUG, "kernel_min: %d\n", kernel_min);
+ av_log(ctx, AV_LOG_DEBUG, "kernel_max: %d\n", kernel_max);
+ av_log(ctx, AV_LOG_DEBUG, "kernel_range: %d\n", kernel_max - kernel_min);
+
+ return kernel_max - kernel_min;
}
static int config_output(AVFilterLink *outlink)
@@ -708,9 +712,12 @@ static int config_output(AVFilterLink *outlink)
s->nb_consumed_samples = 65536;
s->input_sample_count = s->nb_consumed_samples;
- s->hop_size = s->nb_consumed_samples >> 1;
- s->input_padding_size = 65536;
- s->output_padding_size = FFMAX(16, av_rescale(s->input_padding_size, s->pps, inlink->sample_rate));
+ s->input_padding_size = 1 << (32 - ff_clz(s->input_sample_count));
+ s->output_sample_count = FFMAX(1, av_rescale(s->input_sample_count, s->pps, inlink->sample_rate));
+ s->output_padding_size = 1 << (32 - ff_clz(s->output_sample_count));
+
+ s->hop_size = s->input_padding_size >> 1;
+ s->ihop_size = s->output_padding_size >> 1;
outlink->w = s->w;
outlink->h = s->h;
@@ -719,11 +726,8 @@ static int config_output(AVFilterLink *outlink)
s->fft_in_size = FFALIGN(s->input_padding_size, av_cpu_max_align());
s->fft_out_size = FFALIGN(s->input_padding_size, av_cpu_max_align());
- s->output_sample_count = s->output_padding_size;
-
s->ifft_in_size = FFALIGN(s->output_padding_size, av_cpu_max_align());
s->ifft_out_size = FFALIGN(s->output_padding_size, av_cpu_max_align());
- s->ihop_size = s->output_padding_size >> 1;
s->fft = av_calloc(s->nb_threads, sizeof(*s->fft));
if (!s->fft)
@@ -821,7 +825,7 @@ static int config_output(AVFilterLink *outlink)
s->outpicref->color_range = AVCOL_RANGE_JPEG;
- factor = s->nb_consumed_samples / (float)inlink->sample_rate;
+ factor = s->input_sample_count / (float)inlink->sample_rate;
minimum_frequency *= factor;
maximum_frequency *= factor;
@@ -861,7 +865,9 @@ static int config_output(AVFilterLink *outlink)
minimum_frequency, s->frequency_scale, s->deviation);
av_log(ctx, AV_LOG_DEBUG, "input_sample_count: %d\n", s->input_sample_count);
+ av_log(ctx, AV_LOG_DEBUG, "input_padding_size: %d\n", s->input_padding_size);
av_log(ctx, AV_LOG_DEBUG, "output_sample_count: %d\n", s->output_sample_count);
+ av_log(ctx, AV_LOG_DEBUG, "output_padding_size: %d\n", s->output_padding_size);
switch (s->direction) {
case DIRECTION_LR:
@@ -1042,7 +1048,7 @@ static int output_frame(AVFilterContext *ctx)
if (s->slide != SLIDE_FRAME || s->new_frame == 1) {
int64_t pts_offset = s->new_frame ? 0LL : av_rescale(s->ihop_index, s->hop_size, s->ihop_size);
- pts_offset = av_rescale_q(pts_offset - 16384LL, av_make_q(1, inlink->sample_rate), inlink->time_base);
+ pts_offset = av_rescale_q(pts_offset - s->input_sample_count/2, av_make_q(1, inlink->sample_rate), inlink->time_base);
s->outpicref->pts = av_rescale_q(s->in_pts + pts_offset, inlink->time_base, outlink->time_base);
s->outpicref->duration = 1;
}
More information about the ffmpeg-cvslog
mailing list