vf_fftdnoiz.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  1. /*
  2. * This file is part of FFmpeg.
  3. *
  4. * FFmpeg is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * FFmpeg is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with FFmpeg; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include <float.h>
  19. #include "libavutil/avassert.h"
  20. #include "libavutil/common.h"
  21. #include "libavutil/imgutils.h"
  22. #include "libavutil/opt.h"
  23. #include "libavutil/pixdesc.h"
  24. #include "internal.h"
  25. #include "libavcodec/avfft.h"
  26. enum BufferTypes {
  27. CURRENT,
  28. PREV,
  29. NEXT,
  30. BSIZE
  31. };
  32. typedef struct PlaneContext {
  33. int planewidth, planeheight;
  34. int nox, noy;
  35. int b;
  36. int o;
  37. float n;
  38. float *buffer[BSIZE];
  39. FFTComplex *hdata, *vdata;
  40. int data_linesize;
  41. int buffer_linesize;
  42. FFTContext *fft, *ifft;
  43. } PlaneContext;
  44. typedef struct FFTdnoizContext {
  45. const AVClass *class;
  46. float sigma;
  47. float amount;
  48. int block_bits;
  49. float overlap;
  50. int nb_prev;
  51. int nb_next;
  52. int planesf;
  53. AVFrame *prev, *cur, *next;
  54. int depth;
  55. int nb_planes;
  56. PlaneContext planes[4];
  57. void (*import_row)(FFTComplex *dst, uint8_t *src, int rw);
  58. void (*export_row)(FFTComplex *src, uint8_t *dst, int rw, float scale, int depth);
  59. } FFTdnoizContext;
  60. #define OFFSET(x) offsetof(FFTdnoizContext, x)
  61. #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
  62. static const AVOption fftdnoiz_options[] = {
  63. { "sigma", "set denoise strength",
  64. OFFSET(sigma), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 30, .flags = FLAGS },
  65. { "amount", "set amount of denoising",
  66. OFFSET(amount), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0.01, 1, .flags = FLAGS },
  67. { "block", "set block log2(size)",
  68. OFFSET(block_bits), AV_OPT_TYPE_INT, {.i64=4}, 3, 6, .flags = FLAGS },
  69. { "overlap", "set block overlap",
  70. OFFSET(overlap), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0.2, 0.8, .flags = FLAGS },
  71. { "prev", "set number of previous frames for temporal denoising",
  72. OFFSET(nb_prev), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, .flags = FLAGS },
  73. { "next", "set number of next frames for temporal denoising",
  74. OFFSET(nb_next), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, .flags = FLAGS },
  75. { "planes", "set planes to filter",
  76. OFFSET(planesf), AV_OPT_TYPE_INT, {.i64=7}, 0, 15, .flags = FLAGS },
  77. { NULL }
  78. };
  79. AVFILTER_DEFINE_CLASS(fftdnoiz);
  80. static av_cold int init(AVFilterContext *ctx)
  81. {
  82. FFTdnoizContext *s = ctx->priv;
  83. int i;
  84. for (i = 0; i < 4; i++) {
  85. PlaneContext *p = &s->planes[i];
  86. p->fft = av_fft_init(s->block_bits, 0);
  87. p->ifft = av_fft_init(s->block_bits, 1);
  88. if (!p->fft || !p->ifft)
  89. return AVERROR(ENOMEM);
  90. }
  91. return 0;
  92. }
  93. static int query_formats(AVFilterContext *ctx)
  94. {
  95. static const enum AVPixelFormat pix_fmts[] = {
  96. AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9,
  97. AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12,
  98. AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16,
  99. AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P,
  100. AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P,
  101. AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P,
  102. AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P,
  103. AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ444P,
  104. AV_PIX_FMT_YUVJ411P,
  105. AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9,
  106. AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10,
  107. AV_PIX_FMT_YUV440P10,
  108. AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12,
  109. AV_PIX_FMT_YUV440P12,
  110. AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV420P14,
  111. AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16,
  112. AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10,
  113. AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16,
  114. AV_PIX_FMT_NONE
  115. };
  116. AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
  117. if (!fmts_list)
  118. return AVERROR(ENOMEM);
  119. return ff_set_common_formats(ctx, fmts_list);
  120. }
  121. typedef struct ThreadData {
  122. float *src, *dst;
  123. } ThreadData;
  124. static void import_row8(FFTComplex *dst, uint8_t *src, int rw)
  125. {
  126. int j;
  127. for (j = 0; j < rw; j++) {
  128. dst[j].re = src[j];
  129. dst[j].im = 0;
  130. }
  131. }
  132. static void export_row8(FFTComplex *src, uint8_t *dst, int rw, float scale, int depth)
  133. {
  134. int j;
  135. for (j = 0; j < rw; j++)
  136. dst[j] = av_clip_uint8(src[j].re * scale);
  137. }
  138. static void import_row16(FFTComplex *dst, uint8_t *srcp, int rw)
  139. {
  140. uint16_t *src = (uint16_t *)srcp;
  141. int j;
  142. for (j = 0; j < rw; j++) {
  143. dst[j].re = src[j];
  144. dst[j].im = 0;
  145. }
  146. }
  147. static void export_row16(FFTComplex *src, uint8_t *dstp, int rw, float scale, int depth)
  148. {
  149. uint16_t *dst = (uint16_t *)dstp;
  150. int j;
  151. for (j = 0; j < rw; j++)
  152. dst[j] = av_clip_uintp2_c(src[j].re * scale, depth);
  153. }
  154. static int config_input(AVFilterLink *inlink)
  155. {
  156. AVFilterContext *ctx = inlink->dst;
  157. const AVPixFmtDescriptor *desc;
  158. FFTdnoizContext *s = ctx->priv;
  159. int i;
  160. desc = av_pix_fmt_desc_get(inlink->format);
  161. s->depth = desc->comp[0].depth;
  162. if (s->depth <= 8) {
  163. s->import_row = import_row8;
  164. s->export_row = export_row8;
  165. } else {
  166. s->import_row = import_row16;
  167. s->export_row = export_row16;
  168. s->sigma *= 1 << (s->depth - 8) * (1 + s->nb_prev + s->nb_next);
  169. }
  170. s->planes[1].planewidth = s->planes[2].planewidth = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w);
  171. s->planes[0].planewidth = s->planes[3].planewidth = inlink->w;
  172. s->planes[1].planeheight = s->planes[2].planeheight = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
  173. s->planes[0].planeheight = s->planes[3].planeheight = inlink->h;
  174. s->nb_planes = av_pix_fmt_count_planes(inlink->format);
  175. for (i = 0; i < s->nb_planes; i++) {
  176. PlaneContext *p = &s->planes[i];
  177. int size;
  178. p->b = 1 << s->block_bits;
  179. p->n = 1.f / (p->b * p->b);
  180. p->o = p->b * s->overlap;
  181. size = p->b - p->o;
  182. p->nox = (p->planewidth + (size - 1)) / size;
  183. p->noy = (p->planeheight + (size - 1)) / size;
  184. av_log(ctx, AV_LOG_DEBUG, "nox:%d noy:%d size:%d\n", p->nox, p->noy, size);
  185. p->buffer_linesize = p->b * p->nox * sizeof(FFTComplex);
  186. p->buffer[CURRENT] = av_calloc(p->b * p->noy, p->buffer_linesize);
  187. if (!p->buffer[CURRENT])
  188. return AVERROR(ENOMEM);
  189. if (s->nb_prev > 0) {
  190. p->buffer[PREV] = av_calloc(p->b * p->noy, p->buffer_linesize);
  191. if (!p->buffer[PREV])
  192. return AVERROR(ENOMEM);
  193. }
  194. if (s->nb_next > 0) {
  195. p->buffer[NEXT] = av_calloc(p->b * p->noy, p->buffer_linesize);
  196. if (!p->buffer[NEXT])
  197. return AVERROR(ENOMEM);
  198. }
  199. p->data_linesize = 2 * p->b * sizeof(float);
  200. p->hdata = av_calloc(p->b, p->data_linesize);
  201. p->vdata = av_calloc(p->b, p->data_linesize);
  202. if (!p->hdata || !p->vdata)
  203. return AVERROR(ENOMEM);
  204. }
  205. return 0;
  206. }
  207. static void import_plane(FFTdnoizContext *s,
  208. uint8_t *srcp, int src_linesize,
  209. float *buffer, int buffer_linesize, int plane)
  210. {
  211. PlaneContext *p = &s->planes[plane];
  212. const int width = p->planewidth;
  213. const int height = p->planeheight;
  214. const int block = p->b;
  215. const int overlap = p->o;
  216. const int size = block - overlap;
  217. const int nox = p->nox;
  218. const int noy = p->noy;
  219. const int bpp = (s->depth + 7) / 8;
  220. const int data_linesize = p->data_linesize / sizeof(FFTComplex);
  221. FFTComplex *hdata = p->hdata;
  222. FFTComplex *vdata = p->vdata;
  223. int x, y, i, j;
  224. buffer_linesize /= sizeof(float);
  225. for (y = 0; y < noy; y++) {
  226. for (x = 0; x < nox; x++) {
  227. const int rh = FFMIN(block, height - y * size);
  228. const int rw = FFMIN(block, width - x * size);
  229. uint8_t *src = srcp + src_linesize * y * size + x * size * bpp;
  230. float *bdst = buffer + buffer_linesize * y * block + x * block * 2;
  231. FFTComplex *ssrc, *dst = hdata;
  232. for (i = 0; i < rh; i++) {
  233. s->import_row(dst, src, rw);
  234. for (j = rw; j < block; j++) {
  235. dst[j].re = dst[block - j - 1].re;
  236. dst[j].im = 0;
  237. }
  238. av_fft_permute(p->fft, dst);
  239. av_fft_calc(p->fft, dst);
  240. src += src_linesize;
  241. dst += data_linesize;
  242. }
  243. dst = hdata;
  244. for (; i < block; i++) {
  245. for (j = 0; j < block; j++) {
  246. dst[j].re = dst[(block - i - 1) * data_linesize + j].re;
  247. dst[j].im = dst[(block - i - 1) * data_linesize + j].im;
  248. }
  249. }
  250. ssrc = hdata;
  251. dst = vdata;
  252. for (i = 0; i < block; i++) {
  253. for (j = 0; j < block; j++)
  254. dst[j] = ssrc[j * data_linesize + i];
  255. av_fft_permute(p->fft, dst);
  256. av_fft_calc(p->fft, dst);
  257. memcpy(bdst, dst, block * sizeof(FFTComplex));
  258. dst += data_linesize;
  259. bdst += buffer_linesize;
  260. }
  261. }
  262. }
  263. }
  264. static void export_plane(FFTdnoizContext *s,
  265. uint8_t *dstp, int dst_linesize,
  266. float *buffer, int buffer_linesize, int plane)
  267. {
  268. PlaneContext *p = &s->planes[plane];
  269. const int depth = s->depth;
  270. const int bpp = (depth + 7) / 8;
  271. const int width = p->planewidth;
  272. const int height = p->planeheight;
  273. const int block = p->b;
  274. const int overlap = p->o;
  275. const int hoverlap = overlap / 2;
  276. const int size = block - overlap;
  277. const int nox = p->nox;
  278. const int noy = p->noy;
  279. const int data_linesize = p->data_linesize / sizeof(FFTComplex);
  280. const float scale = 1.f / (block * block);
  281. FFTComplex *hdata = p->hdata;
  282. FFTComplex *vdata = p->vdata;
  283. int x, y, i, j;
  284. buffer_linesize /= sizeof(float);
  285. for (y = 0; y < noy; y++) {
  286. for (x = 0; x < nox; x++) {
  287. const int woff = x == 0 ? 0 : hoverlap;
  288. const int hoff = y == 0 ? 0 : hoverlap;
  289. const int rw = x == 0 ? block : FFMIN(size, width - x * size - woff);
  290. const int rh = y == 0 ? block : FFMIN(size, height - y * size - hoff);
  291. float *bsrc = buffer + buffer_linesize * y * block + x * block * 2;
  292. uint8_t *dst = dstp + dst_linesize * (y * size + hoff) + (x * size + woff) * bpp;
  293. FFTComplex *hdst, *ddst = vdata;
  294. hdst = hdata;
  295. for (i = 0; i < block; i++) {
  296. memcpy(ddst, bsrc, block * sizeof(FFTComplex));
  297. av_fft_permute(p->ifft, ddst);
  298. av_fft_calc(p->ifft, ddst);
  299. for (j = 0; j < block; j++) {
  300. hdst[j * data_linesize + i] = ddst[j];
  301. }
  302. ddst += data_linesize;
  303. bsrc += buffer_linesize;
  304. }
  305. hdst = hdata + hoff * data_linesize;
  306. for (i = 0; i < rh; i++) {
  307. av_fft_permute(p->ifft, hdst);
  308. av_fft_calc(p->ifft, hdst);
  309. s->export_row(hdst + woff, dst, rw, scale, depth);
  310. hdst += data_linesize;
  311. dst += dst_linesize;
  312. }
  313. }
  314. }
  315. }
  316. static void filter_plane3d2(FFTdnoizContext *s, int plane, float *pbuffer, float *nbuffer)
  317. {
  318. PlaneContext *p = &s->planes[plane];
  319. const int block = p->b;
  320. const int nox = p->nox;
  321. const int noy = p->noy;
  322. const int buffer_linesize = p->buffer_linesize / sizeof(float);
  323. const float sigma = s->sigma * s->sigma * block * block;
  324. const float limit = 1.f - s->amount;
  325. float *cbuffer = p->buffer[CURRENT];
  326. const float cfactor = sqrtf(3.f) * 0.5f;
  327. const float scale = 1.f / 3.f;
  328. int y, x, i, j;
  329. for (y = 0; y < noy; y++) {
  330. for (x = 0; x < nox; x++) {
  331. float *cbuff = cbuffer + buffer_linesize * y * block + x * block * 2;
  332. float *pbuff = pbuffer + buffer_linesize * y * block + x * block * 2;
  333. float *nbuff = nbuffer + buffer_linesize * y * block + x * block * 2;
  334. for (i = 0; i < block; i++) {
  335. for (j = 0; j < block; j++) {
  336. float sumr, sumi, difr, difi, mpr, mpi, mnr, mni;
  337. float factor, power, sumpnr, sumpni;
  338. sumpnr = pbuff[2 * j ] + nbuff[2 * j ];
  339. sumpni = pbuff[2 * j + 1] + nbuff[2 * j + 1];
  340. sumr = cbuff[2 * j ] + sumpnr;
  341. sumi = cbuff[2 * j + 1] + sumpni;
  342. difr = cfactor * (nbuff[2 * j ] - pbuff[2 * j ]);
  343. difi = cfactor * (pbuff[2 * j + 1] - nbuff[2 * j + 1]);
  344. mpr = cbuff[2 * j ] - 0.5f * sumpnr + difi;
  345. mnr = mpr - difi - difi;
  346. mpi = cbuff[2 * j + 1] - 0.5f * sumpni + difr;
  347. mni = mpi - difr - difr;
  348. power = sumr * sumr + sumi * sumi + 1e-15f;
  349. factor = FFMAX((power - sigma) / power, limit);
  350. sumr *= factor;
  351. sumi *= factor;
  352. power = mpr * mpr + mpi * mpi + 1e-15f;
  353. factor = FFMAX((power - sigma) / power, limit);
  354. mpr *= factor;
  355. mpi *= factor;
  356. power = mnr * mnr + mni * mni + 1e-15f;
  357. factor = FFMAX((power - sigma) / power, limit);
  358. mnr *= factor;
  359. mni *= factor;
  360. cbuff[2 * j ] = (sumr + mpr + mnr) * scale;
  361. cbuff[2 * j + 1] = (sumi + mpi + mni) * scale;
  362. }
  363. cbuff += buffer_linesize;
  364. pbuff += buffer_linesize;
  365. nbuff += buffer_linesize;
  366. }
  367. }
  368. }
  369. }
  370. static void filter_plane3d1(FFTdnoizContext *s, int plane, float *pbuffer)
  371. {
  372. PlaneContext *p = &s->planes[plane];
  373. const int block = p->b;
  374. const int nox = p->nox;
  375. const int noy = p->noy;
  376. const int buffer_linesize = p->buffer_linesize / sizeof(float);
  377. const float sigma = s->sigma * s->sigma * block * block;
  378. const float limit = 1.f - s->amount;
  379. float *cbuffer = p->buffer[CURRENT];
  380. int y, x, i, j;
  381. for (y = 0; y < noy; y++) {
  382. for (x = 0; x < nox; x++) {
  383. float *cbuff = cbuffer + buffer_linesize * y * block + x * block * 2;
  384. float *pbuff = pbuffer + buffer_linesize * y * block + x * block * 2;
  385. for (i = 0; i < block; i++) {
  386. for (j = 0; j < block; j++) {
  387. float factor, power, re, im, pre, pim;
  388. float sumr, sumi, difr, difi;
  389. re = cbuff[j * 2 ];
  390. pre = pbuff[j * 2 ];
  391. im = cbuff[j * 2 + 1];
  392. pim = pbuff[j * 2 + 1];
  393. sumr = re + pre;
  394. sumi = im + pim;
  395. difr = re - pre;
  396. difi = im - pim;
  397. power = sumr * sumr + sumi * sumi + 1e-15f;
  398. factor = FFMAX(limit, (power - sigma) / power);
  399. sumr *= factor;
  400. sumi *= factor;
  401. power = difr * difr + difi * difi + 1e-15f;
  402. factor = FFMAX(limit, (power - sigma) / power);
  403. difr *= factor;
  404. difi *= factor;
  405. cbuff[j * 2 ] = (sumr + difr) * 0.5f;
  406. cbuff[j * 2 + 1] = (sumi + difi) * 0.5f;
  407. }
  408. cbuff += buffer_linesize;
  409. pbuff += buffer_linesize;
  410. }
  411. }
  412. }
  413. }
  414. static void filter_plane2d(FFTdnoizContext *s, int plane)
  415. {
  416. PlaneContext *p = &s->planes[plane];
  417. const int block = p->b;
  418. const int nox = p->nox;
  419. const int noy = p->noy;
  420. const int buffer_linesize = p->buffer_linesize / 4;
  421. const float sigma = s->sigma * s->sigma * block * block;
  422. const float limit = 1.f - s->amount;
  423. float *buffer = p->buffer[CURRENT];
  424. int y, x, i, j;
  425. for (y = 0; y < noy; y++) {
  426. for (x = 0; x < nox; x++) {
  427. float *buff = buffer + buffer_linesize * y * block + x * block * 2;
  428. for (i = 0; i < block; i++) {
  429. for (j = 0; j < block; j++) {
  430. float factor, power, re, im;
  431. re = buff[j * 2 ];
  432. im = buff[j * 2 + 1];
  433. power = re * re + im * im + 1e-15f;
  434. factor = FFMAX(limit, (power - sigma) / power);
  435. buff[j * 2 ] *= factor;
  436. buff[j * 2 + 1] *= factor;
  437. }
  438. buff += buffer_linesize;
  439. }
  440. }
  441. }
  442. }
  443. static int filter_frame(AVFilterLink *inlink, AVFrame *in)
  444. {
  445. AVFilterContext *ctx = inlink->dst;
  446. FFTdnoizContext *s = ctx->priv;
  447. AVFilterLink *outlink = ctx->outputs[0];
  448. int direct, plane;
  449. AVFrame *out;
  450. if (s->nb_next > 0 && s->nb_prev > 0) {
  451. av_frame_free(&s->prev);
  452. s->prev = s->cur;
  453. s->cur = s->next;
  454. s->next = in;
  455. if (!s->prev && s->cur) {
  456. s->prev = av_frame_clone(s->cur);
  457. if (!s->prev)
  458. return AVERROR(ENOMEM);
  459. }
  460. if (!s->cur)
  461. return 0;
  462. } else if (s->nb_next > 0) {
  463. av_frame_free(&s->cur);
  464. s->cur = s->next;
  465. s->next = in;
  466. if (!s->cur)
  467. return 0;
  468. } else if (s->nb_prev > 0) {
  469. av_frame_free(&s->prev);
  470. s->prev = s->cur;
  471. s->cur = in;
  472. if (!s->prev)
  473. s->prev = av_frame_clone(s->cur);
  474. if (!s->prev)
  475. return AVERROR(ENOMEM);
  476. } else {
  477. s->cur = in;
  478. }
  479. if (av_frame_is_writable(in) && s->nb_next == 0 && s->nb_prev == 0) {
  480. direct = 1;
  481. out = in;
  482. } else {
  483. direct = 0;
  484. out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
  485. if (!out)
  486. return AVERROR(ENOMEM);
  487. av_frame_copy_props(out, s->cur);
  488. }
  489. for (plane = 0; plane < s->nb_planes; plane++) {
  490. PlaneContext *p = &s->planes[plane];
  491. if (!((1 << plane) & s->planesf) || ctx->is_disabled) {
  492. if (!direct)
  493. av_image_copy_plane(out->data[plane], out->linesize[plane],
  494. s->cur->data[plane], s->cur->linesize[plane],
  495. p->planewidth, p->planeheight);
  496. continue;
  497. }
  498. if (s->next) {
  499. import_plane(s, s->next->data[plane], s->next->linesize[plane],
  500. p->buffer[NEXT], p->buffer_linesize, plane);
  501. }
  502. if (s->prev) {
  503. import_plane(s, s->prev->data[plane], s->prev->linesize[plane],
  504. p->buffer[PREV], p->buffer_linesize, plane);
  505. }
  506. import_plane(s, s->cur->data[plane], s->cur->linesize[plane],
  507. p->buffer[CURRENT], p->buffer_linesize, plane);
  508. if (s->next && s->prev) {
  509. filter_plane3d2(s, plane, p->buffer[PREV], p->buffer[NEXT]);
  510. } else if (s->next) {
  511. filter_plane3d1(s, plane, p->buffer[NEXT]);
  512. } else if (s->prev) {
  513. filter_plane3d1(s, plane, p->buffer[PREV]);
  514. } else {
  515. filter_plane2d(s, plane);
  516. }
  517. export_plane(s, out->data[plane], out->linesize[plane],
  518. p->buffer[CURRENT], p->buffer_linesize, plane);
  519. }
  520. if (s->nb_next == 0 && s->nb_prev == 0) {
  521. if (direct) {
  522. s->cur = NULL;
  523. } else {
  524. av_frame_free(&s->cur);
  525. }
  526. }
  527. return ff_filter_frame(outlink, out);
  528. }
  529. static int request_frame(AVFilterLink *outlink)
  530. {
  531. AVFilterContext *ctx = outlink->src;
  532. FFTdnoizContext *s = ctx->priv;
  533. int ret = 0;
  534. ret = ff_request_frame(ctx->inputs[0]);
  535. if (ret == AVERROR_EOF && (s->nb_next > 0)) {
  536. AVFrame *buf;
  537. if (s->next && s->nb_next > 0)
  538. buf = av_frame_clone(s->next);
  539. else if (s->cur)
  540. buf = av_frame_clone(s->cur);
  541. else
  542. buf = av_frame_clone(s->prev);
  543. if (!buf)
  544. return AVERROR(ENOMEM);
  545. ret = filter_frame(ctx->inputs[0], buf);
  546. if (ret < 0)
  547. return ret;
  548. ret = AVERROR_EOF;
  549. }
  550. return ret;
  551. }
  552. static av_cold void uninit(AVFilterContext *ctx)
  553. {
  554. FFTdnoizContext *s = ctx->priv;
  555. int i;
  556. for (i = 0; i < 4; i++) {
  557. PlaneContext *p = &s->planes[i];
  558. av_freep(&p->hdata);
  559. av_freep(&p->vdata);
  560. av_freep(&p->buffer[PREV]);
  561. av_freep(&p->buffer[CURRENT]);
  562. av_freep(&p->buffer[NEXT]);
  563. av_fft_end(p->fft);
  564. av_fft_end(p->ifft);
  565. }
  566. av_frame_free(&s->prev);
  567. av_frame_free(&s->cur);
  568. av_frame_free(&s->next);
  569. }
  570. static const AVFilterPad fftdnoiz_inputs[] = {
  571. {
  572. .name = "default",
  573. .type = AVMEDIA_TYPE_VIDEO,
  574. .filter_frame = filter_frame,
  575. .config_props = config_input,
  576. },
  577. { NULL }
  578. };
  579. static const AVFilterPad fftdnoiz_outputs[] = {
  580. {
  581. .name = "default",
  582. .type = AVMEDIA_TYPE_VIDEO,
  583. .request_frame = request_frame,
  584. },
  585. { NULL }
  586. };
  587. AVFilter ff_vf_fftdnoiz = {
  588. .name = "fftdnoiz",
  589. .description = NULL_IF_CONFIG_SMALL("Denoise frames using 3D FFT."),
  590. .priv_size = sizeof(FFTdnoizContext),
  591. .init = init,
  592. .uninit = uninit,
  593. .query_formats = query_formats,
  594. .inputs = fftdnoiz_inputs,
  595. .outputs = fftdnoiz_outputs,
  596. .priv_class = &fftdnoiz_class,
  597. .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
  598. };