[FFmpeg-cvslog] avfilter/avf_showcwt: reduce memory usage

Paul B Mahol git at videolan.org
Sat Jul 22 23:31:49 EEST 2023


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Sat Jul 22 21:45:48 2023 +0200| [b2ceed406b4648d34e233cb456072ce040dea483] | committer: Paul B Mahol

avfilter/avf_showcwt: reduce memory usage

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=b2ceed406b4648d34e233cb456072ce040dea483
---

 libavfilter/avf_showcwt.c | 92 ++++++++++++++++++++++++++---------------------
 1 file changed, 52 insertions(+), 40 deletions(-)

diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c
index 120ce63b62..0661afbcdd 100644
--- a/libavfilter/avf_showcwt.c
+++ b/libavfilter/avf_showcwt.c
@@ -78,7 +78,7 @@ typedef struct ShowCWTContext {
     int64_t old_pts;
     int64_t eof_pts;
     float *frequency_band;
-    AVFrame *kernel;
+    AVComplexFloat **kernel;
     unsigned *index;
     int *kernel_start, *kernel_stop;
     AVFrame *cache;
@@ -87,7 +87,6 @@ typedef struct ShowCWTContext {
     AVFrame *fft_out;
     AVFrame *dst_x;
     AVFrame *src_x;
-    AVFrame *kernel_x;
     AVFrame *ifft_in;
     AVFrame *ifft_out;
     AVFrame *ch_out;
@@ -169,14 +168,12 @@ static av_cold void uninit(AVFilterContext *ctx)
     av_freep(&s->kernel_stop);
     av_freep(&s->index);
 
-    av_frame_free(&s->kernel);
     av_frame_free(&s->cache);
     av_frame_free(&s->outpicref);
     av_frame_free(&s->fft_in);
     av_frame_free(&s->fft_out);
     av_frame_free(&s->dst_x);
     av_frame_free(&s->src_x);
-    av_frame_free(&s->kernel_x);
     av_frame_free(&s->ifft_in);
     av_frame_free(&s->ifft_out);
     av_frame_free(&s->ch_out);
@@ -194,6 +191,12 @@ static av_cold void uninit(AVFilterContext *ctx)
         av_freep(&s->ifft);
     }
 
+    if (s->kernel) {
+        for (int n = 0; n < s->frequency_band_count; n++)
+            av_freep(&s->kernel[n]);
+    }
+    av_freep(&s->kernel);
+
     av_freep(&s->fdsp);
 }
 
@@ -588,18 +591,16 @@ static int run_channel_cwt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo
         AVComplexFloat *chout = ((AVComplexFloat *)s->ch_out->extended_data[ch]) + y * ihop_size;
         AVComplexFloat *dstx = (AVComplexFloat *)s->dst_x->extended_data[jobnr];
         AVComplexFloat *srcx = (AVComplexFloat *)s->src_x->extended_data[jobnr];
-        AVComplexFloat *kernelx = (AVComplexFloat *)s->kernel_x->extended_data[jobnr];
-        const AVComplexFloat *kernel = (const AVComplexFloat *)s->kernel->extended_data[y];
+        const AVComplexFloat *kernel = s->kernel[y];
         const unsigned *index = (const unsigned *)s->index;
         const int kernel_start = s->kernel_start[y];
         const int kernel_stop = s->kernel_stop[y];
         const int kernel_range = kernel_stop - kernel_start;
 
