You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

700 lines
23KB

  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_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P,
  115. AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16,
  116. AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16,
  117. AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16,
  118. AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16,
  119. AV_PIX_FMT_NONE
  120. };
  121. AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
  122. if (!fmts_list)
  123. return AVERROR(ENOMEM);
  124. return ff_set_common_formats(ctx, fmts_list);
  125. }
  126. typedef struct ThreadData {
  127. float *src, *dst;
  128. } ThreadData;
  129. static void import_row8(FFTComplex *dst, uint8_t *src, int rw)
  130. {
  131. int j;
  132. for (j = 0; j < rw; j++) {
  133. dst[j].re = src[j];
  134. dst[j].im = 0;
  135. }
  136. }
  137. static void export_row8(FFTComplex *src, uint8_t *dst, int rw, float scale, int depth)
  138. {
  139. int j;
  140. for (j = 0; j < rw; j++)
  141. dst[j] = av_clip_uint8(src[j].re * scale + 0.5f);
  142. }
  143. static void import_row16(FFTComplex *dst, uint8_t *srcp, int rw)
  144. {
  145. uint16_t *src = (uint16_t *)srcp;
  146. int j;
  147. for (j = 0; j < rw; j++) {
  148. dst[j].re = src[j];
  149. dst[j].im = 0;
  150. }
  151. }
  152. static void export_row16(FFTComplex *src, uint8_t *dstp, int rw, float scale, int depth)
  153. {
  154. uint16_t *dst = (uint16_t *)dstp;
  155. int j;
  156. for (j = 0; j < rw; j++)
  157. dst[j] = av_clip_uintp2_c(src[j].re * scale + 0.5f, depth);
  158. }
  159. static int config_input(AVFilterLink *inlink)
  160. {
  161. AVFilterContext *ctx = inlink->dst;
  162. const AVPixFmtDescriptor *desc;
  163. FFTdnoizContext *s = ctx->priv;
  164. int i;
  165. desc = av_pix_fmt_desc_get(inlink->format);
  166. s->depth = desc->comp[0].depth;
  167. if (s->depth <= 8) {
  168. s->import_row = import_row8;
  169. s->export_row = export_row8;
  170. } else {
  171. s->import_row = import_row16;
  172. s->export_row = export_row16;
  173. s->sigma *= 1 << (s->depth - 8) * (1 + s->nb_prev + s->nb_next);
  174. }
  175. s->planes[1].planewidth = s->planes[2].planewidth = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w);
  176. s->planes[0].planewidth = s->planes[3].planewidth = inlink->w;
  177. s->planes[1].planeheight = s->planes[2].planeheight = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
  178. s->planes[0].planeheight = s->planes[3].planeheight = inlink->h;
  179. s->nb_planes = av_pix_fmt_count_planes(inlink->format);
  180. for (i = 0; i < s->nb_planes; i++) {
  181. PlaneContext *p = &s->planes[i];
  182. int size;
  183. p->b = 1 << s->block_bits;
  184. p->n = 1.f / (p->b * p->b);
  185. p->o = p->b * s->overlap;
  186. size = p->b - p->o;
  187. p->nox = (p->planewidth + (size - 1)) / size;
  188. p->noy = (p->planeheight + (size - 1)) / size;
  189. av_log(ctx, AV_LOG_DEBUG, "nox:%d noy:%d size:%d\n", p->nox, p->noy, size);
  190. p->buffer_linesize = p->b * p->nox * sizeof(FFTComplex);
  191. p->buffer[CURRENT] = av_calloc(p->b * p->noy, p->buffer_linesize);
  192. if (!p->buffer[CURRENT])
  193. return AVERROR(ENOMEM);
  194. if (s->nb_prev > 0) {
  195. p->buffer[PREV] = av_calloc(p->b * p->noy, p->buffer_linesize);
  196. if (!p->buffer[PREV])
  197. return AVERROR(ENOMEM);
  198. }
  199. if (s->nb_next > 0) {
  200. p->buffer[NEXT] = av_calloc(p->b * p->noy, p->buffer_linesize);
  201. if (!p->buffer[NEXT])
  202. return AVERROR(ENOMEM);
  203. }
  204. p->data_linesize = 2 * p->b * sizeof(float);
  205. p->hdata = av_calloc(p->b, p->data_linesize);
  206. p->vdata = av_calloc(p->b, p->data_linesize);
  207. if (!p->hdata || !p->vdata)
  208. return AVERROR(ENOMEM);
  209. }
  210. return 0;
  211. }
  212. static void import_plane(FFTdnoizContext *s,
  213. uint8_t *srcp, int src_linesize,
  214. float *buffer, int buffer_linesize, int plane)
  215. {
  216. PlaneContext *p = &s->planes[plane];
  217. const int width = p->planewidth;
  218. const int height = p->planeheight;
  219. const int block = p->b;
  220. const int overlap = p->o;
  221. const int size = block - overlap;
  222. const int nox = p->nox;
  223. const int noy = p->noy;
  224. const int bpp = (s->depth + 7) / 8;
  225. const int data_linesize = p->data_linesize / sizeof(FFTComplex);
  226. FFTComplex *hdata = p->hdata;
  227. FFTComplex *vdata = p->vdata;
  228. int x, y, i, j;
  229. buffer_linesize /= sizeof(float);
  230. for (y = 0; y < noy; y++) {
  231. for (x = 0; x < nox; x++) {
  232. const int rh = FFMIN(block, height - y * size);
  233. const int rw = FFMIN(block, width - x * size);
  234. uint8_t *src = srcp + src_linesize * y * size + x * size * bpp;
  235. float *bdst = buffer + buffer_linesize * y * block + x * block * 2;
  236. FFTComplex *ssrc, *dst = hdata;
  237. for (i = 0; i < rh; i++) {
  238. s->import_row(dst, src, rw);
  239. for (j = rw; j < block; j++) {
  240. dst[j].re = dst[block - j - 1].re;
  241. dst[j].im = 0;
  242. }
  243. av_fft_permute(p->fft, dst);
  244. av_fft_calc(p->fft, dst);
  245. src += src_linesize;
  246. dst += data_linesize;
  247. }
  248. dst = hdata;
  249. for (; i < block; i++) {
  250. for (j = 0; j < block; j++) {
  251. dst[j].re = dst[(block - i - 1) * data_linesize + j].re;
  252. dst[j].im = dst[(block - i - 1) * data_linesize + j].im;
  253. }
  254. }
  255. ssrc = hdata;
  256. dst = vdata;
  257. for (i = 0; i < block; i++) {
  258. for (j = 0; j < block; j++)
  259. dst[j] = ssrc[j * data_linesize + i];
  260. av_fft_permute(p->fft, dst);
  261. av_fft_calc(p->fft, dst);
  262. memcpy(bdst, dst, block * sizeof(FFTComplex));
  263. dst += data_linesize;
  264. bdst += buffer_linesize;
  265. }
  266. }
  267. }
  268. }
  269. static void export_plane(FFTdnoizContext *s,
  270. uint8_t *dstp, int dst_linesize,
  271. float *buffer, int buffer_linesize, int plane)
  272. {
  273. PlaneContext *p = &s->planes[plane];
  274. const int depth = s->depth;
  275. const int bpp = (depth + 7) / 8;
  276. const int width = p->planewidth;
  277. const int height = p->planeheight;
  278. const int block = p->b;
  279. const int overlap = p->o;
  280. const int hoverlap = overlap / 2;
  281. const int size = block - overlap;
  282. const int nox = p->nox;
  283. const int noy = p->noy;
  284. const int data_linesize = p->data_linesize / sizeof(FFTComplex);
  285. const float scale = 1.f / (block * block);
  286. FFTComplex *hdata = p->hdata;
  287. FFTComplex *vdata = p->vdata;
  288. int x, y, i, j;
  289. buffer_linesize /= sizeof(float);
  290. for (y = 0; y < noy; y++) {
  291. for (x = 0; x < nox; x++) {
  292. const int woff = x == 0 ? 0 : hoverlap;
  293. const int hoff = y == 0 ? 0 : hoverlap;
  294. const int rw = x == 0 ? block : FFMIN(size, width - x * size - woff);
  295. const int rh = y == 0 ? block : FFMIN(size, height - y * size - hoff);
  296. float *bsrc = buffer + buffer_linesize * y * block + x * block * 2;
  297. uint8_t *dst = dstp + dst_linesize * (y * size + hoff) + (x * size + woff) * bpp;
  298. FFTComplex *hdst, *ddst = vdata;
  299. hdst = hdata;
  300. for (i = 0; i < block; i++) {
  301. memcpy(ddst, bsrc, block * sizeof(FFTComplex));
  302. av_fft_permute(p->ifft, ddst);
  303. av_fft_calc(p->ifft, ddst);
  304. for (j = 0; j < block; j++) {
  305. hdst[j * data_linesize + i] = ddst[j];
  306. }
  307. ddst += data_linesize;
  308. bsrc += buffer_linesize;
  309. }
  310. hdst = hdata + hoff * data_linesize;
  311. for (i = 0; i < rh; i++) {
  312. av_fft_permute(p->ifft, hdst);
  313. av_fft_calc(p->ifft, hdst);
  314. s->export_row(hdst + woff, dst, rw, scale, depth);
  315. hdst += data_linesize;
  316. dst += dst_linesize;
  317. }
  318. }
  319. }
  320. }
  321. static void filter_plane3d2(FFTdnoizContext *s, int plane, float *pbuffer, float *nbuffer)
  322. {
  323. PlaneContext *p = &s->planes[plane];
  324. const int block = p->b;
  325. const int nox = p->nox;
  326. const int noy = p->noy;
  327. const int buffer_linesize = p->buffer_linesize / sizeof(float);
  328. const float sigma = s->sigma * s->sigma * block * block;
  329. const float limit = 1.f - s->amount;
  330. float *cbuffer = p->buffer[CURRENT];
  331. const float cfactor = sqrtf(3.f) * 0.5f;
  332. const float scale = 1.f / 3.f;
  333. int y, x, i, j;
  334. for (y = 0; y < noy; y++) {
  335. for (x = 0; x < nox; x++) {
  336. float *cbuff = cbuffer + buffer_linesize * y * block + x * block * 2;
  337. float *pbuff = pbuffer + buffer_linesize * y * block + x * block * 2;
  338. float *nbuff = nbuffer + buffer_linesize * y * block + x * block * 2;
  339. for (i = 0; i < block; i++) {
  340. for (j = 0; j < block; j++) {
  341. float sumr, sumi, difr, difi, mpr, mpi, mnr, mni;
  342. float factor, power, sumpnr, sumpni;
  343. sumpnr = pbuff[2 * j ] + nbuff[2 * j ];
  344. sumpni = pbuff[2 * j + 1] + nbuff[2 * j + 1];
  345. sumr = cbuff[2 * j ] + sumpnr;
  346. sumi = cbuff[2 * j + 1] + sumpni;
  347. difr = cfactor * (nbuff[2 * j ] - pbuff[2 * j ]);
  348. difi = cfactor * (pbuff[2 * j + 1] - nbuff[2 * j + 1]);
  349. mpr = cbuff[2 * j ] - 0.5f * sumpnr + difi;
  350. mnr = mpr - difi - difi;
  351. mpi = cbuff[2 * j + 1] - 0.5f * sumpni + difr;
  352. mni = mpi - difr - difr;
  353. power = sumr * sumr + sumi * sumi + 1e-15f;
  354. factor = FFMAX((power - sigma) / power, limit);
  355. sumr *= factor;
  356. sumi *= factor;
  357. power = mpr * mpr + mpi * mpi + 1e-15f;
  358. factor = FFMAX((power - sigma) / power, limit);
  359. mpr *= factor;
  360. mpi *= factor;
  361. power = mnr * mnr + mni * mni + 1e-15f;
  362. factor = FFMAX((power - sigma) / power, limit);
  363. mnr *= factor;
  364. mni *= factor;
  365. cbuff[2 * j ] = (sumr + mpr + mnr) * scale;
  366. cbuff[2 * j + 1] = (sumi + mpi + mni) * scale;
  367. }
  368. cbuff += buffer_linesize;
  369. pbuff += buffer_linesize;
  370. nbuff += buffer_linesize;
  371. }
  372. }
  373. }
  374. }
  375. static void filter_plane3d1(FFTdnoizContext *s, int plane, float *pbuffer)
  376. {
  377. PlaneContext *p = &s->planes[plane];
  378. const int block = p->b;
  379. const int nox = p->nox;
  380. const int noy = p->noy;
  381. const int buffer_linesize = p->buffer_linesize / sizeof(float);
  382. const float sigma = s->sigma * s->sigma * block * block;
  383. const float limit = 1.f - s->amount;
  384. float *cbuffer = p->buffer[CURRENT];
  385. int y, x, i, j;
  386. for (y = 0; y < noy; y++) {
  387. for (x = 0; x < nox; x++) {
  388. float *cbuff = cbuffer + buffer_linesize * y * block + x * block * 2;
  389. float *pbuff = pbuffer + buffer_linesize * y * block + x * block * 2;
  390. for (i = 0; i < block; i++) {
  391. for (j = 0; j < block; j++) {
  392. float factor, power, re, im, pre, pim;
  393. float sumr, sumi, difr, difi;
  394. re = cbuff[j * 2 ];
  395. pre = pbuff[j * 2 ];
  396. im = cbuff[j * 2 + 1];
  397. pim = pbuff[j * 2 + 1];
  398. sumr = re + pre;
  399. sumi = im + pim;
  400. difr = re - pre;
  401. difi = im - pim;
  402. power = sumr * sumr + sumi * sumi + 1e-15f;
  403. factor = FFMAX(limit, (power - sigma) / power);
  404. sumr *= factor;
  405. sumi *= factor;
  406. power = difr * difr + difi * difi + 1e-15f;
  407. factor = FFMAX(limit, (power - sigma) / power);
  408. difr *= factor;
  409. difi *= factor;
  410. cbuff[j * 2 ] = (sumr + difr) * 0.5f;
  411. cbuff[j * 2 + 1] = (sumi + difi) * 0.5f;
  412. }
  413. cbuff += buffer_linesize;
  414. pbuff += buffer_linesize;
  415. }
  416. }
  417. }
  418. }
  419. static void filter_plane2d(FFTdnoizContext *s, int plane)
  420. {
  421. PlaneContext *p = &s->planes[plane];
  422. const int block = p->b;
  423. const int nox = p->nox;
  424. const int noy = p->noy;
  425. const int buffer_linesize = p->buffer_linesize / 4;
  426. const float sigma = s->sigma * s->sigma * block * block;
  427. const float limit = 1.f - s->amount;
  428. float *buffer = p->buffer[CURRENT];
  429. int y, x, i, j;
  430. for (y = 0; y < noy; y++) {
  431. for (x = 0; x < nox; x++) {
  432. float *buff = buffer + buffer_linesize * y * block + x * block * 2;
  433. for (i = 0; i < block; i++) {
  434. for (j = 0; j < block; j++) {
  435. float factor, power, re, im;
  436. re = buff[j * 2 ];
  437. im = buff[j * 2 + 1];
  438. power = re * re + im * im + 1e-15f;
  439. factor = FFMAX(limit, (power - sigma) / power);
  440. buff[j * 2 ] *= factor;
  441. buff[j * 2 + 1] *= factor;
  442. }
  443. buff += buffer_linesize;
  444. }
  445. }
  446. }
  447. }
  448. static int filter_frame(AVFilterLink *inlink, AVFrame *in)
  449. {
  450. AVFilterContext *ctx = inlink->dst;
  451. FFTdnoizContext *s = ctx->priv;
  452. AVFilterLink *outlink = ctx->outputs[0];
  453. int direct, plane;
  454. AVFrame *out;
  455. if (s->nb_next > 0 && s->nb_prev > 0) {
  456. av_frame_free(&s->prev);
  457. s->prev = s->cur;
  458. s->cur = s->next;
  459. s->next = in;
  460. if (!s->prev && s->cur) {
  461. s->prev = av_frame_clone(s->cur);
  462. if (!s->prev)
  463. return AVERROR(ENOMEM);
  464. }
  465. if (!s->cur)
  466. return 0;
  467. } else if (s->nb_next > 0) {
  468. av_frame_free(&s->cur);
  469. s->cur = s->next;
  470. s->next = in;
  471. if (!s->cur)
  472. return 0;
  473. } else if (s->nb_prev > 0) {
  474. av_frame_free(&s->prev);
  475. s->prev = s->cur;
  476. s->cur = in;
  477. if (!s->prev)
  478. s->prev = av_frame_clone(s->cur);
  479. if (!s->prev)
  480. return AVERROR(ENOMEM);
  481. } else {
  482. s->cur = in;
  483. }
  484. if (av_frame_is_writable(in) && s->nb_next == 0 && s->nb_prev == 0) {
  485. direct = 1;
  486. out = in;
  487. } else {
  488. direct = 0;
  489. out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
  490. if (!out)
  491. return AVERROR(ENOMEM);
  492. av_frame_copy_props(out, s->cur);
  493. }
  494. for (plane = 0; plane < s->nb_planes; plane++) {
  495. PlaneContext *p = &s->planes[plane];
  496. if (!((1 << plane) & s->planesf) || ctx->is_disabled) {
  497. if (!direct)
  498. av_image_copy_plane(out->data[plane], out->linesize[plane],
  499. s->cur->data[plane], s->cur->linesize[plane],
  500. p->planewidth, p->planeheight);
  501. continue;
  502. }
  503. if (s->next) {
  504. import_plane(s, s->next->data[plane], s->next->linesize[plane],
  505. p->buffer[NEXT], p->buffer_linesize, plane);
  506. }
  507. if (s->prev) {
  508. import_plane(s, s->prev->data[plane], s->prev->linesize[plane],
  509. p->buffer[PREV], p->buffer_linesize, plane);
  510. }
  511. import_plane(s, s->cur->data[plane], s->cur->linesize[plane],
  512. p->buffer[CURRENT], p->buffer_linesize, plane);
  513. if (s->next && s->prev) {
  514. filter_plane3d2(s, plane, p->buffer[PREV], p->buffer[NEXT]);
  515. } else if (s->next) {
  516. filter_plane3d1(s, plane, p->buffer[NEXT]);
  517. } else if (s->prev) {
  518. filter_plane3d1(s, plane, p->buffer[PREV]);
  519. } else {
  520. filter_plane2d(s, plane);
  521. }
  522. export_plane(s, out->data[plane], out->linesize[plane],
  523. p->buffer[CURRENT], p->buffer_linesize, plane);
  524. }
  525. if (s->nb_next == 0 && s->nb_prev == 0) {
  526. if (direct) {
  527. s->cur = NULL;
  528. } else {
  529. av_frame_free(&s->cur);
  530. }
  531. }
  532. return ff_filter_frame(outlink, out);
  533. }
  534. static int request_frame(AVFilterLink *outlink)
  535. {
  536. AVFilterContext *ctx = outlink->src;
  537. FFTdnoizContext *s = ctx->priv;
  538. int ret = 0;
  539. ret = ff_request_frame(ctx->inputs[0]);
  540. if (ret == AVERROR_EOF && (s->nb_next > 0)) {
  541. AVFrame *buf;
  542. if (s->next && s->nb_next > 0)
  543. buf = av_frame_clone(s->next);
  544. else if (s->cur)
  545. buf = av_frame_clone(s->cur);
  546. else
  547. buf = av_frame_clone(s->prev);
  548. if (!buf)
  549. return AVERROR(ENOMEM);
  550. ret = filter_frame(ctx->inputs[0], buf);
  551. if (ret < 0)
  552. return ret;
  553. ret = AVERROR_EOF;
  554. }
  555. return ret;
  556. }
  557. static av_cold void uninit(AVFilterContext *ctx)
  558. {
  559. FFTdnoizContext *s = ctx->priv;
  560. int i;
  561. for (i = 0; i < 4; i++) {
  562. PlaneContext *p = &s->planes[i];
  563. av_freep(&p->hdata);
  564. av_freep(&p->vdata);
  565. av_freep(&p->buffer[PREV]);
  566. av_freep(&p->buffer[CURRENT]);
  567. av_freep(&p->buffer[NEXT]);
  568. av_fft_end(p->fft);
  569. av_fft_end(p->ifft);
  570. }
  571. av_frame_free(&s->prev);
  572. av_frame_free(&s->cur);
  573. av_frame_free(&s->next);
  574. }
  575. static const AVFilterPad fftdnoiz_inputs[] = {
  576. {
  577. .name = "default",
  578. .type = AVMEDIA_TYPE_VIDEO,
  579. .filter_frame = filter_frame,
  580. .config_props = config_input,
  581. },
  582. { NULL }
  583. };
  584. static const AVFilterPad fftdnoiz_outputs[] = {
  585. {
  586. .name = "default",
  587. .type = AVMEDIA_TYPE_VIDEO,
  588. .request_frame = request_frame,
  589. },
  590. { NULL }
  591. };
  592. AVFilter ff_vf_fftdnoiz = {
  593. .name = "fftdnoiz",
  594. .description = NULL_IF_CONFIG_SMALL("Denoise frames using 3D FFT."),
  595. .priv_size = sizeof(FFTdnoizContext),
  596. .init = init,
  597. .uninit = uninit,
  598. .query_formats = query_formats,
  599. .inputs = fftdnoiz_inputs,
  600. .outputs = fftdnoiz_outputs,
  601. .priv_class = &fftdnoiz_class,
  602. .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
  603. };