[FFmpeg-cvslog] avfilter/vf_fftdnoiz: refactor code and improve 3d filtering

Paul B Mahol git at videolan.org
Thu May 5 20:05:42 EEST 2022


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Thu May  5 13:19:55 2022 +0200| [a6f136aef1e3d108516c37a505f03631a75a3099] | committer: Paul B Mahol

avfilter/vf_fftdnoiz: refactor code and improve 3d filtering

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

 libavfilter/vf_fftdnoiz.c | 529 +++++++++++++++++++++-------------------------
 1 file changed, 240 insertions(+), 289 deletions(-)

diff --git a/libavfilter/vf_fftdnoiz.c b/libavfilter/vf_fftdnoiz.c
index f22b3dbb54..2da9b25baf 100644
--- a/libavfilter/vf_fftdnoiz.c
+++ b/libavfilter/vf_fftdnoiz.c
@@ -41,7 +41,7 @@ typedef struct PlaneContext {
     int o;
     float n;
 
-    float *buffer[BSIZE];
+    float *buffer[MAX_THREADS][BSIZE];
     AVComplexFloat *hdata[MAX_THREADS], *vdata[MAX_THREADS];
     AVComplexFloat *hdata_out[MAX_THREADS], *vdata_out[MAX_THREADS];
     int data_linesize;
@@ -68,7 +68,10 @@ typedef struct FFTdnoizContext {
     PlaneContext planes[4];
 
     AVTXContext *fft[MAX_THREADS], *ifft[MAX_THREADS];
+    AVTXContext *fft_r[MAX_THREADS], *ifft_r[MAX_THREADS];
+
     av_tx_fn tx_fn, itx_fn;
+    av_tx_fn tx_r_fn, itx_r_fn;
 
     void (*import_row)(AVComplexFloat *dst, uint8_t *src, int rw, float scale);
     void (*export_row)(AVComplexFloat *src, uint8_t *dst, int rw, int depth);
@@ -203,7 +206,9 @@ static int config_input(AVFilterLink *inlink)
 
         av_tx_init(&s->fft[i],  &s->tx_fn,  AV_TX_FLOAT_FFT, 0, s->block_size, &scale,  0);
         av_tx_init(&s->ifft[i], &s->itx_fn, AV_TX_FLOAT_FFT, 1, s->block_size, &iscale, 0);
-        if (!s->fft[i] || !s->ifft[i])
+        av_tx_init(&s->fft_r[i],  &s->tx_r_fn,  AV_TX_FLOAT_FFT, 0, 1 + s->nb_prev + s->nb_next, &scale,  0);
+        av_tx_init(&s->ifft_r[i], &s->itx_r_fn, AV_TX_FLOAT_FFT, 1, 1 + s->nb_prev + s->nb_next, &iscale, 0);
+        if (!s->fft[i] || !s->ifft[i] || !s->fft_r[i] || !s->ifft_r[i])
             return AVERROR(ENOMEM);
     }
 
@@ -220,26 +225,26 @@ static int config_input(AVFilterLink *inlink)
 
         av_log(ctx, AV_LOG_DEBUG, "nox:%d noy:%d size:%d\n", p->nox, p->noy, size);
 
-        p->buffer_linesize = p->b * p->nox * sizeof(AVComplexFloat);
-        p->buffer[CURRENT] = av_calloc(p->b * p->noy, p->buffer_linesize);
-        if (!p->buffer[CURRENT])
-            return AVERROR(ENOMEM);
-        if (s->nb_prev > 0) {
-            p->buffer[PREV] = av_calloc(p->b * p->noy, p->buffer_linesize);
-            if (!p->buffer[PREV])
-                return AVERROR(ENOMEM);
-        }
-        if (s->nb_next > 0) {
-            p->buffer[NEXT] = av_calloc(p->b * p->noy, p->buffer_linesize);
-            if (!p->buffer[NEXT])
-                return AVERROR(ENOMEM);
-        }
+        p->buffer_linesize = p->b * sizeof(AVComplexFloat);
         p->data_linesize = 2 * p->b * sizeof(float);
         for (int j = 0; j < s->nb_threads; j++) {
             p->hdata[j] = av_calloc(p->b, p->data_linesize);
             p->hdata_out[j] = av_calloc(p->b, p->data_linesize);
             p->vdata[j] = av_calloc(p->b, p->data_linesize);
             p->vdata_out[j] = av_calloc(p->b, p->data_linesize);
+            p->buffer[j][CURRENT] = av_calloc(p->b, p->buffer_linesize);
+            if (!p->buffer[j][CURRENT])
+                return AVERROR(ENOMEM);
+            if (s->nb_prev > 0) {
+                p->buffer[j][PREV] = av_calloc(p->b, p->buffer_linesize);
+                if (!p->buffer[j][PREV])
+                    return AVERROR(ENOMEM);
+            }
+            if (s->nb_next > 0) {
+                p->buffer[j][NEXT] = av_calloc(p->b, p->buffer_linesize);
+                if (!p->buffer[j][NEXT])
+                    return AVERROR(ENOMEM);
+            }
             if (!p->hdata[j] || !p->vdata[j] ||
                 !p->hdata_out[j] || !p->vdata_out[j])
                 return AVERROR(ENOMEM);
@@ -249,10 +254,10 @@ static int config_input(AVFilterLink *inlink)
     return 0;
 }
 
-static void import_plane(FFTdnoizContext *s,
+static void import_block(FFTdnoizContext *s,
                          uint8_t *srcp, int src_linesize,
                          float *buffer, int buffer_linesize, int plane,
-                         int jobnr, int nb_jobs)
+                         int jobnr, int y, int x)
 {
     PlaneContext *p = &s->planes[plane];
     const int width = p->planewidth;
@@ -260,68 +265,60 @@ static void import_plane(FFTdnoizContext *s,
     const int block = p->b;
     const int overlap = p->o;
     const int size = block - overlap;
-    const int nox = p->nox;
-    const int noy = p->noy;
     const int bpp = (s->depth + 7) / 8;
     const int data_linesize = p->data_linesize / sizeof(AVComplexFloat);
-    const int slice_start = (noy * jobnr) / nb_jobs;
-    const int slice_end = (noy * (jobnr+1)) / nb_jobs;
-    const float scale = 1.f / (s->block_size * s->block_size);
+    const float scale = 1.f / ((1.f + s->nb_prev + s->nb_next) * s->block_size * s->block_size);
     AVComplexFloat *hdata = p->hdata[jobnr];
     AVComplexFloat *hdata_out = p->hdata_out[jobnr];
     AVComplexFloat *vdata_out = p->vdata_out[jobnr];
-    int x, y, i, j;
+
+    const int rh = FFMIN(block, height - y * size);
+    const int rw = FFMIN(block, width  - x * size);
+    uint8_t *src = srcp + src_linesize * y * size + x * size * bpp;
+    AVComplexFloat *ssrc, *ddst, *dst = hdata, *dst_out = hdata_out;
+    float *bdst = buffer;
 
     buffer_linesize /= sizeof(float);
-    for (y = slice_start; y < slice_end; y++) {
-        for (x = 0; x < nox; x++) {
-            const int rh = FFMIN(block, height - y * size);
-            const int rw = FFMIN(block, width  - x * size);
-            uint8_t *src = srcp + src_linesize * y * size + x * size * bpp;
-            float *bdst = buffer + buffer_linesize * y * block + x * block * 2;
-            AVComplexFloat *ssrc, *ddst, *dst = hdata, *dst_out = hdata_out;
-
-            for (i = 0; i < rh; i++) {
-                s->import_row(dst, src, rw, scale);
-                for (j = rw; j < block; j++) {
-                    dst[j].re = dst[rw - 1].re;
-                    dst[j].im = 0.f;
-                }
-                s->tx_fn(s->fft[jobnr], dst_out, dst, sizeof(float));
 
-                ddst = dst_out;
-                src += src_linesize;
-                dst += data_linesize;
-                dst_out += data_linesize;
-            }
+    for (int i = 0; i < rh; i++) {
+        s->import_row(dst, src, rw, scale);
+        for (int j = rw; j < block; j++) {
+            dst[j].re = dst[rw - 1].re;
+            dst[j].im = 0.f;
+        }
+        s->tx_fn(s->fft[jobnr], dst_out, dst, sizeof(float));
 
-            for (i = rh; i < block; i++) {
-                for (j = 0; j < block; j++) {
-                    dst[j].re = ddst[j].re;
-                    dst[j].im = ddst[j].im;
-                }
+        ddst = dst_out;
+        src += src_linesize;
+        dst += data_linesize;
+        dst_out += data_linesize;
+    }
 
-                dst += data_linesize;
-            }
+    for (int i = rh; i < block; i++) {
+        for (int j = 0; j < block; j++) {
+            dst[j].re = ddst[j].re;
+            dst[j].im = ddst[j].im;
+        }
 
-            ssrc = hdata_out;
-            dst = vdata_out;
-            for (i = 0; i < block; i++) {
-                for (j = 0; j < block; j++)
-                    dst[j] = ssrc[j * data_linesize + i];
-                s->tx_fn(s->fft[jobnr], bdst, dst, sizeof(float));
+        dst += data_linesize;
+    }
 
-                dst += data_linesize;
-                bdst += buffer_linesize;
-            }
-        }
+    ssrc = hdata_out;
+    dst = vdata_out;
+    for (int i = 0; i < block; i++) {
+        for (int j = 0; j < block; j++)
+            dst[j] = ssrc[j * data_linesize + i];
+        s->tx_fn(s->fft[jobnr], bdst, dst, sizeof(float));
+
+        dst += data_linesize;
+        bdst += buffer_linesize;
     }
 }
 
-static void export_plane(FFTdnoizContext *s,
+static void export_block(FFTdnoizContext *s,
                          uint8_t *dstp, int dst_linesize,
                          float *buffer, int buffer_linesize, int plane,
-                         int jobnr, int nb_jobs)
+                         int jobnr, int y, int x)
 {
     PlaneContext *p = &s->planes[plane];
     const int depth = s->depth;
@@ -332,286 +329,245 @@ static void export_plane(FFTdnoizContext *s,
     const int overlap = p->o;
     const int hoverlap = overlap / 2;
     const int size = block - overlap;
-    const int nox = p->nox;
-    const int noy = p->noy;
     const int data_linesize = p->data_linesize / sizeof(AVComplexFloat);
-    const int slice_start = (noy * jobnr) / nb_jobs;
-    const int slice_end = (noy * (jobnr+1)) / nb_jobs;
     AVComplexFloat *hdata = p->hdata[jobnr];
     AVComplexFloat *hdata_out = p->hdata_out[jobnr];
     AVComplexFloat *vdata_out = p->vdata_out[jobnr];
-    int x, y, i, j;
-
+    const int woff = x == 0 ? 0 : hoverlap;
+    const int hoff = y == 0 ? 0 : hoverlap;
+    const int rw = x == 0 ? FFMIN(block, width)  : FFMIN(size, width  - x * size - woff);
+    const int rh = y == 0 ? FFMIN(block, height) : FFMIN(size, height - y * size - hoff);
+    uint8_t *dst = dstp + dst_linesize * (y * size + hoff) + (x * size + woff) * bpp;
+    AVComplexFloat *hdst, *vdst = vdata_out, *hdst_out = hdata_out;
+    float *bsrc = buffer;
+
+    hdst = hdata;
     buffer_linesize /= sizeof(float);
-    for (y = slice_start; y < slice_end; y++) {
-        for (x = 0; x < nox; x++) {
-            const int woff = x == 0 ? 0 : hoverlap;
-            const int hoff = y == 0 ? 0 : hoverlap;
-            const int rw = x == 0 ? FFMIN(block, width)  : FFMIN(size, width  - x * size - woff);
-            const int rh = y == 0 ? FFMIN(block, height) : FFMIN(size, height - y * size - hoff);
-            float *bsrc = buffer + buffer_linesize * y * block + x * block * 2;
-            uint8_t *dst = dstp + dst_linesize * (y * size + hoff) + (x * size + woff) * bpp;
-            AVComplexFloat *hdst, *vdst = vdata_out, *hdst_out = hdata_out;
-
-            hdst = hdata;
-            for (i = 0; i < block; i++) {
-                s->itx_fn(s->ifft[jobnr], vdst, bsrc, sizeof(float));
-                for (j = 0; j < block; j++)
-                    hdst[j * data_linesize + i] = vdst[j];
-
-                vdst += data_linesize;
-                bsrc += buffer_linesize;
-            }
 
-            hdst = hdata + hoff * data_linesize;
-            for (i = 0; i < rh; i++) {
-                s->itx_fn(s->ifft[jobnr], hdst_out, hdst, sizeof(float));
-                s->export_row(hdst_out + woff, dst, rw, depth);
+    for (int i = 0; i < block; i++) {
+        s->itx_fn(s->ifft[jobnr], vdst, bsrc, sizeof(float));
+        for (int j = 0; j < block; j++)
+            hdst[j * data_linesize + i] = vdst[j];
 
-                hdst += data_linesize;
-                hdst_out += data_linesize;
-                dst += dst_linesize;
-            }
-        }
+        vdst += data_linesize;
+        bsrc += buffer_linesize;
+    }
+
+    hdst = hdata + hoff * data_linesize;
+    for (int i = 0; i < rh; i++) {
+        s->itx_fn(s->ifft[jobnr], hdst_out, hdst, sizeof(float));
+        s->export_row(hdst_out + woff, dst, rw, depth);
+
+        hdst += data_linesize;
+        hdst_out += data_linesize;
+        dst += dst_linesize;
     }
 }
 
-static void filter_plane3d2(FFTdnoizContext *s, int plane, float *pbuffer, float *nbuffer,
-                            int jobnr, int nb_jobs)
+static void filter_block3d2(FFTdnoizContext *s, int plane, float *pbuffer, float *nbuffer,
+                            int jobnr)
 {
     PlaneContext *p = &s->planes[plane];
     const int block = p->b;
-    const int nox = p->nox;
-    const int noy = p->noy;
     const int buffer_linesize = p->buffer_linesize / sizeof(float);
     const float depthx = (1 << (s->depth - 8)) * (1 << (s->depth - 8));
-    const float sigma = s->sigma * depthx / (s->block_size * s->block_size);
-    const int slice_start = (noy * jobnr) / nb_jobs;
-    const int slice_end = (noy * (jobnr+1)) / nb_jobs;
+    const float sigma = s->sigma * depthx / (3.f * s->block_size * s->block_size);
     const float limit = 1.f - s->amount;
-    float *cbuffer = p->buffer[CURRENT];
-    const float cfactor = sqrtf(3.f) * 0.5f;
-    const float scale = 1.f / 3.f;
-    int y, x, i, j;
-
-    for (y = slice_start; y < slice_end; y++) {
-        for (x = 0; x < nox; x++) {
-            float *cbuff = cbuffer + buffer_linesize * y * block + x * block * 2;
-            float *pbuff = pbuffer + buffer_linesize * y * block + x * block * 2;
-            float *nbuff = nbuffer + buffer_linesize * y * block + x * block * 2;
-
-            for (i = 0; i < block; i++) {
-                for (j = 0; j < block; j++) {
-                    float sumr, sumi, difr, difi, mpr, mpi, mnr, mni;
-                    float factor, power, sumpnr, sumpni;
-
-                    sumpnr = pbuff[2 * j    ] + nbuff[2 * j    ];
-                    sumpni = pbuff[2 * j + 1] + nbuff[2 * j + 1];
-                    sumr = cbuff[2 * j    ] + sumpnr;
-                    sumi = cbuff[2 * j + 1] + sumpni;
-                    difr = cfactor * (nbuff[2 * j    ] - pbuff[2 * j    ]);
-                    difi = cfactor * (pbuff[2 * j + 1] - nbuff[2 * j + 1]);
-                    mpr = cbuff[2 * j    ] - 0.5f * sumpnr + difi;
-                    mnr = mpr - difi - difi;
-                    mpi = cbuff[2 * j + 1] - 0.5f * sumpni + difr;
-                    mni = mpi - difr - difr;
-                    power = sumr * sumr + sumi * sumi;
-                    factor = fmaxf((power - sigma) / (power + 1e-15f), limit);
-                    sumr *= factor;
-                    sumi *= factor;
-                    power = mpr * mpr + mpi * mpi;
-                    factor = fmaxf((power - sigma) / (power + 1e-15f), limit);
-                    mpr *= factor;
-                    mpi *= factor;
-                    power = mnr * mnr + mni * mni;
-                    factor = fmaxf((power - sigma) / (power + 1e-15f), limit);
-                    mnr *= factor;
-                    mni *= factor;
-                    cbuff[2 * j    ] = (sumr + mpr + mnr) * scale;
-                    cbuff[2 * j + 1] = (sumi + mpi + mni) * scale;
+    float *cbuffer = p->buffer[jobnr][CURRENT];
+    const int method = s->method;
+    float *cbuff = cbuffer;
+    float *pbuff = pbuffer;
+    float *nbuff = nbuffer;
+
+    for (int i = 0; i < block; i++) {
+        for (int j = 0; j < block; j++) {
+            AVComplexFloat buffer[BSIZE];
+            AVComplexFloat outbuffer[BSIZE];
+
+            buffer[0].re = pbuff[2 * j    ];
+            buffer[0].im = pbuff[2 * j + 1];
+
+            buffer[1].re = cbuff[2 * j    ];
+            buffer[1].im = cbuff[2 * j + 1];
+
+            buffer[2].re = nbuff[2 * j    ];
+            buffer[2].im = nbuff[2 * j + 1];
+
+            s->tx_r_fn(s->fft_r[jobnr], outbuffer, buffer, sizeof(float));
+
+            for (int z = 0; z < 3; z++) {
+                const float re = outbuffer[z].re;
+                const float im = outbuffer[z].im;
+                const float power = re * re + im * im;;
+                float factor;
+
+                switch (method) {
+                case 0:
+                    factor = fmaxf(limit, (power - sigma) / (power + 1e-15f));
+                    break;
+                case 1:
+                    factor = power < sigma ? limit : 1.f;
+                    break;
                 }
 
-                cbuff += buffer_linesize;
-                pbuff += buffer_linesize;
-                nbuff += buffer_linesize;
+                outbuffer[z].re *= factor;
+                outbuffer[z].im *= factor;
             }
+
+            s->itx_r_fn(s->ifft_r[jobnr], buffer, outbuffer, sizeof(float));
+
+            cbuff[2 * j + 0] = buffer[1].re;
+            cbuff[2 * j + 1] = buffer[1].im;
         }
+
+        cbuff += buffer_linesize;
+        pbuff += buffer_linesize;
+        nbuff += buffer_linesize;
     }
 }
 
-static void filter_plane3d1(FFTdnoizContext *s, int plane, float *pbuffer,
-                            int jobnr, int nb_jobs)
+static void filter_block3d1(FFTdnoizContext *s, int plane, float *pbuffer,
+                            int jobnr)
 {
     PlaneContext *p = &s->planes[plane];
     const int block = p->b;
-    const int nox = p->nox;
-    const int noy = p->noy;
     const int buffer_linesize = p->buffer_linesize / sizeof(float);
     const float depthx = (1 << (s->depth - 8)) * (1 << (s->depth - 8));
-    const float sigma = s->sigma * depthx / (s->block_size * s->block_size);
-    const int slice_start = (noy * jobnr) / nb_jobs;
-    const int slice_end = (noy * (jobnr+1)) / nb_jobs;
+    const float sigma = s->sigma * depthx / (2.f * s->block_size * s->block_size);
     const float limit = 1.f - s->amount;
-    float *cbuffer = p->buffer[CURRENT];
-    int y, x, i, j;
-
-    for (y = slice_start; y < slice_end; y++) {
-        for (x = 0; x < nox; x++) {
-            float *cbuff = cbuffer + buffer_linesize * y * block + x * block * 2;
-            float *pbuff = pbuffer + buffer_linesize * y * block + x * block * 2;
-
-            for (i = 0; i < block; i++) {
-                for (j = 0; j < block; j++) {
-                    float factor, power, re, im, pre, pim;
-                    float sumr, sumi, difr, difi;
-
-                    re = cbuff[j * 2    ];
-                    pre = pbuff[j * 2    ];
-                    im = cbuff[j * 2 + 1];
-                    pim = pbuff[j * 2 + 1];
-
-                    sumr = re + pre;
-                    sumi = im + pim;
-                    difr = re - pre;
-                    difi = im - pim;
-
-                    power = sumr * sumr + sumi * sumi;
-                    factor = fmaxf(limit, (power - sigma) / (power + 1e-15f));
-                    sumr *= factor;
-                    sumi *= factor;
-                    power = difr * difr + difi * difi;
-                    factor = fmaxf(limit, (power - sigma) / (power + 1e-15f));
-                    difr *= factor;
-                    difi *= factor;
+    float *cbuffer = p->buffer[jobnr][CURRENT];
+    const int method = s->method;
+    float *cbuff = cbuffer;
+    float *pbuff = pbuffer;
+
+    for (int i = 0; i < block; i++) {
+        for (int j = 0; j < block; j++) {
+            AVComplexFloat buffer[BSIZE];
+            AVComplexFloat outbuffer[BSIZE];
+
+            buffer[0].re = pbuff[2 * j    ];
+            buffer[0].im = pbuff[2 * j + 1];
+
+            buffer[1].re = cbuff[2 * j    ];
+            buffer[1].im = cbuff[2 * j + 1];
+
+            s->tx_r_fn(s->fft_r[jobnr], outbuffer, buffer, sizeof(float));
 
-                    cbuff[j * 2    ] = (sumr + difr) * 0.5f;
-                    cbuff[j * 2 + 1] = (sumi + difi) * 0.5f;
+            for (int z = 0; z < 2; z++) {
+                const float re = outbuffer[z].re;
+                const float im = outbuffer[z].im;
+                const float power = re * re + im * im;;
+                float factor;
+
+                switch (method) {
+                case 0:
+                    factor = fmaxf(limit, (power - sigma) / (power + 1e-15f));
+                    break;
+                case 1:
+                    factor = power < sigma ? limit : 1.f;
+                    break;
                 }
 
-                cbuff += buffer_linesize;
-                pbuff += buffer_linesize;
+                outbuffer[z].re *= factor;
+                outbuffer[z].im *= factor;
             }
+
+            s->itx_r_fn(s->ifft_r[jobnr], buffer, outbuffer, sizeof(float));
+
+            cbuff[2 * j + 0] = buffer[1].re;
+            cbuff[2 * j + 1] = buffer[1].im;
         }
+
+        cbuff += buffer_linesize;
+        pbuff += buffer_linesize;
     }
 }
 
-static void filter_plane2d(FFTdnoizContext *s, int plane,
-                           int jobnr, int nb_jobs)
+static void filter_block2d(FFTdnoizContext *s, int plane,
+                           int jobnr)
 {
     PlaneContext *p = &s->planes[plane];
     const int block = p->b;
-    const int nox = p->nox;
-    const int noy = p->noy;
     const int method = s->method;
     const int buffer_linesize = p->buffer_linesize / sizeof(float);
     const float depthx = (1 << (s->depth - 8)) * (1 << (s->depth - 8));
     const float sigma = s->sigma * depthx / (s->block_size * s->block_size);
     const float limit = 1.f - s->amount;
-    const int slice_start = (noy * jobnr) / nb_jobs;
-    const int slice_end = (noy * (jobnr+1)) / nb_jobs;
-    float *buffer = p->buffer[CURRENT];
-
-    for (int y = slice_start; y < slice_end; y++) {
-        for (int x = 0; x < nox; x++) {
-            float *buff = buffer + buffer_linesize * y * block + x * block * 2;
-
-            for (int i = 0; i < block; i++) {
-                for (int j = 0; j < block; j++) {
-                    float factor, power, re, im;
-
-                    re = buff[j * 2    ];
-                    im = buff[j * 2 + 1];
-                    power = re * re + im * im;
-                    switch (method) {
-                    case 0:
-                        factor = fmaxf(limit, (power - sigma) / (power + 1e-15f));
-                        break;
-                    case 1:
-                        factor = power < sigma ? limit : 1.f;
-                        break;
-                    }
-
-                    buff[j * 2    ] *= factor;
-                    buff[j * 2 + 1] *= factor;
-                }
+    float *buff = p->buffer[jobnr][CURRENT];
 
-                buff += buffer_linesize;
-            }
-        }
-    }
-}
-
-static int import_pass(AVFilterContext *ctx, void *arg,
-                       int jobnr, int nb_jobs)
-{
-    FFTdnoizContext *s = ctx->priv;
+    for (int i = 0; i < block; i++) {
+        for (int j = 0; j < block; j++) {
+            float factor, power, re, im;
 
-    for (int plane = 0; plane < s->nb_planes; plane++) {
-        PlaneContext *p = &s->planes[plane];
-
-        if (!((1 << plane) & s->planesf) || ctx->is_disabled)
-            continue;
-
-        if (s->next) {
-            import_plane(s, s->next->data[plane], s->next->linesize[plane],
-                         p->buffer[NEXT], p->buffer_linesize, plane,
-                         jobnr, nb_jobs);
-        }
+            re = buff[j * 2    ];
+            im = buff[j * 2 + 1];
+            power = re * re + im * im;
+            switch (method) {
+                case 0:
+                    factor = fmaxf(limit, (power - sigma) / (power + 1e-15f));
+                    break;
+                case 1:
+                    factor = power < sigma ? limit : 1.f;
+                    break;
+            }
 
-        if (s->prev) {
-            import_plane(s, s->prev->data[plane], s->prev->linesize[plane],
-                         p->buffer[PREV], p->buffer_linesize, plane,
-                         jobnr, nb_jobs);
+            buff[j * 2    ] *= factor;
+            buff[j * 2 + 1] *= factor;
         }
 
-        import_plane(s, s->cur->data[plane], s->cur->linesize[plane],
-                     p->buffer[CURRENT], p->buffer_linesize, plane,
-                     jobnr, nb_jobs);
+        buff += buffer_linesize;
     }
-
-    return 0;
 }
 
-static int filter_pass(AVFilterContext *ctx, void *arg,
-                       int jobnr, int nb_jobs)
+static int denoise(AVFilterContext *ctx, void *arg,
+                   int jobnr, int nb_jobs)
 {
     FFTdnoizContext *s = ctx->priv;
+    AVFrame *out = arg;
 
     for (int plane = 0; plane < s->nb_planes; plane++) {
         PlaneContext *p = &s->planes[plane];
+        const int nox = p->nox;
+        const int noy = p->noy;
+        const int slice_start = (noy * jobnr) / nb_jobs;
+        const int slice_end = (noy * (jobnr+1)) / nb_jobs;
 
         if (!((1 << plane) & s->planesf) || ctx->is_disabled)
             continue;
 
-        if (s->next && s->prev) {
-            filter_plane3d2(s, plane, p->buffer[PREV], p->buffer[NEXT], jobnr, nb_jobs);
-        } else if (s->next) {
-            filter_plane3d1(s, plane, p->buffer[NEXT], jobnr, nb_jobs);
-        } else  if (s->prev) {
-            filter_plane3d1(s, plane, p->buffer[PREV], jobnr, nb_jobs);
-        } else {
-            filter_plane2d(s, plane, jobnr, nb_jobs);
-        }
-    }
-
-    return 0;
-}
-
-static int export_pass(AVFilterContext *ctx, void *arg,
-                       int jobnr, int nb_jobs)
-{
-    FFTdnoizContext *s = ctx->priv;
-    AVFrame *out = arg;
+        for (int y = slice_start; y < slice_end; y++) {
+            for (int x = 0; x < nox; x++) {
+                if (s->next) {
+                    import_block(s, s->next->data[plane], s->next->linesize[plane],
+                                 p->buffer[jobnr][NEXT], p->buffer_linesize, plane,
+                                 jobnr, y, x);
+                }
 
-    for (int plane = 0; plane < s->nb_planes; plane++) {
-        PlaneContext *p = &s->planes[plane];
+                if (s->prev) {
+                    import_block(s, s->prev->data[plane], s->prev->linesize[plane],
+                                 p->buffer[jobnr][PREV], p->buffer_linesize, plane,
+                                 jobnr, y, x);
+                }
 
-        if (!((1 << plane) & s->planesf) || ctx->is_disabled)
-            continue;
+                import_block(s, s->cur->data[plane], s->cur->linesize[plane],
+                             p->buffer[jobnr][CURRENT], p->buffer_linesize, plane,
+                             jobnr, y, x);
+
+                if (s->next && s->prev) {
+                    filter_block3d2(s, plane, p->buffer[jobnr][PREV], p->buffer[jobnr][NEXT], jobnr);
+                } else if (s->next) {
+                    filter_block3d1(s, plane, p->buffer[jobnr][NEXT], jobnr);
+                } else  if (s->prev) {
+                    filter_block3d1(s, plane, p->buffer[jobnr][PREV], jobnr);
+                } else {
+                    filter_block2d(s, plane, jobnr);
+                }
 
-        export_plane(s, out->data[plane], out->linesize[plane],
-                     p->buffer[CURRENT], p->buffer_linesize, plane,
-                     jobnr, nb_jobs);
+                export_block(s, out->data[plane], out->linesize[plane],
+                             p->buffer[jobnr][CURRENT], p->buffer_linesize, plane,
+                             jobnr, y, x);
+            }
+        }
     }
 
     return 0;
@@ -669,13 +625,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
         av_frame_copy_props(out, s->cur);
     }
 
-    ff_filter_execute(ctx, import_pass, NULL, NULL,
-                      FFMIN(s->planes[0].noy, s->nb_threads));
-
-    ff_filter_execute(ctx, filter_pass, NULL, NULL,
-                      FFMIN(s->planes[0].noy, s->nb_threads));
-
-    ff_filter_execute(ctx, export_pass, out, NULL,
+    ff_filter_execute(ctx, denoise, out, NULL,
                       FFMIN(s->planes[0].noy, s->nb_threads));
 
     for (plane = 0; plane < s->nb_planes; plane++) {
@@ -742,16 +692,17 @@ static av_cold void uninit(AVFilterContext *ctx)
             av_freep(&p->vdata[j]);
             av_freep(&p->hdata_out[j]);
             av_freep(&p->vdata_out[j]);
+            av_freep(&p->buffer[j][PREV]);
+            av_freep(&p->buffer[j][CURRENT]);
+            av_freep(&p->buffer[j][NEXT]);
         }
-
-        av_freep(&p->buffer[PREV]);
-        av_freep(&p->buffer[CURRENT]);
-        av_freep(&p->buffer[NEXT]);
     }
 
     for (i = 0; i < s->nb_threads; i++) {
         av_tx_uninit(&s->fft[i]);
         av_tx_uninit(&s->ifft[i]);
+        av_tx_uninit(&s->fft_r[i]);
+        av_tx_uninit(&s->ifft_r[i]);
     }
 
     av_frame_free(&s->prev);



More information about the ffmpeg-cvslog mailing list