Line |
Branch |
Exec |
Source |
1 |
|
|
/* |
2 |
|
|
* Copyright (c) 2013 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 |
|
|
*/ |
20 |
|
|
|
21 |
|
|
#include <float.h> |
22 |
|
|
|
23 |
|
|
#undef pixel |
24 |
|
|
#undef cpixel |
25 |
|
|
#undef ROUND |
26 |
|
|
#if DEPTH == 8 |
27 |
|
|
#define pixel uint8_t |
28 |
|
|
#define cpixel int |
29 |
|
|
#define ROUND lrintf |
30 |
|
|
#elif DEPTH == 16 |
31 |
|
|
#define pixel uint16_t |
32 |
|
|
#define cpixel int |
33 |
|
|
#define ROUND lrintf |
34 |
|
|
#else |
35 |
|
|
#define NOP(x) (x) |
36 |
|
|
#define pixel float |
37 |
|
|
#define cpixel float |
38 |
|
|
#define ROUND NOP |
39 |
|
|
#endif |
40 |
|
|
|
41 |
|
|
#undef fn |
42 |
|
|
#undef fn2 |
43 |
|
|
#undef fn3 |
44 |
|
|
#define fn3(a,b) a##_##b |
45 |
|
|
#define fn2(a,b) fn3(a,b) |
46 |
|
|
#define fn(a) fn2(a, DEPTH) |
47 |
|
|
|
48 |
|
✗ |
static av_always_inline int fn(filter_slice_rgba_planar)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, |
49 |
|
|
int have_alpha, int depth, int pc) |
50 |
|
|
{ |
51 |
|
✗ |
ColorChannelMixerContext *s = ctx->priv; |
52 |
|
✗ |
ThreadData *td = arg; |
53 |
|
✗ |
AVFrame *in = td->in; |
54 |
|
✗ |
AVFrame *out = td->out; |
55 |
|
✗ |
const float pa = s->preserve_amount; |
56 |
|
✗ |
const float max = (1 << depth) - 1; |
57 |
|
✗ |
const int slice_start = (out->height * jobnr) / nb_jobs; |
58 |
|
✗ |
const int slice_end = (out->height * (jobnr+1)) / nb_jobs; |
59 |
|
✗ |
const pixel *srcg = (const pixel *)(in->data[0] + slice_start * in->linesize[0]); |
60 |
|
✗ |
const pixel *srcb = (const pixel *)(in->data[1] + slice_start * in->linesize[1]); |
61 |
|
✗ |
const pixel *srcr = (const pixel *)(in->data[2] + slice_start * in->linesize[2]); |
62 |
|
✗ |
const pixel *srca = (const pixel *)(in->data[3] + slice_start * in->linesize[3]); |
63 |
|
✗ |
pixel *dstg = (pixel *)(out->data[0] + slice_start * out->linesize[0]); |
64 |
|
✗ |
pixel *dstb = (pixel *)(out->data[1] + slice_start * out->linesize[1]); |
65 |
|
✗ |
pixel *dstr = (pixel *)(out->data[2] + slice_start * out->linesize[2]); |
66 |
|
✗ |
pixel *dsta = (pixel *)(out->data[3] + slice_start * out->linesize[3]); |
67 |
|
|
|
68 |
|
✗ |
for (int i = slice_start; i < slice_end; i++) { |
69 |
|
✗ |
for (int j = 0; j < out->width; j++) { |
70 |
|
✗ |
const pixel rin = srcr[j]; |
71 |
|
✗ |
const pixel gin = srcg[j]; |
72 |
|
✗ |
const pixel bin = srcb[j]; |
73 |
|
✗ |
const pixel ain = have_alpha ? srca[j] : 0; |
74 |
|
|
cpixel rout, gout, bout; |
75 |
|
|
|
76 |
|
|
#if DEPTH == 32 |
77 |
|
✗ |
rout = s->rr * rin + |
78 |
|
✗ |
s->rg * gin + |
79 |
|
✗ |
s->rb * bin + |
80 |
|
✗ |
(have_alpha == 1 ? s->ra * ain : 0); |
81 |
|
✗ |
gout = s->gr * rin + |
82 |
|
✗ |
s->gg * gin + |
83 |
|
✗ |
s->gb * bin + |
84 |
|
✗ |
(have_alpha == 1 ? s->ga * ain : 0); |
85 |
|
✗ |
bout = s->br * rin + |
86 |
|
✗ |
s->bg * gin + |
87 |
|
✗ |
s->bb * bin + |
88 |
|
✗ |
(have_alpha == 1 ? s->ba * ain : 0); |
89 |
|
|
#else |
90 |
|
✗ |
rout = s->lut[R][R][rin] + |
91 |
|
✗ |
s->lut[R][G][gin] + |
92 |
|
✗ |
s->lut[R][B][bin] + |
93 |
|
✗ |
(have_alpha == 1 ? s->lut[R][A][ain] : 0); |
94 |
|
✗ |
gout = s->lut[G][R][rin] + |
95 |
|
✗ |
s->lut[G][G][gin] + |
96 |
|
✗ |
s->lut[G][B][bin] + |
97 |
|
✗ |
(have_alpha == 1 ? s->lut[G][A][ain] : 0); |
98 |
|
✗ |
bout = s->lut[B][R][rin] + |
99 |
|
✗ |
s->lut[B][G][gin] + |
100 |
|
✗ |
s->lut[B][B][bin] + |
101 |
|
✗ |
(have_alpha == 1 ? s->lut[B][A][ain] : 0); |
102 |
|
|
#endif |
103 |
|
|
|
104 |
|
✗ |
if (pc) { |
105 |
|
|
float frout, fgout, fbout, lin, lout; |
106 |
|
|
|
107 |
|
|
#if DEPTH < 32 |
108 |
|
✗ |
frout = av_clipf(rout, 0.f, max); |
109 |
|
✗ |
fgout = av_clipf(gout, 0.f, max); |
110 |
|
✗ |
fbout = av_clipf(bout, 0.f, max); |
111 |
|
|
#else |
112 |
|
✗ |
frout = rout; |
113 |
|
✗ |
fgout = gout; |
114 |
|
✗ |
fbout = bout; |
115 |
|
|
#endif |
116 |
|
|
|
117 |
|
✗ |
preserve_color(s->preserve_color, rin, gin, bin, |
118 |
|
|
rout, gout, bout, max, &lin, &lout); |
119 |
|
✗ |
preservel(&frout, &fgout, &fbout, lin, lout, max); |
120 |
|
|
|
121 |
|
✗ |
rout = ROUND(lerpf(rout, frout, pa)); |
122 |
|
✗ |
gout = ROUND(lerpf(gout, fgout, pa)); |
123 |
|
✗ |
bout = ROUND(lerpf(bout, fbout, pa)); |
124 |
|
|
} |
125 |
|
|
|
126 |
|
|
#if DEPTH < 32 |
127 |
|
✗ |
dstr[j] = av_clip_uintp2(rout, depth); |
128 |
|
✗ |
dstg[j] = av_clip_uintp2(gout, depth); |
129 |
|
✗ |
dstb[j] = av_clip_uintp2(bout, depth); |
130 |
|
|
#else |
131 |
|
✗ |
dstr[j] = rout; |
132 |
|
✗ |
dstg[j] = gout; |
133 |
|
✗ |
dstb[j] = bout; |
134 |
|
|
#endif |
135 |
|
|
|
136 |
|
✗ |
if (have_alpha == 1) { |
137 |
|
|
#if DEPTH < 32 |
138 |
|
✗ |
dsta[j] = av_clip_uintp2(s->lut[A][R][rin] + |
139 |
|
✗ |
s->lut[A][G][gin] + |
140 |
|
✗ |
s->lut[A][B][bin] + |
141 |
|
✗ |
s->lut[A][A][ain], depth); |
142 |
|
|
#else |
143 |
|
✗ |
dsta[j] = s->ar * rin + |
144 |
|
✗ |
s->ag * gin + |
145 |
|
✗ |
s->ab * bin + |
146 |
|
✗ |
s->aa * ain; |
147 |
|
|
#endif |
148 |
|
|
} |
149 |
|
|
} |
150 |
|
|
|
151 |
|
✗ |
srcg += in->linesize[0] / sizeof(pixel); |
152 |
|
✗ |
srcb += in->linesize[1] / sizeof(pixel); |
153 |
|
✗ |
srcr += in->linesize[2] / sizeof(pixel); |
154 |
|
✗ |
srca += in->linesize[3] / sizeof(pixel); |
155 |
|
✗ |
dstg += out->linesize[0] / sizeof(pixel); |
156 |
|
✗ |
dstb += out->linesize[1] / sizeof(pixel); |
157 |
|
✗ |
dstr += out->linesize[2] / sizeof(pixel); |
158 |
|
✗ |
dsta += out->linesize[3] / sizeof(pixel); |
159 |
|
|
} |
160 |
|
|
|
161 |
|
✗ |
return 0; |
162 |
|
|
} |
163 |
|
|
|
164 |
|
|
#if DEPTH < 32 |
165 |
|
|
|
166 |
|
450 |
static av_always_inline int fn(filter_slice_rgba_packed)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, |
167 |
|
|
int have_alpha, int step, int pc, int depth) |
168 |
|
|
{ |
169 |
|
450 |
ColorChannelMixerContext *s = ctx->priv; |
170 |
|
450 |
ThreadData *td = arg; |
171 |
|
450 |
AVFrame *in = td->in; |
172 |
|
450 |
AVFrame *out = td->out; |
173 |
|
450 |
const float pa = s->preserve_amount; |
174 |
|
450 |
const float max = (1 << depth) - 1; |
175 |
|
450 |
const int slice_start = (out->height * jobnr) / nb_jobs; |
176 |
|
450 |
const int slice_end = (out->height * (jobnr+1)) / nb_jobs; |
177 |
|
450 |
const uint8_t roffset = s->rgba_map[R]; |
178 |
|
450 |
const uint8_t goffset = s->rgba_map[G]; |
179 |
|
450 |
const uint8_t boffset = s->rgba_map[B]; |
180 |
|
450 |
const uint8_t aoffset = s->rgba_map[A]; |
181 |
|
450 |
const uint8_t *srcrow = in->data[0] + slice_start * in->linesize[0]; |
182 |
|
450 |
uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0]; |
183 |
|
|
int i, j; |
184 |
|
|
|
185 |
|
14850 |
for (i = slice_start; i < slice_end; i++) { |
186 |
|
14400 |
const pixel *src = (const pixel *)srcrow; |
187 |
|
14400 |
pixel *dst = (pixel *)dstrow; |
188 |
|
|
|
189 |
|
5083200 |
for (j = 0; j < out->width * step; j += step) { |
190 |
|
5068800 |
const pixel rin = src[j + roffset]; |
191 |
|
5068800 |
const pixel gin = src[j + goffset]; |
192 |
|
5068800 |
const pixel bin = src[j + boffset]; |
193 |
|
5068800 |
const pixel ain = src[j + aoffset]; |
194 |
|
|
int rout, gout, bout; |
195 |
|
|
|
196 |
|
10137600 |
rout = s->lut[R][R][rin] + |
197 |
|
5068800 |
s->lut[R][G][gin] + |
198 |
|
5068800 |
s->lut[R][B][bin] + |
199 |
|
5068800 |
(have_alpha == 1 ? s->lut[R][A][ain] : 0); |
200 |
|
10137600 |
gout = s->lut[G][R][rin] + |
201 |
|
5068800 |
s->lut[G][G][gin] + |
202 |
|
5068800 |
s->lut[G][B][bin] + |
203 |
|
5068800 |
(have_alpha == 1 ? s->lut[G][A][ain] : 0); |
204 |
|
10137600 |
bout = s->lut[B][R][rin] + |
205 |
|
5068800 |
s->lut[B][G][gin] + |
206 |
|
5068800 |
s->lut[B][B][bin] + |
207 |
|
5068800 |
(have_alpha == 1 ? s->lut[B][A][ain] : 0); |
208 |
|
|
|
209 |
|
5068800 |
if (pc) { |
210 |
|
✗ |
float frout = av_clipf(rout, 0.f, max); |
211 |
|
✗ |
float fgout = av_clipf(gout, 0.f, max); |
212 |
|
✗ |
float fbout = av_clipf(bout, 0.f, max); |
213 |
|
|
float lin, lout; |
214 |
|
|
|
215 |
|
✗ |
preserve_color(s->preserve_color, rin, gin, bin, |
216 |
|
|
rout, gout, bout, max, &lin, &lout); |
217 |
|
✗ |
preservel(&frout, &fgout, &fbout, lin, lout, max); |
218 |
|
|
|
219 |
|
✗ |
rout = lrintf(lerpf(rout, frout, pa)); |
220 |
|
✗ |
gout = lrintf(lerpf(gout, fgout, pa)); |
221 |
|
✗ |
bout = lrintf(lerpf(bout, fbout, pa)); |
222 |
|
|
} |
223 |
|
|
|
224 |
|
5068800 |
dst[j + roffset] = av_clip_uintp2(rout, depth); |
225 |
|
5068800 |
dst[j + goffset] = av_clip_uintp2(gout, depth); |
226 |
|
5068800 |
dst[j + boffset] = av_clip_uintp2(bout, depth); |
227 |
|
|
|
228 |
|
5068800 |
if (have_alpha == 1) { |
229 |
|
✗ |
dst[j + aoffset] = av_clip_uintp2(s->lut[A][R][rin] + |
230 |
|
✗ |
s->lut[A][G][gin] + |
231 |
|
✗ |
s->lut[A][B][bin] + |
232 |
|
✗ |
s->lut[A][A][ain], depth); |
233 |
|
|
} |
234 |
|
|
} |
235 |
|
|
|
236 |
|
14400 |
srcrow += in->linesize[0]; |
237 |
|
14400 |
dstrow += out->linesize[0]; |
238 |
|
|
} |
239 |
|
|
|
240 |
|
450 |
return 0; |
241 |
|
|
} |
242 |
|
|
|
243 |
|
|
#endif |
244 |
|
|
|