History

avfilter/avf_showcwt: optimize multiplication with kernel

Paul B Mahol committed 3 years ago

Commit 2f2f76d1 parent 587189c1 file · +61 −12Browse files

Unified · Split

libavfilter/avf_showcwt.c+61−12
@@ -25,6 +25,7 @@ · 24 unmodified lines
25#include "libavutil/avassert.h"25#include "libavutil/avassert.h"
26#include "libavutil/avstring.h"26#include "libavutil/avstring.h"
27#include "libavutil/channel_layout.h"27#include "libavutil/channel_layout.h"
28#include "libavutil/float_dsp.h"
28#include "libavutil/cpu.h"29#include "libavutil/cpu.h"
29#include "libavutil/opt.h"30#include "libavutil/opt.h"
30#include "libavutil/parseutils.h"31#include "libavutil/parseutils.h"
@@ -89,6 +90,9 @@ typedef struct ShowCWTContext { · 58 unmodified lines
89 AVFrame *outpicref;90 AVFrame *outpicref;
90 AVFrame *fft_in;91 AVFrame *fft_in;
91 AVFrame *fft_out;92 AVFrame *fft_out;
93 AVFrame *dst_x;
94 AVFrame *src_x;
95 AVFrame *kernel_x;
92 AVFrame *ifft_in;96 AVFrame *ifft_in;
93 AVFrame *ifft_out;97 AVFrame *ifft_out;
94 AVFrame *ch_out;98 AVFrame *ch_out;
@@ -114,6 +118,8 @@ typedef struct ShowCWTContext { · 19 unmodified lines
114 float minimum_frequency;118 float minimum_frequency;
115 float maximum_frequency;119 float maximum_frequency;
116 float deviation;120 float deviation;
121
122 AVFloatDSPContext *fdsp;
117} ShowCWTContext;123} ShowCWTContext;
118 124
119#define OFFSET(x) offsetof(ShowCWTContext, x)125#define OFFSET(x) offsetof(ShowCWTContext, x)
@@ -172,6 +178,9 @@ static av_cold void uninit(AVFilterContext *ctx) · 52 unmodified lines
172 av_frame_free(&s->outpicref);178 av_frame_free(&s->outpicref);
173 av_frame_free(&s->fft_in);179 av_frame_free(&s->fft_in);
174 av_frame_free(&s->fft_out);180 av_frame_free(&s->fft_out);
181 av_frame_free(&s->dst_x);
182 av_frame_free(&s->src_x);
183 av_frame_free(&s->kernel_x);
175 av_frame_free(&s->ifft_in);184 av_frame_free(&s->ifft_in);
176 av_frame_free(&s->ifft_out);185 av_frame_free(&s->ifft_out);
177 av_frame_free(&s->ch_out);186 av_frame_free(&s->ch_out);
@@ -187,6 +196,8 @@ static av_cold void uninit(AVFilterContext *ctx) · 9 unmodified lines
187 av_tx_uninit(&s->ifft[n]);196 av_tx_uninit(&s->ifft[n]);
188 av_freep(&s->ifft);197 av_freep(&s->ifft);
189 }198 }
199
200 av_freep(&s->fdsp);
190}201}
191 202
192static int query_formats(AVFilterContext *ctx)203static int query_formats(AVFilterContext *ctx)
@@ -483,18 +494,27 @@ static int run_channel_cwt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo · 290 unmodified lines
483 AVComplexFloat *isrc = (AVComplexFloat *)s->ifft_in->extended_data[y];494 AVComplexFloat *isrc = (AVComplexFloat *)s->ifft_in->extended_data[y];
484 AVComplexFloat *idst = (AVComplexFloat *)s->ifft_out->extended_data[y];495 AVComplexFloat *idst = (AVComplexFloat *)s->ifft_out->extended_data[y];
485 AVComplexFloat *chout = ((AVComplexFloat *)s->ch_out->extended_data[ch]) + y * ihop_size;496 AVComplexFloat *chout = ((AVComplexFloat *)s->ch_out->extended_data[ch]) + y * ihop_size;
486 const float *kernel = (const float *)s->kernel->extended_data[y];497 AVComplexFloat *dstx = (AVComplexFloat *)s->dst_x->extended_data[jobnr];
498 AVComplexFloat *srcx = (AVComplexFloat *)s->src_x->extended_data[jobnr];
499 AVComplexFloat *kernelx = (AVComplexFloat *)s->kernel_x->extended_data[jobnr];
500 const AVComplexFloat *kernel = (const AVComplexFloat *)s->kernel->extended_data[y];
487 const unsigned *index = (const unsigned *)s->index;501 const unsigned *index = (const unsigned *)s->index;
488 const int kernel_start = s->kernel_start[y];502 const int kernel_start = s->kernel_start[y];
489 const int kernel_stop = s->kernel_stop[y];503 const int kernel_stop = s->kernel_stop[y];
504 const int kernel_range = kernel_stop - kernel_start;
505
506 memcpy(kernelx, kernel + kernel_start, sizeof(*kernel) * kernel_range);
507 memcpy(srcx, dst + kernel_start, sizeof(*dst) * kernel_range);
508
509 s->fdsp->vector_fmul((float *)dstx, (const float *)srcx,
510 (const float *)kernelx, FFALIGN(kernel_range * 2, 16));
490 511
491 memset(isrc, 0, sizeof(*isrc) * output_sample_count);512 memset(isrc, 0, sizeof(*isrc) * output_sample_count);
492 for (int i = kernel_start; i < kernel_stop; i++) {513 for (int i = 0; i < kernel_range; i++) {
493 const unsigned n = index[i];514 const unsigned n = index[i + kernel_start];
494 const float ff = kernel[i];
495 515
496 isrc[n].re += ff * dst[i].re;516 isrc[n].re += dstx[i].re;
497 isrc[n].im += ff * dst[i].im;517 isrc[n].im += dstx[i].im;
498 }518 }
499 519
500 s->itx_fn(s->ifft[jobnr], idst, isrc, sizeof(*isrc));520 s->itx_fn(s->ifft[jobnr], idst, isrc, sizeof(*isrc));
@@ -515,7 +535,7 @@ static void compute_kernel(AVFilterContext *ctx) · 14 unmodified lines
515 unsigned *index = s->index;535 unsigned *index = s->index;
516 536
517 for (int y = 0; y < fsize; y++) {537 for (int y = 0; y < fsize; y++) {
518 float *kernel = (float *)s->kernel->extended_data[y];538 AVComplexFloat *kernel = (AVComplexFloat *)s->kernel->extended_data[y];
519 int *kernel_start = s->kernel_start;539 int *kernel_start = s->kernel_start;
520 int *kernel_stop = s->kernel_stop;540 int *kernel_stop = s->kernel_stop;
521 float frequency = s->frequency_band[y*2];541 float frequency = s->frequency_band[y*2];
@@ -527,18 +547,19 @@ static void compute_kernel(AVFilterContext *ctx) · 5 unmodified lines
527 547
528 f = size - fabsf(f - size);548 f = size - fabsf(f - size);
529 ff = expf(-f*f*deviation) * scale_factor;549 ff = expf(-f*f*deviation) * scale_factor;
530 kernel[n] = ff;550 kernel[n].re = ff;
551 kernel[n].im = ff;
531 }552 }
532 553
533 for (int n = 0; n < size; n++) {554 for (int n = 0; n < size; n++) {
534 if (kernel[n] != 0.f) {555 if (kernel[n].re != 0.f) {
535 kernel_start[y] = n;556 kernel_start[y] = n;
536 break;557 break;
537 }558 }
538 }559 }
539 560
540 for (int n = 0; n < size; n++) {561 for (int n = 0; n < size; n++) {
541 if (kernel[size - n - 1] != 0.f) {562 if (kernel[size - n - 1].re != 0.f) {
542 kernel_stop[y] = size - n;563 kernel_stop[y] = size - n;
543 break;564 break;
544 }565 }
@@ -561,6 +582,10 @@ static int config_output(AVFilterLink *outlink) · 16 unmodified lines
561 582
562 uninit(ctx);583 uninit(ctx);
563 584
585 s->fdsp = avpriv_float_dsp_alloc(0);
586 if (!s->fdsp)
587 return AVERROR(ENOMEM);
588
564 switch (s->direction) {589 switch (s->direction) {
565 case DIRECTION_LR:590 case DIRECTION_LR:
566 case DIRECTION_RL:591 case DIRECTION_RL:
@@ -622,6 +647,9 @@ static int config_output(AVFilterLink *outlink) · 55 unmodified lines
622 s->outpicref = ff_get_video_buffer(outlink, outlink->w, outlink->h);647 s->outpicref = ff_get_video_buffer(outlink, outlink->w, outlink->h);
623 s->fft_in = ff_get_audio_buffer(inlink, s->fft_in_size * 2);648 s->fft_in = ff_get_audio_buffer(inlink, s->fft_in_size * 2);
624 s->fft_out = ff_get_audio_buffer(inlink, s->fft_out_size * 2);649 s->fft_out = ff_get_audio_buffer(inlink, s->fft_out_size * 2);
650 s->dst_x = av_frame_alloc();
651 s->src_x = av_frame_alloc();
652 s->kernel_x = av_frame_alloc();
625 s->cache = ff_get_audio_buffer(inlink, s->fft_in_size * 2);653 s->cache = ff_get_audio_buffer(inlink, s->fft_in_size * 2);
626 s->ch_out = ff_get_audio_buffer(inlink, s->frequency_band_count * 2 * s->ihop_size);654 s->ch_out = ff_get_audio_buffer(inlink, s->frequency_band_count * 2 * s->ihop_size);
627 s->ifft_in = av_frame_alloc();655 s->ifft_in = av_frame_alloc();
@@ -630,7 +658,7 @@ static int config_output(AVFilterLink *outlink) · 2 unmodified lines
630 s->index = av_calloc(s->input_padding_size, sizeof(*s->index));658 s->index = av_calloc(s->input_padding_size, sizeof(*s->index));
631 s->kernel_start = av_calloc(s->frequency_band_count, sizeof(*s->kernel_start));659 s->kernel_start = av_calloc(s->frequency_band_count, sizeof(*s->kernel_start));
632 s->kernel_stop = av_calloc(s->frequency_band_count, sizeof(*s->kernel_stop));660 s->kernel_stop = av_calloc(s->frequency_band_count, sizeof(*s->kernel_stop));
633 if (!s->outpicref || !s->fft_in || !s->fft_out ||661 if (!s->outpicref || !s->fft_in || !s->fft_out || !s->src_x || !s->dst_x || !s->kernel_x ||
634 !s->ifft_in || !s->ifft_out || !s->kernel_start || !s->kernel_stop ||662 !s->ifft_in || !s->ifft_out || !s->kernel_start || !s->kernel_stop ||
635 !s->frequency_band || !s->kernel || !s->cache || !s->index)663 !s->frequency_band || !s->kernel || !s->cache || !s->index)
636 return AVERROR(ENOMEM);664 return AVERROR(ENOMEM);
@@ -650,12 +678,33 @@ static int config_output(AVFilterLink *outlink) · 13 unmodified lines
650 return ret;678 return ret;
651 679
652 s->kernel->format = inlink->format;680 s->kernel->format = inlink->format;
653 s->kernel->nb_samples = s->input_padding_size;681 s->kernel->nb_samples = s->input_padding_size * 2;
654 s->kernel->ch_layout.nb_channels = s->frequency_band_count;682 s->kernel->ch_layout.nb_channels = s->frequency_band_count;
655 ret = av_frame_get_buffer(s->kernel, 0);683 ret = av_frame_get_buffer(s->kernel, 0);
656 if (ret < 0)684 if (ret < 0)
657 return ret;685 return ret;
658 686
687 s->src_x->format = inlink->format;
688 s->src_x->nb_samples = s->fft_out_size * 2;
689 s->src_x->ch_layout.nb_channels = s->nb_threads;
690 ret = av_frame_get_buffer(s->src_x, 0);
691 if (ret < 0)
692 return ret;
693
694 s->dst_x->format = inlink->format;
695 s->dst_x->nb_samples = s->fft_out_size * 2;
696 s->dst_x->ch_layout.nb_channels = s->nb_threads;
697 ret = av_frame_get_buffer(s->dst_x, 0);
698 if (ret < 0)
699 return ret;
700
701 s->kernel_x->format = inlink->format;
702 s->kernel_x->nb_samples = s->fft_out_size * 2;
703 s->kernel_x->ch_layout.nb_channels = s->nb_threads;
704 ret = av_frame_get_buffer(s->kernel_x, 0);
705 if (ret < 0)
706 return ret;
707
659 s->outpicref->sample_aspect_ratio = (AVRational){1,1};708 s->outpicref->sample_aspect_ratio = (AVRational){1,1};
660 709
661 for (int y = 0; y < outlink->h; y++) {710 for (int y = 0; y < outlink->h; y++) {

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