FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavfilter/colorchannelmixer_template.c
Date: 2024-04-24 18:52:15
Exec Total Coverage
Lines: 43 138 31.2%
Functions: 0 3 0.0%
Branches: 0 22 0.0%

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