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.

161 lines
5.3KB

  1. /*
  2. * Copyright (c) 2019 Paul B Mahol
  3. *
  4. * This file is part of FFmpeg.
  5. *
  6. * FFmpeg is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * FFmpeg is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with FFmpeg; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. * Redistribution and use in source and binary forms, with or without modification,
  20. * are permitted provided that the following conditions are met:
  21. */
  22. #include "libavutil/avassert.h"
  23. #include "avfilter.h"
  24. #include "formats.h"
  25. #include "internal.h"
  26. #include "video.h"
  27. #undef pixel
  28. #if DEPTH == 8
  29. #define pixel uint8_t
  30. #else
  31. #define pixel uint16_t
  32. #endif
  33. #undef htype
  34. #define htype uint16_t
  35. #undef fn
  36. #undef fn2
  37. #undef fn3
  38. #define SHIFT ((DEPTH + 1) / 2)
  39. #define BINS (1 << SHIFT)
  40. #define MASK (BINS - 1)
  41. #define fn3(a,b) a##_##b
  42. #define fn2(a,b) fn3(a,b)
  43. #define fn(a) fn2(a, DEPTH)
  44. #define PICK_COARSE_BIN(x, y) (BINS * (x) + ((y) >> SHIFT))
  45. #define PICK_FINE_BIN(x, y, z) (BINS * ((x) * ((y) >> SHIFT) + (z)) + ((y) & MASK))
  46. static void fn(filter_plane)(AVFilterContext *ctx, const uint8_t *ssrc, int src_linesize,
  47. uint8_t *ddst, int dst_linesize, int width, int height,
  48. int slice_h_start, int slice_h_end, int jobnr)
  49. {
  50. MedianContext *s = ctx->priv;
  51. htype *ccoarse = s->coarse[jobnr];
  52. htype *cfine = s->fine[jobnr];
  53. const int radius = s->radius;
  54. const int radiusV = s->radiusV;
  55. const int t = s->t;
  56. const pixel *src = (const pixel *)ssrc;
  57. pixel *dst = (pixel *)ddst;
  58. const pixel *srcp;
  59. const pixel *p;
  60. src_linesize /= sizeof(pixel);
  61. dst_linesize /= sizeof(pixel);
  62. memset(cfine, 0, s->fine_size * sizeof(*cfine));
  63. memset(ccoarse, 0, s->coarse_size * sizeof(*ccoarse));
  64. srcp = src + FFMAX(0, slice_h_start - radiusV) * src_linesize;
  65. if (jobnr == 0) {
  66. for (int i = 0; i < width; i++) {
  67. cfine[PICK_FINE_BIN(width, srcp[i], i)] += radiusV + 1;
  68. ccoarse[PICK_COARSE_BIN(i, srcp[i])] += radiusV + 1;
  69. }
  70. }
  71. srcp = src + FFMAX(0, slice_h_start - radiusV - (jobnr != 0)) * src_linesize;
  72. for (int i = 0; i < radiusV + (jobnr != 0) * (1 + radiusV); i++) {
  73. for (int j = 0; j < width; j++) {
  74. cfine[PICK_FINE_BIN(width, srcp[j], j)]++;
  75. ccoarse[PICK_COARSE_BIN(j, srcp[j])]++;
  76. }
  77. srcp += src_linesize;
  78. }
  79. srcp = src;
  80. for (int i = slice_h_start; i < slice_h_end; i++) {
  81. htype coarse[BINS] = { 0 };
  82. htype fine[BINS][BINS] = { { 0 } };
  83. htype luc[BINS] = { 0 };
  84. p = srcp + src_linesize * FFMAX(0, i - radiusV - 1);
  85. for (int j = 0; j < width; j++) {
  86. cfine[PICK_FINE_BIN(width, p[j], j)]--;
  87. ccoarse[PICK_COARSE_BIN(j, p[j])]--;
  88. }
  89. p = srcp + src_linesize * FFMIN(height - 1, i + radiusV);
  90. for (int j = 0; j < width; j++) {
  91. cfine[PICK_FINE_BIN(width, p[j], j)]++;
  92. ccoarse[PICK_COARSE_BIN(j, p[j])]++;
  93. }
  94. s->hmuladd(coarse, &ccoarse[0], radius, BINS);
  95. for (int j = 0; j < radius; j++)
  96. s->hadd(coarse, &ccoarse[BINS * j], BINS);
  97. for (int k = 0; k < BINS; k++)
  98. s->hmuladd(&fine[k][0], &cfine[BINS * width * k], 2 * radius + 1, BINS);
  99. for (int j = 0; j < width; j++) {
  100. int sum = 0, k, b;
  101. htype *segment;
  102. s->hadd(coarse, &ccoarse[BINS * FFMIN(j + radius, width - 1)], BINS);
  103. for (k = 0; k < BINS; k++) {
  104. sum += coarse[k];
  105. if (sum > t) {
  106. sum -= coarse[k];
  107. break;
  108. }
  109. }
  110. av_assert0(k < BINS);
  111. if (luc[k] <= j - radius) {
  112. memset(&fine[k], 0, BINS * sizeof(htype));
  113. for (luc[k] = j - radius; luc[k] < FFMIN(j + radius + 1, width); luc[k]++)
  114. s->hadd(fine[k], &cfine[BINS * (width * k + luc[k])], BINS);
  115. if (luc[k] < j + radius + 1) {
  116. s->hmuladd(&fine[k][0], &cfine[BINS * (width * k + width - 1)], j + radius + 1 - width, BINS);
  117. luc[k] = j + radius + 1;
  118. }
  119. } else {
  120. for (; luc[k] < j + radius + 1; luc[k]++) {
  121. s->hsub(fine[k], &cfine[BINS * (width * k + FFMAX(luc[k] - 2 * radius - 1, 0))], BINS);
  122. s->hadd(fine[k], &cfine[BINS * (width * k + FFMIN(luc[k], width - 1))], BINS);
  123. }
  124. }
  125. s->hsub(coarse, &ccoarse[BINS * FFMAX(j - radius, 0)], BINS);
  126. segment = fine[k];
  127. for (b = 0; b < BINS; b++) {
  128. sum += segment[b];
  129. if (sum > t) {
  130. dst[j] = BINS * k + b;
  131. break;
  132. }
  133. }
  134. av_assert0(b < BINS);
  135. }
  136. dst += dst_linesize;
  137. }
  138. }