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 |
|
|
|
23 |
|
|
#include "libavutil/avassert.h" |
24 |
|
|
#include "avfilter.h" |
25 |
|
|
#include "formats.h" |
26 |
|
|
#include "internal.h" |
27 |
|
|
#include "video.h" |
28 |
|
|
|
29 |
|
|
#undef pixel |
30 |
|
|
#if DEPTH == 8 |
31 |
|
|
#define pixel uint8_t |
32 |
|
|
#else |
33 |
|
|
#define pixel uint16_t |
34 |
|
|
#endif |
35 |
|
|
|
36 |
|
|
#undef htype |
37 |
|
|
#define htype uint16_t |
38 |
|
|
|
39 |
|
|
#undef fn |
40 |
|
|
#undef fn2 |
41 |
|
|
#undef fn3 |
42 |
|
|
#define SHIFT ((DEPTH + 1) / 2) |
43 |
|
|
#define BINS (1 << SHIFT) |
44 |
|
|
#define MASK (BINS - 1) |
45 |
|
|
#define fn3(a,b) a##_##b |
46 |
|
|
#define fn2(a,b) fn3(a,b) |
47 |
|
|
#define fn(a) fn2(a, DEPTH) |
48 |
|
|
|
49 |
|
|
#define PICK_COARSE_BIN(x, y) (BINS * (x) + ((y) >> SHIFT)) |
50 |
|
|
#define PICK_FINE_BIN(x, y, z) (BINS * ((x) * ((y) >> SHIFT) + (z)) + ((y) & MASK)) |
51 |
|
|
|
52 |
|
|
static void fn(filter_plane)(AVFilterContext *ctx, const uint8_t *ssrc, int src_linesize, |
53 |
|
|
uint8_t *ddst, int dst_linesize, int width, int height, |
54 |
|
|
int slice_h_start, int slice_h_end, int jobnr) |
55 |
|
|
{ |
56 |
|
|
MedianContext *s = ctx->priv; |
57 |
|
|
htype *ccoarse = s->coarse[jobnr]; |
58 |
|
|
htype *cfine = s->fine[jobnr]; |
59 |
|
|
const int radius = s->radius; |
60 |
|
|
const int radiusV = s->radiusV; |
61 |
|
|
const int t = s->t; |
62 |
|
|
const pixel *src = (const pixel *)ssrc; |
63 |
|
|
pixel *dst = (pixel *)ddst; |
64 |
|
|
const pixel *srcp; |
65 |
|
|
const pixel *p; |
66 |
|
|
|
67 |
|
|
src_linesize /= sizeof(pixel); |
68 |
|
|
dst_linesize /= sizeof(pixel); |
69 |
|
|
|
70 |
|
|
memset(cfine, 0, s->fine_size * sizeof(*cfine)); |
71 |
|
|
memset(ccoarse, 0, s->coarse_size * sizeof(*ccoarse)); |
72 |
|
|
|
73 |
|
|
srcp = src + FFMAX(0, slice_h_start - radiusV) * src_linesize; |
74 |
|
|
if (jobnr == 0) { |
75 |
|
|
for (int i = 0; i < width; i++) { |
76 |
|
|
cfine[PICK_FINE_BIN(width, srcp[i], i)] += radiusV + 1; |
77 |
|
|
ccoarse[PICK_COARSE_BIN(i, srcp[i])] += radiusV + 1; |
78 |
|
|
} |
79 |
|
|
} |
80 |
|
|
|
81 |
|
|
srcp = src + FFMAX(0, slice_h_start - radiusV - (jobnr != 0)) * src_linesize; |
82 |
|
|
for (int i = 0; i < radiusV + (jobnr != 0) * (1 + radiusV); i++) { |
83 |
|
|
for (int j = 0; j < width; j++) { |
84 |
|
|
cfine[PICK_FINE_BIN(width, srcp[j], j)]++; |
85 |
|
|
ccoarse[PICK_COARSE_BIN(j, srcp[j])]++; |
86 |
|
|
} |
87 |
|
|
srcp += src_linesize; |
88 |
|
|
} |
89 |
|
|
|
90 |
|
|
srcp = src; |
91 |
|
|
|
92 |
|
|
for (int i = slice_h_start; i < slice_h_end; i++) { |
93 |
|
|
htype coarse[BINS] = { 0 }; |
94 |
|
|
htype fine[BINS][BINS] = { { 0 } }; |
95 |
|
|
htype luc[BINS] = { 0 }; |
96 |
|
|
|
97 |
|
|
p = srcp + src_linesize * FFMAX(0, i - radiusV - 1); |
98 |
|
|
for (int j = 0; j < width; j++) { |
99 |
|
|
cfine[PICK_FINE_BIN(width, p[j], j)]--; |
100 |
|
|
ccoarse[PICK_COARSE_BIN(j, p[j])]--; |
101 |
|
|
} |
102 |
|
|
|
103 |
|
|
p = srcp + src_linesize * FFMIN(height - 1, i + radiusV); |
104 |
|
|
for (int j = 0; j < width; j++) { |
105 |
|
|
cfine[PICK_FINE_BIN(width, p[j], j)]++; |
106 |
|
|
ccoarse[PICK_COARSE_BIN(j, p[j])]++; |
107 |
|
|
} |
108 |
|
|
|
109 |
|
|
s->hmuladd(coarse, &ccoarse[0], radius, BINS); |
110 |
|
|
for (int j = 0; j < radius; j++) |
111 |
|
|
s->hadd(coarse, &ccoarse[BINS * j], BINS); |
112 |
|
|
for (int k = 0; k < BINS; k++) |
113 |
|
|
s->hmuladd(&fine[k][0], &cfine[BINS * width * k], 2 * radius + 1, BINS); |
114 |
|
|
|
115 |
|
|
for (int j = 0; j < width; j++) { |
116 |
|
|
int sum = 0, k, b; |
117 |
|
|
htype *segment; |
118 |
|
|
|
119 |
|
|
s->hadd(coarse, &ccoarse[BINS * FFMIN(j + radius, width - 1)], BINS); |
120 |
|
|
|
121 |
|
|
for (k = 0; k < BINS; k++) { |
122 |
|
|
sum += coarse[k]; |
123 |
|
|
if (sum > t) { |
124 |
|
|
sum -= coarse[k]; |
125 |
|
|
break; |
126 |
|
|
} |
127 |
|
|
} |
128 |
|
|
av_assert0(k < BINS); |
129 |
|
|
|
130 |
|
|
if (luc[k] <= j - radius) { |
131 |
|
|
memset(&fine[k], 0, BINS * sizeof(htype)); |
132 |
|
|
for (luc[k] = j - radius; luc[k] < FFMIN(j + radius + 1, width); luc[k]++) |
133 |
|
|
s->hadd(fine[k], &cfine[BINS * (width * k + luc[k])], BINS); |
134 |
|
|
if (luc[k] < j + radius + 1) { |
135 |
|
|
s->hmuladd(&fine[k][0], &cfine[BINS * (width * k + width - 1)], j + radius + 1 - width, BINS); |
136 |
|
|
luc[k] = j + radius + 1; |
137 |
|
|
} |
138 |
|
|
} else { |
139 |
|
|
for (; luc[k] < j + radius + 1; luc[k]++) { |
140 |
|
|
s->hsub(fine[k], &cfine[BINS * (width * k + FFMAX(luc[k] - 2 * radius - 1, 0))], BINS); |
141 |
|
|
s->hadd(fine[k], &cfine[BINS * (width * k + FFMIN(luc[k], width - 1))], BINS); |
142 |
|
|
} |
143 |
|
|
} |
144 |
|
|
|
145 |
|
|
s->hsub(coarse, &ccoarse[BINS * FFMAX(j - radius, 0)], BINS); |
146 |
|
|
|
147 |
|
|
segment = fine[k]; |
148 |
|
|
for (b = 0; b < BINS; b++) { |
149 |
|
|
sum += segment[b]; |
150 |
|
|
if (sum > t) { |
151 |
|
|
dst[j] = BINS * k + b; |
152 |
|
|
break; |
153 |
|
|
} |
154 |
|
|
} |
155 |
|
|
av_assert0(b < BINS); |
156 |
|
|
} |
157 |
|
|
|
158 |
|
|
dst += dst_linesize; |
159 |
|
|
} |
160 |
|
|
} |