-        memcpy(kernelx, kernel + kernel_start, sizeof(*kernel) * kernel_range);
         memcpy(srcx, dst + kernel_start, sizeof(*dst) * kernel_range);
 
         s->fdsp->vector_fmul((float *)dstx, (const float *)srcx,
-                             (const float *)kernelx, FFALIGN(kernel_range * 2, 16));
+                             (const float *)kernel, FFALIGN(kernel_range * 2, 16));
 
         memset(isrc, 0, sizeof(*isrc) * output_padding_size);
         for (int i = 0; i < kernel_range; i++) {
@@ -629,41 +630,63 @@ static int compute_kernel(AVFilterContext *ctx)
     int *kernel_stop = s->kernel_stop;
     unsigned *index = s->index;
     int kernel_min = INT_MAX;
-    int kernel_max = 0;
+    int kernel_max = 0, ret = 0;
+    float *tkernel;
+
+    tkernel = av_malloc_array(size, sizeof(*tkernel));
+    if (!tkernel)
+        return AVERROR(ENOMEM);
 
     for (int y = 0; y < fsize; y++) {
-        AVComplexFloat *kernel = (AVComplexFloat *)s->kernel->extended_data[y];
+        AVComplexFloat *kernel = s->kernel[y];
+        int start = 0, stop = 0;
         float frequency = s->frequency_band[y*2] * correction;
         float deviation = 1.f / (s->frequency_band[y*2+1] *
                                  output_sample_count * correction);
 
+        memset(tkernel, 0, size * sizeof(*tkernel));
         for (int n = 0; n < size; n++) {
             float ff, f = fabsf(n-frequency);
 
             ff = expf(-f*f*deviation) * scale_factor;
-            kernel[n].re = ff;
-            kernel[n].im = ff;
+            tkernel[n] = ff;
         }
 
         for (int n = 0; n < size; n++) {
-            if (kernel[n].re != 0.f) {
-                if (kernel[n].re > FLT_MIN)
+            if (tkernel[n] != 0.f) {
+                if (tkernel[n] > 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);
+                start = n;
+                kernel_min = FFMIN(start, 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)
+            if (tkernel[size - n - 1] != 0.f) {
+                if (tkernel[size - n - 1] > 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);
+                stop = size - n - 1;
+                kernel_max = FFMAX(stop, kernel_max);
                 break;
             }
         }
+
+        kernel_start[y] = start;
+        kernel_stop[y] = stop;
+
+        kernel = av_calloc(FFALIGN(stop - start + 1, 16), sizeof(*kernel));
+        if (!kernel) {
+            ret = AVERROR(ENOMEM);
+            break;
+        }
+
+        for (int n = start; n <= stop; n++) {
+            kernel[n - start].re = tkernel[n];
+            kernel[n - start].im = tkernel[n];
+        }
+
+        s->kernel[y] = kernel;
     }
 
     for (int n = 0; n < size; n++)
@@ -673,7 +696,9 @@ static int compute_kernel(AVFilterContext *ctx)
     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;
+    av_freep(&tkernel);
+
+    return ret;
 }
 
 static int config_output(AVFilterLink *outlink)
@@ -762,19 +787,18 @@ static int config_output(AVFilterLink *outlink)
     s->fft_out = ff_get_audio_buffer(inlink, s->fft_out_size * 2);
     s->dst_x = av_frame_alloc();
     s->src_x = av_frame_alloc();
-    s->kernel_x = av_frame_alloc();
+    s->kernel = av_calloc(s->frequency_band_count, sizeof(*s->kernel));
     s->cache = ff_get_audio_buffer(inlink, s->fft_in_size * 2);
     s->ch_out = ff_get_audio_buffer(inlink, s->frequency_band_count * 2 * s->ihop_size);
     s->bh_out = ff_get_audio_buffer(inlink, s->frequency_band_count);
     s->ifft_in = av_frame_alloc();
     s->ifft_out = av_frame_alloc();
-    s->kernel = av_frame_alloc();
     s->index = av_calloc(s->input_padding_size, sizeof(*s->index));
     s->kernel_start = av_calloc(s->frequency_band_count, sizeof(*s->kernel_start));
     s->kernel_stop = av_calloc(s->frequency_band_count, sizeof(*s->kernel_stop));
-    if (!s->outpicref || !s->fft_in || !s->fft_out || !s->src_x || !s->dst_x || !s->kernel_x ||
+    if (!s->outpicref || !s->fft_in || !s->fft_out || !s->src_x || !s->dst_x ||
         !s->ifft_in || !s->ifft_out || !s->kernel_start || !s->kernel_stop || !s->ch_out ||
-        !s->frequency_band || !s->kernel || !s->cache || !s->index || !s->bh_out)
+        !s->frequency_band || !s->cache || !s->index || !s->bh_out || !s->kernel)
         return AVERROR(ENOMEM);
 
     s->ifft_in->format     = inlink->format;
@@ -791,13 +815,6 @@ static int config_output(AVFilterLink *outlink)
     if (ret < 0)
         return ret;
 
-    s->kernel->format     = inlink->format;
-    s->kernel->nb_samples = s->input_padding_size * 2;
-    s->kernel->ch_layout.nb_channels = s->frequency_band_count;
-    ret = av_frame_get_buffer(s->kernel, 0);
-    if (ret < 0)
-        return ret;
-
     s->src_x->format     = inlink->format;
     s->src_x->nb_samples = s->fft_out_size * 2;
     s->src_x->ch_layout.nb_channels = s->nb_threads;
@@ -812,13 +829,6 @@ static int config_output(AVFilterLink *outlink)
     if (ret < 0)
         return ret;
 
-    s->kernel_x->format     = inlink->format;
-    s->kernel_x->nb_samples = s->fft_out_size * 2;
-    s->kernel_x->ch_layout.nb_channels = s->nb_threads;
-    ret = av_frame_get_buffer(s->kernel_x, 0);
-    if (ret < 0)
-        return ret;
-
     s->outpicref->sample_aspect_ratio = (AVRational){1,1};
 
     for (int y = 0; y < outlink->h; y++) {
@@ -899,7 +909,9 @@ static int config_output(AVFilterLink *outlink)
     outlink->frame_rate = s->frame_rate;
     outlink->time_base = av_inv_q(outlink->frame_rate);
 
-    compute_kernel(ctx);
+    ret = compute_kernel(ctx);
+    if (ret < 0)
+        return ret;
 
     return 0;
 }



More information about the ffmpeg-cvslog mailing list